WSN追加案: コモンと式にリスト型を追加

Issue #909 new
k4nagatsuki repo owner created an issue

現在、コモンと式の型には数値・文字列・真偽値がありますが、ここにリスト型を加えると表現力が大幅に向上します。

以下は素案です。


リストは要素として任意数の値を持ちます。生成には関数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)

  1. hand.onlooker

    かなりLISPっぽいですね。将来的には再帰と名前呼びも実装されるのでしょうか?

  2. k4nagatsuki reporter

    いわゆる遅延評価は、副作用のない関数呼び出ししか存在しない状態を維持できれば、あとから実装してデフォルト化してしまっても問題ないはずです。表面上違いが無いのであれば、仕様にする必要すら無いかもしれません。とりあえず今は何も考えていません。

    再帰は、まずユーザ関数を定義できるようにしなければなりません。パッケージに引数や戻り値を実装できれば(そして使用時イベントからもパッケージを使えるようになれば)不要かもしれません。

  3. k4nagatsuki reporter

    ランダムに結果が変わる関数呼び出しはあるので(DICE()やフラグ・ステップ値内の#R)、遅延評価を実装するにあたって必要呼びは小細工無しには採れないとは思います。

    呼び出し回数によって結果に予測可能な変化が発生する処理は、たしか無かったはずです。

  4. k4nagatsuki reporter

    issue #922

    IFについて実害のある仕様の考慮漏れが発覚したので、遅延評価を実装する事になりました。

  5. hand.onlooker

    気になるところとしては
    ・初期値の入力はどうするのでしょうか?
    ・リストは、数値・文字列・真偽値の混在が可能という理解でいいんでしょうか?

  6. k4nagatsuki reporter

    初期値については、最初はUIを用意するべきかと思ったのですが、かなり煩わしいものになってしまいそうだったので(なにしろリストの要素の一つ一つで型指定と値の入力を行う必要があります)、式を書けるようにしてしまった方がよいです。この考えが#913の元になっています。

    異なる型の混在はもちろん可能です。

  7. k4nagatsuki reporter

    最初に書いた関数群のうち、GETという名前はしっくり来ないので、C++のvectorやRubyなどに合わせてATにした方がよさそうな気がします。

  8. k4nagatsuki reporter

    実装をやりかけて気づいた事をいくつか:

    • 素案ではLENLEFT等の関数を文字列操作と共用にしていましたが、目視でも機械的にも型チェックが厄介になるというデメリットを抱えるので、別にした方がよさそうです。似たような関数はLLENLLEFT等、接頭辞Lをつけて区別することを考えています。
    • リスト同士が比較できた方がよいです。具体的には<><=>==<>に対応するべきです。
    • 演算子~でリストの結合が行えた方がよいです。これでCONCATは事実上不要になります。
    • HEADTAILATLMIDがあれば当面不要そうです。

  9. k4nagatsuki reporter

    pull request #206

    実装です。

    上に書き忘れましたが、検索関数LFINDも作ってあります。

    また、メッセージ等に表示した時にどのように出るべきか少し悩んだのですが、とりあえずLIST関数の表現がそのまま出てくるようにしています。おそらくテスト目的以外に需要はないでしょう。

  10. hand.onlooker

    関数や演算子はLが付く以外は文字列型コモンとそろえたほうがわかりやすそうに感じます。

  11. k4nagatsuki reporter

    そうですね、文字列は実質文字のリストなので。

    そのようにしているつもりです(FINDLFINDだけは検索対象が文字列内の文字列→リスト内の要素なのでちょっと挙動が違いますが)。

  12. 暗黒 騎士

    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))のミスでしょうか?

  13. Log in to comment