(defnsum-number-pairs [input-file output-file] "Read the data from input-file, which contains two floats per line separated by a space. Open file named output-file and, for each line in input-file, write a line to the output file that contains the two floats from the corresponding line of input-file plus a space and the sum of the two floats." (with-open [rdr (io/reader input-file) wtr (io/writer output-file :appendtrue)] (loop [line (.readLine rdr)] (when line (let [pair (map read-string (str/split line #"\s")) first (first pair) second (second pair) sum (+ first second)] (.write wtr (str first " " second " " sum "\n"))) (recur (.readLine rdr))))))
COMPND AMMONIA ATOM 1 N 0.257 -0.363 0.000 ATOM 2 H 0.257 0.727 0.000 ATOM 3 H 0.771 -0.727 0.890 ATOM 4 H 0.771 -0.727 -0.890 END COMPND METHANOL ATOM 1 C -0.748 -0.015 0.024 ATOM 2 O 0.558 0.420 -0.278 ATOM 3 H -1.293 -0.202 -0.901 ATOM 4 H -1.263 0.754 0.600 ATOM 5 H -0.699 -0.934 0.609 ATOM 6 H 0.716 1.404 0.137 END
第一行描述的是分子的名字,接下来到END为止的每行代表原子的ID、类型以及在分子中分布的[x y z]坐标。 我们需要一个函数,将数据读取出来并且以规定的格式输出,格式如下:
COMPND AMMONIA ATOM 1 N 0.257-0.3630.000 ATOM 2 H 0.2570.7270.000 ATOM 3 H 0.771-0.7270.890 ATOM 4 H 0.771-0.727-0.890 COMPND METHANOL ATOM 1 C -0.748-0.0150.024 ATOM 2 O 0.5580.420-0.278 ATOM 3 H -1.293-0.202-0.901 ATOM 4 H -1.2630.7540.600 ATOM 5 H -0.699-0.9340.609 ATOM 6 H 0.7161.4040.137
clojure.core/line-seq [rdr] Added in 1.0 Returns the lines of text from rdr as a lazy sequence of strings. rdr must implement java.io.BufferedReader.
可以确认line-seq返回一个惰性的字符串序列。 再看看(doc take)的文档,得到
1 2 3 4 5 6 7
clojure.core/take [n] [n coll] Added in 1.0 Returns a lazy sequence of the first n items in coll, or all items if there are fewer than n. Returns a stateful transducer when no collection is provided.
插件确实不好写,因为插件是插入庞大的系统当中工作的,那也就意味着写插件需要具备一定的领域知识,包括系统架构、扩展点、业务共性及差异、API及其业务模型对应、安装和测试。而对于开发者而言,学习这些知识的代价绝对是昂贵的。 在《函数式编程思想》一书中,作者Neal Ford提到开发过程当中的两种抽象方式——composable and contextual abstract. 谈及contextual抽象的时候,他把插件系统列为这一抽象中最经典的例子。
Plugin-based architectures are excellent examples of the contextual abstraction. The plug-in API provides a plethora of data structures and other useful context that developers inherit from or summon via already existing methods. But to use the API, a developer must understand what that context provides, and that understanding is sometimes expensive.
Scanner, which runs the source code analysis Compute Engine, which consolidates the output of scanners, for example by computing 2nd-level measures such as ratings aggregating measures (for example number of lines of code of project = sum of lines of code of all files) assigning new issues to developers persisting everything in data stores Web application
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports Java, JavaScript, PLSQL, Apache Velocity, XML, XSL.
<description> Example set of configured PMD rules </description>
<rulename="ComponentsMustNotBeFollowedByComponentsRule" message="Components tags followed by components tag found!" language="xml" class="net.sourceforge.pmd.lang.rule.XPathRule">
<description> Tag components must not be followed by components tag. </description>
privatevoidconvertToIssues(SensorContext context, Document doc) { finalElementroot= doc.getRootElement(); final List<Element> files = root.elements("file"); for (Element file : files) {
final List<Element> violations = file.elements("violation"); finalStringfilePath= file.attributeValue("name"); finalFileSystemfs= context.fileSystem(); finalInputFileinputFile= fs.inputFile(fs.predicates().hasAbsolutePath(filePath)); if (inputFile == null) { LOG.info("fs predicates that there is no {}", filePath); continue; } for (Element violation : violations) { finalStringrule= violation.attributeValue("rule"); finalintbeginLine= Integer.parseInt(violation.attributeValue("beginline")); finalintendLine= Integer.parseInt(violation.attributeValue("endline")); finalintbeginColumn= Integer.parseInt(violation.attributeValue("begincolumn")); finalintendColumn= Integer.parseInt(violation.attributeValue("endcolumn")); finalNewIssuenewIssue= context.newIssue() .forRule(RuleKey.of(CustomRulesDefinition.REPOSITORY_KEY, rule)); finalNewIssueLocationnewIssueLocation= newIssue .newLocation() .on(inputFile) .at(inputFile.newRange(beginLine, beginColumn, endLine, endColumn)) .message(violation.getText()); newIssue.at(newIssueLocation).save(); } } }
这里主要是对PMD生成XML报告的解析和转换。比较需要关注是这块代码:
1 2 3 4 5
finalInputFileinputFile= fs.inputFile(fs.predicates().hasAbsolutePath(filePath)); if (inputFile == null) { LOG.info("fs predicates that there is no {}", filePath); continue; }
$ javac App.java $ javap -v App.class |grep major major version: 52
如果指定source和target参数,再用javac编译App.java
1 2 3 4 5 6 7 8
$ java -version java version "1.8.0_45" ... $ javac -source 7 -target 7 App.java warning: [options] bootstrap class path not set in conjunction with -source 1.7 1 warning $ ls App.class App.java
目前为止还没有任何问题。但若是运行时,这段程序很可能抛出异常java.io.FileNotFoundException: your-file-name (No such file or directory)。原因在于file的路径当中可能存在多级父级目录,例如:outputDir/p1/p2/srcX.html,那么当FileWriter尝试创建srcX.html就会失败。此时最简单的方法就是提前创建好所有的父级目录,于是*outputPath()*方法会变成下面这样:
public boolean mkdirs() Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories. Note that if this operation fails it may have succeeded in creating some of the necessary parent directories. Returns: true if and only if the directory was created, along with all necessary parent directories; false otherwise
With the throws type parameter on the Block interface, we can now accurately generify over the set of exceptions thrown by the Block; with the generic forEach method, we can mirror the exception behavior of the block in forEach(). This is called exception transparency because now the exception behavior of forEach can match the exception behavior of its block argument. Exception transparency simplifies the construction of library classes that implement idioms like internal iteration of data structures, because it is common that methods that accept function-valued arguments will invoke those functions, meaning that the library method will throw a superset of the exceptions thrown by its function-valued arguments.
1. Download nvm-noinstall.zip 2. Update the system environment variables: NVM_HOME, NVM_SYMLINK (C:\Users\Program Files\nodejs This directory should not exist in previously.) 3. Create settings.txt file
var bin = new Buffer('hello', 'utf8');// <Buffer 68 65 6c 6c 6f> bin.toString(); //'hello' var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); bin.toString(); //'hello'
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); var dump = new Buffer(bin.length); bin.copy(dump);
wrapSetTimeout(() => {x.func()}, (err, data) => { if(err) console.log("I catch you again", err); }) =>I catch you again [ReferenceError: x is not defined
f :: Number -> (Number,String) => F :: (Number,String) -> (Number,String)
var bind = function(f) { returnfunctionF(tuple) { var x = tuple[0], s = tuple[1], fx = f(x), y = fx[0], t = fx[1];
return [y, s + t]; }; };
我们来实现元组自函子范畴上的结合律:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var cube = function(x) { return [x * x * x, 'cube was called.']; };
var sine = function(x) { return [Math.sin(x), 'sine was called.']; };
var f = compose(compose(bind(sine), bind(cube)), bind(cube)); f([3, ''])
var f1 = compose(bind(sine), compose(bind(cube), bind(cube))); f1([3,'']) >>> [0.956, 'cube was called.cube was called.sine was called.'] [0.956, 'cube was called.cube was called.sine was called.']
这里f和f1代表的调用顺序产生同样的结果,说明元组自函子范畴满足结合律。
那如何找到这样一个e,使得a*e=e*a=a
1 2 3 4 5 6
// unit :: Number -> (Number,String) var unit = function(x) { return [x, ''] };
var f = compose(bind(sine), bind(cube));
compose(f, bind(unit)) = compose(bind(unit), f) = f
这里的bind(unit)就是e了。
Monads for functional programming一书中介绍说monad是一个三元组(M, unit, *),对应此处就是(Tuple, unit, bind).