読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

Forthで多目的カッコ

forth

Forthでメタプログラミングを行う際にちょっと面倒な点として、本当は次のように書きたいんだけど

list { 1 2 3 }


class Point {
   var: x
   var: y
   :m get-x  ( -- x )  x @ ;
   :m set-x  ( x -- )  x ! ;
}

全てがワードなので、次のように「どの構造の終了なのか」を明示する必要がある。

list{ 1 2 3 }list


class Point
   var: x
   var: y
   :m get-x  x @ ;m
   :m get-y  y @ ;m
end-class

ちょっとウームというカンジですね。

で、Reforthのimmediate structuresを見てて思いついたのが、汎用の「構造を終了する」ワードを作るという解決法。便利なのでjf64の頃から毎回実装してる。仕組みは単純で

  • 構造を開始するときに、「終了する際に実行するワード」のxtを専用のスタックに置く
  • end}など、汎用の終了ワードは、専用スタックから一つxtを取って実行する

これだけ。immediateモードかどうかの判断などいろいろやる必要があるけど、終了するためのワードを定義する必要は無くなる。

更にycombinatorのあるポスト見て笑ってたんだけど、ふと、開くワードも汎化できるじゃないかと気づいた。

{[は、単に無視するワードにしていい。開始xtスタックも作って、空なら元のローカル変数宣言開始などを実行してもいい。

で、上のポストみたいなスタックポインタの操作、gc.fsのconsセルと組み合わせて、general-brackets.fsなどを作ってみた。コンパイルモード時にまだ対応してないけど、とりあえずREPLで次のように書けるようになった。

list { 1 2 3 } .cons 1 2 3  ok
list { } null? . -1  ok

一番最初のクラス定義も書けるでしょう。

広告を非表示にする