2016-03-29 7 views
2

Ich möchte gerne eine einfache Verkettungssprache (alias Joy oder Factor) als DSL in Julia implementieren und ich habe Probleme, den Stack optimal darzustellen.Wie stelle ich einen performanten heterogenen Stack in Julia dar?

Der Stapel, der sowohl Daten als auch Programmcode darstellt, sollte in der Lage sein, eine Sequenz von Elementen unterschiedlicher Typen zu halten. Im einfachsten Fall werden Ints, Symbole und, wieder rekursiv, Stacks (um den zitierten Code darzustellen). Das Programm wird dann stark push! und pop! um Werte zwischen verschiedenen solchen Stapeln zu mischen.

Eine offensichtliche Implementierung in Julia, die funktioniert, aber ziemlich langsam läuft, ist die Verwendung von Zellen-Arrays. Beispielsweise kann der folgende Joy-Stapel [ 1 [ 1 2 +] i + ] (der auswertet) in Julia als stack = Any[:+,:i,Any[:+,2,1],1] implementiert werden. Meine typische Code sieht dann wie folgt aus:

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

Dies läuft jedoch sehr langsam und nutzt große Speicherzuordnungen, wahrscheinlich, weil ein solcher Code nicht typestable ist (was ein großer Performance-Engpass in Julia ist).

Verwendung von C, würde ich den Stapel kompakt als Array repräsentieren (oder alternativ als eine verknüpfte Liste) eine Vereinigung:

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

Stackelem stack[n]; 

Aber wie kann ich erreichen so eine kompakte Darstellung des heterogenen Stapels in Julia und wie vermeide ich die Instabilität?

Antwort

3

Dieser Weg ist, wäre eine andere Art und Weise args mit Typ-Vektor darzustellen {any}:

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

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

edit: Eine andere Art und Weise zu repräsentieren könnte sein:

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

und Sie dann kann Folgendes tun:

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

Ich verstehe Ihre Antwort nicht vollständig. Exp: Sind Tuples eine Datenstruktur, die sich für viele Operationen von Push und Pop eignet? Wie würden Sie einen Joy-Stapel darstellen, der keine Symbole enthält, z. [1 [2 3]]; würde dies verschachtelte Tupel beinhalten? unveränderlich: Was ist der Vorteil der Verwendung einer unveränderlichen Datenstruktur in diesem Zusammenhang? Würden nicht wiederholte Pops und Pushs zu hohen Performance-Kosten führen? – Bernd

+0

Vector {Any}: Was ist der Vorteil gegenüber dem Zellenarray von meiner Frage? Gibt es in Julia keinen besseren Weg, die möglichen Typen der Array-Elemente für den Compiler einzuschränken als Any? Und - was ist der idiomatische Weg zur Vermeidung von Typinstabilität bei der Verarbeitung eines solchen heterogenen Arrays? – Bernd

+0

Von Ihrem Beispiel oben wusste ich nicht, dass Joy keine Symbole hat, es sah aus wie eine typische AST. Hast du einen Link zur Joy-Syntax? –

Verwandte Themen