Struktur in Julia löschen

8

Ich habe einen zusammengesetzten Typ erstellt

mutable struct Person
    id::Int64
end

Das ging gut, also möchte ich den Typ so erweitern

mutable struct Person
    id::Int64
    contacts::Array{Int64}
end

aber mir wird gesagt, dass dies ein ist invalid redefinition of constant Person.

Wie lösche ich einen Typ? Gibt es neben dem Neustart der REPL noch eine andere Möglichkeit? (Bitte sag ja.)

Georgery
quelle
Haben Sie versucht, zu verwenden Revise?
Oscar Smith
Revise behandelt keine Strukturneudefinitionen, siehe timholy.github.io/Revise.jl/stable/limitations .
fredrikekre

Antworten:

17

Dies ist leider eine der wenigen Einschränkungen von Revise.jl(und wenn es einen Weg gäbe, dies zu tun, würde es wahrscheinlich in implementiert werden Revise). Selbst wenn ReviseSie dies verwenden, müssen Sie Julia derzeit neu starten, um die Definition eines Typs zu ändern.

Lassen Sie mich nur versuchen, den Grund zu veranschaulichen, warum dies derzeit nicht möglich ist:

julia> struct Person
           name :: String
       end

julia> alice = Person("Alice")
Person("Alice")

# Imagine you have some magic trick that makes this possible:
julia> struct Person
           id   :: Int
           name :: String
       end

julia> bob = Person(42, "Bob")
Person(42, "Bob")

# What should be the type of alice now?
julia> alice
Person("Alice") # Not consistent with the current definition of Person




Ich verwende manchmal den folgenden Trick während der Entwicklungsphase eines neuen Typs. Es ist jedoch ein Hack, und ich bin mir nicht sicher, ob ich es empfehlen sollte: Verwenden Sie es auf eigenes Risiko.

Die Idee besteht Ihre tatsächliche Typdefinitionen in Nummerierung, benennen Sie Typen wie Person1, Person2mit einer Versionsnummer , die jedes Mal erhöht wird die Definition ändert. Um die Verwendung dieser nummerierten Typnamen in Methodendefinitionen im gesamten Code zu verteilen, können Sie die neueste Definition vorübergehend auf einen gemeinsamen, nicht nummerierten Namen aliasen.

Angenommen, Sie haben eine erste Implementierung Ihres PersonTyps mit nur einem Namen:

# First version of the type
julia> struct Person1
           name :: String
       end

# Aliased to just "Person"
julia> Person = Person1
Person1

# Define methods and instances like usual, using the "Person" alias
julia> hello(p::Person) = println("Hello $(p.name)")
hello (generic function with 1 method)

julia> alice = Person("Alice")
Person1("Alice")

julia> hello(alice)
Hello Alice

Angenommen, Sie möchten die Definition des PersonTyps ändern , um ein idFeld hinzuzufügen :

# Second version of the type: increment the number
# This is strictly a new, different type
julia> struct Person2
           id   :: Int
           name :: String
       end

# But you can alias "Person" to this new type
julia> Person = Person2
Person2

# It looks as though you update the definition of the same "hello" method...
julia> hello(p::Person) = println("Hello $(p.name), you have id: $(p.id)")
hello (generic function with 2 methods)

# ...when in reality you are defining a new method
julia> methods(hello)
# 2 methods for generic function "hello":
[1] hello(p::Person2) in Main at REPL[8]:1
[2] hello(p::Person1) in Main at REPL[3]:1

julia> bob = Person(42, "Bob")
Person2(42, "Bob")

julia> hello(bob)
Hello Bob, you have id: 42

# alice is still of type "Person1", and old methods still work
julia> hello(alice)
Hello Alice
François Févotte
quelle
2
Ich mag deine Antwort wirklich. Es beantwortet die Frage, erklärt den Hintergrund und bietet eine wirklich gute Problemumgehung. Vielen Dank.
Georgery
5

Nein, dies ist nicht möglich, ohne Julia neu zu starten.

fredrikekre
quelle
Entschuldigung, was soll dieser Satz sagen?
Georgery
2
Ich denke, "das ist nicht möglich, ohne Julia neu zu starten."
DNF
Entschuldigung, ich habe meine Bearbeitung durcheinander gebracht. Behoben, danke.
fredrikekre