2

シンプルな連結言語 (Joy または Factor とも呼ばれます) を Julia の DSL として実装したいのですが、スタックを最適に表現する方法に悩んでいます。

データとプログラム コードの両方を表すスタックは、さまざまな種類のアイテムのシーケンスを保持できる必要があります。最も単純なケースでは、Int、Symbol、および再帰的にスタック (引用符で囲まれたコードを表す) です。プログラムは push! を多用します。そしてポップ!そのような異なるスタック間で値をシャッフルします。

Julia での明らかな実装の 1 つは、機能しますが実行速度がかなり遅いため、セル配列を使用することです。たとえば、次の Joy スタック[ 1 [ 1 2 +] i + ](評価結果は[4]) は Julia で として実装できます stack = Any[:+,:i,Any[:+,2,1],1]。私の典型的なコードは次のようになります。

x = pop!(callstack)
if isa(x,Int)
   push!(x,datastack)
elseif isa(x,Symbol)
   do_stuff(x,datastack)
end

ただし、これは実行が非常に遅く、大量のメモリ割り当てを使用します。おそらく、そのようなコードは型安定性がないためです (これは Julia のパフォーマンスの大きなボトルネックです)。

C を使用して、スタックを共用体の配列 (またはリンク リスト) としてコンパクトに表現します。

typedef union Stackelem{
    int val;
    char *sym;
    union Stackelem *quote;
} Stackelem;

Stackelem stack[n];

しかし、Julia で異種スタックのこのようなコンパクトな表現を実現するにはどうすればよいでしょうか。また、型の不安定性を回避するにはどうすればよいでしょうか?

4

1 に答える 1

3

これは 1 つの方法ですが、Vector{Any} 型で引数を表す別の方法もあります。

julia> immutable Exp
          head::Symbol
          args::Tuple
       end

julia> q = Exp(:+, (1, Exp(:-, (3, 4))))
Exp(:+,(1,Exp(:-,(3,4))))

編集:それを表す別の方法は次のとおりです。

immutable QuoteExp{T} ; vec::Vector{T} ; end
typealias ExpTyp Union{QuoteExp, Int, Symbol}
typealias Exp QuoteExp{ExpTyp}

そして、次のことができます。

julia> x = Exp(ExpTyp[:+, 1, 2])
QuoteExp{Union{Int64,QuoteExp{T},Symbol}}(Union{Int64,QuoteExp{T},Symbol}[:+,1,2])
julia> x.vec[1]
:+
julia> x.vec[2]
1
julia> x.vec[3]
2
julia> push!(x.vec,:Scott)
4-element Array{Union{Int64,QuoteExp{T},Symbol},1}:
  :+    
 1      
 2      
  :Scott
julia> x.vec[4]
:Scott
于 2016-03-29T23:59:04.387 に答える