2016-03-29 3 views
2

JuliaのDSLとして単純な連結言語(別名JoyまたはFactor)を実装したいと思っています。スタックを最適に表現する方法に問題があります。Juliaでperformantな異種スタックを表現する方法

データとプログラムコードの両方を表すスタックは、異なるタイプの項目のシーケンスを保持できる必要があります。最も単純なケースでは、Ints、Symbols、そして、再帰的にスタックします(引用符付きのコードを表す)。プログラムは、大量のプッシュを使用します!ポップ!異なるスタック間で値をシャッフルします。

動作が遅いがゆっくりと動作するJuliaの明白な実装の1つは、セル配列を使用することです。例えば、次のJoyスタック[ 1 [ 1 2 +] i + ][4]と評価される)は、ジュリアで stack = Any[:+,:i,Any[:+,2,1],1]と実装できます。 (ジュリアで大きなパフォーマンスのボトルネックになっている)、このようなコードがtypestableではないだろうので、

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

これは、しかし、本当に遅い実行され、巨大なメモリ割り当てを使用しています。私の典型的なコードは次のようになります。 Cを使用し

、私は組合のアレイ(あるいはリンクされたリストなど)としてコンパクトスタックを表すことになる。

​​

しかし、どのようにジュリアにおける異種スタックのようなコンパクトな表現を実現することができますどのようにタイプの不安定性を避けるのですか?

答えて

3

これは一つの方法、種類のベクトル{どれ}と引数を表すようになり、別の方法である:

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 
+0

私はあなたの答えを完全に理解していません。 Exp:タプルはプッシュとポップの多くの操作に役立つデータ構造ですか? シンボルを含まないJoyスタックをどのように表現しますか? [1 [2 3]];これにネストされたタプルが含まれますか? 変更不可:このコンテキストで不変のデータ構造を使用する利点は何ですか?繰り返されるポップスとプッシュの結果はパフォーマンスの大幅な上昇につながりませんか? – Bernd

+0

ベクター{Any}:質問からのセル配列と比較した利点は何ですか? Juliaには、Anyよりもコンパイラの配列要素の可能な型を制限するより良い方法はありませんか?そして、そのような異種配列を処理するときに、型の不安定性を避けるための慣用的な方法は何ですか? – Bernd

+0

上記の例から、私はジョイがシンボルを持たないかもしれないことに気付かず、典型的なASTのように見えました。 Joy構文へのリンクがありますか? –

関連する問題