ï¼Pythonã«ããç°¡åãªLispã¤ã³ã¿ã¼ããªã¿å®è£ æ¹æ³ï¼ååæ¼ç®ç·¨ï¼ï¼
ãã®è¨äºã¯Python Advent Calendar 2014 11æ¥ç®ã®è¨äºã§ã
Pythonã«ããç°¡åãªLispã¤ã³ã¿ã¼ããªã¿å®è£ æ¹æ³
lispã®ã¤ã³ã¿ã¼ããªã¿ã®å®è£ ãè¡ãäºã«ããï¼ããã°ã©ãã³ã°ï¼ã³ã³ãã¥ã¼ã¿ã¸ã®ç¥èã æ·±ããäºãç®çã¨ãã¦ãã¾ãï¼ä»åã¯ï¼ä»¥ä¸ã®ããã«2é¨ã«åãã¦Lispã¤ã³ã¿ã¼ããªã¿å®è£ æ¹æ³ãç´¹ä»ãã¾ãï¼ ï¼ãã ï¼lispã§ååæ¼ç®ãã§ããã¤ã³ã¿ã¼ããªã¿ãä½æã§ããã°ï¼ã¤ã³ã¿ã¼ããªã¿ã®æ¦å¿µã¯ç解åºæ¥ãã¨æãã¾ãï¼ã¾ãï¼ä»åã¯python3以éãæ³å®ãã¦ãã¾ãï¼ï¼
- ååæ¼ç®ç·¨
- é¢æ°ç·¨ (
ä¸é±éå¾ãããã«æ¸ãã¾ãï¼ãã¿ã¾ããï¼ãããè½ã¡çãããæ¸ãã¾ãï¼)
ãªãï¼ä»åã®Lispã¤ã³ã¿ã¼ããªã¿å®è£ ãç´¹ä»ãããã£ããã¨ãªã£ãã®ãï¼「ギークエンジニア必見!Lispインタープリター」勉強会 with すごい広島 - すごい広島 | Doorkeeperã«åå ããäºã§ããï¼ãããæ©ã«Pythonã§ãå®è£ ãã¦ã¿ããã¨æãã¾ããï¼å¹¸ãï¼Peterãããããã°(How to Write a (Lisp) Interpreter (in Python))ã§æ¢ã«Pythonã§ã®å®è£ ãç´¹ä»ãã¦ããã¾ãï¼ä»åã¯ãã®ããã°ãåèã«ãï¼lispã¤ã³ã¿ã¼ããªã¿å®è£ ãç´¹ä»ãããã¨æãã¾ãï¼
å ã«ï¼å½¼ãã«æ¬æã¨æè¬ã®æ°æã¡ãè¨ãã¦ããããã¨æãã¾ãï¼ ãã¦ï¼åç½®ããé·ããªãã¾ãããï¼ã¾ãã¯ååæ¼ç®ç·¨ãç´¹ä»ãã¦ããããã¨æãã¾ãï¼
ã¤ã³ã¿ã¼ããªã¿æ¦è¦
ãã¦ï¼ä»åã¯ã¤ã³ã¿ã¼ããªã¿ãä½ãããããã§ããï¼ã¤ã³ã¿ã¼ããªã¿ã£ã¦ã©ãåä½ããã®ã§ããããï¼ ç°¡åã«å³ç¤ºããã¨ä»¥ä¸ã®éãã«ãªãã¾ãï¼
ããã°ã©ã ï¼æååï¼âãæ§æ解æå¨ãâãæ§ææ¨ï¼listï¼ âãè©ä¾¡ï¼evalï¼ âãçµæ
ã¨ãªãã¾ãï¼ã¤ã¾ãï¼æååã§ããããã°ã©ã ãæ§æ解æå¨ã«å ¥ãã¾ãï¼ããããã¨ï¼æ§ææ¨ï¼ä»åã¯pythonã§æ±ããæ§é ãªã®ã§listï¼ã åºæ¥ä¸ããã¾ãï¼æ§ææ¨ã¯ã¤ã³ã¿ã¼ããªã¿å ã§å¦çåºæ¥ãå½¢ã§ãï¼æå¾ã«æ§ææ¨ãè©ä¾¡ãããã°ã©ã ãæå³ãã¦ããçµæãåºåãã¾ãï¼
å®éã«ä½æããã¤ã³ã¿ã¼ããªã¿ã§ã¯ï¼ä»¥ä¸ã®ãããªã¹ããããè¸ãã§ããã°ã©ã ãè©ä¾¡ï¼å®è¡ï¼ãã¾ãï¼
>>> program = "(* 1 3)" # ãã®ãããªããã°ã©ã ãããã¾ã # ããã°ã©ã ãparserï¼æ§æ解æå¨ï¼ã«å ¥ãã¾ãï¼ >>> ast = parse(program) # æ§ææ¨ãçæãã¾ãï¼astã¯abstract syntax tree(æ½è±¡æ§ææ¨ã®ç¥) >>> ast ['*', 1, 3]ã#ãã®ããã«Pythonã§æ±ãããããªlistæ§é ã«å¤æãã¾ãï¼ã¤ã¾ãï¼ã¤ã³ã¿ã¼ããªã¿ã§æ±ããæ§ææ¨ã«ãªã£ã¦ããï¼ >>> eval(ast) # astãè©ä¾¡ 4 # 1 * 3ã®çµæ
è¡ã£ã¦ããäºã¯åãåç´ã§ãï¼æååãã¤ã³ã¿ã¼ããªã¿ï¼pythonï¼ãæ±ããå½¢ã«å¤æãã¦ï¼ãããlispã®æ§æã«æ²¿ã£ã¦è§£éããã ãã§ãï¼ ä»¥ä¸ãï¼æ¦è¦ã¨ãªãã¾ãï¼æ¬¡ã¯ï¼ååæ¼ç®ãæ©éä½ã£ã¦ããã¾ãããï¼
ååæ¼ç®ä½æã«å½ãã£ã¦ï¼ä»¥ä¸ã®äºãé ã«èª¬æãã¦ããã¾ãï¼
- æååãããã¼ã¯ã³ãçæããï¼åå¥è§£æï¼Lexical Analysisï¼ï¼âã
tokenize
- 1ã®çµæãç¨ãã¦æ§æ解æãããï¼Syntactic Analysisï¼â
parse
- ååæ¼ç®çã®æç¶ããåç
§å¯è½ã¨ããç°å¢(Enviornment)ã®æ§ç¯ï¼ã¡ã¢ãªã®æ§ç¯ï¼ â
starndard_env
- 2ã®çµæãè©ä¾¡(eval)ãã
1. åå¥è§£æ(Lexical Analysis)
æ§æ解æã¯åå¥è§£æã¨æ§æ解æé¨ã«åãããã¾ãï¼åå¥è§£æã§ã¯ï¼æå³ã®ãããã¼ã¯ã³ã«åãã¾ãï¼
æ¬æ¥ãªãã°ï¼æ£è¦è¡¨ç¾ã使ãã¹ãã§ããï¼ã¤ã³ã¿ã¼ããªã¿ã®åä½ãç解ããã®ãæ¬ç¨¿ã®ç®çãªã®ã§ããã¯å²æãã¾ãï¼
ä»åã®åå¥è§£æã¯ä»¥ä¸ã®ããã«ã«ãã³ã«ã¹ãã¼ã¹ã追å ããå½¢ã«ãã¦(replace
)ï¼ã¹ãã¼ã¹ã§ãã¼ã¯ã³ãåºåãã¾ã(split
)ï¼
def tokenize(chars): return chars.replace('(', ' ( ').replace(')', ' ) ').split()
å®è¡ä¾
>>> tokenize("(* 1 3)") ['(', '*', '1', '3', ')'] #ãã¼ã¯ã³æ¯ã«åé¢ >>> tokenize("(define square (lambda (r) (* r r)))") #squareé¢æ°ã®å®ç¾©(ããã¯é¢æ°ç·¨ã§è©³ããè¦ã¦ããã¾ãï¼) ['(', 'define', 'square', '(', 'lambda', '(', 'r', ')', '(', '*', 'r', 'r', ')', ')', ')']
2. æ§æ解æ(Syntactic Analysis)
ãã¦ï¼æ¬¡ã«æ§æ解æã§ããï¼æ§æ解æã¯ï¼ã¤ã®é¢æ°ããæ§ç¯ãã¦ããã¾ãï¼
parse
ã¯ããã°ã©ã ãåå¥è§£æããçµæãèªã¿è¾¼ãé¢æ°read_from_tokens
ã®ã©ããã¼é¢æ°ã§ãï¼
def parse(program): return read_from_tokens(tokenize(program))
次ã«ï¼read_from_tokens
ãè¦ã¦ããã¾ãããï¼
3è¡ç®ï¼é¢æ°tokenize
ã®çµætokens
ã¯list
ãªã®ã§ï¼pop(0)
ã§æåã®è¦ç´ ãtoken
ã«å
¥ãã¾ãï¼
11è¡ç®:token
ã)
ããå§ã¾ãã¨ã¨ã©ã¼SyntaxError('unexpected')
ãè¿ãã¾ãï¼
12è¡ç®:token
ã(
,)
ã®ã©ã¡ãã§ãç¡ããã°ï¼æååã§ããã·ã³ãã«ãæ£ããåã«å¤æããé¢æ°atom
ã«æ¸¡ãï¼
14è¡ç®ããå§ã¾ãatom
ã¯åç´ã«intãã£ã¹ã
ã試ã¿ã¦ï¼ãã¡ã ã£ããfloat
,ãã¡ã ã£ããstr
ãè¿ãé¢æ°ã§ãï¼
ããã¾ã§ã§ï¼read_from_tokens
ãã·ã³ãã«ãããã°ï¼ã·ã³ãã«ãé©åãªå¤ã«ãã¦è¿ãé¢æ°ã§ããäºããããã¾ããï¼
次ã«ï¼
4è¡ç®:token
ã(
ããå§ã¾ãã®ã§ããã°ä»¥ä¸ã®åä½ãè¡ãã¾ãï¼
æ°ãããªã¹ãL
ãä½æãtokens
ã®æåã®è¦ç´ ã)
ã«ãªãã¾ã§å帰çã«èªåã®è¿ãå¤ãLã«å
¥ããï¼
ã¤ã¾ãï¼ï¼ã¤ã®ã«ãã³ã®å§ã¾ãããï¼çµç«¯ã¾ã§ã®ãã¼ã¯ã³ãå
¥ãã¦ããã¾ãï¼ã¾ãï¼ãã®ä¸ã«ã«ãã³ãå«ã¾ããã¨æ°ããL
ãä½æãï¼
åæ§ã®åä½ãè¡ãã¾ãï¼æç« ã§èª¬æããã®ã¯é£ããã§ããï¼ä¾ãè¦ã¦ããã¾ãããï¼
ãã®é¢æ°ã®åä½ä¾ï¼
ããã°ã©ã (* 1 3)ããããã¨ãã¾ãï¼ parseã«æ¸¡ãã¾ãï¼ >>> parse("(* 1 3)") åå¥è§£æãã¦ãã¼ã¯ã³ã«åãã¾ãï¼ tokenize("(* 1 3)") ['(', '*', '1', '3', ')'] ãå¾ã¾ãï¼ ãããread_from_tokensã«æ¸¡ãã¾ãï¼ read_from_tokens(tokens) ããã¨ï¼ã«ãã³ãããã®ã§ï¼ ãLãä½æ(以ä¸å帰çã«å®è¡) ãLã«*ãå ¥ãã¾ãï¼atomã§stråã«ããï¼ ãLã«1ãå ¥ãã¾ãï¼atomã§intåã«ããï¼ ãLã«3ãå ¥ãã¾ãï¼atomã§intåã«ããï¼ )ã¾ã§ããã®ã§ï¼ã«ãã³ãæ¨ã¦ã¾ãï¼ Lãè¿ãã¾ãï¼ read_from_tokens(tokens)ã®çµæï¼ ['*', 1, 3]ãread_from_tokensã®çµæã¨ãã¦è¿ãã¾ãï¼parseã®çµæï¼
ã§ï¼Lãªãã®çºã«ããã®ã¨æãããããã¾ããï¼ããã¯ï¼ã«ãã³ããã¹ãã«ãªã£ã¦ããæã«ï¼
åã«ãã³ã®ä¸èº«ãä¸æçã«ä¿æããå½¹ç®ãæã¡ã¾ãï¼ä¸æçã«ä¿æãã¦ãããï¼æçµçã«ã¯ï¼ã¤ã®ãªã¹ãã«æ¸¡ãã¾ãï¼
ã¤ã¾ãï¼ãã¹ãæ§é ãã¨ããªã¹ãã«ãªãã¾ãï¼[[],[],[]]
ã®ãããªæã
ããï¼ã¤ä¾ãè¦ã¦ã¿ã¾ãããï¼
ããã°ã©ã (* (* 1 3) 5)ããããã¨ãã¾ãï¼ parseã«æ¸¡ãã¾ãï¼ >>> parse("(* (* 1 3) 5)") åå¥è§£æãã¦ãã¼ã¯ã³ã«åãã¾ãï¼ tokenize("(* (* 1 3) 5)") ['(', '*', '(', '*', '1', '3', ')', '5', ')'] ãå¾ã¾ãï¼ ãããread_from_tokensã«æ¸¡ãã¾ãï¼ read_from_tokens(tokens) ããã¨ï¼ã«ãã³ãããã®ã§ï¼ ãLãä½æ(以ä¸å帰çã«å®è¡) ãLã«*ãå ¥ãã¾ãï¼atomã§stråã«ããï¼ ã«ãã³ãããã®ã§ï¼ ãã Lãä½æãã¾ãï¼ï¼äºåç®ã®Lã§ï¼ããã¯ä¸çªæåã®Lã¨ã¯ã¡ã¢ãªã®å ´æãç°ãªãï¼ã¤ã¾ãï¼ãã¹ããã¦ããä¸ã§ã®Lã§ããï¼ ãã Lã«*ãå ¥ãã¾ãï¼atomã§stråã«ããï¼ã ãã Lã«1ãå ¥ãã¾ãï¼atomã§intåã«ããï¼ ãã Lã«3ãå ¥ãã¾ãï¼atomã§intåã«ããï¼ ãã )ã¾ã§ããã®ã§ï¼ã«ãã³ãæ¨ã¦ã¾ãï¼ çµæãè¿ãã¾ãï¼ãã®çµæã¯å¤æ ã®Lã«æ¸¡ãã¾ãï¼ Lã«5ãå ¥ãã¾ãï¼atomã§intåã«ããï¼ )ã¾ã§ããã®ã§ï¼ã«ãã³ãæ¨ã¦ã¾ãï¼ Lãè¿ãã¾ãï¼ read_from_tokens(tokens)ã®çµæï¼ ['*', ['*', 1, 3], 5]ãread_from_tokensã®çµæã¨ãã¦è¿ãã¾ãï¼ï¼parseã®çµæï¼
ä»åã¯ï¼8è¡ç®ã«ããããã«åãã確èªããããã«Lã®printæãæãã§ãã¾ãï¼ printæã®å®è¡çµæãè¦ã¦ã¾ãããï¼
parse("(* (* 1 3) 5)") ['*'] ['*'] ['*', 1] ['*', 1, 3] ['*', ['*', 1, 3]] ['*', ['*', 1, 3], 5]
ã¾ãã«ä¸è¨ã§èª¬æããããã«ï¼Lã«å¤ãå ¥ãã¦ãã£ã¦ï¼ã«ãã³ããããæ°ããL(list)ãä½ã£ã¦ãããå ã®Lã«å ¥ãã¦ããã¨ããã®ãï¼ å帰ã§è¡¨ç¾ããäºã§ï¼lispã®ãã¹ãã表ç¾ãã¦ãã¾ãï¼
ããªãéè¤ããã¨ãããããã¾ãããï¼ããã§parseã®åããåãã£ããã¨æãã¾ãï¼
æå¾ã«ã¾ã¨ããã¨ï¼parseã¯æååã§ããããã°ã©ã ãåå¥è§£æã§ãã¼ã¯ã³åãï¼ãããã¤ã³ã¿ã¼ããªã¿ã解éåºæ¥ãå½¢ã«
ãã¦ããã¾ããï¼ä»åã§ã¯ï¼pythonãç解åºæ¥ãliståãå©ç¨ãã¦ï¼æ§ææ¨ã表ç¾ãã¾ããï¼
ãªãããã®åãé·ãæ¸ãéãã¦ãããï¼
ããããããã¨æã£ããããã¾ãããã©ã次ã«é²ã¿ããã¨æãã¾ãï¼
3. ç°å¢(Environment)
次ã¯ï¼ç°å¢ã«ã¤ãã¦ã§ãï¼ããã¾ã§ã¯ï¼æååã§ããããã°ã©ã ãã¤ã³ã¿ã¼ããªã¿å
é¨ã§ã©ã解éãã¦ãããã
è¦ã¦ãã¾ããï¼ã§ã¯ï¼*
çã®æ¼ç®åãæç¶ã(procedure)ãã©ã解éãï¼ããã被æ¼ç®åï¼operandï¼ã«é©ç¨ãã¦ããã°
è¯ãã®ã§ããããï¼ç°å¢ã¯ï¼æ¼ç®åã»æç¶ãã¨ãã®åä½ãç´ã¥ãã¦ãã¾ãï¼
ã§ã¯ï¼ãã®ç°å¢ãã©ã表ç¾ãããè¦ã¦ããã¾ãããï¼pythonã®è¾æ¸ã§ç´ã¥ãã¦ããã¾ãï¼
7 ~ 10è¡ç®ã§åæ¼ç®åã®è¨å·ãpythonã®æ¼ç®åã«ç´ã¥ãã¦ãã¾ãï¼ãã®pythonã®åæ¼ç®åã¯å¼æ°ã2ã¤ã¨ãã¾ãï¼
e.g
>>> import operator as op >>> op.add(1,3) 4
ãã®ããã«ï¼ç°å¢ã«åã·ã³ãã«ã«å¯¾å¿ã¥ããå¦çã®ãã¢ãæ ¼ç´ãã¾ãï¼
4. è©ä¾¡(eval)
ç°å¢ã«åã·ã³ãã«ã®è¡ãå¦çã®ãã¢ãæ ¼ç´ãã¾ããï¼ããã§ã¯ï¼ã·ã³ãã«ãã©ãè©ä¾¡ãçµæãåºãã®ã§ããããï¼ ã¾ãå ã«ï¼å¾©ç¿ãããã¦è©ä¾¡ã¾ã§ã®ã¹ãããä¾ãè¦ã¾ãããï¼
>>> ast = parse("(* (* 1 3) 5)") #æååã®ããã°ã©ã ããæ§ææ¨astãä½æ >>> print(ast) ['*', ['*', 1, 3], 5] >>> eval(ast) #astãè©ä¾¡ãï¼å®è¡çµæãå¾ãï¼ 15
è©ä¾¡ã§ã¯ï¼ããã°ã©ã ã解æãã¦å¾ãããæ§ææ¨ãå®è¡ãã¦çµæãå¾ã¾ãï¼ ãã®ããã«ï¼å¼æ°ã¨ãã¦astã¨å©ç¨ããç°å¢ãæå®ãã¾ãï¼
ã§ã¯ï¼å®è¡ä¾ã交ãã¦ã³ã¼ãã®è§£èª¬ã«å ¥ãã¾ãï¼
>>> ast = parse("(* (* 1 3) 5)") #['*', ['*', 1, 3], 5] >>> eval(ast)
ä¸è¨ã®ã¨ãï¼ã¾ãevalã§ã¯ï¼listã§ããastãå¼æ°ã¨åãï¼ç°å¢envã¯å ç¨å®ç¾©ããç°å¢ï¼global envï¼ãå©ç¨ãã¾ãï¼
1.ãx(=ast)ã¯ã·ã³ãã«ã§ãªãï¼ãªã¹ãã§ããã®ã§ï¼ä¸çªæå¾ã®ãããã¯(7è¡ç®~)ãå®è¡ããã¾ãï¼ 2. æç¶ãprocã¨ãã¦ï¼astã®æåã®è¦ç´ ãå帰çã«è©ä¾¡ãã¾ãï¼è©ä¾¡çµæãprcã«ä»£å ¥ããã¾ãï¼ 2.1 x(='*')ã¯ã·ã³ãã«ãªã®ã§ï¼3è¡ç®ãå®è¡ããã¾ãï¼3è¡ç®ã§ã¯ï¼ç°å¢ã«å ¥ã£ã¦ããé¢æ°ãå¼ã³åºãã¾ãï¼ãã®å ´å`op.mul`ãè¿ãï¼procã«op.mulãä»£å ¥ãã¾ã 3 å¼æ°argsã¨ãã¦ï¼æåã®è¦ç´ 以å¤ã®é¨åãå ¨ã¦è©ä¾¡ãï¼å¼æ°ã¨ãã¦argsã«ä»£å ¥ãã¾ãï¼ 3.1 ã¾ãæåã¯argsã«['*', 1, 3]ãå²ãå½ã¦ããï¼ãããè©ä¾¡ããã¦ããã¾ã 3.1.1 2.1, 2.2ã¨åæ§ã«'*'ãè©ä¾¡ããï¼procã«op.mulãä»£å ¥ããã¾ãï¼ 3.1.2 x(=1)ã¯ã·ã³ãã«ã§ãï¼ãªã¹ãã§ãç¡ãã®ã§ï¼ãã®ã¾ã¾1ãè¿ãã¾ã 3.1.3 x(=3)ã¯ã·ã³ãã«ã§ãï¼ãªã¹ãã§ãç¡ãã®ã§ï¼ãã®ã¾ã¾3ãè¿ãã¾ã 3.1.4 args = [1,3]ãã¨ãï¼op.mul(1,3)ãå®è¡ããï¼3ãè¿ãã¾ãï¼ 2.2 x(=5)ã¯ã·ã³ãã«ã§ãï¼ãªã¹ãã§ãç¡ãã®ã§ï¼ãã®ã¾ã¾5ãè¿ãã¾ã 2.3 args = [3,5]ãã¨ãï¼op.mul(3,5)ãå®è¡ããï¼15ãè¿ãã¾ãï¼ çµæï¼15ãå¾ããã¾ã
ãã®ããã«å帰çã«ï¼ã«æ¼ç®åã»æç¶ãã被æ¼ç®åã«é©ç¨ãè©ä¾¡ãã¦ããå½¢ãã¨ãï¼æçµçãªè©ä¾¡ãè¡ãã¾ãï¼ ããã§ï¼æ¼ç®åãè©ä¾¡ããlispã¤ã³ã¿ã¼ããªã¿ãä½æããäºãã§ãã¾ããï¼
REPL(read-evaluation-print-loop)ãå®è£ ããã°ã¤ã³ã¿ã¼ããªã¿ã®ããã«å®è¡ãï¼çµæã®ç¢ºèªãããäºãã§ãã¾ãï¼ ç°¡åã«è¨è¿°ããã¨ä»¥ä¸ã®ããã«ãªãã¾ãï¼
ã©ãã§ããããï¼æ¼ç®åãè©ä¾¡åºæ¥ãç°¡åãªlispã¤ã³ã¿ã¼ããªã¿ãä½æã§ãã¾ããï¼ åç´ãªåä½ãç©ã¿ä¸ãã¦ããã ãã§ã¤ã³ã¿ã¼ããªã¿ãä½æã§ããã®ã¯åãé¢ç½ãã£ãã¨æãã¾ãï¼
次åã¯ï¼é¢æ°å®ç¾©ï¼ifæçãå®è£ ãã¦lispããã°ã©ãã³ã°ã§ããããã«ãã¦ããããã¨æãã¾ãï¼ ã§ããï¼ä»åã®æ¼ç®åã®ä½ææ¹æ³ãåããã°ãã¨ã¯èªåã§ä½ãäºãå¯è½ã§ãï¼æ¬¡åã®æ稿ã¾ã§ã« å®è£ æ¹æ³ãèãã¦ã¿ã¦ä¸ããï¼
ä»åã®å ¨ä½ãéãã¦ã®ã³ã¼ãã¯ä»¥ä¸ã®ããã«ãªãã¾ãï¼