top recent

ポーランド記法モドキの言語


目次

  1. 現状のまとめ...
  2. まとめ2...
  3. 制御構造...
  4. ローカル変数...
  5. まとめ3...
  6. とりあえず...
  7. PostScriptとLispのいいとこどり。...
  8. まだちょっと普通すぎるのでもうすこし無駄を省こう...
  9. 式の定義...
  10. 式のパースと評価...
  11. ポーランド記法には区切りが必要ない?...
  12. これってパイプラインモデルだ!...
  13. おもろい。...
  14. パイプが有りならリダイレクトも有りか?...
  15. 例題: 15 - (150 + 120) を計算する式を書け。...
  16. 括弧が無い言語...
  17. カッコの存在とその意味について...
  18. あれ、これがそうなんですかね。...
  19. 勉強しようと思ってWebでいろいろ検索してたら‥‥‥...
  20. λ算法はかじってみるとおもしろいですね。硬いけど。...
  21. ポーランド記法ではできることがこの言語では苦労する...
  22. 文という単位があることに気づきました...
  23. 値を貯める場である「変数(など)」は無しですか?...
  24. 書くの忘れてた。...
  25. 多値の取り扱い方法(案)...
  26. 手続きを返す手続きについて(再考)...
  27. []と()って統一できませんか?...
  28. [...] ≒ (...) ?...
  29. ...
  30. おもしろそうではあるんだけど...
  31. [ + + ]の意味がわかんないや。...
  32. [...]みたいな記号よりは、...
  33. イテレート...
  34. 寄り道してFPについて調べていますが...
  35. もうちょっと考えがまとまったら...

現状のまとめ


プログラムと文、式の定義
プログラムは複数の文の集まりです。
文は複数の式の集まりです。
文はカンマまたはセミコロンで区切られ、ピリオドで終わる複数の式です。
一つの式は、一つ以上のアトムの並びです。アトムとアトムの間は任意個数の空白文字で区切られます。
-アトムはリテラルまたは名前です。リテラルは数、文字列、配列、手続きなどがあると思います。
-名前は値への束縛を持ちます。

式評価: 基本
先頭のアトムを手続きとし、後続のアトムの並びを引数として実行します。
-先頭のアトムの値が手続きでなければエラー
-引数の数が手続きの定義と合っていなければエラー

式評価: 値の引渡し
直前の式が…
-カンマで終わっていた場合、その式の値が引き渡されます。引き渡された値は引数列の先頭に並んでいるとみなされます。
-ピリオドで終わっていた場合、その式の値は捨てられます。
-セミコロンで終わっていた場合、その値は残されますが、この式には引き渡されません。次の式に先送りされます。

手続きと仮引数
手続きが実行されるとき、引数の先頭から順に評価され、仮引数に束縛されます。

----
TODO:
-コード例を入れる

[[id:793]] 2002-06-27 13:22:45


まとめ2

今までに出てきた(思いついた)記号や手続き

文法要素
- . 文の終結。値を捨てる。
- , 式の終結。値を残す。
- ; 式の終結。次の式には値を渡さない。

リテラル
- "" 文字列
- [仮引数列: 文の並び] 引数をとる手続きを返すリテラル
- [手続き 引数列] currying

手続きの名前
- + - * / 四則演算
- values 引数列をそのまま返す
- void 引数列を捨てる
- apply 引数列を式として実行する

[[id:794]] 2002-06-28 14:10:26


制御構造


if <真偽値> <true-block> <false-block>.

and <真偽値> <true-block>.

or <真偽値> <false-block>.

while <test-block> <loop-block>.

----
使用例:
< x y, if [
print "x is small".
]
[
print "x is big".
].

[[id:783]] 2002-06-26 14:26:15


ローカル変数

無名手続きへの引数を使って導入可能。

values 1 2 3, [x y z:
print z y x.
].
=> 3 2 1

[[id:784]] 2002-06-26 14:27:16


まとめ3

処理系の仕組み的な説明

プログラムの実行にあたって、なにかFIFOとなるようなデータ構造を使います。

文の実行
-式を評価し、値をFIFOに入れます。
-"," で文が続いていたら、FIFOの読み込みを許可して次の式の評価に移ります。
-";" で文が続いていたら、FIFOの読み込みを禁止して次の式の評価に移ります。
-"." で文が終わったら、FIFOをリセットして次の文の評価に移ります。

式評価
まず先頭にあるアトムを評価し手続きならばどこか専用の場所に覚えておきます。
-評価値が手続きでなければエラー

次に2番目から最後までのアトムを順に評価し、値をFIFOに入れていきます。
-ピリオドかカンマに当たったらそこが最後と分かります。

それから覚えておいた手続きの仮引数の定義を取り出し、ローカルな環境を作ってFIFOから取り出した値を順に束縛していきます。
-FIFOに入っている値の数と仮引数の数が合わなければエラー

最後に手続きを実行して値を返します。

[[id:797]] 2002-06-30 21:49:16


とりあえず

途中経過をここから上にまとめておきます。ディスカッション・ツッコミはここから下の別パラグラフで。

[[id:795]] 2002-06-27 12:17:54


PostScriptとLispのいいとこどり。

どちらもパーザに優しい言語仕様だけど、その中間的な記法を目指す
#謎言語withOOPではbbbbに先越されたのでリターンマッチ?

PostScript:
arg1 arg2 arg3 procedure

Lisp:
(procedure arg1 arg2 arg3)

NewLang:
procedure arg1, arg2, arg3.

しかもLispのように括弧だらけにならず、かつPostScriptのように難解にならないようなスタックの使い方を工夫してみる。 ";" を使うと式の値をスタックに残したまま次の式を評価できる。代名詞 "it" でスタック上の値を取り出す。ピリオド "." でスタックはクリアされる。
it : スタック上の値を取り出す代名詞。(実質はPOP)

Lisp:
(procedure2 (procedure1 arg1 arg2) arg3)

PostScript:
arg1 arg2 procedure1 arg3 procedure 2

NewLang:
procedure1 arg1, arg2``;'' procedure2 ``it'', arg3.

オブジェクト指向言語の小気味よさもできればとりいれたい。(ちょっと苦しげ)

Ruby:
obj.proc1().proc2().proc3()

NewLang:
proc1 obj``;'' proc2 ``it''``;'' proc3 ``it''.


them : スタック上のすべての値を取り出す代名詞(POP ALL)

split "colon:seperated:string", ":"``;'' sort ``them''``;'' join ``them'', "/".


引数なしの手続き呼び出し

procedure.

名前のデリファレンス(任意の個数の引数をスタックにそのまま残す``何もしない''手続き "get")


get name.

----
言語の語順による「不気味さ」をいかに除くか (プログラミング言語) を参考に。

get obj; proc1 it; proc2 it; proc3 it.

----
これってやっぱり、「名詞スタック」と「動詞スタック」との2つが有るんでしょうか?

----
スタックの「何処まで」をクリアするんでしょうか?
多分、1つの手続きを処理してるコンテキストによって導入された変数(?)の分、だと思うのですが。
-個々の手続き実行コンテキスト「に」スタックを所有させるとか?
ひとつの式の評価が終わると(ピリオドならば)スタックをまったくの空にします。詳しくは式のパースと評価 (#10)で。

[[id:768]] 2002-06-26 00:59:29


まだちょっと普通すぎるのでもうすこし無駄を省こう

というわけでカンマと "it", "them" をなくしてしまうことにします。
-カンマの代わりに引数の間も空白文字で区切ります。
-セミコロンによってスタック上に残されたn個の値は、後ろに続く式の、先頭n個の引数とみなされます。

proc1 arg1 arg2 arg3. -- (proc1 arg1 arg2 arg3)
proc1 arg1 arg2; proc2 arg3. -- (proc2 (proc1 arg1 arg2) arg3)
proc1 arg1; proc2; proc3. -- (proc3 (proc2 (proc1 arg1)))
get obj; proc1; proc2; proc3. (上と同じ意味)

[[id:773]] 2002-06-26 01:00:18


式の定義

プログラムは複数の式の集まりです。
一つの式は、
 アトムの並び+ピリオドまたはセミコロン
になります。アトムとアトムの間は任意個数の空白文字で区切られます。(カンマはやめました)
-アトムはリテラルまたは名前です。リテラルは数、文字列、配列、手続きなどがあると思います。
-名前は値への束縛を持ちます。

セミコロンをカンマに置き換えれば、
run away, look-around. みたいに英語の文章っぽくていいかも。
- いいですね。ピリオドとカンマの形も似てるし。採用させていただきます。

[[id:774]] 2002-06-26 12:40:56


式のパースと評価


前提として、式の評価を行う前段階ではスタックは空です。
(例外は前の式が``カンマ''で終わっている場合のみ。)

まず先頭にあるアトムを評価し手続きならばどこか専用の場所に覚えておきます。
-評価値が手続きでなければエラー
次に2番目から最後までのアトムを順に``評価し、値を''スタックに積んでいきます。
ピリオドか``カンマ''に当たったらそこが最後と分かります。
それから覚えておいた手続きの仮引数の定義を取り出し、ローカルな環境を作って``スタックの底''から順に束縛していきます。
-スタックに置かれている値の数と仮引数の数が合わなければエラー
最後に手続きを実行して、返された値は文末が``カンマ''ならばスタックに残しピリオドならば捨てます。

----
おもしろげですね。
-オペレータスタックをつくり、オペレータ以外のものがでてくるまで順にオペレータを積んでいく。
-オペレータ以外がでた場合は、スタックトップのオペレータを起動して後に続く部分を自分でパースする。
と言うルールにすれば、ピリオドも必要ないと思います。
ていうかもともとポーランド記法(逆ポーランドも)は括弧などの区切りをつかわなくてもロジックが一意に決まるのが利点だと思います。
FORTHでプロトタイプをためしてみようかしらん。
ーばし
-ばしさん、その路線を正ポーランド記法の言語に展開してみてはいかがでしょう。--SHIMADA
--なにかいろいろ考えているうちに「裏返った(?)」FORTHを再発明しているだけのような気分になってきました。(しょぼーん)
--SHIMADAさんのアプローチの方が興味深いと思うので、このぺージのほうのアプローチで私もしばらく妄想してみようと思います。ーばし

[[id:775]] 2002-06-27 15:09:40


ポーランド記法には区切りが必要ない?

Re: 式のパースと評価 (#10)

シンボルが値への束縛でしかない場合、評価してみないとそれが手続きなのかどうなのか分かりませんよね。
-ちなみにFORTHでは値に束縛されたシンボルとはすなわち値を返す手続きです。だから問題無し。;-) ーばし
手続きならば実行し、それ以外ならばオペランドとする、という動作にしてしまうと、ロジックが一意に決まるどころか、コンテキストによって、どこからどこまでが一つの式なのか解釈が変わってしまうという恐ろしいことになってしまわないでしょうか。
-ポーランド記法(逆も)が人間にとって読みにくいのは確かです。激しく同意。ーばし (でもやめられん。)

foo bar baz hoge hago gogogo

というプログラム片があり、あるコンテキストでは foo, baz, hago がオペレータでしたが別のコンテキストでおなじプログラム片が出てくるときは foo, bar, hoge, gogogo がオペレータでした、なんていうことも起きるような気がします。

----
bbbbは、メソッド(実はデータメンバも同じなのだが)は.で始まる、という文法でしたね。

PS系は、コンテキスト非依存で文脈の区切りをつけるという努力を、いろいろな面で(^^;放棄した言語なんで、ちとスパゲティに陥りやすいかな。

それよりはもうすこしマシな(lispに近づく)やりかたとして、
たとえば手続きは必ず.で始まる、ということにしても良いんだろけど、
それってピリオドの位置を少々「後ろに移動した」だけだよね。
(前略) .hoge fuga .foo bar .(後略)

(前略). hoge fuga. foo bar. (後略)
との差なんだから(笑)

----
中置記法
 15 * (150 + 200)
逆ポーランド
 15 150 200 + *
LISP
 (* 15 (+ 150 200))
ポーランド記法
 <ご存じの方ここを埋めていただけます?>
たぶん
 * + 150 200 15
ポーランド記法 (正ポーランド記法の言語)を参照のこと。ーばし

この言語の記法
 + 150 200``,'' * 15.

[[id:777]] 2002-06-26 13:02:13


これってパイプラインモデルだ!

まだちょっと普通すぎるのでもうすこし無駄を省こう (#8)
>proc1 arg1; proc2; proc3. -- (proc3 (proc2 (proc1 arg1)))
>get obj; proc1; proc2; proc3. (上と同じ意味)

1行目と2行目が同じ意味になるというパターンを、俺はどっかで見たことが有る。
それも一度や二度じゃなく、毎日のように接しているような気が…

あ。あれだ! unix コマンドラインの、パイプだ!!

prog1 file1 | prog2 | prog3
cat file1 | prog1 | prog2 | prog3

の両者が同じ意味であるのと、全く同じだ!

で、なんで同じになるんだろう?と考えて、そして気づいた。

式のパースと評価 (#10)
>スタックの底から順に束縛

物事が逆順になるスタックだが、それを更に逆に使うことでデータは結局正順になり、
つまり「パイプラインにargを流している」のと等価になるわけだ!!!

#ということは、スタックを使っているのは結局、終端もとい先端の、位置を把握しやすくするためですね。

unixのアレと違うところは、
-引数と標準入出力という2つの入出力形態が混在していたりしない。おかげですっきりする(^^;
-標準入出力みたいに、データを全部まぜまぜしてしまったりしない。あくまで個々のデータは区別できる状態のまま扱える。

----
そういえば、FORTHのスタック(LIFO)の代わりにパイプ(FIFO)をもった言語がどこかにあると聞きました。
(でも思い出せません。)
ーばし

-たとえばStackじゃなくFIFOでやっちゃう、あれ系言語? (プログラミング言語)とか
----
そうですねー。よく考えたらこれスタックじゃなくてFIFOですよねー。
言われて気づきました。--SHIMADA

[[id:778]] 2002-08-05 13:54:00


おもろい。

- スタックを使うことで、多値渡しがすっきりしますね。
- オペレータかどうかで動作を変えると、オペレータそのものを引数として渡したい時に困るので、やっぱり区切りは必要かと。(クオートしてもいいですが、それだとcall by nameになるんで意味が違って来る)
- 最初のn個の引数がimplicitに指定できるってことは、最後のm個の引数だけをspecializeしたコードブロックを作って返せるということ、つまり、逆curryingができる?

--Schemer

----
>引数として渡したい時に困る
Lispでのクオート渡しはcall by nameになるかもしれないんですが、
オペーレータへの参照とか(関数ポインタとか笑)を返すオペレータを実装すればそれで良いとおもひます。
FORTHにおけるtickみたいな。
ーばし

なるほど。そういえばLispにも#' ってのがあった。 --Schemer

[[id:779]] 2002-06-27 11:05:47


パイプが有りならリダイレクトも有りか?

これってパイプラインモデルだ! (#12)

じゃあ、データを変数(?)に束縛するための擬似手続き(lispではletとかでしたっけ?)も有りですかね?
unix pipelineの喩えで言えば、ファイルへのリダイレクト。

get obj; proc1; proc2; proc3 ; > obj2 > obj3 . #>はstack topを束縛する
get obj; proc1; proc2; proc3 ; >> objs . #>>はstackの内容全部を束縛する

とか。

[[id:780]] 2002-06-26 11:31:53


例題: 15 - (150 + 120) を計算する式を書け。


RPN
15 150 120 + -

LISP
(- 15 (+ 150 120))

PN
- 15 + 150 120

----
この言語でやってみよう!

+ 150 120, - 15.
‥‥‥間違い。うぐぐ。

+ 150 120, reverse 15, -.
‥‥‥スタックをひっくり返す手続き reverse。今考えた。

+ 150 120, [x: - 15 x.].
‥‥‥ [仮引数列: 式] で手続きを返す。(Smalltalk風)

[[id:781]] 2002-06-26 17:06:46


括弧が無い言語

例題: 15 - (150 + 120) を計算する式を書け。 (#15)

Lispは優先順位というか処理順序を括弧によって自在(?)に変えられるが、
Forth系や今回言語には括弧に相当する概念が無いので、
処理の順序ではなく、処理が生成したデータが参照される順序(ここではStack上での順序)を、
ひっくりかえす必要が(状況によって)生じるわけですね。

逆にいうと今回言語、括弧のような順序制御の仕組みは
有ったほうが良いんでしょうか?それとも無いほうが良い? -戯

[[id:786]] 2002-06-26 16:12:58


カッコの存在とその意味について

予約された引数つきの手続きを返すもの、としてみるテスト。

(proc arg...) という記述は、先頭に arg... という引数が並んだ proc という意味の手続きを返す。

+ 120 150, (- 15).
( + 120 150, [i: - 15 i]. と一応同じ結果を返す。)

どうだろう。破綻しないかよく考えてみよう。

- これ、curryingじゃないですか。--Schemer

----
[...] ≒ (...) ? (#28) で (...) と [...] を統合。

[[id:787]] 2002-06-26 19:26:13


あれ、これがそうなんですかね。

Re: カッコの存在とその意味について (#17)
> これ、curryingじゃないですか。--Schemer

カリー化についてはいくつかのサイトで説明を読んだんですけど、分かったような分からないような…。
こんなに分からないのは多分 Haskell や ML を知らないからだ! と気づいて、最近勉強しはじめています。
そうか、これが currying なのか…。

#ところで逆curryingってどういうものなんでしょう。

----
「逆currying」ってのはうまくなかったかな。curryの逆操作、という意味ではなく(それはuncurrying)、curryingが引数の最初の方だけをspecializeしたクロージャを返すのに対し、この言語では引数の後ろの方をspecializeしたクロージャというかコードブロックを簡単に作れるかなあと思ったのです。

get 3; [x y: - x y].

いう式は、これだけだと引数が足りませんよね (stack underflowとかになるのかな)。でもこのブロックをどっかに保存しておいて、

get 5; { ブロック }

みたいに呼び出せれば(カーリーブレースは構文要素ではなくて、何らかの手段でもってそのブロックを呼び出したということだと思って下さい)、2を返すはず、ですよね。だとすると、最初のブロックは、二つ引数を取る手続きのうち、あたかもyを3に束縛したブロック(手続き)を作成していることになります。

通常のcurryingでは逆に引数リストの最初の方から固定されていきます。Haskell風に書けばこうかな。

(\x y -> x - y) 3

これはxが3に固定(束縛)された関数になります。そういう意味で逆curryingと言いました。
でもカッコの存在とその意味について (#17) の方がわかりやすいかな。

ただ、curryingと可変長引数とはたぶん相性が悪いので、注意が必要だと思います (例: (print 2 3) はいくつ引数を取るべき? )

-- Schemer

----
私もカリー化ってよくわからないなぁ、と思ってたのですが、こういうのってカリー化だったのかぁ。
どうもありがとうございます。
FORTHで

: inc 1 + ;

と定義して、

5 inc

とするとスタックに6が返るっていうのも一種のカリー化と考えてよろしいんでしょうか?
ーばし
-λ算法はかじってみるとおもしろいですね。硬いけど。 (#20)を読んで何か大きな勘違いをしているような気がしてきました‥‥。むつかすい。ーばし

[[id:788]] 2002-06-27 15:18:26


勉強しようと思ってWebでいろいろ検索してたら‥‥‥

なんかヘンなものが引っ掛かってきました。
逆ポーランドな関数型言語 Joy (URLメモ)
ーばし

----
ざっとですが目を通してみました。
むー、リストとそれを評価するオペレータがあればそれで十分、という訳ですね。
逆ポーランドだし。

[...] がわざわざ手続きを返す必要はないのかなー、と迷ってしまいます。

--SHIMADA

----
個人的にはリストと手続きを返すブロックは別の方がいいんじゃないかなぁ、と思います。
リストと同じにしてしまうと、ブランケットの中身を全部遅延評価する事になるから、レキシカルな変数のバインドとかがメンドくさいことになりそう、とか。

--ばし

[[id:812]] 2002-06-29 09:17:32


λ算法はかじってみるとおもしろいですね。硬いけど。

Re: あれ、これがそうなんですかね。 (#18)
> (\x y -> x - y) 3

ええと、
{λxλy(x - y)} where x = 3
みたいな感じの意味かな。
関数を適用しないままで束縛変数に値を置いておくみたいな。

----
私もHaskell初心者なんですが、curryingのキモは適用するしないじゃなくて、「n個の引数(n>1)を取る関数ってのは1個の引数を取って『n-1個の引数を取る関数』を返す関数だ」と考えることなんではないかと。こうすると全ての関数が1引数の関数へと変換できてしまって扱いがシンプルになるのと、部分適用が自然に書けるというメリットがあると。

ですんで、
\x y -> x-y は \x -> (\y -> x-y) と同じ。
(\x y -> x-y) 3 は (\y -> 3-y) と同じ。
ということになるのではないかと。

--Schemer

----
なるほど、
\x y -> x-y から \x -> (\y -> x-y) への操作は
ラムダ抽象そのものですね。

[[id:791]] 2002-06-27 11:10:08


ポーランド記法ではできることがこの言語では苦労する

その理由はなにかと思ったらスタックに値をためておいて別の計算をするという機能がないからだった。
そういう能力をこの言語に新しく追加するためには?

対策案1 カンマ、ピリオドに続く第三の記号を制定する。
- 記号はセミコロンかなー。でもここ読んでる人たちは混乱するだろうなー。

対策案2 スタックからの値を渡さずに引数の式を実行するという手続きを作る。
- "protect-current-value-and-apply" みたいな名前だろうか。call/cc並に長いな。"pcv-apply"?

対策案3 括弧はこっちの意味にする
- ( ) の中は新しいスタックフレームの中で計算が進むことにする
- left-curryingの記号は別のもの({}とか)を使う


例題: (1 + 2) - (4 / 2)

RPN
1 2 + 4 2 / -

PN
- + 1 2 / 4 2

この言語

案1
+ 1 2; / 4 2, -

案2
+ 1 2, pcv-apply / 4 2, -

案3
+ 1 2,( / 4 2 ), -

‥‥‥案3が一番すっきりするなー。
でも括弧と別にカンマを書いてるけど必要なんだろうか。必要ないんだろうか。もうちょっと考えよう。
- それに括弧をネストしはじめたらもうLISPと同じことになってしまうなー。案1のほうがもともとの趣旨には合ってるような気もしてきた‥‥‥。

[[id:792]] 2002-06-27 11:07:30


文という単位があることに気づきました

複数の式がカンマやセミコロンで繋がっていて、最後はピリオドで終わっています。
ということは式がまとまってなにかの実行単位となっているわけで、それを文と呼ぶことにします。

[[id:796]] 2002-06-27 13:30:23


値を貯める場である「変数(など)」は無しですか?

> ポーランド記法ではできることがこの言語では苦労する (#21)

今のところ、戯以外は(^^;、引数以外の変数というものに言及していないような気がするんですが、
それで万事いけるものなんでしょうか?

Lisp系にも…ええとletっていうんでしたっけ?…引数ではない変数だか束縛だかを作成する命令が有りますよね。あれ。
パイプが有りならリダイレクトも有りか? (#14) は、そういう積もりもあって書きました。

ポーランド記法ではできることがこの言語では苦労する (#21)
>スタックに値をためておいて別の計算をするという機能

それが有るにも関わらず、Forth/PostScript系はコーディングに苦労します(^^;。

[[id:798]] 2002-06-27 15:30:50


書くの忘れてた。

Re: 値を貯める場である「変数(など)」は無しですか? (#23)

全体の方向性とかに関わって来る、いろいろと影響の大きそうな部分なので、とりあえず暫定で。
----
バインディング

名前
手続きを含むすべての値は、名前を定義して束縛することができる。

名前の定義
``現在の環境に''新たな名前を定義する手続き "define"
※二重に定義しようとするとエラー。


- define 'i 1. ==> i = 1
- * 12 30, (define 'j). ==> j = 360
- define 'plus [i j: + i j].
- define 'swap [i j: values j i].
- define 'pow [i: * i i].

値の書き換え
名前の値を書き換える手続き "set"
(破壊的代入…なくてもいいのかなー。もっと全貌が分かってこないと判断つかない。)
※定義されていない名前に適用しようとするとエラー。

- set 'i 2. ==> i = 2.

[[id:799]] 2002-06-27 17:52:49


多値の取り扱い方法(案)

ひとつの文の中ではとりあえず多値が扱える、次の式に渡せるということになってきましたが、
基本的に一つの名前には一つの値しか束縛できないと考えています。

文を超えてどうやって持ち運ぶ?

*リストというデータ構造を使えることにしてそれに入れる。
"make-list" ... 引数列をリスト化する手続き。

split "/" "foo/bar/baz", make-list, (define words).


*クロージャに入れて持ち運ぶ
"make-function" ... 引数列を手続き化する手続きを考える。"apply" の逆(?)

split "/" "foo/bar/baz", (make-function values), (define words). ==> [values foo bar baz]
words. ==> foo bar baz
(評価すると多値が返る)

[[id:800]] 2002-06-27 18:40:29


手続きを返す手続きについて(再考)

[x y z: define a. + x y, + z, (set 'a)].
このリテラル表現は、
- 仮引数の宣言
- 複数の式からなる文と複数の文からなる手続き
などが表現されている。
それと同じことを手続きの組み合わせでどう表現するか。
----
なんとなく名づけてしまった make-function を更に掘り下げると、どういう操作が行なわれているか?

手続きAと手続きBを受け取って手続き[A.B.]を返す。単に並べるだけ。
手続きAと手続きBを受け取って手続き[A,B.]や[A;B.]を返す。手続きの合成?

----
[...] と [... : ...] の整合性について

[...: ....] は、シグニチャという情報を含んだ手続きデータ。
[...] は、シグニチャという情報を含まない手続きデータ。

[...] に何かの操作を施して [...: ...] を作り出せるというのは世界観に破綻を生む?
----
foo bar baz を受けて [foo bar baz] を返す手続きは必要?

[[id:802]] 2002-06-28 13:59:38


[]と()って統一できませんか?


なんか2種類有ると無駄遣いしてるような気分になっちゃって。
#でも統一するとますますLispに似る罠

[[id:803]] 2002-06-28 02:26:49


[...] ≒ (...) ?

Re: []と()って統一できませんか? (#27)
確かに。
[...] をいままで (...) といっていたものだとすると、まとめられそうですね。
- [a b c: body....] 三つの引数をとる手続きを返す。
- [: body...] ゼロ個の引数をとる手続きを返す。
- [body...] 可変引数をとる手続きを返す。仮引数に束縛されずボディの最初の式に書いてある引数の後ろに(無名のまま)渡される。

[[id:807]] 2002-06-28 07:12:39


[[id:804]] 2002-06-28 02:29:43


おもしろそうではあるんだけど

(define (a b c d) (+ b c d))
(define a (lambda (b c d) (+ b c d)))

define a lambda b c d body + b c d.

うーむ、なにを持って「ポーランド記法」というのかよくわからないな。

----
Lispから括弧を取ったもの≠正PNですよん。
正PN的に書くと

define a [ + + ] .

もしくは

define a [ x y z : + + x y z ] .

みたいな感じになると思います。
- + が二引数演算子であるなら.
-- 複数とれるなら define a [ x y z : + x y z]. で済んでしまうし.
-- そうすると記法を変えた Lisp と区別つかない.
--- でもLispじゃ define a [ + + ] . と書けない。:p
- PN って実はオペレータの引数の数が明らかであるっていう前提があるのかな?
--- オペレータの数がわかっていないと括弧なり区切りが必要なやうな‥‥‥。
--- そしてそれは正格(?)PNじゃないんではと。。
--- ちゃちゃ入れすみません。Implicitなパラメタの受け渡しがPNとRPNのキモではないかと思ったもので。。。ポーランド記法 (正ポーランド記法の言語)
--- SHIMADAさんの言語とは関係ない話ですみません。ーばし
- 最初のアイディアが正 PN だっただけで,既に違う話になってると見るのが正解?
-- そんな感じです。名前変えたほうがいいなあ。--SHIMADA

[[id:805]] 2002-06-28 12:54:02


[ + + ]の意味がわかんないや。

[...]ってネストするの?
現段階だと、schemeのvaluesを暗黙的にした感じ?
----
もはやここで話し合っている言語そのものとは関係ない話になっているのでアレですが‥‥。
[ ] は手続きを返すブロックのつもりでした。
RPNなGikoForthだと同様な処理は、
: a :[ + + ]: ;
と書きます。だからPNな言語でもそのように定義できるべきだと考えました。
--ばし

[[id:815]] 2002-06-30 01:39:00


[...]みたいな記号よりは、

素直にletにしたほうがいいとおもうけど。
でも終端がなあ・・・

[[id:806]] 2002-06-28 02:36:37


イテレート

map <手続き> <引数列>
<引数列>のひとつずつを順に <手続き> に適用し、結果を多値として返す。

map [+ 1] 1 7 10
==> 2 8 11

----
仮に "compose-procedure"(長い)というものが、foo bar baz を [foo, bar, baz.] とする手続きならば

define 'sum [
map [i: values [+ i]],
[compose-procedure [values 0]],
apply.
].
sum 1 7 10.
=> apply [[values 0], [+ 1], [+ 7], [+ 10]].
=> 18

という感じにできないかなー。
# なんか物事をややこしくしているだけのような気がしてきたぞ。ま、面白いからいいか。

[[id:810]] 2002-06-28 22:27:09


寄り道してFPについて調べていますが

いろいろと面白いです。
最近思っているのは、
パイプラインと関数合成が似ているなー、ということ。

関数合成:
(f1・f2・f3) x == f3 (f2 (f1 x))
- 間違いでした。正: (f1・f2・f3) x == f1 (f2 (f3 x))

この言語:
f1 x, f2, f3; == ???
# 今のところ括弧がない

shellのパイプライン:
c1 x | c2 | c3 /= c3 `c2 \`c1 x\``
# 引数とstdin/outの違いから意味が異なる。

[[id:926]] 2002-08-07 13:29:53


もうちょっと考えがまとまったら

ページを改めて再開するかも。
方向性は、
- 関数はデフォでカリー化
- FIFOの引き継ぎ規則も見直し
- パイプラインを関数合成として再定義する
- 多値の扱いを整理
- シンボルを引数とする関数としてのオブジェクト
- 状態を局所化するツールとしてのオブジェクト
- もうちょっとshellに似せる ( "|", ";", ">", "<" などを使う?)

…これらを当初のような単純な機構に納めることが果してできるのでしょうか?(笑)

[[id:927]] 2002-08-07 13:31:14


top recent

HashedWiki version 3 beta
SHIMADA Keiki