開発環境
- macOS Sierra - Apple (OS)
- Emacs (Text Editor)
- Scheme (プログラミング言語)
- kscheme (ksi)(github) (処理系)
Scheme でクロージャー、環境について考えてる時、処理系によってエラーになったりならなかったり、結果が違うことを見つけた。
その他参考書籍
- 計算機プログラムの構造と解釈[第2版] (ハロルド エイブルソン (著)、ジュリー サスマン (著)、ジェラルド・ジェイ サスマン (著)、Harold Abelson (原著)、Julie Sussman (原著)、Gerald Jay Sussman (原著)、和田 英一 (翻訳)、翔泳社) 原著
- Instructor's Manual to Accompany Structure & Interpretation of Computer Programs
試した処理系/翻訳系(インタプリタ/コンパイラ/JIT)は、Gauche、Guile、MIT/GNU Scheme、CHICKEN Scheme(とkscheme(ksi))。
結果が違ったコード
コード(Emacs)
sample1.scm
01: (begin 02: (define (p o) (display o) (newline)) 03: 04: ((lambda (add) 05: (set! + (lambda (x y) (add x y))) 06: ) 07: +) 08: 09: (define add #f) 10: (p (+ 2 3)) 11: (p (+ 2 3 4)) 12: ) 13:
sample2.scm
01: (begin 02: (define (p o) (display o) (newline)) 03: 04: ((lambda () 05: (define add +) 06: (set! + (lambda (x y) (add x y))))) 07: 08: (define add #f) 09: (p (+ 2 3)) 10: (p (+ 2 3 4)) 11: ) 12:
入出力結果(Terminal(kscheme), REPL(Read, Eval, Print, Loop))
001: $ gosh sample1.scm 002: WARNING: altering binding of inlinable procedure: scheme#+ 003: 5 004: 9 005: $ gosh sample2.scm 006: WARNING: altering binding of inlinable procedure: scheme#+ 007: 5 008: 9 009: $ guile sample1.scm 010: ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 011: ;;; or pass the --no-auto-compile argument to disable. 012: ;;; compiling /Users/kamimura/Desktop/sample1.scm 013: ;;; compiled /Users/kamimura/.cache/guile/ccache/2.0-LE-8-2.0/Users/kamimura/Desktop/sample1.scm.go 014: 5 015: 9 016: $ guile sample2.scm 017: ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 018: ;;; or pass the --no-auto-compile argument to disable. 019: ;;; compiling /Users/kamimura/Desktop/sample2.scm 020: ;;; compiled /Users/kamimura/.cache/guile/ccache/2.0-LE-8-2.0/Users/kamimura/Desktop/sample2.scm.go 021: 5 022: 9 023: $ rm ~/.cache/guile/ccache/2.0-LE-8-2.0/Users/kamimura/Desktop/sample* 024: remove /Users/kamimura/.cache/guile/ccache/2.0-LE-8-2.0/Users/kamimura/Desktop/sample1.scm.go? y 025: remove /Users/kamimura/.cache/guile/ccache/2.0-LE-8-2.0/Users/kamimura/Desktop/sample2.scm.go? y 026: $ guile --no-auto-compile sample1.scm 027: 5 028: Backtrace: 029: In ice-9/boot-9.scm: 030: 160: 10 [catch #t #<catch-closure 1068d5460> ...] 031: In unknown file: 032: ?: 9 [apply-smob/1 #<catch-closure 1068d5460>] 033: In ice-9/boot-9.scm: 034: 66: 8 [call-with-prompt prompt0 ...] 035: In ice-9/eval.scm: 036: 432: 7 [eval # #] 037: In ice-9/boot-9.scm: 038: 2404: 6 [save-module-excursion #<procedure 1067de940 at ice-9/boot-9.scm:4051:3 ()>] 039: 4058: 5 [#<procedure 1067de940 at ice-9/boot-9.scm:4051:3 ()>] 040: 1727: 4 [%start-stack load-stack ...] 041: 1732: 3 [#<procedure 1068fe6c0 ()>] 042: In unknown file: 043: ?: 2 [primitive-load "/Users/kamimura/Desktop/sample1.scm"] 044: In ice-9/eval.scm: 045: 387: 1 [eval # ()] 046: 416: 0 [#<procedure 106908cf0 at ice-9/eval.scm:416:20 (a b)> 2 3 4] 047: 048: ice-9/eval.scm:416:20: In procedure #<procedure 106908cf0 at ice-9/eval.scm:416:20 (a b)>: 049: ice-9/eval.scm:416:20: Wrong number of arguments to #<procedure 106908cf0 at ice-9/eval.scm:416:20 (a b)> 050: $ guile --no-auto-compile sample2.scm 051: 5 052: Backtrace: 053: In ice-9/boot-9.scm: 054: 160: 10 [catch #t #<catch-closure 1085e61a0> ...] 055: In unknown file: 056: ?: 9 [apply-smob/1 #<catch-closure 1085e61a0>] 057: In ice-9/boot-9.scm: 058: 66: 8 [call-with-prompt prompt0 ...] 059: In ice-9/eval.scm: 060: 432: 7 [eval # #] 061: In ice-9/boot-9.scm: 062: 2404: 6 [save-module-excursion #<procedure 1083b7940 at ice-9/boot-9.scm:4051:3 ()>] 063: 4058: 5 [#<procedure 1083b7940 at ice-9/boot-9.scm:4051:3 ()>] 064: 1727: 4 [%start-stack load-stack ...] 065: 1732: 3 [#<procedure 1086156c0 ()>] 066: In unknown file: 067: ?: 2 [primitive-load "/Users/kamimura/Desktop/sample2.scm"] 068: In ice-9/eval.scm: 069: 387: 1 [eval # ()] 070: 416: 0 [#<procedure 10861fc30 at ice-9/eval.scm:416:20 (a b)> 2 3 4] 071: 072: ice-9/eval.scm:416:20: In procedure #<procedure 10861fc30 at ice-9/eval.scm:416:20 (a b)>: 073: ice-9/eval.scm:416:20: Wrong number of arguments to #<procedure 10861fc30 at ice-9/eval.scm:416:20 (a b)> 074: $ mit-scheme < sample1.scm 075: MIT/GNU Scheme running under OS X 076: Type `^C' (control-C) followed by `H' to obtain information about interrupts. 077: 078: Copyright (C) 2014 Massachusetts Institute of Technology 079: This is free software; see the source for copying conditions. There is NO 080: warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 081: 082: Image saved on Thursday March 10, 2016 at 8:26:27 PM 083: Release 9.2 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/C 4.118 084: Edwin 3.116 085: 086: 1 ]=> (begin 087: (define (p o) (display o) (newline)) 088: 089: ((lambda (add) 090: (set! + (lambda (x y) (add x y))) 091: ) 092: +) 093: 094: (define add #f) 095: (p (+ 2 3)) 096: (p (+ 2 3 4)) 097: )5 098: ;The procedure #[compound-procedure 2] has been called with 3 arguments; it requires exactly 2 arguments. 099: ;To continue, call RESTART with an option number: 100: ; (RESTART 1) => Return to read-eval-print level 1. 101: 102: 2 error> 103: End of input stream reached. 104: Moriturus te saluto. 105: $ mit-scheme < sample2.scm 106: MIT/GNU Scheme running under OS X 107: Type `^C' (control-C) followed by `H' to obtain information about interrupts. 108: 109: Copyright (C) 2014 Massachusetts Institute of Technology 110: This is free software; see the source for copying conditions. There is NO 111: warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 112: 113: Image saved on Thursday March 10, 2016 at 8:26:27 PM 114: Release 9.2 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/C 4.118 115: Edwin 3.116 116: 117: 1 ]=> (begin 118: (define (p o) (display o) (newline)) 119: 120: ((lambda () 121: (define add +) 122: (set! + (lambda (x y) (add x y))))) 123: 124: (define add #f) 125: (p (+ 2 3)) 126: (p (+ 2 3 4)) 127: )5 128: ;The procedure #[compound-procedure 2] has been called with 3 arguments; it requires exactly 2 arguments. 129: ;To continue, call RESTART with an option number: 130: ; (RESTART 1) => Return to read-eval-print level 1. 131: 132: 2 error> 133: End of input stream reached. 134: Moriturus te saluto. 135: $ csi sample1.scm 136: 137: CHICKEN 138: (c) 2008-2013, The Chicken Team 139: (c) 2000-2007, Felix L. Winkelmann 140: Version 4.8.0.2 (stability/4.8.0) (rev b7e1215) 141: macosx-unix-clang-x86-64 [ 64bit manyargs dload ptables ] 142: compiled 2013-02-19 on aeryn.xorinia.dim (Darwin) 143: 144: ; loading sample1.scm ... 145: 5 146: 147: Error: bad argument count - received 3 but expected 2: #<procedure (+ x y)> 148: 149: Call history: 150: 151: <syntax> (##core#begin (define add #f) (p (+ 2 3)) (p (+ 2 3 4))) 152: <syntax> (define add #f) 153: <syntax> (##core#set! add #f) 154: <syntax> (p (+ 2 3)) 155: <syntax> (+ 2 3) 156: <syntax> (##core#begin (p (+ 2 3 4))) 157: <syntax> (p (+ 2 3 4)) 158: <syntax> (+ 2 3 4) 159: <eval> ((lambda (add) (set! + (lambda (x y) (add x y)))) +) 160: <eval> (p (+ 2 3)) 161: <eval> (+ 2 3) 162: <eval> [+] (add x y) 163: <eval> [p] (display o) 164: <eval> [p] (newline) 165: <eval> (p (+ 2 3 4)) 166: <eval> (+ 2 3 4) <-- 167: $ csi sample2.scm 168: 169: CHICKEN 170: (c) 2008-2013, The Chicken Team 171: (c) 2000-2007, Felix L. Winkelmann 172: Version 4.8.0.2 (stability/4.8.0) (rev b7e1215) 173: macosx-unix-clang-x86-64 [ 64bit manyargs dload ptables ] 174: compiled 2013-02-19 on aeryn.xorinia.dim (Darwin) 175: 176: ; loading sample2.scm ... 177: 5 178: 179: Error: bad argument count - received 3 but expected 2: #<procedure (+ x y)> 180: 181: Call history: 182: 183: <syntax> (##core#begin (define add #f) (p (+ 2 3)) (p (+ 2 3 4))) 184: <syntax> (define add #f) 185: <syntax> (##core#set! add #f) 186: <syntax> (p (+ 2 3)) 187: <syntax> (+ 2 3) 188: <syntax> (##core#begin (p (+ 2 3 4))) 189: <syntax> (p (+ 2 3 4)) 190: <syntax> (+ 2 3 4) 191: <eval> ((lambda () (define add +) (set! + (lambda (x y) (add x y))))) 192: <eval> (p (+ 2 3)) 193: <eval> (+ 2 3) 194: <eval> [+] (add x y) 195: <eval> [p] (display o) 196: <eval> [p] (newline) 197: <eval> (p (+ 2 3 4)) 198: <eval> (+ 2 3 4) <-- 199: $ ksi < sample1.scm 200: ksi> 5 201: Error: #<compound-procedure (x y) ((add x y))> wrong number of arguments -- (4) 202: ksi> $ ksi < sample2.scm 203: ksi> 5 204: Error: #<compound-procedure (x y) ((add x y))> wrong number of arguments -- (4) 205: ksi> $ 206:
(+ 2 3 4) について、Gauche(gosh 1行目、5行目)は警告有り(2行目、6行目)、Guileはコンパイル有り(9行目、16行目)だと警告無し、コンパイルしない(--no-auto-compile、26行目、50行目)とエラー、MIT/GNU Scheme(mit-scheme、74行目、105行目)、CHICKEN Scheme(csi、135行目、167行目)、kscheme(ksi、199行目、202行目) はエラー。
実行前に想像してたのは、エラー。(引数の個数が異なる)
こんな感じ。
;; 大域環境(グローバル) +: 基本手続き(+) ;; 4行目で環境1ができる add: 基本手続き(+) ;; 5行目から見える順。 環境1[add: 基本手続き(+)] 大域環境[+: 基本手続き(+)] ;; (set! + (lambda (x y) (add x y)))で 環境1[add: 基本手続き(+)] 大域環境[+: (lambda (x y) (add x y)) {環境1[add: 基本手続き(+)]、大域環境[+: 基本手続き(+)]}] ;; (環境1、大域環境)出て、8行目から 大域環境[+: (lambda (x y) (add x y)) {環境1[add: 基本手続き(+)]、大域環境[+: 基本手続き(+)]}] ;; 10行目の式の評価 (+ 2 3 4) ((lambda (x y) (add x y z)) 2 3 4) ;; 引数の個数が合わない
どれも仕様通りなのか、それとも、Gauche と Guile はコンパイルによる高速化、最適化で、再定義される可能性が低い、基本手続き(+)の部分を何か変換するのか。(Gauche は警告出してくれるけど、Guile はコンパイル時に何も警告出さないのが少し気になったり。)
0 コメント:
コメントを投稿