2014-12-09 30 views
7

İlk not: Julia'da çalışıyorum ama bu soru muhtemelen birçok dil için geçerli.Julia'da değişken türlerin alanları ile değişmez bileşik türleri anlama

Kurulumu: şöyle bir kompozit türü var:

type MyType 
    x::Vector{String} 
end 

Ben MyType hareket etmeye bazı yöntemler yazın. Örneğin, x numaralı telefona yeni bir eleman eklememi sağlayan bir yöntem yazdım. function insert!(d::MyType, itemToInsert::String).

Soru:MyType değişken veya değişmez olmalı mı?

Benim anlayış: Ben Stackoverflow üzerinde soruları daha genel, hem de bu konuda Julia docs okumak (ve son derece upvoted) ettik (örn here veya here), ama yine de gerçekten iyi bir kolu yok bir pratik perspektiften den değişmez/kesilebilir olmanın anlamı

Yine de, burada benim girişimi (iletmenin türleri kesilebilir bir dizi içeren, özellikle değişmez bir kompozit tip durumu için!): MyType değişmez ise, daha sonra x alanın her zaman aynı nesneyi göstermesi gerektiği anlamına gelir. Bu nesnenin kendisi (Strings'in bir vektörü) değişebilir, bu yüzden ona yeni elemanlar eklemek benim için tamamdır. Ne yapmam izin vermemek'u değiştirip değiştirmektir, böylece alan x tamamen farklı bir nesneye işaret eder. Örneğin, aşağıdakileri yapın yöntemler tamam şunlardır:

MyType.x[1] = "NewValue" 
push!(MyType.x, "NewElementToAdd") 

Ama aşağıdakileri yapın yöntemler tamam değildir:

MyType.x = ["a", "different", "string", "array"] 

bu doğru mu? Ayrıca, değişmez tip alan değerlerinin kilitlendiği nesnenin yapıcıda oluşturulanlar olduğu fikri midir?

Son Nokta: Bu, SO hakkındaki diğer soruların çoğaltılması gibi görünüyorsa özür dileriz. Belirtildiği gibi, onlara baktım ve peşindeyim anlayışını elde edemedim. Yani burada

cevap

5

şey aklın (en azından bana) dikkate almak bükme edilir: vektör büyür ve yeniden tahsis edilmesi gerekmektedir olarak

julia> immutable Foo 
     data::Vector{Float64} 
     end 

julia> x = Foo([1.0, 2.0, 4.0]) 
Foo([1.0,2.0,4.0]) 

julia> append!(x.data, x.data); pointer(x.data) 
Ptr{Float64} @0x00007ffbc3332018 

julia> append!(x.data, x.data); pointer(x.data) 
Ptr{Float64} @0x00007ffbc296ac28 

julia> append!(x.data, x.data); pointer(x.data) 
Ptr{Float64} @0x00007ffbc34809d8 

Yani data adresi aslında değişiyor! Ama - işaret ettiğin gibi, verileri kendin değiştiremezsin.

% 100 doğru cevap olduğundan emin değilim. Öncelikli olarak, bazı performans kritik durumlarda, dokümanlarda Complex örneğindeki gibi basit tipler için immutable kullanın ve örneğin "savunma programlaması" nedenleri için yapıyorum. Kodun bu tür alanlara yazılmasına gerek yoktur, bu yüzden bunu yapmak için bir hata yapıyorum. Tür, her ne zaman, bir sayı, örneğin, bir sayının bir uzantısı olduğu zaman iyi bir seçim IMO'dur. Complex, RGBColor, ve bunları bir çeşit tuple olarak kullanıyorum, (tuplelar Julia ile şu anda iyi performans göstermiyorlar, değişmez tipler mükemmel performans gösteriyor).

+4

Julian dizileri Julia'nın kendisinde uygulanmadığı halde, bir dizinin birden fazla alana sahip olduğunu düşünüyorum (verilerin bulunduğu yerde bellek için boyutsallık ve işaretçi için). imleç (x.data) ', bu bellek alanının nerede olduğunu gösterir… ve vektör nesnesinin içinde * değiştirir. Ancak, denemenizi tekrarlamak için ['pointer_from_objref (x.data)'] (http://docs.julialang.org/en/latest/stdlib/base/?highlight=pointer_from_objref#Base.pointer_from_objref) ile denemenizi tekrarlayın. Vektör nesnesinin kendisi. –

+2

(julia.h: 88-120) (https://github.com/JuliaLang/julia/blob/master/src/julia.h#L88-L120) dizisi nesnelerinin bellekte nasıl düzenlendiğine bakın. çıplak C yapısı. –

+0

Ah bu daha mantıklı geliyor – IainDunning