Lisp講義1

6,107
-1

Published on

use in the Lisp lesson of NPCA

1 Comment
25 Likes
Statistics
Notes
  • 9ページ,演算子に先行して,ではなく演算子への適用に先行して,の方が正しそう
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
6,107
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
54
Comments
1
Likes
25
Embeds 0
No embeds

No notes for slide

Lisp講義1

  1. 1. stibear (@stibear1996) LISP講義 PART Ⅰ
  2. 2. LISPの文法 いきなり…
  3. 3. と,その前に…
  4. 4. Scheme • Lispには,たくさんの方言があります • 今回の講義では,その中でも,Schemeを使います • 理由としては,シンプルで理解しやすいと思われるためです
  5. 5. • 3 • 3 • 6 • 2 • (+ 1 2) • (- 5 2) • (* 2 3) • (/ 8 4) LISPの文法 式(プログラム) 評価結果(実行後)
  6. 6. 簡単にはこんな感じ
  7. 7. 仕組み • 読み込み(READ) • 評価(EVAL) • 表示(PRINT) • これがループして行われる • REPL(Read-Eval-Print Loop)と呼ばれる
  8. 8. LISPの式 (+ 1 2) 演算子 引数
  9. 9. LISPの式 (+ 1 2) 演算子 引数 ※ 引数は演算子に先行して評価されます
  10. 10. 文法に関してはこれだけ
  11. 11. LISPの構文1 さて次は…
  12. 12. • x • y • 30 • ERROR!! • (define x 10) • (define y 20) • (+ x y) • (* x z) define 式(プログラム) 評価結果(実行後)
  13. 13. 仕組み • Lispの環境に記憶 • (define x 10)とすると,xは10と記憶される • 環境に記憶することを束縛という • xは10に束縛される,という
  14. 14. 図解 環境 x=10 y=20 … … … (define x 10) x (define y 20) y 束縛 (+ x y) 30 評価 参照
  15. 15. ならば…
  16. 16. (+ x 40)とすると?
  17. 17. 図解 (+ x 40) 50 評価 10 40
  18. 18. 整数はそのまま整数に評価されます
  19. 19. シンボル • xやyといったものは,シンボルと呼ばれます • シンボルはhoge,stibearなどなんでも良い • hideo54やsaiko-no-natsuもシンボルとして扱えます
  20. 20. define • よって,defineはシンボルと値を結びつけます • つまり,束縛するということです
  21. 21. アトムとリスト Lispといえば…
  22. 22. リストとアトム • ()で囲われた式をリストといいます • そうでないものをアトムといいます • (+ 1 2) • (define hoge fuga) • (foo bar baz) • これらはすべてリスト • a • 200 • これらはすべてアトム
  23. 23. LISPの構文2 try to eat...
  24. 24. いきなりですが
  25. 25. 40を評価すると40です
  26. 26. では
  27. 27. 何を評価すると シンボルxになるでしょう?
  28. 28. 答え:quoteを使います
  29. 29. • x • hoge • saiko-no-natsu • (quote foo) • (quote x) • (quote hoge) • (quote saiko-no-natsu) • (quote (quote foo)) quote 式(プログラム) 評価結果(実行後)
  30. 30. quote • quoteを使うと,評価を1回止めることができます • 便利のため,(quote 何々)と書く代わりに,‘何々と書けます
  31. 31. 評価のおさらい 環境 x=10 y=20 … … … (quote x) x x 10 評価 参照 評価
  32. 32. (define husband ‘wife)として
  33. 33. husbandを評価すると?
  34. 34. 答え:シンボルwifeが返ります
  35. 35. 特殊オペレータ すぺしゃる!
  36. 36. 特殊オペレータ • quoteやdefineはすべての引数が必ずしも評価されません • これらが特殊オペレータであるためです • ほかにも,ifなどが特殊オペレータです • 特殊オペレータが成す式を特殊フォームといいます
  37. 37. 関数 • 特殊オペレータに対して,+や-のような, 引数がすべて評価されるような演算子を関数といいます • (関数 引数0 引数1...)のような式を関数呼び出しといいます • 関数呼び出しを評価すると,関数の返り値が得られます
  38. 38. 同図像性 ホモイコニシティ
  39. 39. いきなりの難しいセクション!
  40. 40. しかし, これぞLispの神髄であります
  41. 41. 同図像性 • 簡単に言うと, • プログラムである式とデータである値が等価だということ
  42. 42. ところで
  43. 43. リスト • 括弧で囲われた式はリスト • コンスによって成ります
  44. 44. コンス • コンスはcar部とcdr部という2つの記憶域を持ちます • コンスは関数consによって作ることができます • (cons ‘a ‘b)→(a . b) • (a . b)はcar部にシンボルa,cdr部にシンボルbを持ちます
  45. 45. コンス car (cons 'a 'b) (a . b) cdr a b 評価
  46. 46. コンス • 関数carや関数cdrでそれぞれcar部,cdr部が得られます • (car (cons ‘a ‘b))→a • (cdr (cons ‘a ‘b))→b • コンスは値へのアドレスを持っているだけ • なのでどんな値も格納できます • コンスのcdr部がコンスなら,ドットは省略されます • (cons 'a (cons 'b 'c))→(a b . c)
  47. 47. コンス car (cons 'a (cons 'b 'c)) (a b . c) cdr a b 評価 c car cdr
  48. 48. コンス • コンスのcdr部が空リスト()だった場合,cdr部の表示は省略 • (cons ‘a (cons ’b ‘())→(a b)
  49. 49. コンス car (cons 'a (cons 'b '())) (a b) cdr a b 評価 car cdr
  50. 50. リスト(再定義) • 空リスト • もしくは,cdr部にリストを格納したコンス
  51. 51. リスト 空リスト 値 値 値
  52. 52. リスト(a b c)を作るには • (cons ‘a (cons ‘b (cons ‘c ‘()))) • ‘(a b c) • (list ‘a ‘b ‘c)
  53. 53. という訳で
  54. 54. データと式は一緒ですね
  55. 55. ちなみに
  56. 56. リストのcdr • (car ‘(a b c))→a • (cdr ‘(a b c))→(b c)
  57. 57. リストのcdr car cdr a b c car cdr car cdr このコンスのcdrを取る
  58. 58. リストのcdr b c car cdr car cdr
  59. 59. 関数 ふぁ,ふぁ,ふぁんくしょんっ
  60. 60. 関数を作ってみましょう
  61. 61. 関数 • 特殊オペレータlambdaを使って作ります • (lambda (n) (+ n 1)) • 上は引数を1つとって,それに1を足したものを返す関数です • 上の式で,nは仮引数で…とかいう話はCとかと一緒なので省略 • 呼び出す時は,リストの最初に置いて,その後に引数を続けます • (+ 10 20)→30 • 同様に • ((lambda (n) (+ n 1)) 10)→11
  62. 62. • #<procedure> • 11 • 21 • (lambda (n) (+ n 1)) • ((lambda (n) (+ n 1)) 10) • ((lambda (n) (+ n 1)) 20) lambda 式(プログラム) 評価結果(実行後)
  63. 63. 関数 • 関数も値 • よってdefineを使ってシンボルを束縛できる • (define plus1 (lambda (n) (+ n 1))) • これでplus1というシンボルを使って関数呼び出しができます • (plus1 29)→30
  64. 64. 関数 • (lambda (仮引数...) 式...) • 仮引数は束縛変数とも呼ばれ,その関数内でのみ参照できます • つまり,束縛変数のスコープはその関数内ということです • 対して,どこでも参照できる変数を大域変数といいます • 束縛変数の,大域変数に対応する呼び方として, • 局所変数という呼び方もあります • 関数は,環境を新たに作ることで,束縛変数を実現しています
  65. 65. 関数 環境 x=10 y=20 … … … ((lambda (x y) (+ x y)) 2 3) 束縛 新たな環境 x=2 y=3 参照
  66. 66. LISPの構文3 Let It Be
  67. 67. let • 局所変数を定義するために,let特殊オペレータを使います • (let ((a 2) (b 3)) (+ a b))→5 • 簡単ですね • let特殊オペレータは新たに環境を作ります
  68. 68. let 環境 x=10 y=20 … … … (let ((x 2) (y 3)) (+ x y)) 束縛 新たな環境 x=2 y=3 参照
  69. 69. lambdaの時とそっくりですね
  70. 70. let • letはlambdaの構文糖衣として考えることができます • つまり,letはlambdaと等価です • (let ((a 2) (b 3)) (+ a b)) • ((lambda (a b) (+ a b)) 2 3)
  71. 71. 構文糖衣 • syntax-sugerの訳語 • Wikipediaには,次のように書いてあります 糖衣構文(とういこうぶん)は、プログラミング言語において、読み 書きのしやすさのために導入される構文であり、既に定義されている 他の構文の(人間にとってより理解しやすい)書換えとして定義され るもののことである。構文糖(こうぶんとう)あるいは構文糖衣とも いう。
  72. 72. 構文糖衣 • quoteの構文糖衣として,「’」があります • また,関数と定義するときの構文糖衣として,次のように書けます • (define hoge (lambda (foo) (bar baz))) • (define (hoge foo) (bar baz)) • どちらも正しい関数定義です
  73. 73. スコープ ちょっと脱線
  74. 74. スコープ • 関数の説明の時にも出てきました • その変数が見えている(=参照可能な)範囲のことです • トップレベルでdefineすると,変数のスコープはグローバルに • 関数の仮引数やletで定義された変数のスコープは,ローカルに なります • また,Schemeは,レキシカルスコープと呼ばれる種類のスコープ を持ちます
  75. 75. レキシカルスコープ • 字句的,構文,静的スコープなどともいいます • これによってクロージャ(関数閉包)というものを成します
  76. 76. • x • test • 100 • 100 • (define x 100) • (define (test) x) • (test) • (let ((x 10)) (test)) レキシカルスコープ 式(プログラム) 評価結果(実行後)
  77. 77. クロージャ 骨を折ります
  78. 78. クロージャ • Schemeにおいて,クロージャは無名関数と同義であるといえます [要出典] • カプセル化や遅延評価などのためによく使います
  79. 79. • counter • c1 • 1 • 2 • 3 • (define (counter) (let ((c 0)) (lambda () (set! c (+ c 1)) c))) • (define c1 (counter)) • (c1) • (c1) • (c1) クロージャ 式(プログラム) 評価結果(実行後)
  80. 80. 副作用 副作用使用罪だ!!
  81. 81. 副作用 • set!は副作用をもたらす特殊オペレータです • その他,displayなども副作用をもたらします • 破壊的代入やI/O制御は副作用を伴います
  82. 82. 再帰 私に還りなさい
  83. 83. 再帰 • あるものについて記述する際に、記述しているものそれ自身への参 照が、その記述中にあらわれることをいう(Wikipediaより) • 再帰的に関数を呼び出すことを再帰呼び出しといいます • ある関数のなかでその関数が呼び出されているとき, それは再帰関数であるといえます
  84. 84. • fact • 120 • (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))) • (fact 5) 再帰関数 式(プログラム) 評価結果(実行後)
  85. 85. 末尾再帰 • 関数の末尾文脈での関数呼び出しは末尾呼び出しと呼ばれます • 再帰的な末尾呼び出しを末尾再帰といいます • Schemeでは,末尾呼び出しが最適化されます • ループ構造と等価なものに展開され,スタックを消費しないものに なります • 非常に簡単にいうと,無駄が少ないです
  86. 86. • (define (fact n) (fact-tc n 1)) • (define (fact-tc n m) (if (= n 0) m (fact-tc (- n 1) (* n m)))) • (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))) 末尾再帰 非末尾再帰版fact 末尾再帰版fact
  87. 87. 非末尾再帰版fact関数呼び出し (fact 5) (* 5 (fact 4)) (* 5 (* 4 (fact 3))) (* 5 (* 4 (* 3 (fact 2)))) (* 5 (* 4 (* 3 (* 2 (fact 1))))) (* 5 (* 4 (* 3 (* 2 (* 1 (fact 0)))))) (* 5 (* 4 (* 3 (* 2 (* 1 1)))))
  88. 88. 非末尾再帰版fact関数呼び出し (* 5 (* 4 (* 3 (* 2 (* 1 1))))) (* 5 (* 4 (* 3 (* 2 1)))) (* 5 (* 4 (* 3 2))) (* 5 (* 4 6)) (* 5 24) 120
  89. 89. 末尾再帰版fact関数呼び出し (fact 5) (fact-tc 5 1) (fact-tc 4 5) (fact-tc 3 20) (fact-tc 2 60) (fact-tc 1 120) (fact-tc 0 120) 120
  90. 90. LISPの構文4 Let It Be再び
  91. 91. named-let • 名前付きletというもので,ループを上手く書くことができます
  92. 92. named-letを使ったfact関数 • (define (fact n) (let rec ((a n) (b 1)) (if (= a 0) b (rec (- a 1) (* a b))))) • letrecを使って似たように定義ができます
  93. 93. 高階関数 今でもあなただけが 青春の...
  94. 94. 高階関数 • 関数を引数として取ったり,返り値として返したりする関数
  95. 95. map関数 • リストの各要素にマッピング • (map func list0 list1 ... listN)
  96. 96. sort関数 • リストの要素をソート • (sort lst func)
  97. 97. fold関数 • 畳み込み
  98. 98. 演習 このセクションを書こうとした人は途中で寝てしまいました。
  99. 99. 適当に演習
  100. 100. 参考 • 今回このスライドを作るにあたって, http://lyrical.bugyo.tk/ (魔法言語 リリカル☆Lisp) を参考にしました • 非常に良い教材です
  101. 101.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×