みねこあ

mineko. A! ―from mi-neko online.

2010-02-03

[]Logo基礎文法最速マスター :接触編 22:10 Logo基礎文法最速マスター :接触編を含むブックマーク

流行のアレをLogoで。Smalltalk はなんだか他の方とかぶりそうだったので、斜め上を狙ってみました。

接触編 と 発動編の 二部構成でお送りします。接触編は、変態編もとい、概念編です。他のLisp言語をある程度知っている人はこれを読めば Logo の基礎をマスターして Logo 処理系を書くことができるようになります。・・たぶん。

Logo はカッコのない Lisp

まず前提知識として、Logo は Lisp です。プログラムは「語(word、Lispのアトム)」と「リスト(list)」から成ります。

Logo と Lisp の最大の違いは、カッコが無いことです。例えば 以下の S式

(F 'x (G 'y 'z))

は Logo では、

F "x G "y "z

と表現します。(Logo のクォートは 「"」 です)

Lisp風 S式からカッコを取り除くルールは、

  1. クォートされていないのは全て関数だ!(つまり直前でカッコが開いている)
  2. その関数が何個引数を取るのかあらかじめ別っていれば、閉じカッコの位置は判断できる

です。このルールですと可変長引数の関数が問題になりそうですが、その点については後述します。


語の評価

Lisp だとクォートしていなければ即評価でしたが、Logoでは 語の評価に thing 手続きを明示的に記載します。

例えば以下の S式

(F x (G y z))

は、

F thing "x G thing "y thing "z

になります。ただ、これではさすがにthing, thing! と鬱陶しいので(モンキーパイソンの SPAM のコントのようです)、

F :x G :y :z

のように 「thing "x」を「:x」と書くことも出来ます(これを「ドット表現」といいます)。

暗黙のクォート

語が 数値語の場合は例外として、暗黙的にクォートされます。つまり、

sum "1 "2

sum 1 2

は、同じ意味になります。


リスト

Logo も Lisp の一種なので、リスト(list) を持ちます。というか、Logo の オブジェクトは 語 または リスト のどちらかです。

丸括弧「()」ではなく角括弧「[]」を使うという些細な違いがありますが、ほぼ同じモノです。例えば、

('x 'y 'z)

は、Logo では

["x "y "z]

になります。

リストの評価は run 手続きで明示的に行います(thing の リスト版です)。

(sum 1 (sum 2 3)

は、

sum "1 run [sum "2 "3]

になります。

リスト操作について。Lisp の car と cdr は、それぞれ first と butfirst に、cons は fput、list は list のまま。append は sentence になります。

>>first [1 2 3]
1

>>butfirst [1 2 3]
[2 3]

>>fput [1 2] [3 4]
[[1 2] 3 4]

>>list [1 2] [3 4]
[[1 2] [3 4]]

>>sentence [1 2] [3 4]
[1 2 3 4]

*1

ちょっと話題とずれるけれど、ついでに、語の合成は wordです。

>>word "mine "koa
"minekoa

なお、list 等は二項オペレーションですが、グルーピングカッコ(後述)で可変長になります。

>>word "mine "ko "a
"mineko

>>(word "mine "ko "a)
"minekoa

中置オペレーション(中置演算子)とグルーピングカッコ

Logo のもっとも Lisp らしからぬところが 中値二項オペレーション を持つところです。極々普通のプログラミング言語のように

>>1 + 2 * 3
7

とか書けます(そして期待通りに動きます)。中置オペレーションには、数値演算と論理演算があります。具体的には 「+」、「-」、「/」、「*」、「=」、「<」、「>」です。*2

演算子の優先順位を変えたいときには、

>>(1 + 2) * 3
9

と、丸括弧を使ってグルーピングできます。また、このグルーピングカッコは、前述したとおり、可変長引数のグルーピングにも使います。

>>(sum 1 2 3 4)
10

手続きの定義

最後に、Logo の Lispっぽいところと、らしくないところを比べて接触編をお終いにします。

Logo では いわゆるプロシージャのことを「コマンド(command)」(戻り値が無い)、ファンクションのことを「オペレーション(operation)」(戻り値がある)と言います。これらを総称して「手続き」と言います。

手続きの定義は、define手続き

define "関数名 [ [仮引数リスト] 本体]

で行います。以下に例を示します。

define "opeFoo [[arg1 arg2]
                [make "hoge sum thing "arg1  256]
                [output prduct thing "hoge arg2]]

とっても Lisp風 ですね。

ただし Logoでは 実は、あまりこんな風には書きません。Logo には もっとカジュアルな表現 to〜end があり、普通はこちらを使います。これを使うと同様のモノを以下のように書けます

to opeFoo :arg1 :arg2
  make "hoge :arg1 + 256
  output :hoge * :arg2
end

というわけで、Logo とは Lisp をベースに、文法の見た目を Lispっぽく無くしたもの、と理解すれば、飲み屋さんでの蘊蓄に困りません。

まとめ

Logo の文法は、

LOGOプログラム : { コマンド }*
コマンド : 手続き名 + { 入力 }*
入力 : "語 | リスト | オペレーション
オペレーション : 手続き名 + { 入力 }*
語 : { 英数字 | 特殊記号 }*
リスト : { { 語 | リスト }* }

これを基本に、ドット表現、数値語の暗黙クォート、中置オペレーション、to〜end を加えたモノ。

本エントリーの記述は 川野 洋 さんの 「LOGO言語入門」を参考にしました。

LOGO入門 (電子計算機のプログラミング)

LOGO入門 (電子計算機のプログラミング)

*1:オペレーションをトップレベルで実行すると、ホントは怒られます。ここでは、まぁ「細かいことはいいんだよ」、ということで (^^;

*2:これに「\」(剰余)が加わる処理系もあります

バッフクランめバッフクランめ 2010/02/05 00:01 発動篇 (Be Invoked)はメソッド呼び出しで、無限の可能性が開けるんですね、分かります。
ちなみに名前の由来はこの画像が「I,D,E,O,Nを重ねたように見えるから」だそうな。

minekoaminekoa 2010/02/05 21:05 惑星だって真っ二つです。最後はみんなガベージコレクトしちゃいます。

あぁっ、今頃「篇」の字が間違いなのにが気がつきました。もう手遅れ...orz

イデの論理イデの論理 2010/02/11 06:07 // すごくいい加減な擬似コード
while(1){
temp1 = new 知的生物();// 例:地球人
temp2 = new 知的生物();// 例:バッフクラン

if( temp1.equals(成功例) && temp2.equals(成功例) ){
ide.invoke(); // 良き生命体によってのみ発動する。
}
else{ // 汚物は消毒だ〜〜!
temp1.kill();
temp2.kill();
}
}

ただし、一回 newするのに数十億年かかります。w

minekoaminekoa 2010/02/12 01:27 例外でも起きないとループから脱出できないのが、また...(^^;