Clisp Program
Clisp program の ルールですが、たいていが セルからの説明があり
意味が分からなくなりなかなか先に進まない。
ここではとにかくプログラムを書けるように
を目的に、記す。
car 先頭の要素抽出
(car '( a 1 b 2 34 yu ))
=>
a
(car '( ( a b c ) 23 ff GO end if 23.234 ))
=>
( a b c)
cdr 先頭の要素除去
(cdr '( a 1 b 2 34 yu ))
=>
(1 b 2 34 yu)
(cdr '( ( a b c ) 23 ff GO end if 23.234 ))
=>
(23 ff GO end if 23.234)
ドット対 car と cdrの明確化
car , cdr で区切れる場所に ドット . を入れる。
ドットの両サイドには半角スペースを入れる。入れないと小数点になる。
(ca . ke) ;;; => OK car::ke cdr::ke
(ca . ke . co ) ;;;=>NG 3要素ある
(ca . ke .co) ;;;=> 3要素 .co の小数点化にならずNG
(ca . ( ke co ) ;;; =>OK ca と ( ke co ) の2要素
ドットは、日本語文法て゜「と」の意味だと思えば理解できる。
例えば、君と僕なら (君 . 僕)
君と僕の家族達なら => (君 . (僕の家族達))
僕の家族達は、妻と子供達なら=>(君 . (妻 . 子供達))
子供達は、チルとデルなので =>(君 . (妻 . (チル . デル)))
と書けそうなもんだが、これはなかなか問題が発生する。後で解説しますがとにかく対になっているということです。
細胞
細胞とは2つのカプセルで構成されていて一般的には要素と方向指示器がそれぞれのカプセルに入っている。
方向指示器で参照する要素がなければnilを入れる。
いまカプセルの区切り線を|を使い表すとすれば ( a )とは、単独なので [a|/]としよう。/:nil
( a b ) => [a|-]->[b|/]
( a . b ) => [a|b]
全く意味が違う。 ドット対で表すともうそこには方向指示器を入れるスペースがないのでただのペアデータとして扱う。
(cdr '( a b )) ;;cdr [a|-]->[b|/] => [b|/] => (b)
(cdr '( a . b)) ;;cdr [a|b] => b
cdr ( a b ) では[b|/]がとりだされ/:nilがついていてカプセルを形作ってしまう。つまり bをカプセルで包んでしまうから( b ) となる。それじゃ bだけ取り出すにはと、考えると[b|/]から先頭を取り出せばよいから carを使い
(car (cdr '( a b ))) => b
となるのだ。
まとめ
( cdr '( a b )) => ( b )
(car (cdr '( a b ))) => b
( cdr '( a . b)) => b
参照
要素のグループをいちいち列挙するのは大変だから
参照させよう、例えば
( 君 ( 妻 ( チル デル )))をlis1という wordで参照させるには、
(setq lis1 '( 君 ( 妻 ( チル デル ))))
と入力すればよい。
これは先ほどの細胞表現でいうと
[lis1|-]->([君|-]->([妻|-]->([チル|-]->[デル|/])))
=================命題1 lis1から 妻を救え===========
lis1 ->(君 (妻 (チル デル)))
(car lis1)
=>
君
先頭が飛び足した
(cdr lis1)
=>
((妻 (チル デル)))
あれ? (妻 (チル デル)) じゃないぞ
()が多い つまり 全体の箱が残ってる
ここでわかるのは、car では [君|-]->の部分から君という要素だけをとりだしたということ。
cdrは、lis1の全体から先頭要素を除去したもの、つまり後半の取り出しではなく、先頭をはぎ取られた残骸なのであり、方向指示器が残っていて
->(([妻|-]->([チル|-]->[デル|/])))
となると理解できる。
=============== いつ妻を救出できるのだ====
(car (cdr lis1))
(妻 (チル デル))
箱から家族達がでてきた。
ここから先頭要素の妻を抽出するのだから car を使え
(car(car(cdr lis1)))
妻
予想どおり妻がでてきた。
~~~~~~~~~~~~ ひとやすみ ~~~~~~~~~~~~~~~~~
たぶんここまで読んだ読者は、もう lispなんてやってられねーと思うだろう。これが人工知能? 低能じゃねーの?ってね、じつにまどろこっしいんだが、コンピュータという機械からみれば実に単純明快なのだろう。また、このげんごの面白いのは、要素を1か所のメモリで占有したら同じ要素は基本的に作らないということだ、方向指示器k向きを変えるだけでいいのだ。
古典言語だけあるし、Fortranは今は僕はしなくなっちゃったのに、なぜかこのLispにはまって20年から30年くらい前の書籍買い集めてしまったが。なかなか上達はできない。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
=============命題2 lis1から チルを救え===========
(cdr(car(cdr lis1)))
((チル デル))
また子供達という箱がある
(car (cdr(car(cdr lis1))))
(チル デル)
(car (car (cdr(car(cdr lis1)))))
チル
やっとチルがでたよ。
デルは
(cdr (car (cdr(car(cdr lis1)))))
(デル)
あれ?まだ箱の中だな
もういっちょcarか
(car (cdr (car (cdr(car(cdr lis1))))))
デル
やっと救えた。
複素数の計算をしてみよう
;;;;; 複素数の加算
;;;; 僕は電気やなので 2d(二次元) では i は使わない jを使うよ
(+
#C(3 4);;; 3 + j4
#C(2 5);;; 2 + j5
)
#C(5 9);;; 5 + j9
( 3 + j4 ) + ( 2 + j5) => 5 + j9となる
== 複素数の絶対値を求めてみる ==
;;;;; 複素数の絶対値の計算
;;;; 僕は電気やなので 2d では i は使わない jを使うよ
(abs #C(3 4))
5.0
;;; 3 + j 4 => sqrt(3^2 +4^2)=5.0 と出た。