WSN追加案: コモンと式にリスト型を追加
現在、コモンと式の型には数値・文字列・真偽値がありますが、ここにリスト型を加えると表現力が大幅に向上します。
以下は素案です。
リストは要素として任意数の値を持ちます。生成には関数LIST(...)
を使います。
LIST("STR", 42, TRUE)
→ 文字列"STR"
・数値42
・真偽値TRUE
の3つの要素を持つリスト
リストにはリストを含める事ができます。
LIST(LIST(1, 2, 3), LIST, 3, 4, 5))
→ 要素として1
,2
,3
のリストと3
,4
,5
のリストの2つを持つリスト
リストは関数によって操作することができます。
HEAD(LIST(42, 43, 44))
→ リストの最初の要素(42
)TAIL(LIST(42, 43, 44))
→ リストから最初の要素を取り除いたリスト(LIST(43, 44)
)LEN(LIST(0, 1, 2))
→LIST(0, 1, 2)
の長さ(3
)LEFT(LIST(0, 1, 2), 2)
→LIST(0, 1, 2)
の左側の2要素のリスト(LIST(0, 1)
)。RIGHT(LIST(0, 1, 2), 2)
→LIST(0, 1, 2)
の右側の2要素のリスト(LIST(1, 2)
)。MID(LIST(1, 2, 3, 4, 5), 2, 3)
→LIST(1, 2, 3, 4, 5)
の2番目からの3要素のリスト(LIST(2, 3, 4)
)。CONCAT(LIST(1, 2), LIST(3, 4), 42, "STR", LIST(LIST(1), LIST(2)))
→ 引数のリストまたはリスト以外の値を結合したリスト(LIST(1, 2, 3, 4, 42, "STR", LIST(1), LIST(2))
)GET(LIST(98, 99), 2)
→ リストの2番めの要素(99
)
関数の名前や定義などは叩き台です。一度作った関数は廃止できないので、よく検討する必要があります。
また、リスト用の書式を用意するべきかも考えた方がよさそうです。
[1, 2, 3] = LIST(1, 2, 3)
LIST(1, 2, 3)[1] = 2
LIST(1, 2, 3, 4)[1:3] = LIST(2, 3)
LIST(1, 2) ~ LIST(3, 4) = LIST(1, 2, 3, 4)
LIST(1, 2) ~ 3 = LIST(1, 2, 3)
0 ~ LIST(1, 2) = LIST(0, 1, 2)
Comments (13)
-
-
reporter いわゆる遅延評価は、副作用のない関数呼び出ししか存在しない状態を維持できれば、あとから実装してデフォルト化してしまっても問題ないはずです。表面上違いが無いのであれば、仕様にする必要すら無いかもしれません。とりあえず今は何も考えていません。
再帰は、まずユーザ関数を定義できるようにしなければなりません。パッケージに引数や戻り値を実装できれば(そして使用時イベントからもパッケージを使えるようになれば)不要かもしれません。
-
reporter ランダムに結果が変わる関数呼び出しはあるので(
DICE()
やフラグ・ステップ値内の#R
)、遅延評価を実装するにあたって必要呼びは小細工無しには採れないとは思います。呼び出し回数によって結果に予測可能な変化が発生する処理は、たしか無かったはずです。
-
reporter issue
#922IF
について実害のある仕様の考慮漏れが発覚したので、遅延評価を実装する事になりました。 -
気になるところとしては
・初期値の入力はどうするのでしょうか?
・リストは、数値・文字列・真偽値の混在が可能という理解でいいんでしょうか? -
reporter 初期値については、最初はUIを用意するべきかと思ったのですが、かなり煩わしいものになってしまいそうだったので(なにしろリストの要素の一つ一つで型指定と値の入力を行う必要があります)、式を書けるようにしてしまった方がよいです。この考えが#913の元になっています。
異なる型の混在はもちろん可能です。
-
reporter 最初に書いた関数群のうち、
GET
という名前はしっくり来ないので、C++のvectorやRubyなどに合わせてAT
にした方がよさそうな気がします。
-
reporter 実装をやりかけて気づいた事をいくつか:
- 素案では
LEN
やLEFT
等の関数を文字列操作と共用にしていましたが、目視でも機械的にも型チェックが厄介になるというデメリットを抱えるので、別にした方がよさそうです。似たような関数はLLEN
やLLEFT
等、接頭辞L
をつけて区別することを考えています。 - リスト同士が比較できた方がよいです。具体的には
<
・>
・<=
・>=
・=
・<>
に対応するべきです。 - 演算子
~
でリストの結合が行えた方がよいです。これでCONCAT
は事実上不要になります。 HEAD
とTAIL
はAT
とLMID
があれば当面不要そうです。
- 素案では
-
reporter 実装です。
上に書き忘れましたが、検索関数
LFIND
も作ってあります。また、メッセージ等に表示した時にどのように出るべきか少し悩んだのですが、とりあえず
LIST
関数の表現がそのまま出てくるようにしています。おそらくテスト目的以外に需要はないでしょう。 -
関数や演算子はLが付く以外は文字列型コモンとそろえたほうがわかりやすそうに感じます。
-
reporter そうですね、文字列は実質文字のリストなので。
そのようにしているつもりです(
FIND
とLFIND
だけは検索対象が文字列内の文字列→リスト内の要素なのでちょっと挙動が違いますが)。 -
LIST(LIST(1, 2, 3), LIST, 3, 4, 5)) → 要素として1,2,3のリストと3,4,5のリストの2つを持つリスト
が理解できない(1・2・3を持つリストと直近の?リストの呼び出し、4・5・6を直接生成しているようにみえる)のですが、閉じ括弧が多いのをみるにLIST(LIST(1, 2, 3), LIST(3, 4, 5))のミスでしょうか?
-
reporter ミスですね、それで正しいです。
- Log in to comment
かなりLISPっぽいですね。将来的には再帰と名前呼びも実装されるのでしょうか?