ããã°ã©ãã³ã°è¨èªAmberã®ç´¹ä»(ãã®1)
3å¹´ã¶ãã«æ´æ°ãã¾ãããã®ï¼å¹´éã«ã(éä¸1年以ä¸å¥ã®äºããã£ã¦ãã¾ããã)èªä½ã®è¨èªã¨ãã®å¦çç³»ã®éçºã¯ç¶ãã¦ãã¾ãããããããç´¹ä»è¨äºãæ¸ãå§ãããã¨æãã¾ããホームページã¯æ¢ã«ããã¾ããããã¡ãã¯æ¨å¹´ã®å¤ããæ´æ°ãã¦ããªãã®ã§å 容ãå¤ããªã£ã¦ãã¾ããæ¬è¨äºãå ã«ãã¦å¾ã§æ´æ°ãã¾ãã
è¨èªã®ååã¯Amberã¨è¨ãã¾ããAmberã¨ã¯æ¥æ¬èªã§ç¥çã¨ããæå³ã§ããå®ã¯ååã®è¨èªå¦çç³»ãããã¤ãåå¨ããã®ã§ãã(larsivi / amber / wiki / Home — Bitbucket, GitHub - eknkc/amber: Amber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade, The Amber Programming Languageãªã©)ããã®ååã«ã¯æçãããã¾ãããããå çã«ã¤ãã¦é ããååã§ããã¨ãããã¨ãããã®ã§ç§ã使ç¨ããã¦é ãã¾ãã
Amberã¯åçåã®ã¹ã¯ãªããè¨èªã§ã以ä¸ã®æ§ãªç¹å¾´ãæã¡ã¾ãã
- åå³è±¡æ§
- ãã¼ã¿è¡¨ç¾ã¯é¢æ°å + å¼æ°
- ãããã¿ã¤ããã¼ã¹ã®ãªãã¸ã§ã¯ãã·ã¹ãã
- é¢æ°ã¯å ¨ã¦é¨åé¢æ°ã§ããé¢æ°å士ã¯åä½µå¯è½
åå³è±¡æ§ã¨ã¯ããã°ã©ã ã¨ã³ã¼ããåã表ç¾ãæã¤ã¨ããæ§è³ªã§Lispç³»è¨èªã«è¦ããããã®ã§ããä½ãããã¼ã¿è¡¨ç¾ã¯ã³ã³ã¹ã»ã«ã§ã¯ãªããé¢æ°åfã¨å¹¾ã¤ãã®å¼æ°e1,e2,...,enãããªã f{e1, e2, ..., en} ã¨ããå½¢å¼ã§ããåå³è±¡æ§ã¨ãããã¿ã¤ããã¼ã¹ã¨ããã®ã¯ã¡ã¿ããã°ã©ãã³ã°ãå¼·ãæèããé¸æã§ããAmberã¯çæçããã°ã©ãã³ã°ãèªå·±åæ çããã°ã©ãã³ã°ãªã©ãé常ã«å¹³æã«è¡ããããã«ä½ããã¦ãã¾ããã¡ã¿ããã°ã©ãã³ã°ãéè¦ããäºã®å ·ä½çãªç®çã¯ã¾ãå¾ã§èª¬æãã¾ããAmberã®é¢æ°ã¯å¼æ°ã®ãã¿ã¼ã³åã³ã¬ã¼ãç¯ã«ãã£ã¦ãã®å®ç¾©åãéå®ãããäºã§é¨åé¢æ°ã¨ãªããããã«é¨åå士ãåä½µããäºã«ãã£ã¦ããããªé¢æ°ãä½ãäºãåºæ¥ã¾ãã
ãã°ã®å ±åãã¢ã¤ãã¢ã»ãæè¦ãããã ãã¾ãã¨å¤§å¤ãããããã§ãããã®å ´åã¯[twitter:@9_ties]ã«ãé¡ããã¾ããAmberã®ä»æ§ã¯ã¾ã åæãã¦ããªãã®ã§ç´°ããªå¤æ´ãä»å¾ãç¶ãã¾ãããã®ææ¸ã¯ææ°ã®ä»æ§ã«åãããããé å¼µãã¾ãããééã£ã¦ããããã¿ã¾ããã
ãã«ãã»ã¤ã³ã¹ãã¼ã«
Amberã®ã¤ã³ã¿ããªã¿amberã¯ä»¥ä¸ã®æé ã§ãã«ãã»ã¤ã³ã¹ãã¼ã«ã§ãã¾ãããã«ãã«ã¯Linuxç°å¢ã¨git,make,binutilsãå¿ è¦ã§ããããã©ã«ãã§ã¯/usr/lib/amber/以ä¸ã«ã©ã¤ãã©ãªç¾¤ãã/usr/bin/以ä¸ã«amberã¨ããã¹ã¯ãªãã1ã¤ãã¤ã³ã¹ãã¼ã«ããã¾ããã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã¯ã¾ã ç¨æãã¦ããªãã®ã§ããææ°ã§ããå¿ è¦ãªãã°Makefileä»ãæ¸ãç´ãã¦ä¸ãããã¤ã³ã¹ãã¼ã«å ã¯/usr/lib/ã¾ãã¯LD_LIBRARY_PATHã«è¨å®ããããã£ã¬ã¯ããªã«ãã¦ãã ããã
% git clone https://github.com/nineties/amber.git % cd amber % make % sudo make install
ãã«ãã¯ä»¥ä¸ã®æé ã§ãã¼ãã¹ãã©ããã³ã°ã«ããè¡ããã¾ãã
- ã¢ã»ã³ããªè¨èªã§æ¸ãããrlcã¨ããç°¡åãªæç¶ãåè¨èªã®ã³ã³ãã¤ã©ãGNU Assemblerã§ã³ã³ãã¤ã«ã
- rlcã§rlciã¨ããç°¡åãªLispã¤ã³ã¿ããªã¿ãã³ã³ãã¤ã«ã
- rlciã§rlvmã¨ããamberã®ä»®æ³ãã·ã³ã®ã¢ã»ã³ããªã³ã¼ããçæããGNU Assemblerã§ã³ã³ãã¤ã«ã
- rlciã§rlvmã®ãã¤ãã³ã¼ãç¨ã®ãªã³ã«(ããèªä½ãrlvmä¸ã§åã)ãã³ã³ãã¤ã«ã
- rlciã§rlvmã®ãã¤ãã³ã¼ãç¨ã®éã¢ã»ã³ãã©(ããèªä½ãrlvmä¸ã§åã)ãã³ã³ãã¤ã«ã
- rlciã§amberã®ã½ã¼ã¹ã³ã¼ããã³ã³ãã¤ã«ããrlvmç¨ã®ãªãã¸ã§ã¯ããã¡ã¤ã«(*.rlo)ãçæã
- ä¸ã§ä½æãããªã³ã«ã使ã£ã¦*.rloããªã³ã¯ã
Hello World
% amber
ã§amberã®ã·ã§ã«ãèµ·åãã¾ãã(注:ã¾ã readlineãhistoryãå®è£
ãã¦ãã¾ããã®ã§è¡ç·¨éãåºæ¥ã¾ããããã®ãã¡å®è£
ãã¾ãã)
ãããã¯ãã¡ã¤ã«ã«ããã°ã©ã ãæ¸ãã¦
% amber hoge.ab
ã¨å®è¡ãã¾ããAmberã¹ã¯ãªããã®æ¡å¼µåã¯.abã§ãã
ã¾ãã¯Hello Worldã§ãã
amber:1> puts("Hello Amber!") Hello Amber! => nil
ã·ã§ã«ãçµäºãããçºã«ã¯exitã¨ã¿ã¤ããã¾ãã
ä»ã«ãå¹¾ã¤ãè¦ã¦ã¿ã¾ããããamberã·ã§ã«ã§ã¯ç´åã®è¨ç®çµæã$ã§åç §ããäºãåºæ¥ã¾ããã¾ãnçªç®ã®ããã³ãã(amber:n> ...)ã®çµæã$nã§åãåºãã¾ããä¾ãã°ä»¥ä¸ã®2 * $ã§ã¯ 2Ã3ãã$2 / $3ã§ã¯3å²ã6ãè¨ç®ãã¦ãã¾ãã
amber:2> 1 + 2 => 3 amber:3> 2 * $ => 6 amber:4> $2 / $3 => 0.5
ã¾ããæ´æ°ã¯æ¡ãããµããã¨èªåçã«å¤åé·æ´æ°ã«å¤æããã¾ãã
amber:5> 7 ^ 160 => 1643184774938171857917000410556544806341837419599523497069764671233207565562287891877564323818254449486910838997871467298047369612896001
åºæ¬çãªæ°å¦é¢æ°ã¯å®è£ ãã¦ããã¾ãã®ã§ãã¨ããããé¢æ°é»åã¨ãã¦ãããã使ããã¨æãã¾ãã
amber:6> import math => Module{math} amber:7> math::sin(1) => 0.8414709848078965
ã¢ã¸ã¥ã¼ã«å¤æ°ã¯ :: ã¨ããè¨å·ã使ã£ã¦åç §ãã¾ããimportã®ãªãã·ã§ã³ã§æå®ãã¦ç¾å¨ã®åå空éã«æã£ã¦ããäºãåºæ¥ã¾ããä¾ãã°ä»¥ä¸ã®æ§ã«ããã¨math::ãªãã§sqrtãå¼ã¹ã¾ãã
amber:8> import math (sqrt) => Module{math} amber:9> sqrt(2) => 1.414213562373095
ä»ã«ãããç¹å®ã®å¤æ°ä»¥å¤ãæã£ã¦ããããå ¨ã¦æã£ã¦ããã¨ãã£ãäºãåºæ¥ã¾ãã
amber:10> import math hiding (tan, cos) => Module{math} amber:11> log(2) => 0.6931471805599454 amber:12> cos(1) Exception: UndefinedVariable{cos} amber:12> import math (*) => Module{math} amber:13> cos(1) => 0.5403023058681398
ã·ã³ãã«ã¯å¤æ°åãªã©ã®å種ãå称ãã表ããã¼ã¿åã§ããAmberã®èå¥å([A-Za-z_][A-Za-z0-9_]*[!?]?ã¨ããææ³)ã«å¯¾å¿ããã·ã³ãã«ã¯ã·ã³ã°ã«ã¯ãªã¼ãã§ä»¥ä¸ã®æ§ã«è¨è¿°ããã¨ä½æåºæ¥ã¾ãã
amber:14> 'this_is_a_symbol => this_is_a_symbol
ä¸è¬ã®æååã«ã¤ãã¦ã¯to_symã¡ã½ããã§ã·ã³ãã«åã§ãã¾ãã
amber:15> "this is a symbol".to_sym() => this is a symbol
ã·ã³ãã«ã¯è¡¨ã«ç»é²ãããåãæååã«å¯¾å¿ããã·ã³ãã«ã¯å¸¸ã«ã¡ã¢ãªä¸ã§åä¸ã®ãã¼ã¿ã§ããäºãä¿è¨¼ããã¾ããåãå¤ãå¦ãã¯æ¼ç®å == ã§ããã¼ã¿ã®å®ä½ãåä¸ãå¦ãã¯é¢æ°identical?ã§èª¿ã¹ããã¾ãã
amber:16> "abc" == "abc" => true amber:17> identical?("abc", "abc") => false amber:18> 'abc == 'abc => true amber:19> identical?('abc, 'abc) => true
ãã®ä»ãåå§çãªãã¼ã¿åã«ã¯çå½å¤true,falseã¨æå³ã®ç¡ãå¤ã§ããäºã表ãnilãããã¾ãã
æ´¾çåã®ä¾ã¨ãã¦ã³ã³ãããç´¹ä»ãã¾ããè¯ã使ãã³ã³ããåã¯ã¿ãã«ã»ãªã¹ãã»é åã»ãã¼ãã«(ããã·ã¥è¡¨)ã§ããæ¼ç®å[ ]ã§åè¦ç´ ã«ã¢ã¯ã»ã¹åºæ¥ã¾ãããã®ä»ã³ã³ããã®ç¹å¾´ã«å¿ããã¡ã½ãããç¨æããã¦ãã¾ãã
amber:20> (1,2,3) => (1, 2, 3) amber:21> [1,2,3,4,5] => [1, 2, 3, 4, 5] amber:22> Array{1, 2, "foo", "bar"} => Array{1, 2, "foo", "bar"} amber:23> Table{("one", 1), ("two", 2), ("three", 3)} => Table{("three", 3), ("two", 2), ("one", 1)} amber:24> $["two"] => 2
å¤æ°ãå®ç¾©ããå ´åã«ã¯ := ã¨ããè¨å·ãç¨ãã¾ããå¤ãã®ã¹ã¯ãªããè¨èªã§ã¯ãããªãå¤æ°ã«ä»£å ¥ãåºæ¥ã¾ãããAmberã§ã¯å®ç¾©ãå¿ è¦ã§ãã
amber:25> x := 2 => 2 amber:26> x + 1 => 3 amber:27> x = 3 => 3 amber:28> x => 3 amber:29> y = 1 Exception: UndefinedVariable{y}
å¶å¾¡æ§é ã¯ifæ, whileæ, foræ, try-catchæãªã©æç¶ãåè¨èªã®æ¨æºçãªãã®ãå®è£ ããã¦ãã¾ããè¤æ°è¡ã®ã³ã¼ããããã¯ã¯ { ... } ã§å²ã¿ã¾ãã
amber:29> if [1,5,3,4].include?(3) { amber:29~ puts("found") amber:29~ } else { amber:29~ puts("not found") amber:29~ } found => nil amber:30> i := 0 => 0 amber:31> while (i < 10) amber:31~ i += 1 => nil amber:32> i => 10 amber:33> for i in 1..10 amber:33~ puts i 1 2 3 4 5 6 7 8 9 10 => nil amber:34> for v in [1,2,3,4] amber:34~ puts v 1 2 3 4 => nil
ãã¨ã¯shift-resetãã¼ã¹ã®éå®ç¶ç¶ãå®é¨çã«å®è£
ãã¦ãã¾ããAmberã®ã¢ããªã±ã¼ã·ã§ã³ã§ã¯å¯¾è©±åã»ãã·ã§ã³ãç©æ¥µçã«ä½¿ã£ã¦ãããã¨æã£ã¦ããã®ã§ç¶ç¶ã¯ãã£ãæ¹ãè¯ãã ããã¨ããèãã§ãããã ããããå®è£
ããå¯è½æ§ãèããã«ã¬ãã¼ã¸ã³ã¬ã¯ã¿ãå®è£
ãã¦ãã¾ã£ãã®ã§ã大åå®è£
ãé¢åãªäºã«ãªã£ã¦ãã¾ãã¾ãããå®è£
ã«ããã£ã¦ã¯ä»¥ä¸ãåèã«ããã¦é ãã¾ããã
益子萌,浅井健一(2009)「MinCamlコンパイラにおけるshift=resetの実装」PPL09
amber:35> cont := nil => nil amber:36> reset () -> { amber:36~ puts("foo") amber:36~ shift k -> { cont = k } amber:36~ puts("bar") amber:36~ shift k -> { cont = k } amber:36~ puts("baz") amber:36~ } foo => <#Function> amber:37> cont(nil) bar => <#Function> amber:38> cont(nil) baz => nil
ãã¼ã¿ã®è¡¨ç¾
Amberã®ãã¼ã¿ã¯æ°å¤åãæåååãªã©ã®åå§çãªãã¸ã§ã¯ã(ã¢ãã )ã¨ãã·ã³ãã«fã¨å¹¾ã¤ãã®å¼æ°e1,e2,...,enãããªãf{e1, e2, ..., en}ã¨ããå½¢å¼ã®æ´¾çãªãã¸ã§ã¯ããããªãã¾ããAmberã§ã¯fããªãã¸ã§ã¯ãã®ããããnãã¢ãªãã£ã¨å¼ãã§ãã¾ãã(ã¢ãªãã£ã¯ãããã®å±æ§ã§ã¯ãªãã¦ãªãã¸ã§ã¯ãã®å±æ§ã§ããé常ã®ç¨æ³ã¨ç°ãªãã®ã§å¥å¦ããããã¾ããããä»ã«è¯ãååãæãæµ®ãã³ã¾ããã§ããã)
fullformã¨ããé¢æ°ã§ä»»æã®ãªãã¸ã§ã¯ãããã®å½¢å¼ã§æåååããäºãã§ãã¾ããã¾ãã.head, .arity, .argumentsã§ãããããåãåºãäºãåºæ¥ã¾ãã(fullformã¨ããå¼ç§°ã¯Mathematicaããé ãã¦ãã¾ãã)
amber:39> obj := (1,2,[3,4]) => (1, 2, [3, 4]) amber:40> fullform(obj) => "Tuple{1, 2, List{3, 4}}" amber:41> obj.head => Tuple amber:42> obj.arity => 3 amber:43> obj.arguments => [1, 2, [3, 4]]
ãã¡ãããfullformãç´ã«å ¥åãã¦ãè¯ãã§ãã
amber:44> List{1, List{2, 3}, List{4, 5}} => [1, [2, 3], [4, 5]]
ã¢ãã ã¯æ´¾çãªãã¸ã§ã¯ãã§ã¯ãªãã®ã§fullformã¯ããã¾ãããããããã«ããããã¨å¼ã°ããã·ã³ãã«ãç´ä»ãããã¦ããã¢ãªãã£ã0ã®ãªãã¸ã§ã¯ãã¨ãã¦æ´¾çãªãã¸ã§ã¯ãã¨åæ§ã«åãæ±ãäºãåºæ¥ã¾ãã
amber:45> "abc".head => String amber:46> "abc".arity => 0 amber:47> "abc".arguments => [] amber:48> fullform("abc") => "\"abc\""
åå³è±¡æ§
Amberã®ããã°ã©ã ããèªä½ãAmberã®ãã¼ã¿ã¨ãã¦åãæ±ãäºãåºæ¥ã¾ããLispã¨åæ§ã«ã¯ãªã¼ã(è¨å·')ãå©ç¨ããã¨è©ä¾¡å¨ã®è©ä¾¡ãæ¢ãã¦æ§ææ¨ãåãåºãäºãåºæ¥ã¾ããåºåã¯æ´å½¢ããã¾ãããfullformã使ãã°é常ã®ãã¼ã¿ã¨åãæ§é ã§ããäºãå¤ãã¾ããã¾ããé¢æ°evalfullã«ãã£ã¦ãããè©ä¾¡ããäºãåºæ¥ã¾ãã
amber:49> '{ amber:49~ s := 0 amber:49~ for i in 1..100 amber:49~ s += i^2 amber:49~ s amber:49~ } => { s := 0 for i in 1..100 { s += i^2 } s } amber:50> fullform($) => "Block{Define{s, 0}, For{i, Range{1, 100}, Block{AddAssign{s, Pow{i, 2}}}}, s}" amber:51> evalfull($49) => 338350
æºã¯ãªã¼ã(è¨å·`)ã¨ã¢ã³ã¯ãªã¼ã(è¨å·!)ãç¨æããã¦ãã¦ãæºã¯ãªã¼ãã®ä¸ã§ã¯ã¢ã³ã¯ãªã¼ããããé¨åã ãè©ä¾¡ãè¡ããã¾ãã
amber:52> `(1 + !(2 + 3)) => 1 + 5
é¢æ°
é¢æ°ãè¨å· := ãç¨ãã¦å®ç¾©ãã¾ãã
amber:53> f(x) := x + 1 => <#Function> amber:54> f(1) => 2
é¢æ°ã®å¼æ°é¨ã«ã¯å種ãã¿ã¼ã³ãæå®ããäºãåºæ¥ã¾ããä¾ãã°å®ç¾©åãæ´æ°ã®ã¿ã«éå®ããé¨åé¢æ°ã¯ä»¥ä¸ã®æ§ã«å®ç¾©ãã¾ãããã®é¢æ°ã«æ´æ°ä»¥å¤ã渡ãã¨MatchingFailedä¾å¤ã¨ãªãã¾ãã
amber:55> g(x @ Int) := x + 1 => <#Function> amber:56> g(1) => 2 amber:57> g(1.5) Exception: MatchingFailed{domain = (x @ Int), [1.5]}
å¼æ°é¨ã«ä½ããã®ãã©ã¼ã ãæ¸ãã¨ãã£ã¨è¤éãªãã¿ã¼ã³ãããã³ã°ãåºæ¥ã¾ãã
amber:57> g(Foo{x, y}) := (x, y) => <#Function> amber:58> g('Foo{1, 2}) => (1, 2) amber:59> g(x + y) := (x, y) => <#Function> amber:60> g('(2 + 3)) => (2, 3)
以ä¸Amberã§ä½¿ç¨ããäºãåºæ¥ããã¿ã¼ã³ãåæãã¦ããã¾ãã
DontCareãã¿ã¼ã³(è¨å·_)
amber:61> g([_, _, x, _]) := x => <#Function> amber:62> g([1,2,3,4]) => 3
ãªãã©ã«ãã¿ã¼ã³(å®æ°å¤)
amber:63> g(0) := "zero" => <#Function> amber:64> g(0) => "zero" amber:65> g('[x,y,z]) := "matched" => <#Function> amber:66> g('[x,y,z]) => "matched"
å¯å¤é·ãã¿ã¼ã³(è¨å·...)
amber:67> g(Foo{_, _, ...}) := "Foo object with arity >= 2" => <#Function> amber:68> g('Foo{1, 2, 3}) => "Foo object with arity >= 2" amber:69> g('Foo{1}) Exception: MatchingFailed{domain = (Foo{_, _, ...}) | ('[x, y, z]) | (0) | ([_, _, x, _]) | (x + y) | (Foo{x, y}) | (x @ Int), [Foo{1}]} amber:69> g([_, _, rest...]) := rest => <#Function> amber:70> g([1,2,3,4,5,6]) => [3, 4, 5, 6]
ã¬ã¼ãç¯
amber:71> g(x) when x > 0 := "positive value" => <#Function> amber:72> g(1) => "positive value"
ORãã¿ã¼ã³
amber:73> g(_ @ Int or _ @ Float) := "a number" => <#Function> amber:74> g(1) => "a number" amber:75> g(1.0) => "a number"
ãã¨ããã¿ã¼ã³ã§ã¯ãªãã®ã§ããããã¼ã¯ã¼ãå¼æ°ã使ãã¾ãã
amber:76> g(x = 0, y = 1) := (x, y) => <#Function> amber:77> g(x = 1, y = 2) => (1, 2) amber:78> g(y = 3) => (0, 3)
ãã®æãgã¨ããååã§å®ç¾©ãããå ¨ã¦ã®é¢æ°ã¯æ¬¡ã ã«åä½µãããä¸ã¤ã®é¢æ°ã«ãªã£ã¦ãã¾ããç¾å¨gã®å®ç¾©åãã©ã®ããã«ãªã£ã¦ãããã¯æ¬¡ã®ããã«ãã¦è¦ããã¨ãåºæ¥ã¾ãã
amber:79> g.domain => domain = (x = 0, y = 1) | (_ @ Int or _ @ Float) | (x) when x > 0 | ([_, _, rest...]) | (Foo{_, _, ...}) | ('[x, y, z]) | (0) | ([_, _, x, _]) | (x + y) | (Foo{x, y}) | (x @ Int)
gã«æ¸¡ãããå¤ã¯domainã®ä¸ããé çªã«ãã§ãã¯ããæåã«ãããããé¢æ°ã®å®ä½ãå¼ã°ãã¾ãã(å®éã«ã¯å®è¡æã«å¤å°ã®æé©åãè¡ããã¦åçã«ãããã³ã°ãè¡ããã¤ãã³ã¼ããçæããã¦ãã¾ãã)
ä¸ã®ä¾ãè¦ãã°åããããã«å¸¸ã«æå¾ã«å®ç¾©ããããã®ãåªå ãããã®ã§ãä¸è¬çãªå ´åãå ã«å®ç¾©ãç¹æ®ãªå ´åãå¾ã«æ¸ãã¾ããä¾ãã°ãã£ããããæ°ãè¿ãé¢æ°fibã¯ä»¥ä¸ã®ããã«æ¸ããã¨ãåºæ¥ã¾ãã
amber:80> fib(n) := fib(n-1) + fib(n-2) => <#Function> amber:81> fib(0) := 0 => <#Function> amber:82> fib(1) := 1 => <#Function> amber:83> fib(20) => 6765
å¤æ°å®ç¾©ãå¢ãã¦ããã®ã§ä¸æ¦åæåãã¾ãããã
amber:84> .clear() => nil
ç¡åé¢æ°ã¯ä»¥ä¸ã®ããã«ãã¦ä½ãäºãåºæ¥ã¾ãã
amber:85> (x, y) -> x + y => <#Function> amber:86> $(2, 3) => 5
1å¼æ°ã®é¢æ°ã¯é常ã«è¯ã使ãã®ã§ã1å¼æ°ã®æã ãã¯å¼æ°ã®æ¬å¼§ãçãäºãåºæ¥ã¾ãã
amber:87> x -> x + 1 => <#Function> amber:88> $(1) => 2
Amberã®é¢æ°ã¯ãã¡ã¼ã¹ãã¯ã©ã¹ãªãã¸ã§ã¯ããªã®ã§ä»ã®é¢æ°ã«æ¸¡ãäºãåºæ¥ã¾ãã
amber:89> [1,2,3,4].map(x -> x + 1) => [2, 3, 4, 5]
é¢æ°f,gã®åä½µã¯æ¼ç®å|ã«ãã£ã¦è¡ãäºãåºæ¥ã¾ãããã®å ´åå·¦å´ã®é¢æ°ããããã³ã°ã«ããã¦é«ãåªå 度ãæã¡ã¾ãã
amber:90> x @ Int -> "integer" | x @ Float -> "floating point" | x @ String -> "string" => <#Function> amber:91> $.domain => domain = (x @ Int) | (x @ Float) | (x @ String) amber:92> $90(1) => "integer" amber:93> $90(1.0) => "floating point" amber:94> $90("Hello") => "string"
ãã¨ãã¬ãã·ã«ã«ã¹ã³ã¼ãã®ã¯ãã¼ã¸ã£ãããã¾ãã
amber:95> make_counter() := { amber:95~ n := 0 amber:95~ () -> { n += 1 } amber:95~ } => <#Function> amber:96> cnt1 := make_counter() => <#Function> amber:97> cnt2 := make_counter() => <#Function> amber:98> cnt1() => 1 amber:99> cnt1() => 2 amber:100> cnt2() => 1 amber:101> cnt1() => 3 amber:102> cnt2() => 2
ãã³ãã¬ã¼ãã¡ã¿ããã°ã©ãã³ã°
æ¼ç®å[ ]ã«é¢æ°fã渡ãã¨fã«ãããããé¨åãæ¸ãæããã¨ããåä½ããã¾ãã
amber:103> obj := 'Foo{1,2,3} => Foo{1, 2, 3} amber:104> obj[ 1 -> 3 | 2 -> 5 ] => Foo{3, 5, 3}
1 -> 3 | 2 -> 5ã®é¨åãé¢æ°ã§ãããããè¦ããªãããæå³çã«ææ³ãä½ã£ã¦ãã¾ãã
ããã使ã£ã¦ãã³ãã¬ã¼ãã¡ã¿ããã°ã©ãã³ã°ãé常ã«ç°¡åã«å®ç¾ããäºãåºæ¥ã¾ããä¾ãã°å f(1) + f(2) + f(3) + ... + f(n) ãæ±ããæ¬ä¼¼ã³ã¼ãã¯ä»¥ä¸ã®ããã«æ¸ãã¾ãã
amber:105> '{ amber:105~ s := 0 amber:105~ for i in 1..n amber:105~ s += f(i) amber:105~ s amber:105~ } => { s := 0 for i in 1..n { s += f(i) } s }
ãããå ã»ã©ã®æ¹æ³ã§æ¸ãæããã°å®è¡å¯è½ãªã³ã¼ããçæããäºãåºæ¥ã¾ãã
amber:106> $[ 'f(i) -> '(1/i^2) | 'n -> 100 ] => { s := 0 for i in 1..100 { s += 1 / i^2 } s } amber:107> evalfull($) => 1.634983900184892
ãããå ã«ãã¯ããä½ã£ã¦ã¿ã¾ããããAmberã¯ãã©ã¼ã ãmacroã¨ããé¢æ°ã§å¤æãã¦ããè©ä¾¡ãã¾ããæ¨æºã§ã¯ä»¥ä¸ã®ãããªãã©ã¼ã ã«å¯¾ãããã¯ããå®ç¾©ããã¦ãã¾ãã
amber:108> macro.domain => domain = (e @ Import{mods, asname, option}) | (DefTrait{head}) | (DefClass{head, fields}) | (WithSlots{obj, init}) | (When{args, guard} -> body) | (Domain{args, List} -> body) | ((for i in a..b body)) | ((for i in container body)) | (ArithAssign{x[idxs...], e, op}) | (x[idxs...] = e) | (x[idxs...]) | (x |= y) | (x %= y) | (x //= y) | (x /= y) | (x ^y) | (x **= y) | (x *= y) | (x -= y) | (x ++= y) | (x += y) | (x <=> y) | (x != y) | (x == y) | (x >= y) | (x <= y) | (x > y) | (x < y) | (x | y) | (x % y) | (x // y) | (x / y) | (x^y) | (x ** y) | (x * y) | (x ++ y) | (x - y) | (x + y) | (-x) | (+x) | (|x|) | (Assign{Send{obj, f, args}, e, g}) | (Define{Send{obj, f, args}, e, g}) | (Assign{Apply{f, args}, e, g}) | (Define{Apply{f, args}, e, g}) | (Send{obj, f, args} = e) | ((Send{obj, f, args} := e)) | ((Apply{f, args} := e)) | (Apply{f, args} = e) | (e)
ãããæ¡å¼µã㦠f(1) + f(2) + ... + f(n) ãè¨ç®ãããã¯ã sum(f, i, n) ãä½ãã¾ãããã"sum"ã®é¨åã¯sumã¨ããã·ã³ãã«èªä½ã«ããããã¦æ¬²ããã®ã§ãªãã©ã«ãã¿ã¼ã³('sum)ã使ãã¾ããã¾ãããã³ãã¬ã¼ãå ã§ä½¿ããã¦ããå¤æ°sã¯å±éå¾ã«ååãè¡çªããªãããã«ãã¦ãã¼ã¯ãªååã«å ã«ç½®ãæãã¦ããã¾ããsymbolã¢ã¸ã¥ã¼ã«ã®uniqueé¢æ°ã¯ã·ã³ãã«è¡¨ã«ç»é²ããã¦ããªã(å¾ã£ã¦ä»ã®ã·ã³ãã«ã¨å¸¸ã«ç°ãªã)ã·ã³ãã«ãçæãã¾ãã
amber:109> macro( ('sum)(f, i, n) ) := { amber:109~ template := '{ amber:109~ s := 0 amber:109~ for i in 1..n amber:109~ s += f(i) amber:109~ s amber:109~ } amber:109~ u := symbol::unique() amber:109~ template['s -> u]['f(i) -> f | 'i -> i | 'n -> n] amber:109~ } => <#Function>
ããã ãã§æ°ãããã©ã¼ã ã使ãäºãåºæ¥ã¾ããsã¨ããååã®å¤æ°ã使ã£ã¦ãæ£ããåä½ãã¦ããäºãåããã¨æãã¾ãã
amber:110> sum(i^2, i, 1000) => 333833500 amber:111> sum(1/s, s, 10000) => 9.787606036044345 amber:112> sum(sum(i*j, i, j), j, 100) => 12920425
Lispã§ã¯æºã¯ãªã¼ããç¨ãã¦ãã³ãã¬ã¼ããè¨è¿°ããæ¹å¼ã使ããã¾ãããç§ã¯ããã¦ããåãè¾¼ãæ¹å¼ãããå¤æããæ¹å¼ã®æ¹ãç解ããããã®ã§ã¯ãªããã¨èãã¦ãã¾ãããã¾ããä¸ã®æ¹å¼ãªãã°æºã¯ãªã¼ãã¨ã¢ã³ã¯ãªã¼ããç¨æããã¦ããªãè¨èªã«å¯¾ãã¦ããã³ãã¬ã¼ãã®ã¤ã³ã¹ã¿ã³ã·ã¨ã¼ã·ã§ã³ãç°¡åã«åºæ¥ã¾ãããã®æ¹å¼ã¯æ¨æºã©ã¤ãã©ãªã®å®è£ ã§ã使ã£ã¦ã¿ã¾ããããã³ã¼ãããã£ããã¨ãä»ã®æã¯è¯ãå°è±¡ãæã£ã¦ãã¾ããæºã¯ãªã¼ãæ¹å¼ã¨æ¯ã¹ããã¡ãªããã«ã¤ãã¦ã¯ã¾ã ååã«èå¯ãåºæ¥ã¦ãã¾ãããã¡ãªã¿ã«å ã»ã©ã®ãã¯ããæºã¯ãªã¼ãæ¹å¼ã§æ¸ãã¨ä»¥ä¸ã®æ§ã«ãªãã¾ãã
amber:113> macro( ('sum)(f, i, n) ) := { amber:113~ u := symbol::unique() amber:113~ `{ amber:113~ !u := 0 amber:113~ for !i in 1..!n amber:113~ !u += !f amber:113~ !u amber:113~ } amber:113~ } => <#Function>
ãã¼ãµçæ
åç¯ã®æ¹æ³ã¯Amberã®ãã³ãã¬ã¼ãã§Amberã®ã³ã¼ããçæããä¾ã§ããã®ã§Amberã®ææ³ã§å ¨ã¦æ¸ããã¨ãåºæ¥ã¾ãããããããä»ã®è¨èªã®æ§ææ¨ãä½æãããå ´åã«ã¯Amberã®ææ³ã使ããªãã®ã§å ¨ã¦fullformã§æ¸ããªããã°ãªããªããªã£ã¦ãã¾ãã¾ããããã§ããã¯ã©ããæ§æ解æå¨ã®ã¸ã§ãã¬ã¼ã¿ãç¨æããã¦ãããAmberå ã§ãã¼ãµãä½æåºæ¥ãããã«ãªã£ã¦ãã¾ãã
å®ã¯ããã¾ã§ä½¿ã£ã¦ããAmberã®ææ³èªä½ããã®ã¸ã§ãã¬ã¼ã¿ã§æ¸ããã¦ãã¾ããã¤ã³ã¿ããªã¿ã«ãããããçµã¿è¾¼ã¾ãã¦ããææ³ã¯ã¢ãã åã³fullformã®ã¿ã§ãèµ·åãã¦ããèªèº«ã®ãã¼ãµãã³ã³ãã¤ã«ããæ¹å¼ã«ãªã£ã¦ãã¾ãã(èµ·åãé ãã®ã¯ä¸»ã«ãã®çºã§ãããããããªã³ã³ãã¤ã«ã«ãã¾ãã)ããã¯lib/syntax/parse.abå ã§è¡ããã¦ãããæåã¯fullformã®ã¿ã§ã³ã¼ããæ¸ãâææ³ãå®ç¾©ããçºã®ææ³ãå®ç¾©ããâAmberã®ææ³ãå®ç¾©ããâãã¯ãã®ä»çµã¿ãä½ãâå種ãã¯ããå®ç¾©ããã¨ããæµãã«ãªã£ã¦ãã¾ãã
以ä¸ã¯ãã®ã¸ã§ãã¬ã¼ã¿ã使ã£ã¦CAST(C Abstract Syntax Tree)ã¨ããCè¨èªé¢¨ã®è¨èªãå®ç¾©ããã©ã¤ãã©ãªã®ä¸é¨ã§ããåºæ¬ã¯è§£æ表ç¾ææ³(PEG)ã§ãããã«ã³ãåºåãã®ãããªè¯ã使ããã¿ã¼ã³ããã¼ã¹ããçºã®delimitedãªã©ããã¤ãã¦ã¼ãã£ãªãã£ã追å ããã¦ãã¾ããä»ã«ã空ç½ã®æ±ããªã©ãç°ãªãã®ã§ã解説ãAmberã®ãã¼ã ãã¼ã¸ã«æ¸ãã¤ããã§ãã
primary_expr ::= identifier { Var.new($0) } | constant | string { StringL.new($0) } | "(" expr ")" { $1 } postfix_expr ::= postfix_expr "[" expr "]" { Subscript.new($0, $2) } | postfix_expr "(" delimited(assign_expr, ",") ")" { Call.new($0, $2) } | postfix_expr "." identifier { Select.new($0, $2) } | postfix_expr "->" identifier { Select.new(Deref.new($0), $2) } | postfix_expr "++" { PostInc.new($0) } | postfix_expr "--" { PostDec.new($0) } | primary_expr
Amberã®ã·ã§ã«ãã以ä¸ã®ããã«ä½¿ãã¾ãã
amber:114> import CAST => Module{CAST} amber:115> template := '<CAST>{ amber:115~ struct hoge { amber:115~ int x; amber:115~ double y; amber:115~ } amber:115~ int main(int argc, char **argv) { amber:115~ struct hoge st; amber:115~ st.x = 0; amber:115~ st.y = 2.0; amber:115~ printf("%d, %f\n", st.x, st.y); amber:115~ } amber:115~ } => CASTProgram{[DefAggregates{none, StructT{hoge}, hoge, [(int, x), (double, y)]}, DefFunc{none, int, main, [(int, argc), (PointerT{PointerT{char}}, argv)], { [DefVar{none, StructT{hoge}, st, nil}, Select{Var{st}, x} = IntL{0}, Select{Var{st}, y} = FloatL{2.0}, Call{Var{printf}, [StringL{"%d, %f\n"}, Select{Var{st}, x}, Select{Var{st}, y}]}] }}]}
ãã®ãããªãã³ãã¬ã¼ãã¯ãã¡ããå ã»ã©ã¨åæ§ã«æä½ããäºãåºæ¥ã¾ããä¸ã§ã¯Amberã®ã³ã¼ãä¸ã«åãè¾¼ã¿ã¾ããããCASTã®ã³ã¼ããæ¸ãããå¤é¨ãã¡ã¤ã«ããã¼ãºããäºãåºæ¥ã¾ãããã¨ã¯ãã¡ã¤ã«ã«ã³ã¼ããæ¸ãåºãpretty printerãå®è£ ããã°CAST -> CASTã®å¤æå¨ãåºæ¥ä¸ããã¾ããä»ã¯å®é¨çãªå®è£ ã§ãããããã¡ããã¨Cè¨èªã®ãã¼ãµãå®è£ ãã¾ãã(PEGã§ã¯æ¸ããªãã®ã§ãã¼ãµãç´ã«æ¸ãä¸ãå½¢ã«ãªãã¾ãã) ã¾ãå種æé©åãã©ã¤ãã©ãªé¢æ°ã¨ãã¦å®è£ ããäºå®ã§ãããã®ã©ã¤ãã©ãªã¯FFIã®å®è£ ãªã©ã§ä½¿ãã¾ããAmberã®æ¬¡æVMã®å®è£ ã«ãããã使ããlibcä»æ¢åã®ã©ã¤ãã©ãªã使ããããã«ããã¤ããã§ãã
ãã¼ãµã¯åã ã®æ§æè¦ç´ ãç¬ç«ããé¢æ°ã¨ãã¦çæããã¾ãã
amber:116> syntax::expr => <#Function> amber:117> syntax::stmt.domain => domain = (parser @ Parser) when *hidden* | (parser @ Parser) when *hidden* | (_ @ Parser)
å¾ã£ã¦ãé¢æ°åä½µã使ã£ã¦æ¢åã®ææ³ãæ¡å¼µããäºãåºæ¥ã¾ãã
amber:118> syntax::mystmt ::= "mystatement" "{" stmt "}" { `printf("my statement %p\n", '!$2) } => <#Function> amber:119> syntax::stmt = syntax::mystmt | syntax::stmt => <#Function> amber:120> mystatement{ puts("Hello") } my statement Apply{puts, ["Hello"]} => nil
è¨èªã®æ§æã«ä½ããã®æ¡å¼µãè¡ãå ´åããã¼ãµå ¨ä½ãä¸ã¤ã®å®ä½ã¨ãã¦ä½ããã¦ããå ´åã«ã¯ã½ã¼ã¹ã³ã¼ãã«æãå ¥ããå¿ è¦ãããã¾ããä¸ã®æ¹æ³ãªãã°ã½ã¼ã¹ã³ã¼ããæ¸ãæããã«å¤å´ããæ¡å¼µã追å ããäºãåºæ¥ã¾ãã
ãªãã¸ã§ã¯ãã·ã¹ãã
Amberã«ã¯ãããã¿ã¤ããã¼ã¹ã®ãªãã¸ã§ã¯ãã·ã¹ãã ãå®è£ ããã¦ãã¾ãã
- ãªãã¸ã§ã¯ãã«ã¯ã¹ãããã追å ããäºãåºæ¥ãã
- parentã¨ããç¹å¥ãªã¹ãããããããåç §ãããã¹ããããè¦ã¤ãããªãã£ãå ´åã«ã¯parentãè¦ã«è¡ãã
- obj.f(...)ã¨ããå½¢ã§é¢æ°ãå¼ã³åºãããå ´åãfå é¨ã§ã¯selfã«ãã£ã¦objãåç §ããäºãåºæ¥ãã
amber:121> a := 'Foo{} => Foo{} amber:122> b := 'Bar{} => Bar{} amber:123> a.f() = "self=" ++ str(self) => <#Function> amber:124> b.parent = a => Foo{} amber:125> a.f() => "self=Foo{}" amber:126> b.f() => "self=Bar{}"
self.x ã¨ããå½¢ã¯é »ç¹ã«ç»å ´ããã®ã§selfãçç¥ãã¦.xã¨æ¸ããããã«ãªã£ã¦ãã¾ãã
amber:127> a.x = 0 => 0 amber:128> a.g() = puts(.x) => <#Function> amber:129> a.g() 0 => nil
ã¾ã, ãªãã¸ã§ã¯ãã®çæã¨ã¹ãããã®è¿½å ãä¸åº¦ã«è¡ããããã« obj with { ã¹ãããã®åæå } ã¨ããæ§æãä½ãã¾ããã
amber:130> obj := 'Foo{} with { amber:130~ .x = 1 amber:130~ .y = 2 amber:130~ .f() = .x + .y amber:130~ } => Foo{} amber:131> obj => Foo{} amber:132> obj.x => 1 amber:133> obj.y => 2 amber:134> obj.f() => 3
親ã¨åãååã®é¢æ°ãæã¤å ´åãåã®é¢æ°ã親ã®é¢æ°ãé è½ãããããªå®è£ ãå¤ãã¨æãã¾ãããAmberã§ã¯è¦ªã¨åã®é¢æ°ãåä½µããæ°ããªé¢æ°ãåã«è¿½å ããã¾ããä¾ãã°ä»¥ä¸ã®ããã«ãªãã¾ãã
amber:135> .clear() => nil amber:136> a := 'Foo{} with { amber:136~ .f(x) = "parent" amber:136~ } => Foo{} amber:137> b := 'Foo{} with { amber:137~ .parent = a amber:137~ .f(0) = "child" amber:137~ } => Foo{} amber:138> b.f(1) => "parent" amber:139> b.f(0) => "child" amber:140> a.f(0) => "parent"
åä½µããããªãå ´åã«ã¯ãobj.f(...) := ã¨ããæ§æã使ããªãã§obj.fã«ç¡åé¢æ°ãä»£å ¥ããããã«æ¸ãã°ããã§ãã
ããã使ã£ã¦é¢ç½ãäºãåºæ¥ã¾ãã
amber:141> fib := 'Fib{} with { amber:141~ .f(n) = .f(n-1) + .f(n-2) amber:141~ .f(0) = 0 amber:141~ .f(1) = 1 amber:141~ } => Fib{} amber:142> fib2 := 'Fib{} with { amber:142~ .parent = fib amber:142~ .f(0) = 1 amber:142~ } => Fib{} amber:143> fib.f(20) => 6765 amber:144> fib2.f(20) => 10946
fib2ã§ã¯f(0) = 1以å¤ã¯è¦ªã®å®ç¾©ã使ã£ã¦æ°ããé¢æ°ãåæãã¦ãã¾ãã.f(n-1) + .f(n-2) ã®é¨åã§å¼ã³åºãããfã®å®ä½ãselfã«ãã£ã¦åçã«æ±ºã¾ãOpen recursionã¨ããæ§è³ªã¨Amberã®é¢æ°åä½µã®ã¡ã«ããºã ãçµåãã¦ä½¿ã£ã¦ãã¾ãããã®ããã«ã親ãä¸åæ¸ãæããã«æ©è½ãæ¡å¼µãããã¼ã¸ã§ã³ãæ°ãã«ä½ããã¨ããäºãé常ã«æ軽ã«å®ç¾åºæ¥ã¾ãã
Amberã®ã¢ã¸ã¥ã¼ã«ã¯å®ã¯é常ã®ãªãã¸ã§ã¯ãã§ããä¸ã®ä»çµã¿ãæ¨æºã©ã¤ãã©ãªã§å®è£ ããã¦ãã¾ãã.push()ã¨ããã¡ã½ããã¯ãç¾å¨ã®å¤æ°è¡¨ã®åä¾ãæ°ãã«ä½ãã¾ãã.pop()ã¯å¤æ°è¡¨ãç ´æ£ãã¦è¦ªã«æ»ãã¾ããããã«ãã£ã¦.push()ãã.pop()ã¾ã§ã®éã®å·®åã®ã¿ãç ´æ£ããã¾ãã
amber:145> x := "old version" => "old version" amber:146> .push() => nil amber:147> x := "new version" => "new version" amber:148> .pop() => nil amber:149> x => "old version"
以ä¸ã®æ§ã«Open recursionã«ãã£ã¦åã¢ã¸ã¥ã¼ã«å¤æ°ã¯å¸¸ã«ææ°ã®å¤æ°è¡¨ãåç §ãã¾ãããã®ç¹ããµãã¹ã³ã¼ããä½ãã®ã¨ã¯ç°ãªãã¾ãã
amber:150> f() := x => <#Function> amber:151> .push() => nil amber:152> x := "new version" => "new version" amber:153> f() => "new version" amber:154> .pop() => nil amber:155> f() => "old version" amber:156> { amber:156~ x := "new version" amber:156~ f() amber:156~ } => "old version"
以ä¸ã®ä¾ã¯ãä¸æçã«æ´æ°ã®ååæ¼ç®ãå ¨ã¦æçæ°ã®ç©ã«ç½®æããpopã«ãã£ã¦ãããå ã«æ»ãã¨ããä¾ã§ãã
amber:157> 1/2 => 0.5 amber:158> .push() => nil amber:159> import algebra::rational (*) => Module{rational} amber:160> 1/2 + 2/3 => 7 / 6 amber:161> s := 0 => 0 amber:162> for i in 1..100 amber:162~ s += 1/i => nil amber:163> s => 14466636279520351160221518043104131447711 / 2788815009188499086581352357412492142272 amber:164> .pop() => nil amber:165> 3/5 => 0.6
ãã®ããã«Amberã§ã¯ãªãã¸ã§ã¯ãã·ã¹ãã ããªãã¸ã§ã¯ãæåã®çºã¨ããããã¯ãããå¤æ°ã®ç®¡çã«çºã«å°å ¥ãã¦ãã¾ããä¸å¿ã以ä¸ã®ããã«åå§çãªã¯ã©ã¹ããã¬ã¤ãã¯æ¨æºã©ã¤ãã©ãªã§ç¨æãã¦ãã¾ãããã¡ãã¯ä½æ©è½ã§ãã
amber:166> class Point{x, y} => Class{Point} amber:167> p := Point.new(x = 1, y = 2) => Point{1, 2} amber:168> trait PairLike with { amber:168~ .to_pair() := (self[0], self[1]) amber:168~ } => Trait{PairLike} amber:169> Point.extend(PairLike) => Class{Point} amber:170> p.to_pair() => (1, 2)
ç´¹ä»ãã®1çµãã
ãã®ï¼ã§ã¯Amberã®ã¢ããªã±ã¼ã·ã§ã³ã¨ãã¦ã対話ã»ãã·ã§ã³ã«ããçããã³ãã¬ã¼ãããCè¨èªã®ã³ã¼ããçæããã¨ããæ°å¤è¨ç®ããã®ä¾ãç´¹ä»ãããã¨æãã¾ãã