çãããã©ãã¯ããã¯ãªã©ããã ããã®ã§ãããã¡ãã£ãšãã®ãã¿ãæžããŠã¿ãããšã«ããŸããã
颿°åæããŠäœãå¬ããã®ãâŠã§ãããåã®äŸã¿ãããªè¶³ãç®ãæãç®ãªããæžããŠãã確ãã«ãããŸããŸãçŸå®å³ãªãã§ããããããããã«ãããããåçŽãªã¡ãœããåŒã³åºãã®çµã¿åãããšæ¯ã¹ãŠãäœãéãïŒã£ãŠè©±ããããšæããŸãã
def f(x) ... def g(x) ... g(f(x)) // f >> gãšæå³çã«ã¯åã
èãæ¹ãšããŠã¯ããå°ããªé¢æ°ãåæããŠå¥ã®å€§ããªé¢æ°ãäœãäžããŠããããšããããšã§ããããããããæèã«çœ®ããäžã§å®è£ ããããã«ããŠãããšãèªç¶ãšèŠéãããã倧ããã®é¢æ°å®çŸ©ãããããã«ãªãããããªãããªãŒãšæããŸãã
ä»ã«äŸ¿å©ãªãšããã¯ã颿°ãåæããããšã§ä»ã®ã颿°ãåŒæ°ã«åã颿°ãã«æå³çã«ã¯2ã€ä»¥äžã®é¢æ°ãæž¡ãããããããã«ãªããšããã§ããããã
äŸãã°ãCollection#collectã¯åŒæ°ã1ã€åãClosureãåŒæ°ãšããŠåããšããŸãããClosureãåæããããšã§2ã€ä»¥äžã®å€æãè¡ãããããšãã§ããŸãã
def add2 = { it + 2 } def multiply3 = { it * 3 } [1, 2, 3].collect(add2 >> multiply3) // [9, 12, 15] [1, 2, 3].collect(add2 << multiply3) // [5, 8, 11]
collectå ã«ãClosure#callãæç€ºçã«æžãããŠããªããšããããã€ã³ãã§ãã
ãã§ããããããã¡ãã£ãšããéã³ã§ãããã£ããåçèšèªã§ãããã®ã ãããClosureãListã«ã§ãæºã蟌ãã§ãããšã§ãŸãšããŠåæã»é©çšãªããŠããã°ã©ã ãæžããŠã¿ãããšæããŸãã
å ãã¿ã¯ããã®æ¬ã«ç»å Žãããcat -nãã®äŸã§ãã

- äœè : éæšå³°é,å±±äžäŒžå€«
- åºç瀟/ã¡ãŒã«ãŒ: ãœãããã³ã¯ã¯ãªãšã€ãã£ã
- çºå£²æ¥: 2006/06/01
- ã¡ãã£ã¢: åè¡æ¬
- è³Œå ¥: 25人 ã¯ãªãã¯: 314å
- ãã®ååãå«ãããã° (320ä»¶) ãèŠã
ãŸããClosureãæºã蟌ãã¯ã©ã¹ãšããŠãããããã®ãçšæããŸããã
class Pipeline { private def closures = [] def call(Object... args) { andThen().call(*args) } def rightShift(closure) { closures << closure this } private def andThen() { assert !closures.empty closures.tail().inject(closures.head(), { acc, c -> acc >> c }) } }
callã¡ãœãããå®è£ ããŠããã®ã§ã颿°ãªããžã§ã¯ãã£ãœãåŒã³åºããã§ããããã«ãªã£ãŠããŸããå éšã«ã¯Closureãæºã蟌ãListãæã£ãŠãããcallã¡ãœãããåŒã³åºãããã¿ã€ãã³ã°ã§Collection#injectã䜿ã£ãŠåæããŸãã
äœ¿ãæ¹ãšããŠã¯ããããªæãã
def pipeline = new Pipeline() pipeline >> { str -> str.split(' ').toList() } pipeline >> { xs -> xs.collect { "***${it}***" } } pipeline >> { xs -> xs.join(' ') } println(pipeline("Hello World")) // => ã***Hello*** ***World***ã
å®éã«ClosureãåæããããŸã§ãã¯ã³ã¯ãã·ã§ã³æãã§ããã®ã§åŸã§Closureã®è¿œå ïŒåé€ãªã©ãäžå¿å¯èœã§ããä»åã¯ããããŸã§çšæããŠããŸãããã
ããã䜿ã£ãŠããcat -nãã³ãã³ããå®è£ ããŠã¿ãŸãããŸãã¯ãããããClosureãçšæããŸãã
def fileContents = { fileName, encoding -> new File(fileName).getText(encoding) } def toLines = { text -> text.split(/\r?\n/).toList() } def sizePair = { lines -> [lines.size(), lines] } def format = { max, lines -> def size = "$max".size() + 1 def zipped = [(1 .. max), lines].transpose() zipped.collect { index, line -> String.format("%${size}d: %s", index, line) } } def toUnlines = { lines -> lines.join(System.getProperty('line.separator'))}
ãããåæãããã®ããcatnãšåä»ããŸãã
def catn = new Pipeline() >> fileContents >> toLines >> sizePair >> format >> toUnlines >> this.&println
Closureã®åæã®æµããããããããšããŠããããšãããããŸãâŠããïŒ
æåŸããããåŒã³åºããŠæšæºåºåã«åãåºããŸããä»åã¯ããã®ã¹ã¯ãªããèªäœã衚瀺ããŸãã
catn('closure_pipeline.groovy', 'UTF-8')
å®è¡çµæã
1: class Pipeline { 2: private def closures = [] 3: 4: def call(Object... args) { 5: andThen().call(*args) 6: } 7: 8: def rightShift(closure) { 9: closures << closure 10: this 11: } 12: 13: private def andThen() { 14: assert !closures.empty 15: closures.tail().inject(closures.head(), { acc, c -> acc >> c }) 16: } 17: } 18: 19: def fileContents = { fileName, encoding -> new File(fileName).getText(encoding) } 20: def toLines = { text -> text.split(/\r?\n/).toList() } 21: def sizePair = { lines -> [lines.size(), lines] } 22: def format = { max, lines -> 23: def size = "$max".size() + 1 24: def zipped = [(1 .. max), lines].transpose() 25: zipped.collect { index, line -> String.format("%${size}d: %s", index, line) } 26: } 27: def toUnlines = { lines -> lines.join(System.getProperty('line.separator'))} 28: 29: def catn = new Pipeline() >> fileContents >> toLines >> sizePair >> format >> toUnlines >> this.&println 30: catn('closure_pipeline.groovy', 'UTF-8')
äœæããPipelineã¯ã©ã¹ã®rightShiftã§Closureã远å ã§ãããã€thisãè¿ãããã«ããŠããã®ã§ãã®ãŸãŸåæããŠãããŸãããããªæãã§ãClosureãåçã«è¿œå ããŠãããClosureã®åŠççµæã«æ¬¡ã ãšClosureãåŒã³åºããŠé©çšããŠããããªããŠããä»çµã¿ã§ãããå°ãã¯é¢çœããªãã§ããããïŒïŒ
ããšãClosureã远å ããæã«ãClosureãã®ãã®ã§ã¯ãªããŠMapã§å ããããã«ãããšãåŸã§åé€ãããããã®ã楜ã«ãªããããããŸãããããããããšã¯ã©ã¹åãšãããã©ãã©ãNettyã®ãã¯ãã«ãªã£ãŠãããŸããâŠã
ãã ãé¢çœãããšã¯é¢çœãã®ã§ããã颿°ã®åŒæ°ééããšãã§ã³ã±ãå Žåã®ãããã°ã¯ããªãé¢åã§ããã§ããããšãªããéçã«å®çŸ©ããŠããã«ãããããšã¯ãããŸãããããããäœ¿ãæ¹ã¯ãäžéšã®æ©èœãšãã«ãšã©ããŠãããæ¹ãç¡é£ã§ããããã
äžå¿ãäœæããã¹ã¯ãªãããèŒããŠãããŸãã
closure_pipeline.groovy
class Pipeline { private def closures = [] def call(Object... args) { andThen().call(*args) } def rightShift(closure) { closures << closure this } private def andThen() { assert !closures.empty closures.tail().inject(closures.head(), { acc, c -> acc >> c }) } } def fileContents = { fileName, encoding -> new File(fileName).getText(encoding) } def toLines = { text -> text.split(/\r?\n/).toList() } def sizePair = { lines -> [lines.size(), lines] } def format = { max, lines -> def size = "$max".size() + 1 def zipped = [(1 .. max), lines].transpose() zipped.collect { index, line -> String.format("%${size}d: %s", index, line) } } def toUnlines = { lines -> lines.join(System.getProperty('line.separator'))} def catn = new Pipeline() >> fileContents >> toLines >> sizePair >> format >> toUnlines >> this.&println catn('closure_pipeline.groovy', 'UTF-8')
ãã®ä»çµã¿ã¯Scalaã¿ãããªéçèšèªã§ããããšãããšããã£ããããã©ãããšã«ãªãããããªãããªããšæããŸãâŠãåæãã颿°ã®åŒæ°ã¯1ã€ã ãããšãå¶éã眮ãããªãå°ãã¯ãã·ïŒããã§ããçžåœã€ãããã§ããããã£ãŠããªã©ã€ãã¯Clojureã§ãã£ãŠã¿ãŸããã
ãã¡ããClojureçã§ãã
function_pipeline.clj
(defn and-then ([f] f) ([f g] (comp g f)) ([f g & fs] (apply comp (reverse (cons f (cons g (vec fs))))))) (defn >> [pipeline f] (dosync (alter pipeline conj f))) (defn apply-pipeline [pipeline & args] (apply (apply and-then @pipeline) args)) (import '(java.io BufferedReader InputStreamReader FileInputStream)) (defn lines [file-name encoding] (line-seq (BufferedReader. (InputStreamReader. (FileInputStream. file-name) encoding)))) (defn size-pair [lines] [(.size lines) lines]) (defn n-format [max-lines] (let [max (+ (first max-lines) 1) lines (second max-lines) size (.. max toString length) zipped (map (fn [s line] [s line]) (range 1 max) lines)] (map (fn [size-line] (let [s (first size-line) line (second size-line)] (format (str "%" size "d: %s") s line))) zipped))) (defn unlines [lines] (let [line-separator (System/getProperty "line.separator")] (reduce (fn [acc line] (str acc line-separator line)) lines))) (defn cat-n [file-name encoding] (def pipeline (ref [])) (>> pipeline lines) (>> pipeline size-pair) (>> pipeline n-format) (>> pipeline unlines) (>> pipeline println) (apply-pipeline pipeline file-name encoding)) (cat-n "function_pipeline.clj" "UTF-8")
Clojureã«ã¯é¢æ°ãåããåæããŠãã颿°ïŒGroovyã®Closure#>>ãScalaã®FunctionN#andThenïŒãç¡ãã®ã§ãèªåã§å®è£ ããŸãããä»åã®ã³ã¬ã¯ã·ã§ã³ã®å€æŽã«ã¯ãçŽ çŽã«STMã䜿çšããŠããŸãã
åäœèªäœã¯Groovyçãšåãã§ãããããã¯ããã§ãã£ãããŠããããŸããâŠã
ïŒè¿œèšïŒ
äžå¿ãScalaã§ãæžããŠã¿ãŸãããããäºæ³éãã¿ã€ãã»ãŒããããªããªã£ã¡ããã®ã§ãåæã¯éçã«ããã®ãããããã§ããã
trait Pipeline { var functions: List[Any => Any] = Nil def apply[A, B](arg: A): B = compose(arg).asInstanceOf[B] def >>[A, B](f: A => B): Pipeline = { functions = f.asInstanceOf[Any => Any] :: functions this } private def compose: Any => Any = functions.reduceLeft((acc, f) => acc compose f) } import scala.io.Source class Catn(encoding: String = System.getProperty("file.encoding")) extends Pipeline { { val fc = fileContents(_: String, encoding) this >> fc >> lines >> sizePair >> nFormat >> unlines >> println } def fileContents(fileName: String, encoding: String): String = { val source = Source.fromFile(fileName, encoding) try { source.mkString } finally { source.close() } } def lines(contents: String): List[String] = contents.lines.toList def sizePair(contents: List[String]): (Int, List[String]) = (contents.size, contents) def nFormat(pair: (Int, List[String])): List[String] = { val (max, lines) = pair val size = max.toString.size lines zip (1 to max) map { case (line, index) => ("%" + size + "d: %s").format(index, line) } } def unlines(contents: List[String]): String = contents mkString System.getProperty("line.separator") } val catn = new Catn("UTF-8") catn("function_pipeline.scala")
Scalaã®å Žåã颿°åæã¯Function1ãã¬ã€ãã®ã€ã³ã¹ã¿ã³ã¹ã§ããã§ããªãã®ã§ãFunction2ãªã©ã®å Žåã¯éšåé©çšã䜿ã£ãŠFunction1ã«å€æããŠãããå¿ èŠããããŸãã
âŠãŸãããã£ã±ããããã埮åŠã§ããã