ラベル ren の投稿を表示しています。 すべての投稿を表示
ラベル ren の投稿を表示しています。 すべての投稿を表示

2014/07/06

ren ジェネリックワード(ファンクション)

ren に Clojure のマルチメソッドみたなものを実装してみた。

:g length dup type-of ;
:m length (( list )) erlang:length/1 ;
:m length (( tuple )) erlang:size/1 ;
:m length (( binary )) erlang:size/1 ;
:m length (( map )) erlang:map_size/1 ;

:g でジェネリックファンクションを定義する。やってることはスタックトップのオブジェクトのタイプをスタックにつむだけ。 :m でメソッドを定義する。スタックトップにつまれたタイプでパターマッチングしている。

Erlang にもマップが導入された。それを使ってこんなふうに OO っぽいことをやってみた。継承をどうするかが悩ましい。

:g + over type-of over type-of ;     # x y -- x y type-of-x type-of-y
:m + (( integer _ )) erlang:+/2 ;
:m + (( float _ )) erlang:+/2 ;
:m + (( list list )) erlang:++/2 ;
: point{ ( 'point >typed-map ) '{ ;
:m + (( #{ x X1 y Y1 } #{ x X2 y Y2 } point point ))
point{ 'x X1 X2 + 'y Y1 Y2 + }
;

point{ 'x 1 'y 2 } point{ 'x 3 'y 4 } +
# => #{'-type-' => point,x => 4,y => 6} Erlang の出力のまま

2014/06/22

データスタックに対するパターンマッチ

Erlang ではほとんど関数引数のパターマッチでプログラムが書ける。それを連鎖性言語でやろうとするとデータスタックに対するパターンマッチになる。

Factor だと http://docs.factorcode.org/content/article-locals-examples.html な感じでいろいろできるようではあるが、とりあえず dup 等をそんな感じで実装してみた。

: drop (( _ )) ;
: dup (( X )) X X ;
: swap (( X Y )) Y X ;
: over (( X Y )) X Y X ;
: rot (( X Y Z )) Y Z X ;
: -rot (( X Y Z )) Z X Y ;
: nip (( _ X )) X ;
: tuck (( X Y )) Y X Y ;

わかりやすい。

reverse と map はこんな感じ

: reverse [] swap reverse' ;
: reverse'
(( [] ))
(( Acc [ H T .] )) [ H Acc .] T reverse'


: map [ -rot map' ; # list function -- [ list function
: map'
(( [] _ )) ]
(( [ H T .] F ))
H F call T F map'

そういえば case の書き方をかえたので、いま fib を書くとこうなる。

: fib
= N
N 2 =<
case
true
( 1 )
_
( N 1- fib N 2 - fib + )
;case
;

( ) でブロックというかクオートというかそんなものができる。 Factor の [ ] と同じようなもの。

( 1+ ) 100 swap call .
# => 101
1 10 ( + ) cons call .
# => 11

2014/06/15

また Forth ライクな言語を作っている

最近まったくブログ書いてなかった。できればまた書くようにしたい。

ちかごろまた Forth ライクな言語を作っている。名前は ren(仮)。chon を付けてもいいかもしれない。 Forth ライクな言語を作るのはこれで4つか5つめ。なんか Forth には思い入れがあるみたい。とても簡単に作れる、というのもある。

今回のは Erlang で書いている。ワードを Erlang の関数にコンパイルする。思えば Erlang もコンパイル関数があるいい言語だ。ワードを Erlang の関数にコンパイルし、呼び出しは普通の Erlang 関数と同じなのでリターンスタックがない。そこは残念なところ。パターンマッチングをきれいに取り込みたいけど、なかなかいい書き方を思い付かない。

いまの fib はこんな感じ。

: fib
= N
N 2 =<
case
true
1
;;
_
N 1- fib N 2 - fib +
;case
;

言語を実装するのは不毛な感じがするものの楽しいね。