Eliminar estructura en Julia

8

Creé un tipo compuesto

mutable struct Person
    id::Int64
end

Esto salió bien, así que quiero expandir el tipo como este

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

pero me dicen que esto es un invalid redefinition of constant Person.

¿Cómo elimino un tipo? ¿Hay otra forma además de reiniciar REPL? (Porfavor di que si.)

Georgery
fuente
¿Has intentado usar Revise?
Oscar Smith
Revisar no maneja redefiniciones de estructuras, ver timholy.github.io/Revise.jl/stable/limitations .
fredrikekre

Respuestas:

17

Desafortunadamente, esta es una de las pocas limitaciones de Revise.jl(y si hubiera una forma de hacerlo, probablemente se implementaría en Revise). Entonces, incluso si usa Reviseactualmente, debe reiniciar julia para cambiar la definición de un tipo.

Permítanme tratar de ilustrar la razón por la cual esto no es posible actualmente:

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




A veces uso el siguiente truco durante la etapa de desarrollo de un nuevo tipo. Sin embargo, es un truco, y no estoy seguro de que deba aconsejarlo: úselo bajo su propio riesgo.

La idea consiste en numerar sus definiciones de tipo reales, nombrando sus tipos como Person1, Person2con un número de versión que se incrementa cada vez que cambia la definición. Para poder utilizar estos nombres de tipo numerados en todo el código en las definiciones de métodos, puede alias temporalmente la última definición a un nombre común sin numerar.

Supongamos, por ejemplo, que tiene una primera implementación de su Persontipo, con solo un nombre:

# 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

Ahora suponga que desea cambiar la definición del Persontipo para agregar un idcampo:

# 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
fuente
2
Realmente me gusta tu respuesta. Responde a la pregunta, explica los antecedentes y proporciona una muy buena solución. Muchas gracias.
Georgery
5

No, esto no es posible sin reiniciar Julia.

fredrikekre
fuente
Lo siento, ¿qué se supone que debe decir esta oración?
Georgery
2
Supongo que "esto no es posible sin reiniciar Julia".
DNF
Lo siento, estropeé mi edición. Fijo, gracias.
fredrikekre