SlideShare a Scribd company logo
1 of 51
Lisp tutorial for Pythonista.
Day #2 : The Basics.




                                                      Ransui Iso
                       Strategic Technology Group, X-Listing Co, Ltd.
今日はプログラムを書くための
  基礎部分を勉強します
前回の宿題は OK ですか?
いちおう Emacs + SLIME が動く前提です
なにはともあれまずは REPL
    Read, Eval, Print Loop の略語
Python なら「インタラクティブシェル」
Emacs 起動して M-x slime
META キーの設定無い人は [ESC] 押して [x]
ちゃんと起動するとこうなるはず
ぱいそん
>>> 1 + 2
>>> x = 1
>>> y = 2
>>> z = x * y
>>> z



りすぷ
CL­USER> (+ 1 2)
CL­USER> (setf x 1)
CL­USER> (setf y 1)
CL­USER> (setf z (+ x y))
CL­USER> z
なんか警告出てます!


; in: LAMBDA NIL
;     (SETF X 1)
; ==>
;   (SETQ X 1)
; 
; caught WARNING:
;   undefined variable: X
変数は宣言してから使うのが基本
    ルーズな Python とは大違いだよ!
管理大好きスーツ族への強力なアピールポイントだ!




     警告ガン無視でも、まあ問題は無いんだが気持ち悪いので宣言しとけ。
変数宣言の前に名前空間の話
Python と似てる部分もあるし違う部分もある
Common Lisp の名前空間

●   大域は package という単位が基本になっている
     ●   概念的には Python のモジュールに近い
     ●   Python のモジュールより厳密に定義するのでお手軽じゃない

●   何も指定しない時は CL­USER がデフォルト
     ●   cl パッケージに Common Lisp の基本機能が入っている
     ●   イメージとしては
          cl­user.py の最初で
          from cl import * してある感覚。

●   もちろんローカル変数とかもちゃんとあるよ
     ●   関数引数とか、 let フォームとか色々ある
     ●   レキシカルスコープなので、基本部分は Python 感覚で OK 。
パッケージ変数の宣言

●   defvar と defparameter
      ●   どちらもパッケージ変数を宣言する
      ●   宣言するときには初期値を与える

●   defvar
      ●   再初期化されない

●   defparameter
      ●   再初期化される



    パッケージ変数という用語は一般的じゃない。 Python 風な名前で呼んで
    みてるだけ。ほんとは「スペシャル変数」と言う。実は深い意味もあるん
    だけど、今は無視しちゃう。
再初期化される?されない?

●   実験してみりゃ一目瞭然
CL­USER> (defvar *foo* nil)
*FOO*
CL­USER> (defparameter *bar* nil)
*BAR*
CL­USER> (setf *foo* 1)
1
CL­USER> (setf *bar* 2)
2
CL­USER> (defvar *foo* nil)
*FOO*
CL­USER> *foo*
1
CL­USER> (defparameter *bar* nil)
*BAR*
CL­USER> *bar*
NIL

    パッケージが再読み込みされた時とかに挙動が変わるよ!
CL のパッケージは取扱いが面倒
なので、今のところは CL-USER 一辺倒でいく

  ライブラリとか作るようになったら
    defpackage とか使うよ
ソースをファイルに書いて実行する

●   C­x 5 2 で新フレームを開いて
●   新しいフレームで C­x C­f hello.lisp とかし
    て新規バッファを開く
●   コード書く
(defun hello (name)
  (format t "Hello ~a~%" name))

(hello "World")

●   C­x C­s でセーブ
●   C­c C­k で REPL 環境にコンパイルしてロード
スクリプトっぽく実行する
ぱいそん
def hello(name):
    print("Hello %s" % name)

def main():
    hello("World")

if __name__ == "__main__":
    main()

りすぷ
(defun hello (name)
    (format t "Hello ~a~%" name))

(defun main()
    (hello "World"))

(eval­when (:compile­toplevel :load­toplevel :execute)
    (main)
    (quit))
eval­when は結構使い方が難しい。コンパイル、ロード、実行のタイミングとかは
Lisp 処理系の動きをイメージしないといけない部分があるからね。
コマンドラインから起動する

●   実は処理系依存なのよ
     ●   SBCL の場合は下のようにする



$ sbcl ­­script hello.lisp
Hello World
$
お待たせしました
プログラム作成のお時間です
すごく教科書的でアレなんですが
     「単語数え」
 プログラムを書いてみませう
慣れ親しんだ Python だと
                  あー、簡単のために単語は空白文字で区切られてるものとしてます。
def main()
    counter = dict()
    for line in open(sys.argv[1], "r"):
        for word in line.strip().split():
            index_word = word.lower()
            if index_word in counter:
                counter[index_word] += 1
            else:
                counter[index_word] = 1

   for (word, num) in counter.items():
       print("%20s : %4d" % (word, num))

if __name__ == "__main__":
    main()




                   まぁ、瞬殺なわけです
             これを Common Lisp で書くとどうなるか
単語数えプログラムを書くために

●   ファイル入出力
     ●   ファイルのオープン
     ●   パスの操作

●   文字列操作
     ●   スペースとかのデリミタでのフィールド分解

●   数え上げ
     ●   Python で言う所の辞書の使い方

●   その他
     ●   コマンドライン引数の扱いとか
とりあえず辞書から攻め込む
  先週の復習からはじめよう
ぱいそん
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)
まぁそのままでもイイんだが
もちっと親しみやすくしたいよね!
辞書っぽくアクセスするようにしてみる
(define­condition key­error (error) 
    ((text :initarg :text :reader text)))

(defun make­dict ()
    (make­hash­table :test #'equal))

(defun set­item (dict key value)
  (setf (gethash key dict) value))

(defun get­item (dict key)
  (multiple­value­bind (value has­key) (gethash key dict)
    (if (not has­key)
        (error 'key­error :text (format nil "KeyError : ~a" key))
        value)))

(defun has­key (dict key)
  (multiple­value­bind (value has­key) (gethash key dict)
    (declare (ignore value))
    has­key))

(defun items (dict)
  (let ((result nil))
    (maphash #'(lambda (key value)
                 (setf result (cons (cons key value) result))) dict)
    result))
なんか、色々と新しいの出た!
細かい部分とか技とかは後日のお楽しみとして
  ポイントになる部分をザックリと解説
define-condition

●   Python で言う所の例外に近い
      ●   厳密には違うけどイメージとしてはこんなかんじ

class KeyError(Exception):
    def __init__(self, text):
        Exception.__init__(self, text)

                    KeyError は組み込みの例外だが、これはあくまで例だ。気にするな。




●   Common Lisp では「コンディション」と言う
      ●   「例外」と呼ばない点に注意
      ●   例外的な事象への対応以外にも色々と使える
      ●   Python の try 〜 except よりもずっと強力
eq, eql, equal, equalp

●       オブジェクトの比較関数だよ
         ●   オブジェクトの同一性と、値としての同値ってのは別腹
         ●   Python の is と == 演算子の違いに似てる

    –   eq     : メモリ上で同一オブジェクトかどうかをチェック

    –   eql    : 数値 or 文字の場合は同値か?それ以外は eq する

    –   equal : 値の構造が同一か?内部構造も再帰的にチェック

    –   equalp :equal よりも緩い判定。詳細は CLtL2 参照
ハッシュテーブルの生成部分

●   キーの比較関数を指定して生成してる
    (make­hash­table :test #'equal)

       ●   #'equal という表記は (function equal) の略記法
       ●   略記法があるってことは、今後もいっぱいでてくる予感
       ●   ちなみに比較関数指定を省略したときは #'eql がデフォルト

●   equal を指定している訳
       ●   今回は文字列をハッシュのキーにする
       ●   文字列は (eql "Hello" "Hello") → nil なのだ

       ●   ちなみに純粋な文字列比較関数の string= を使ってもいい
            –   その場合、この hash-table のキーはマジで文字列限定になる。
setf ってなんだ?

●   これは違和感ないはず
(setf x 10)


●   で、これは?
(setf (gethash key dict) value)


●   そもそも gethash 関数って
(gethash "Hello" dict) → "World"

     ●   みたいに値を取り出す関数なんじゃねーの?
     ●   つーことは、 "Hello" とか、出てきた値になんか代入すんの?
setf には値を入れる場所を指定する

●   ぶっちゃけ、ポインタです
       ●    setf は関数じゃないんです。マクロなんです。つーことは引数は
             評価される前の状態で setf に渡されてるということ
       ●    第一引数は「値を入れる場所」として解釈される

    dict
    Hello             (gethash "Hello" dict)
    foo
                      setf マクロと組み合わせてポインタ
    bar               として振る舞う関数には制限がある
                      詳しくは「 CLtL2 C7.2: 汎変数」を
                      参照のこと
多値関数

●   複数の値を返す関数
      ●   Python でタプル返すのとはちょっと違う。
def foo(x):
    return ((True if x % 2 else False), x + 1)

(is_odd, next) = foo(3) # OK
is_odd = foo(3)         # is_odd は単純にタプルを指すだけ



(defun foo(x)
    (values 
        (if (= (mod x 2) 1) t nil)
        (+ x 1)))

(multiple­value­bind (is_odd next_x) (foo 3)  ; 多値を受け取るための形式
    (cons is_odd next_x))

(setf is_odd (foo 3))                         ; 最初の値だけが採用される
gethash 関数の戻り値

●   2 値の多値関数
       ●   第一値: Key に対応する Value, Key が存在しない場合は nil
       ●   第二値: Key が存在した場合は t, 存在しない場合は nil
(defvar dict (make­hash­table :test #'equal))
(setf (gethash "foo" dict) nil)

       ●   上のとき、 (gethash "foo" dict) → nil
             foo というキーが登録されていないから nil なのか?
             foo というキーに対応している値が nil なのか?

            –
(defun has­key (dict key)
  (multiple­value­bind (value has­key) (gethash key dict)
    (declare (ignore value))
    has­key))

       ●   多値関数の戻り値を受け取っても使わない場合は「変数使ってない
            が大丈夫か?」とコンパイラが五月蝿いので declare を使って
            「大丈夫だ。問題ない。」と伝えておくと吉。
if フォーム

●   分岐の基本なんだがイマイチな部分もある
(if ( 条件テスト式 ) (then 節 ) (else 節 ))

      ●   then 節と else 節はブロックじゃない。 1 個の式しか書けない !
           –   しょうがないので progn とか let とか使ってブロック化する。

      ●   Python で言う所の elif が無い!
           –   ネストして頑張る。
           –   cond マクロを使う。
           –   case マクロを使う。

      ●   Python と違って if は " 文 " じゃない!
           –   値を返せるよ!戻り値は then 節とか else 節の式の評価値になる
let とローカル変数

●   正確には「レキシカル変数」と言う
      ●   呼称はまあいい。要するに let の範囲内のローカル変数だ
CL­USER> (let ((x 10) (y 20))
           (print x)
           (print y)
           (let ((x "Hello"))
             (print x)
             (print y)))

      ●   実行結果は予想のとおり。
      ●   let と関数定義を組み合わせたりと色々な技がある
      ●   let 以外にもレキシカル変数を取り扱うフォームは色々ある
lambda 式

●   関数の実体・無名関数
     ●   関数を使い捨てしたいときとかに良く使う
     ●   let と組み合わせてクロージャとか作ったりもする
(setf (symbol­function 'foo) #'(lambda (x) (+ x 1)))
                         ||
(defun foo(x) (+ x 1))


foo
value
func                (function (lambda (x) (+ x 1)))
prop             Common Lisp のシンボルは値用と関数用の 2 つのスロットを持っ
                 ているのだ!こういうタイプの Lisp を Lisp-2 という。ちなみに
                 Scheme は値と関数のスロットは分かれていない Lisp-1 。
                 Python も Lisp-1 風。
文字列いってみよう!
文字列って実用では重要
でも何故か多くの Lisp 本とかでの解説は少なめ
Lisp の文字列

●   実体は文字型の 1 次元配列
     ●   Common Lisp は文字型が存在する。文字型はエンコードとは独立
          するように設計されている。が、まぁモゴモゴ…
          –   C の char とは違う。 Java の char に似た立ち位置と思えばいい。

          –   文字をリテラルとして書く場合は #A とか #Newline とか書く。

          –   Python には文字型は無い。 1 文字の文字列として扱うか、エンコードされた整数コード
                として扱っている


     ●   リテラルで書く場合は "Hello World" のようにダブルクォート
          で囲んで書く。 'Hello' のようにシングルクオートはダメ

     ●   Common Lisp の文字列は mutable に振る舞う。取扱い注意。
文字列が mutable なので

●   こんなことができちゃいます
(defvar s1 "Hello World")
(defvar s2 s1)
(eq s1 s2)
(setf (char s 5) #­)
s1
s2
(eq s1 s2)


     ●   REPL 環境で実験してみて!
     ●   シンボル s1 と s2 は「同一の」文字列を参照している
     ●   setf はやっぱりポインタ操作でしょ?
     ●   メモリ上の文字列を直接書換えてるイメージなわけですよ。
文字列の操作

●   文字の配列なので配列の操作関数が使える
      ●   さらに配列はシーケンスの一種なのでシーケンス操作関数が使える
      ●   なので、文字列特有の解説が少ないのかも
      ●   文字列用に特別に準備された関数もいくつかある
ぱいそん
s = "Hello World"
s[3]
s[3:5]
s = s.strip()
s = s.lower()

りすぷ
(defvar s "Hello World")
(char s 3)
(subseq s 3 5)
(setf s (string­trim '(#Space #Tab #Newline) s))
(setf s (string­downcase s))
split を作る
(defmacro while (test­exp &body body)
  `(do () ((not ,test­exp)) ,@body))

(defun string­split (target­str &key (separators '(#Space #Tab)))
  (let ((result nil)
        (startpos 0)
        (curpos 0)
        (endpos (length target­str)))

    (while (< curpos endpos)
      (if (member (char target­str curpos) separators)
          (progn
            (setf result (cons (subseq target­str startpos curpos) result))
            (setf startpos (+ curpos 1))))

      (setf curpos (+ curpos 1)))

    (setf result (cons (subseq target­str startpos endpos) result))
    (nreverse result)))

                                         loop マクロ使って格好良くもできるけど分かり易さ重視のベタ実装。
使い方                                      にしても、ちょっと不格好過ぎ。コンパイル結果は以外といい。


CL­USER> (string­split "Hello World foo bar  波浪ワールド ")
("Hello" "World" "foo" "bar" " 波浪ワールド ")
関数のキーワード引数

●   Python と同じようにキーワード引数が使えるよ
      ●   関数の引数部分に &key というマークに続けて書く
      ●   デフォルト値を与える&与えないの選択可

ぱいそん
def foo(x, y, z=100):
    return x + y + z

foo(10, 20)
foo(10, 20, z=50)

りすぷ
(defun foo (x y &key (z 100))
    (+ x y z))

(foo 10 20)
(foo 10 20 :z 50)
cons 関数                     リストは cons セルで構成されている。
 (X Y)            (X . Y)
                            セルの左側を car
                            セルの右側を cdr

                            と呼ぶ。長大な薀蓄を聞きたいのでなけれ
                            ば、なんで left, right とかじゃないのかと
  X       Y        X    Y   いう質問はしないこと。



(cons 1 '(a b))
                       cons 関数は新しい cons セルを用意して、第一引
                       数を car 部に第二引数を cdr 部にセットする。

                       これを繰り返せば、どんな複雑なリストの構造も作
                       成できる。

  1                    まぁ実際は cons だけでは面倒くさいので色々と便
                       利関数は用意されている

                       リストのあれこれ tips については後日っす。
      a       b
cons をもう少し
L1                        L2


        X       Y                1       2


     (cons l1 (cons l2 nil)) → ((x y) (1 2))




        X       Y        1       2
setf をリストに使うときの注意

●   リストに対して setf してみると…
CL­USER> (defvar lst '(a b c))
CL­USER> (setf (cdr lst) '(1 2))
CL­USER> lst

      ●   上の結果はどうなるか?

lst


              A            B       C



                                       1   2
setf をリストに使う時の注意

 ●    新しいセル作らずに無理やりポインタ書換え!
 CL­USER> (defvar lst '(a b c))
 CL­USER> (setf (cdr lst) '(1 2))
 CL­USER> lst



lst
                      (cdr lst) の位置
                      を強制的に書換えた!
             A                         B        C


                                      これらのオブジェクトはもう参照
                                      できない!いずれ GC の餌食にな
                                      る
                  1            2
次はファイルの読み込み
結構簡単よ!
ぱいそん
with open("/tmp/foobar.txt", "r") as input_file:
   for line in input_file:
       print line

りすぷ
(with­open­file (input­file "/tmp/foobar.txt" :direction :input)
    (loop for line = (read­line input­file)
        while line
        do (princ (format nil "~a~%" line)) ))

       ●   loop マクロは相変わらず魔法だけど何となく分かるでしょ?
       ●   format 関数は超便利。後日まとめて機能を紹介するですよ
コマンドライン引数の取得

●   *posix­argv* というグローバル変数に入ってる
(defun main()
  (dolist (arg *posix­argv*)
    (princ (format nil "~a~%" arg))))

(eval­when (:compile­toplevel :load­toplevel :execute)
  (main)
  (quit))

$ sbcl ­­script argtest.lisp foo bar baz



       ●   dolist フォームの使い方。上の例で十分に分かるかと。
課題演習
「単語数え」プログラム
  もう作れるよね?

More Related Content

What's hot

中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexprGenya Murakami
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarrayRyosuke839
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~CHY72
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)parrotstudio
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScriptbleis tift
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかYuki Miyatake
 
Scalaのオブジェクトの話
Scalaのオブジェクトの話Scalaのオブジェクトの話
Scalaのオブジェクトの話Yasuyuki Maeda
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~Nobuhisa Koizumi
 
Python勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージPython勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージ理 小林
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールNobuhisa Koizumi
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
Haskell勉強会 in ie
Haskell勉強会 in ieHaskell勉強会 in ie
Haskell勉強会 in iemaeken2010
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会Akihiko Matuura
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 

What's hot (20)

中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScript
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
 
Scalaのオブジェクトの話
Scalaのオブジェクトの話Scalaのオブジェクトの話
Scalaのオブジェクトの話
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
 
Python勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージPython勉強会4-制御構文とパッケージ
Python勉強会4-制御構文とパッケージ
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツール
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
Haskell勉強会 in ie
Haskell勉強会 in ieHaskell勉強会 in ie
Haskell勉強会 in ie
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
Power of Scala
Power of ScalaPower of Scala
Power of Scala
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 

Viewers also liked

小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話Ransui Iso
 
Playing with curses
Playing with cursesPlaying with curses
Playing with cursesRansui Iso
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Ransui Iso
 
XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由Ransui Iso
 
Pythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターPythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターRansui Iso
 
ソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングRansui Iso
 
PyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングPyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングRansui Iso
 
My client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoMy client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoToru Furukawa
 

Viewers also liked (8)

小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話
 
Playing with curses
Playing with cursesPlaying with curses
Playing with curses
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
 
XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由
 
Pythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターPythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクター
 
ソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミング
 
PyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングPyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミング
 
My client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoMy client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with Go
 

Similar to Lisp tutorial for Pythonista : Day 2

モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座bleis tift
 
関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』Kenta USAMI
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへNaoki Kitora
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミングOuka Yuka
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)啓 小笠原
 
X hago2 shortcoding 20110827
X hago2 shortcoding 20110827X hago2 shortcoding 20110827
X hago2 shortcoding 20110827uskey512
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式digitalghost
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Ra Zon
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)Masahiro Hayashi
 
Lispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 HyのすすめLispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 HyのすすめSatoshi imai
 
初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)Masahiro Hayashi
 
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章Tomonobu_Hirano
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語RShuyo Nakatani
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案yushin_hirano
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜Hiromi Ishii
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Ra Zon
 

Similar to Lisp tutorial for Pythonista : Day 2 (20)

モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
X hago2 shortcoding 20110827
X hago2 shortcoding 20110827X hago2 shortcoding 20110827
X hago2 shortcoding 20110827
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)
 
Lispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 HyのすすめLispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
Lispmeetup #53 PythonベースのLisp方言、 Hyのすすめ
 
初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)初心者講習会資料(Osaka.r#6)
初心者講習会資料(Osaka.r#6)
 
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語R
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案
 
Lispでやる記号微分
Lispでやる記号微分Lispでやる記号微分
Lispでやる記号微分
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 

More from Ransui Iso

「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~Ransui Iso
 
アドテクを支える人と技術
アドテクを支える人と技術アドテクを支える人と技術
アドテクを支える人と技術Ransui Iso
 
Introduction of ToySynth
Introduction of ToySynthIntroduction of ToySynth
Introduction of ToySynthRansui Iso
 
PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.Ransui Iso
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Ransui Iso
 
Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Ransui Iso
 

More from Ransui Iso (7)

「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~
 
アドテクを支える人と技術
アドテクを支える人と技術アドテクを支える人と技術
アドテクを支える人と技術
 
Introduction of ToySynth
Introduction of ToySynthIntroduction of ToySynth
Introduction of ToySynth
 
PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5
 
Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4
 

Recently uploaded

IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 

Recently uploaded (9)

IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 

Lisp tutorial for Pythonista : Day 2

  • 1. Lisp tutorial for Pythonista. Day #2 : The Basics. Ransui Iso Strategic Technology Group, X-Listing Co, Ltd.
  • 3. 前回の宿題は OK ですか? いちおう Emacs + SLIME が動く前提です
  • 4. なにはともあれまずは REPL Read, Eval, Print Loop の略語 Python なら「インタラクティブシェル」
  • 5. Emacs 起動して M-x slime META キーの設定無い人は [ESC] 押して [x]
  • 9. 変数は宣言してから使うのが基本 ルーズな Python とは大違いだよ! 管理大好きスーツ族への強力なアピールポイントだ! 警告ガン無視でも、まあ問題は無いんだが気持ち悪いので宣言しとけ。
  • 11. Common Lisp の名前空間 ● 大域は package という単位が基本になっている ● 概念的には Python のモジュールに近い ● Python のモジュールより厳密に定義するのでお手軽じゃない ● 何も指定しない時は CL­USER がデフォルト ● cl パッケージに Common Lisp の基本機能が入っている ● イメージとしては cl­user.py の最初で from cl import * してある感覚。 ● もちろんローカル変数とかもちゃんとあるよ ● 関数引数とか、 let フォームとか色々ある ● レキシカルスコープなので、基本部分は Python 感覚で OK 。
  • 12. パッケージ変数の宣言 ● defvar と defparameter ● どちらもパッケージ変数を宣言する ● 宣言するときには初期値を与える ● defvar ● 再初期化されない ● defparameter ● 再初期化される パッケージ変数という用語は一般的じゃない。 Python 風な名前で呼んで みてるだけ。ほんとは「スペシャル変数」と言う。実は深い意味もあるん だけど、今は無視しちゃう。
  • 13. 再初期化される?されない? ● 実験してみりゃ一目瞭然 CL­USER> (defvar *foo* nil) *FOO* CL­USER> (defparameter *bar* nil) *BAR* CL­USER> (setf *foo* 1) 1 CL­USER> (setf *bar* 2) 2 CL­USER> (defvar *foo* nil) *FOO* CL­USER> *foo* 1 CL­USER> (defparameter *bar* nil) *BAR* CL­USER> *bar* NIL パッケージが再読み込みされた時とかに挙動が変わるよ!
  • 14. CL のパッケージは取扱いが面倒 なので、今のところは CL-USER 一辺倒でいく ライブラリとか作るようになったら defpackage とか使うよ
  • 15. ソースをファイルに書いて実行する ● C­x 5 2 で新フレームを開いて ● 新しいフレームで C­x C­f hello.lisp とかし て新規バッファを開く ● コード書く (defun hello (name)   (format t "Hello ~a~%" name)) (hello "World") ● C­x C­s でセーブ ● C­c C­k で REPL 環境にコンパイルしてロード
  • 16. スクリプトっぽく実行する ぱいそん def hello(name): print("Hello %s" % name) def main(): hello("World") if __name__ == "__main__": main() りすぷ (defun hello (name) (format t "Hello ~a~%" name)) (defun main() (hello "World")) (eval­when (:compile­toplevel :load­toplevel :execute) (main) (quit)) eval­when は結構使い方が難しい。コンパイル、ロード、実行のタイミングとかは Lisp 処理系の動きをイメージしないといけない部分があるからね。
  • 17. コマンドラインから起動する ● 実は処理系依存なのよ ● SBCL の場合は下のようにする $ sbcl ­­script hello.lisp Hello World $
  • 19. すごく教科書的でアレなんですが 「単語数え」 プログラムを書いてみませう
  • 20. 慣れ親しんだ Python だと あー、簡単のために単語は空白文字で区切られてるものとしてます。 def main() counter = dict() for line in open(sys.argv[1], "r"): for word in line.strip().split(): index_word = word.lower() if index_word in counter: counter[index_word] += 1 else: counter[index_word] = 1 for (word, num) in counter.items(): print("%20s : %4d" % (word, num)) if __name__ == "__main__": main() まぁ、瞬殺なわけです これを Common Lisp で書くとどうなるか
  • 21. 単語数えプログラムを書くために ● ファイル入出力 ● ファイルのオープン ● パスの操作 ● 文字列操作 ● スペースとかのデリミタでのフィールド分解 ● 数え上げ ● Python で言う所の辞書の使い方 ● その他 ● コマンドライン引数の扱いとか
  • 23. ぱいそん 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)
  • 25. 辞書っぽくアクセスするようにしてみる (define­condition key­error (error)  ((text :initarg :text :reader text))) (defun make­dict ()     (make­hash­table :test #'equal)) (defun set­item (dict key value)   (setf (gethash key dict) value)) (defun get­item (dict key)   (multiple­value­bind (value has­key) (gethash key dict)     (if (not has­key)         (error 'key­error :text (format nil "KeyError : ~a" key))         value))) (defun has­key (dict key)   (multiple­value­bind (value has­key) (gethash key dict)     (declare (ignore value))     has­key)) (defun items (dict)   (let ((result nil))     (maphash #'(lambda (key value)                  (setf result (cons (cons key value) result))) dict)     result))
  • 27. define-condition ● Python で言う所の例外に近い ● 厳密には違うけどイメージとしてはこんなかんじ class KeyError(Exception): def __init__(self, text): Exception.__init__(self, text) KeyError は組み込みの例外だが、これはあくまで例だ。気にするな。 ● Common Lisp では「コンディション」と言う ● 「例外」と呼ばない点に注意 ● 例外的な事象への対応以外にも色々と使える ● Python の try 〜 except よりもずっと強力
  • 28. eq, eql, equal, equalp ● オブジェクトの比較関数だよ ● オブジェクトの同一性と、値としての同値ってのは別腹 ● Python の is と == 演算子の違いに似てる – eq : メモリ上で同一オブジェクトかどうかをチェック – eql : 数値 or 文字の場合は同値か?それ以外は eq する – equal : 値の構造が同一か?内部構造も再帰的にチェック – equalp :equal よりも緩い判定。詳細は CLtL2 参照
  • 29. ハッシュテーブルの生成部分 ● キーの比較関数を指定して生成してる (make­hash­table :test #'equal) ● #'equal という表記は (function equal) の略記法 ● 略記法があるってことは、今後もいっぱいでてくる予感 ● ちなみに比較関数指定を省略したときは #'eql がデフォルト ● equal を指定している訳 ● 今回は文字列をハッシュのキーにする ● 文字列は (eql "Hello" "Hello") → nil なのだ ● ちなみに純粋な文字列比較関数の string= を使ってもいい – その場合、この hash-table のキーはマジで文字列限定になる。
  • 30. setf ってなんだ? ● これは違和感ないはず (setf x 10) ● で、これは? (setf (gethash key dict) value) ● そもそも gethash 関数って (gethash "Hello" dict) → "World" ● みたいに値を取り出す関数なんじゃねーの? ● つーことは、 "Hello" とか、出てきた値になんか代入すんの?
  • 31. setf には値を入れる場所を指定する ● ぶっちゃけ、ポインタです ● setf は関数じゃないんです。マクロなんです。つーことは引数は 評価される前の状態で setf に渡されてるということ ● 第一引数は「値を入れる場所」として解釈される dict Hello (gethash "Hello" dict) foo setf マクロと組み合わせてポインタ bar として振る舞う関数には制限がある 詳しくは「 CLtL2 C7.2: 汎変数」を 参照のこと
  • 32. 多値関数 ● 複数の値を返す関数 ● Python でタプル返すのとはちょっと違う。 def foo(x): return ((True if x % 2 else False), x + 1) (is_odd, next) = foo(3) # OK is_odd = foo(3)         # is_odd は単純にタプルを指すだけ (defun foo(x) (values  (if (= (mod x 2) 1) t nil) (+ x 1))) (multiple­value­bind (is_odd next_x) (foo 3)  ; 多値を受け取るための形式 (cons is_odd next_x)) (setf is_odd (foo 3))                         ; 最初の値だけが採用される
  • 33. gethash 関数の戻り値 ● 2 値の多値関数 ● 第一値: Key に対応する Value, Key が存在しない場合は nil ● 第二値: Key が存在した場合は t, 存在しない場合は nil (defvar dict (make­hash­table :test #'equal)) (setf (gethash "foo" dict) nil) ● 上のとき、 (gethash "foo" dict) → nil foo というキーが登録されていないから nil なのか? foo というキーに対応している値が nil なのか? – (defun has­key (dict key)   (multiple­value­bind (value has­key) (gethash key dict)     (declare (ignore value))     has­key)) ● 多値関数の戻り値を受け取っても使わない場合は「変数使ってない が大丈夫か?」とコンパイラが五月蝿いので declare を使って 「大丈夫だ。問題ない。」と伝えておくと吉。
  • 34. if フォーム ● 分岐の基本なんだがイマイチな部分もある (if ( 条件テスト式 ) (then 節 ) (else 節 )) ● then 節と else 節はブロックじゃない。 1 個の式しか書けない ! – しょうがないので progn とか let とか使ってブロック化する。 ● Python で言う所の elif が無い! – ネストして頑張る。 – cond マクロを使う。 – case マクロを使う。 ● Python と違って if は " 文 " じゃない! – 値を返せるよ!戻り値は then 節とか else 節の式の評価値になる
  • 35. let とローカル変数 ● 正確には「レキシカル変数」と言う ● 呼称はまあいい。要するに let の範囲内のローカル変数だ CL­USER> (let ((x 10) (y 20))            (print x)            (print y)            (let ((x "Hello"))              (print x)              (print y))) ● 実行結果は予想のとおり。 ● let と関数定義を組み合わせたりと色々な技がある ● let 以外にもレキシカル変数を取り扱うフォームは色々ある
  • 36. lambda 式 ● 関数の実体・無名関数 ● 関数を使い捨てしたいときとかに良く使う ● let と組み合わせてクロージャとか作ったりもする (setf (symbol­function 'foo) #'(lambda (x) (+ x 1))) || (defun foo(x) (+ x 1)) foo value func (function (lambda (x) (+ x 1))) prop Common Lisp のシンボルは値用と関数用の 2 つのスロットを持っ ているのだ!こういうタイプの Lisp を Lisp-2 という。ちなみに Scheme は値と関数のスロットは分かれていない Lisp-1 。 Python も Lisp-1 風。
  • 39. Lisp の文字列 ● 実体は文字型の 1 次元配列 ● Common Lisp は文字型が存在する。文字型はエンコードとは独立 するように設計されている。が、まぁモゴモゴ… – C の char とは違う。 Java の char に似た立ち位置と思えばいい。 – 文字をリテラルとして書く場合は #A とか #Newline とか書く。 – Python には文字型は無い。 1 文字の文字列として扱うか、エンコードされた整数コード として扱っている ● リテラルで書く場合は "Hello World" のようにダブルクォート で囲んで書く。 'Hello' のようにシングルクオートはダメ ● Common Lisp の文字列は mutable に振る舞う。取扱い注意。
  • 40. 文字列が mutable なので ● こんなことができちゃいます (defvar s1 "Hello World") (defvar s2 s1) (eq s1 s2) (setf (char s 5) #­) s1 s2 (eq s1 s2) ● REPL 環境で実験してみて! ● シンボル s1 と s2 は「同一の」文字列を参照している ● setf はやっぱりポインタ操作でしょ? ● メモリ上の文字列を直接書換えてるイメージなわけですよ。
  • 41. 文字列の操作 ● 文字の配列なので配列の操作関数が使える ● さらに配列はシーケンスの一種なのでシーケンス操作関数が使える ● なので、文字列特有の解説が少ないのかも ● 文字列用に特別に準備された関数もいくつかある ぱいそん s = "Hello World" s[3] s[3:5] s = s.strip() s = s.lower() りすぷ (defvar s "Hello World") (char s 3) (subseq s 3 5) (setf s (string­trim '(#Space #Tab #Newline) s)) (setf s (string­downcase s))
  • 42. split を作る (defmacro while (test­exp &body body)   `(do () ((not ,test­exp)) ,@body)) (defun string­split (target­str &key (separators '(#Space #Tab)))   (let ((result nil)         (startpos 0)         (curpos 0)         (endpos (length target­str)))     (while (< curpos endpos)       (if (member (char target­str curpos) separators)           (progn             (setf result (cons (subseq target­str startpos curpos) result))             (setf startpos (+ curpos 1))))       (setf curpos (+ curpos 1)))     (setf result (cons (subseq target­str startpos endpos) result))     (nreverse result))) loop マクロ使って格好良くもできるけど分かり易さ重視のベタ実装。 使い方 にしても、ちょっと不格好過ぎ。コンパイル結果は以外といい。 CL­USER> (string­split "Hello World foo bar  波浪ワールド ") ("Hello" "World" "foo" "bar" " 波浪ワールド ")
  • 43. 関数のキーワード引数 ● Python と同じようにキーワード引数が使えるよ ● 関数の引数部分に &key というマークに続けて書く ● デフォルト値を与える&与えないの選択可 ぱいそん def foo(x, y, z=100): return x + y + z foo(10, 20) foo(10, 20, z=50) りすぷ (defun foo (x y &key (z 100))     (+ x y z)) (foo 10 20) (foo 10 20 :z 50)
  • 44. cons 関数 リストは cons セルで構成されている。 (X Y) (X . Y) セルの左側を car セルの右側を cdr と呼ぶ。長大な薀蓄を聞きたいのでなけれ ば、なんで left, right とかじゃないのかと X Y X Y いう質問はしないこと。 (cons 1 '(a b)) cons 関数は新しい cons セルを用意して、第一引 数を car 部に第二引数を cdr 部にセットする。 これを繰り返せば、どんな複雑なリストの構造も作 成できる。 1 まぁ実際は cons だけでは面倒くさいので色々と便 利関数は用意されている リストのあれこれ tips については後日っす。 a b
  • 45. cons をもう少し L1 L2 X Y 1 2 (cons l1 (cons l2 nil)) → ((x y) (1 2)) X Y 1 2
  • 46. setf をリストに使うときの注意 ● リストに対して setf してみると… CL­USER> (defvar lst '(a b c)) CL­USER> (setf (cdr lst) '(1 2)) CL­USER> lst ● 上の結果はどうなるか? lst A B C 1 2
  • 47. setf をリストに使う時の注意 ● 新しいセル作らずに無理やりポインタ書換え! CL­USER> (defvar lst '(a b c)) CL­USER> (setf (cdr lst) '(1 2)) CL­USER> lst lst (cdr lst) の位置 を強制的に書換えた! A B C これらのオブジェクトはもう参照 できない!いずれ GC の餌食にな る 1 2
  • 49. 結構簡単よ! ぱいそん with open("/tmp/foobar.txt", "r") as input_file: for line in input_file: print line りすぷ (with­open­file (input­file "/tmp/foobar.txt" :direction :input) (loop for line = (read­line input­file) while line do (princ (format nil "~a~%" line)) )) ● loop マクロは相変わらず魔法だけど何となく分かるでしょ? ● format 関数は超便利。後日まとめて機能を紹介するですよ
  • 50. コマンドライン引数の取得 ● *posix­argv* というグローバル変数に入ってる (defun main()   (dolist (arg *posix­argv*)     (princ (format nil "~a~%" arg)))) (eval­when (:compile­toplevel :load­toplevel :execute)   (main)   (quit)) $ sbcl ­­script argtest.lisp foo bar baz ● dolist フォームの使い方。上の例で十分に分かるかと。