Lisp tutorial for Pythonista.
Day #1 : Gentlemen, Start your engine.




                                                         Ransui Iso
                          Strategic Technology Group, X-Listing Co, Ltd.
これから Lisp の話をします
Lisp の歴史とか概要
Wikipedia でも読んどいて下さい
それでも覚えておきたい
 Lisp の神々のお姿
John McCarthy
Richard M. Stallman
Guy L Steel Jr.
Paul Graham
その他にも神はいっぱいいる
 しかも全員超絶 Hacker
Lisp は難しいって良く聞くよ!
   そんな Super Hacker 向け言語を、
 ( 僕 | 私 ) も使えるようになるのかな?
Lisp は実用言語!怖くないよ!
 ちょっと加齢臭のするとこはあるけどな!
Lisp は長年使われてきたので
     その時々の流行とか
      知恵が詰まってる

 ちょっと詰め込みすぎで整理できてない感もある
先人の知恵を拝借して楽できるということでもある
商用 Lisp 処理系売ってる会社は
        食えている
   粛々とお仕事に Lisp を使っている
     たくさんの人たちがいる

      我々はオタクの腐海に
  孤独に漕ぎ出そうとしているんじゃない
で、本題。
Pythonista のための Lisp 入門
今日は最初なのでイントロだけ
対象は Common Lisp
対象は Common Lisp

          処理系はいろいろあるけど
SteelBank Common Lisp というやつを使いますよ
対象は Common Lisp

Scheme とかいう象牙の塔は今のところ無視してかまいません
対象は Common Lisp
Emacs Lisp は本物の Lisp ですが古文・漢文の世界です
       現代文を学んでいる間は忘れましょう
Lisp→Python→Lisp
 な俺から言わせると
Python を使えるなら
Lisp なんて余裕じゃね?
   とか思うんです。
Python と Lisp は意外と似てるしな!

            そりゃそうだよ
      Python のほうが新しい言語で
        いろんな言語のいい所を
    上手に取捨選択して取り込んでるもの
では、まず
関数とか見てみる
ぱいそん
def fact(x):
    result = 0L
    for i in xrange(1, x + 1):
        result *= i
    return result




りすぷ
(defun fact(x)
    (if (< x 1) 1 (* x (fact (1- x))) ))
ぱいそん
def fact(x):
    result = 0L
    for i in xrange(1, x + 1):
        result *= i
    return result




りすぷ
(defun fact(x)
    (if (< x 1) 1 (* x (fact (1- x))) ))



  カッコつけて再帰とか使わなくてもいいよ!
ぱいそん
def fact(x):
    result = 1
    for i in xrange(1, x + 1):
        result *= i
    return result




りすぷ
(defun fact(x)
  (let ((result 1))
    (loop for i from 1 to x do
         (setf result (* result i)))
    result))
ぱいそん
def fact(x):
    result = 1
    for i in xrange(1, x + 1):
        result *= i
    return result




りすぷ
(defun fact(x)
  (let ((result 1))
    (loop for i from 1 to x do
         (setf result (* result i)))
  Common Lisp は「ループ上等」な世界
    result))
末尾再帰原理主義者の戯言はガン無視してよし!
確かに似てはいる…しかし…
そんなに括弧ばかりで大丈夫か?
大丈夫だ。問題ない。

     Python のインデントの代わりに
      括弧を使っていると思えばいい

普通はエディタがよろしくインデントしてくれるしな!
さっきの例はあまりにアレなので
もうすこしカッコつけた fact 関数
(defun fact(x)
  (apply #'* 
     (loop for i from 1 to x collect i)))



      ベタなループでチマチマ掛け算なんて
           小学生までよねー

                 って感じ?
で、最初の単純ループ版と
さっきのカッコつけバージョンの
  コンパイル結果を見ると
単純ループ版   157bytes
カッコつけ版   440bytes
m9(^Д^)

素直に書くって大事!
気を取り直して
データ型とか見てみる
ぱいそん
l = [1, "a", "b", ["ham", "spam"], 5]
l[0]          → 1
l[1:]         → ['a', 'b', ['ham', 'spam'], 5]
l[3]          → ['ham', 'spam']
l[3][0]       → 'ham'
5 in l        → True

for x in l: print x

りすぷ
(setf l '(1 "a" "b" ("ham" "spam") 5)
(car l)           → 1
(cdr l)           → ("a" "b" ("ham" "spam") 5)
(cadddr l)        → ("ham" "spam")
(car (cadddr l)) → "ham"
(member 5 l)      → (5)

(loop for x in l do (print x))
ぱいそん
d = dict()
d["Hello"] = "World"
d["Hello"] → "World"
d[1] = 2
len(d) → 2
for (key, value) in d.items():
    print("%s : %s" % (key, value))


りすぷ
(setf d (make-hash-table :test #'equal))
(setf (gethash "Hello" d) "World)
(gethash "Hello" d) → "World"
(setf (gethash 1 d) 2)
(hash-table-count d) → 2
(maphash #'(lambda (key value)
             (princ (format nil "~a : ~a~%" key value))) d)
ぱいそん
class Greeting(object):
    def __init__(self):
        self.name = None
    def setName(self, name):
        self.name = name
    def hello(self, name=None):
        print("Hello %s!" % name if name else self.name)
obj = greeting()
obj.hello(name="World")

りすぷ
(defclass Greeting ()
    ((name :initform nil)))
(defmethod set-name ((self Greeting) name)
    (setf (slot-value self 'name) name))
(defmethod hello ((self Greeting) &key name)
    (princ (format nil "Hello ~a!~%"
             (or name (slot-value self 'name)))))
(setf obj (make-instance 'Greeting)
(hello obj :name "World")
…… なんか、全然違くね?
見た目に騙されてはイカ〜ン!
 機能としては同じものが提供されてるし
       面倒な部分は
   言語そのものをカスタマイズ
     してしまえば無問題!
言語そのものをカスタマイズするだって?
言語そのものをカスタマイズ!?
(setf count 10)
(do () ((<= count 0))
  (print count)
  (setf count (1- count))


(defmacro while (test-exp &body body)
    `(do ()
        ((not ,test-exp)) ,@body))

(setf count 10)
(while (>= count 0)
    (print count)
    (setf count (1- count)) )


(defmacro for ((init-exp test-exp update-exp) &body body)
    `(do ((,@init-exp ,update-exp))
        ((not ,test-exp)) ,@body))

(for ((count 10) (> count 0) (decf count 1))
    (print count))
構文要素を自由に追加できるよ!

 こういうのは関数とかライブラリとかじゃ
         実現不能
「めんどくせーなー」
と思ったら俺様流にカスタマイズ
       これ!
ただしやりすぎると
  他人がまったく読めない
謎言語に変貌するという諸刃の剣
素人にはお勧めできない
けど、使い所をちゃんと心得てればホントに便利な機能!
   macro については後日詳しく勉強するよ!
その他の Python と Lisp の対応は

「 Lisp プログラマのための Python 入門」
                   by Peter Norvig

                       を見てね!

http://www.unixuser.org/~euske/doc/python/python-lisp-j.html
と、簡単に Lisp を紹介したので
 実際に Lisp をお勉強する
   環境の話をします
準備するお道具

●   SBCL
●   Emacs
●   quicklisp
●   Windows を端末にしたい場合は
     ●   Xming
     ●   PuTTY の適切な設定
SBCL のインストール

●       emerge sbcl

    –   できるだけ新しいのを使いたいので ~amd64 すべし
    –   USE フラグは threads と unicode は必須で
    –   インストールできたら ~/.sbclrc ファイルを作成&編集

;; -*- coding: utf-8 -*-
(setf sb-impl::*default-external-format* :utf-8)
(setf sb-alien::*default-c-string-external-format* :utf-8)
Emacs のインストール

●   vi 派の人。ごめん、やっぱ Emacs 便利なんで。
●   ~amd64 はしなくていいです。
●   USE フラグとかは
     capella で equery uses emacs とかして調べてね!
●   あと、日本語入力のために USE フラグに emacs
    を指定して emerge anthy
●   自分の ~/.emacs.el 持ってない人は
    ~ransui/.emacs.el コピーして適当に編集して使っ
    て下さい。
QuickLisp のインストール

●   PyPi みたいなもん
●   wget http://beta.quicklisp.org/quicklisp.lisp
●   sbcl --load quicklisp.lisp
      ●   (quicklisp-quickstart:install)
      ●   ややあって
      ●   (ql:add-to-init-file)
      ●   (ql:quickload "quicklisp-slime-helper")
      ●   (quit)
Xming のインストール

●       ここから DL してインストール
    –   http://www.straightrunning.com/XmingNotes/

●       PuTTY の 設定パネルで
         ●   接続→ SSH→X11 で
         ●   X11 フォワーディング:チェック
         ●   X ディスプレイの場所 localhost:10

    –   鯖側の sshd_conf で X11Forwarding が有効になってい
         るかを確認
Eclipse 使いたいひと向け情報

●       cusp っていう Lisp 用の Plug-in があるらしい
    –   情報は
         ●   http://bitfauna.com/projects/cusp/index.html   
             にある。

●       dandelion ってのもあるらしい
    –   情報は
         ●   http://sourceforge.net/projects/dandelion-ecl/


●       使ってみた人、感想希望
    –   もし超イケてるのであれば、 Emacs から乗り換えも有り
参考書

●       ふくちゃんのブログ見てね!
    –   http://caddr.blog98.fc2.com/

●       最初のお勧めは
    –   Common Lisp 入門
    –   実践 Common Lisp

●       On Lisp はオンラインで読める
    –   http://www.komaba.utmc.or.jp/~flatline/onlispjhtml/
    –   けど、このテキストは Lisp の基礎は分かってるレベルを想定してる
宿題

●   Emacs + SLIME もしくは eclipse とかの環境を
    ちゃんと作っておいてね!

●   次回から実際にプログラム書きます

●   どういう形式でやるかは考え中
     ●   ハンズオン形式?
     ●   全員がノート PC 持ってるわけじゃないし…

Lisp tutorial for Pythonista : Day 1