ãªãRubyã¯è¨±å®¹å¯è½ãªLISPãªã®ã
LISPの真実ãèªãã§ããæå¾ã«åºã¦ããã®ã§ãããªãå¤ãè¨äºã ããã©ããEric Kiddæ°ã®Why Ruby is an acceptable LISPã訳ãã¦ã¿ã¾ãããまつもとさんによる反応ãããããã®ã¨ã³ããªã®ä¸ã§åæã¯ã»ã¼è¦ç´ããã¦ãã¾ãã
ä¸å¹´åãç§ã¯Rubyã«æ³¨ç®ãã¦ã¯ãããã®ã®ããããç¡è¦ãããã¨ã«ãããRubyã¯Pythonã»ã©ããã¥ã©ã¼ã§ã¯ãªãããLISPã»ã©å¼·åã¨ããããã§ããªãããªã®ã«ä½æ
æ°ã«ãããªããã°ãªããªãã¨ããã®ãã
ãã¡ããããããã®è©ä¾¡åºæºã¯èããªãããã¨ãã§ãããããRubyãLISPãããããã¥ã©ã¼ã§ãPythonãããå¼·åã ã£ããã©ããªãã ãããï¼*1 ããã¯Rubyãèå³æ·±ããã®ã«ããã«è¶³ãã®ã§ã¯ãªããï¼
ãã®çåã«çããåã«ãLISPãå¼·åããããã¦ãããã®ã¯ä½ãªã®ããå®ç¾©ãã¦ããã¹ãã ãããPaul GrahamはLISPの美徳について雄弁に語ったããããã§ã¯è°è«ã®ããã«æ¬¡ã®2ã¤ã«çµããã¨ã«ãããã
- LISPã¯æ¿ã(dence)é¢æ°åè¨èªã§ãã
- LISPã¯ããã°ã©ã å¯è½ãªãã¯ããæã£ã¦ãã
çµå±ã®ã¨ãããRubyã¯é¢æ°åè¨èªã¨ã»ã¼åçã§ãããç§ãèãã¦ãããããä¸æããã¯ãã模å£ãããã¨ãåãã£ãã
Rubyã¯LISPãããæ¿ãé¢æ°åè¨èªã§ãã
æ¿ãè¨èªã¨ããã®ã¯ã½ã¼ã¹ãé£èªåãããã¨ãªããç©äºãç°¡æã«è¡¨ç¾ããããããªãã¯ä¸ç®ã§ããå¤ãã®ããã°ã©ã ãè¦æ¸¡ããã¨ãã§ããèªç¶ããã«ã¯ãã°ã®é ããä½å°ãå°ãªããªããããä¸å®ã®ã¬ãã«ãè¶ ãã¦ãããã°ã©ã ãããâæ¿ãâããããã®å¯ä¸ã®æ¹æ³ã¯ãããå¼·åãªæ½è±¡åã使ç¨ãããã¨ã ã
ç¹ã«å¼·åãªæ½è±¡åã®1ã¤ãlambdaã ã lambdaã使ããã¨ã§ãããªãã¯ãã®å ´ã§ããã«æ°ããé¢æ°ãä½ã£ã¦ãä»ã®é¢æ°ã«æ¸¡ããããå¾ã§ä½¿ãããã«æ ¼ç´ãããã¨ããã§ããã
ä¾ãã°ãLISPã§ãªã¹ãä¸ã®åã
ã®æ°ãåã«ããããªãã次ã®ããã«æ¸ãã ãã:
(mapcar (lambda (n) (* n 2)) mylist)
mapcarã¯mylistã®åè¦ç´ ãå¤æãããã¨ã«ãã£ã¦æ°ãããªã¹ããä½ãã ãããã®å ´åã®å¤æã¯ãnã®ããããã®å¤ã«ã¤ãã¦ãnã«2ãæãããã¨èªãããJavaScriptã§ã¯lambdaã¯functionã¨ãã¦æ¸ããããããã¯ããããå°ãã ãLISPããæå¿«ã :
map(function (n) { return n*2 }, mylist)
ãã¡ãããããã¯ããªããlambdaã§ã§ãããã¨ã«é¢ããä¸ã¤ã®ãã³ãã«ãããªãããã®ãããªããã°ã©ãã³ã°ã¹ã¿ã¤ã«ãæ¯æããè¨èªã¯é¢æ°åè¨èªã¨å¼ã°ãããé¢æ°ããã¼ã¹ã¨ãã¦åä½ããããã ãå®éã«ãæ¿ãé¢æ°åè¨èªã¯é常ã«ç°¡æ½ã«ãªããããã²ã¨ãã³é¢æ°åè¨èªã®èªã¿æ¹ãå¦ã¹ã°ãããã¯ã¾ã£ããæå¿«ãªãã®ã«ãªãã ããã
ã©ã®ããã«ãã¦Rubyã¯é¢æ°åããã°ã©ãã³ã°ã¨ããç¹ã§LISPã«å¹æµãããã®ã«ãªã£ã¦ããã®ã ããããPaul Grahamによる規範的な例ãèãã¦ã¿ãããä¸ã¤ã®ã¢ãã¥ã¼ã ã¬ã¼ã¿ãä½ããããªé¢æ°ãå®ç¾©ãã:
(defun foo (n) (lambda (i) (incf n i)))
ãã®ã³ã¼ãã¯Rubyã§ã¯ãããã§ã¯ãããããçããªãããã®è¡¨è¨ã¯Cããã«ã¼ã«ã¨ã£ã¦ãã親ãã¿ããããã®ã«ãªãã
def foo(n) lambda {|i| n+=i} end acc = foo 3 acc.call(1) # --> 4 acc.call(10) # --> 14 acc.call(0) # --> 14
ããããRubyã®å ´åãæã ãããã¿ã¤ãã³ã°éãç¯ç´ã§ãããããªèå³æ·±ãç¹å¥ãªå ´åããããlambdaãå¼æ°ã«åããããªãããåç´ãªé¢æ°ãèãããã
;; 'fn'ãåã ã®èªç¶æ°ã«ã¤ãã¦ä¸åå¼ã¶ (defun each-natural-number (fn) (loop for n from 1 do (funcall fn n))) ;; 1, 2, 3... ã¨è¡¨ç¤º (each-natural-number (lambda (n) (format t "~D~%" n)))
ããããæã ã¯Rubyã§ããã¨åããã¨ãããä¸æããããã¨ãã§ãããyieldã使ããã¨ã§lambdaãfnãä¸æãã¦ã¿ããã
def each_natural_number n = 0 loop { yield n += 1 } end each_natural_number {|n| puts n }
ãããyieldã¯ç¹æ®ç®çã®ããã¯ã ãããã¯ä¸ã¤ã®lambdaãå¼æ°ã«åãé¢æ°ã«å¯¾ãã¦ã®ã¿ä½¿ããããããé度ã®é¢æ°çã³ã¼ãã«ããã¦ã¯ãyieldã¯å¤ãã®æéãçãã¦ãããã次ã®2ã¤ãæ¯è¼ãã¦æ¬²ããã
[1,2,3].map {|n| n*n }.reject {|n| n%3==1 }
(remove-if (lambda (n) (= (mod n 3) 1)) (mapcar (lambda (n) (* n n)) '(1 2 3)))
大ããªããã°ã©ã ã§ã¯ããã®å·®ãç©ã¿éãªã£ã¦ãããï¼LISPã«å¯¾ããå¼è·ã¨ãã¦ã¯ãlambdaãããç°¡æ½ã«ãããªã¼ãã¼ãã¯ããæ¸ããã¨ãå¯è½ã ã¨ãããã¨ã ãã ãããããã®ã¯ç¨ã ãï¼
Rubyã¯ããªãããã¯ãã§ããããã¨ã®ç´80%ã¯ä¸ãã¦ããã
LISPããã«ã¼ã¯ããè¨ãã ããããlambdaã®è¯ãæ§æãããã®ã¯ããã£ããã§ããã¯ãã«ã¤ãã¦ã¯ã©ããï¼ãããã¯è¯ã質åã ãLISPã®ãã¯ãã¯æ¬¡ã®ãããªæ©è½ãæã£ã¦ããã
- ã³ã³ãã¤ã©ã®ä¸ã§èµ°ã
- ã«ã¹ã¿ãã¤ãºãããæ§æãçã®LISPã«å¤æãã
LISPãã¯ãã®æãä¸è¬çãªä½¿ç¨æ³ã¯æ²¢å±±ã®lambdaãã¿ã¤ãããã®ãé¿ãããã¨ã ã
(defmacro with-each-natural-number (n expr) `(each-natural-number (lambda (,n) ,expr))) (with-each-natural-number n (format t "~D~%" n))
defmacroã¯ä¸ã¤ã®ãªã¹ããå¼æ°ã¨ãã¦åããããã¦å¥ã®ãªã¹ããè¿ãé¢æ°ãå®ç¾©ããããã®ä¾ã®ä¸ã§æã ã®ãã¯ãã¯ãã³ã³ãã¤ã©ãwith-each-natural-numberãè¦ã度ã«å¼ã°ããããã®ãã¯ãå®ç¾©ã§ã¯ãnã¨exprããã³ãã¬ã¼ãã«åãè¾¼ã¿ãç´ æ©ããªã¹ããæ§ç¯ããããã«ãLISPã®ããã¯ã¯ã©ã¼ãæ§æãå©ç¨ãã¦ãããããããå¤æããããªã¹ãã¯åã³ã³ã³ãã¤ã©ã«æ¸¡ãããã
ãã¡ããããã®ãã¯ãã¯Rubyã«ããã¦ã¯å½¹ã«ç«ããªããRubyã§ã¯çããªãåé¡ã®å¨ãã§åããã¯ãã ããã ã
ãã®æ¬¡ã«æãä¸è¬çãªLISPãã¯ãã®ä½¿ããæ¹ã¯ãä½ããå®ç¾©ããããã®ããè¨èªãä½ããã¨ã ã
;; æ¶ç©ºã®ãã¬ã¼ã ã¯ã¼ã¯"LISP on Rails"ãå©ç¨ãã¦ã ;; ãã¼ã¿ãã¼ã¹ã¸ã®ãã¤ã³ãã£ã³ã°ãçæãã (defmodel <order> () (belongs-to <customer>) (has-many <item> :dependent? t))
Ruby on Railsã使ãã°ãããæ¸ããã¨ãã§ããã
class Order < ActiveRecord::Base belongs_to :customer has_many :items, :dependent => true end
ããã§ãbelongs_toã¯ã¯ã©ã¹é¢æ°ã ããããå¼ã°ããã¨ããã¡ã³ãé¢æ°ã®æãOrderã«è¿½å ããã実装はかなり汚ないããã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ããã§ãã¦ããã
ãããããã¯ãã«ä¼¼ãæ©è½ã«å¯¾ããç¾å®ã®ãã¹ãã¯ã ã©ããããã®é »åº¦ã§ããè¨èªãä½ãã®ã«ä½¿ããããã¨ãããã¨ã ããã¹ãã«å¯¾ããRubyã®ã¹ã³ã¢ã¯ããã ï¼ Railsã«å ããRakeï¼Makefileãæ¸ãã®ã«ä½¿ãããï¼ãNeedleï¼ã³ã³ãã¼ãã³ããæ¥ç¶ããããã«ï¼ãOptionParserï¼ã³ãã³ãã©ã¤ã³ãªãã·ã§ã³ããã¼ã¹ããããã«ï¼ãDLï¼Cè¨èªã®APIã¨ä¼è©±ããããã«ï¼ãããã¦ãã®ä»ã«ãæ°ãåããªãã»ã©ã«ãããRubyããã°ã©ãã¯ãªãã§ãRubyã§æ¸ãã®ã ã
ãã¡ãããç°¡åã«Rubyã«è¼¸åºã§ããªããããª高度なLISPマクロは沢山あるãç¹ã«ãããè¨èªãæ¬å½ã«ã³ã³ãã¤ã«ãããããªãã¯ãã¯Rubyã§ã¯ã¾ã åºã¦ãã¦ããªãã(Ryan Davisã¯ãã®æ¹åã§ParseTreeã¨RubyInlineã¨ãããã¤ãã®ææãªä»äºããã¦ãããç§ã¯ãããç解ã次第é¢é£ãããã¯ããã¯ã«ã¤ãã¦æ¸ãã¤ããã ã)
Rubyã®ã©ã¤ãã©ãªãã³ãã¥ããã£ãå¢ãã¯è¯å¥½ã
ããã§ãããLISPãä¾ç¶ã¨ãã¦Rubyãããå¼·åãªããä½æ LISPã使ããªãã®ãï¼ LISPã§ããã°ã©ãã³ã°ãããã¨ã«å¯¾ããå ¸åçãªç°è°ã¯:
- ååãªã©ã¤ãã©ãªãç¡ã
- LISPããã°ã©ããéããããªã
- LISPã¯éå»20å¹´ã©ããåãããªãæã«è¡ã£ã¦ãã¾ã£ã
ãããã¯æãé£ãã»ã©ã®ç°è°ã§ã¯ãªããã確ãã«ä¸èã«å¤ããã
ã¯ããæãCommon Lispの標準ライブラリã¯å·¨å¤§ãªãã®ã ã¨èãããã¦ããããããä»æ¥ã§ã¯ãããã¯çã ããã¾ã§ã«å°ãããJavaã®ããã¥ã¢ã«ã¯å£ãåãå°½ãã¦ãã¦ãPerlã®CPANã¢ã¼ã«ã¤ãã¯ããªããæ³åãå¾ããããªãã¢ã¸ã¥ã¼ã«ã§ãæã£ã¦ãããããã«å¯¾ãã¦Common Lispã¯ãããã¯ã¼ã¯ã¨èªãæ¨æºçãªæ¹æ³ããæã£ã¦ããªãã®ã ã
åæ§ã«ãLISPããã°ã©ãã¼ã¯ç¨å°ã§ãããããããªãããã¹ãã³ã®å¨è¾ºã«ãããªããã»ã¨ãã©éæ³ã«è¿ãä»äºãããç°è²ã®ããã«ã¼éã®å°ããªãã¾ãå ´ãããããä»ã®å ´æã§ã¯å¥½å¥å¿ããããããè¥ãããã«ã¼ãèãæ£å¨ãã¦ããã®ã¿ã ããããLISPã¯å¸¸ã«å°æ°æ´¾ã®è¨èªã¨ãã¦åå¨ãã¦ããã
ä¸æ¹ã§Rubyã¯æ¥éã«äººæ°ãå¾ã¦ãã¦ããã大ããªæ¨é²åãä¸ãã¦ããã®ã¯Railsã®ããã ãRailsã®æé·ã¯2004å¹´ã®æ®ãããå§ã¾ã£ããããããªããä¼ç¤¾ãç«ã¡ä¸ãããã¨ãããªããå¯è½æ§ã®ããå¾æ¥å¡ã¯çRailsæ好è ã ã¨è¨ã£ã¦ãéè¨ã§ã¯ãªããRailsã¯ããã«ãããµããWEBã³ã³ãµã«ãã£ã³ã°ã¸æµ¸éãã¦ããããããã¯å¤§ããªãã¸ãã¹ã¨ãªã£ã¦ããã ããã
Rubyãã¾ããè¯ãæ¨æºã©ã¤ãã©ãªã¨追加ライブラリの豊富なアーカイブãéçºããã®ã«ååãªæéãè²»ãã¦ãããããããªããWEBãã¼ã¸ããã¦ã³ãã¼ãããããRSSããã¼ã¹ããããã°ã©ããçæããããSOAP APIãå¼ã¶ãã¨ãå¿ è¦ã¨ãã¦ãããªãããããã¯å ¨ã¦ç¨æããã¦ããã®ã ã
å¼·åãªè¨èªã¨ããã¥ã©ã¼ãªè¨èªã¨ã®éã§é¸æãè¿«ãããã¨ããå¼·åãªãã®ãé¸ã¶ãã¨ã素晴しい意味を成すãã¨ããããããããªãã
ããããããå¼·åãã®ç¹ã§å·®ãå°ããã®ãªããããã¥ã©ã¼ã§ãããã¨ã¯ããããã®ç¹ã§å¥½ã¾ããå©ç¹ãæã¤ã2005å¹´ã«ã¯ãç§ã¯RubyãããLISPãé¸ã¶åã«ããã£ããèãããã¨ã«ãããæé©åãããã³ã¼ãããããã¯å®å
¨ã«ç¬ç«ããã³ã³ãã¤ã©ã¨ãã¦ä½ç¨ãããã¯ããå¿
è¦ãªã¨ãã®ã¿ãLISPãé¸ã¶ããã«ã
*1:Pythonã«ã¯ãã¯ãã¯ãªã http://www.unixuser.org/~euske/doc/python/python-lisp-j.html