Open bgnori opened 10 years ago
reflect.MakeFuncにしてしまう?
後者を実現するにはreflectをEvalで使用して TypeOf(v).Kind()してreflect.Funcかどうかをみるとかか.
Eval, そもそもdefaultの場合は現状nilを返しているがこれでいいのか.
func Eval(env Environment, expr interface{}) interface{} {
switch x := expr.(type) {
case bool,
int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64,
float32, float64,
complex64, complex128,
string:
return expr
case func(Environment, Sequence) interface{}:
return expr
case *Recur:
return expr
case Symbol: // variables?
if v, err := env.Resolve(x); err != nil {
panic(err)
} else {
return v
}
case Sequence:
switch v := Eval(env, x.First()).(type) {
case *Recur:
v.Update(Seq2Slice(x.Rest()), env)
return v
case ([]interface{}):
idx := Second(x).(int)
return v[idx]
case func(Environment, Sequence) interface{}:
return v(env, x.Rest())
default:
panic("application error, expected SExprOperator, but got " + fmt.Sprintf("%v", v))
}
}
return nil
}
外側のSwtich 1) defaultでnilを返しているが良いのか?
2) []interface{}でのマッチはうれしくない. Slice, Map, Arrayでmatchしたい
3) 一方でreflectにするとSymbolがうれしくない. PtrかStructが返ってきてもう一度testする必要がある.
idea: defaultの中でreflectするのでどうだろうか?
case Sequence内のswitch 全部reflectで良いような.
e03b624e1d3b177ac65f9f4e6d23393f96e51bfe 準備.
reflect.Zero() でZero Valueを与えることで解決.
とりあえず後半部分はある程度できた. 526073084a70ee7852ed0f16a3cb99f70c08ae08 マクロの取扱を変える必要がある.
(setmacro fn)で関数にmacro flagを設定することで適用時の処理を切り替えるようにする. 環境に持たせるかな.
(fn [] ~)はgolangの関数を生成してほしいし, 逆にgolangの関数gを(g ...)としたら適用されてほしい.