2016-06-14 3 views
2

Turtleモジュールのメソッドに構文ツリーをコンパイルしたい。ラムダのツリーと弁別されたユニオンのツリー

type TurtleCommand = 
    | Rotate of float32 
    | Move of Vector2 
/... 
match symbol with 
     | 'w' -> Move (Vector2.up) 
     | '\' -> Rotate 90.0f 
//... 
let applyCommand command state = 
    match command with 
      | Move shift -> Turtle.move shift state 
      | Rotate amount -> Turtle.rotate amount state 
applyCommand command someState 

が、私はこれでそれを置き換える:

type TurtleCommand = TurtleState -> TurtleState 
/... 
match symbol with 
     | 'w' -> Turtle.move (Vector2.up) 
     | '\' -> Turtle.rotate 90.0f 
//... 
command someState 

は、今私は、コマンド Turtle.moveAndEvadeCollisionを持って

module Turtle = 
    let rotateDefaultAmount amount state = ... 
    let move vector state = ... 

このオプションは、コードの重複(実際にはより多くのコマンドがあります)を生成します。それは他のコマンドに依存します。特に、の後にを実行し、それぞれmoveコマンドを使用して占有位置に移動しないようにする必要があります。また、ツリーの中にコマンドmoveを続けてはいけません。

moveAndEvadeCollisionの後にmoveが付いていないという方法を書くことはできません。すべてが区別できないので、TurtleState -> TurtleStateラムダです。私の最初のリファクタリングが間違っていて、私は重複に戻るべきですか?関数型言語のプログラムは、関数からなるデータ構造を持つのが普通ですか?

答えて

2

私は、(input - > command)と(command - > movement)フェーズを分けるので、最初のバージョンが優れていると思います。これは、インタープリタのための非常に一般的な設計であり、それぞれ解析と実行の段階に対応しています。

実際のコードの重複はありませんが、コードはもう少し長くなってしまいます。しかし、コンパイラでapplyState関数がすべての可能なコマンドを処理することを検証できるようにするなど、非常に大きなメリットがあります。また、各パートを個別にテストすることもできます。

さらに、既に発見したように、コマンドのツリーに入力を解析すると、ツリー全体の静的検証を行い、無効なプログラムを入力していないことを確認できます。

関連する問題