Excluir Struct em Julia

8

Eu criei um tipo composto

mutable struct Person
    id::Int64
end

Tudo correu bem, então eu quero expandir o tipo assim

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

mas me disseram que isso é um invalid redefinition of constant Person.

Como faço para excluir um tipo? Existe outra maneira além de reiniciar o REPL? (Por favor diga sim.)

Georgery
fonte
Você já tentou usar Revise?
Oscar Smith
A revisão não lida com redefinições de estrutura, consulte timholy.github.io/Revise.jl/stable/limitations .
fredrikekre 15/03

Respostas:

17

Infelizmente, essa é uma das poucas limitações de Revise.jl(e se houvesse uma maneira de fazê-lo, provavelmente seria implementada no Revise). Portanto, mesmo usando Revisevocê atualmente, você deve reiniciar julia para alterar a definição de um tipo.

Deixe-me apenas tentar ilustrar o motivo pelo qual isso atualmente não é possível:

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




Às vezes, uso o seguinte truque durante o estágio de desenvolvimento de um novo tipo. É um pouco complicado, no entanto, e não tenho certeza se devo aconselhá-lo: use por seu próprio risco.

A ideia consiste em numerar suas definições de tipo reais, nomear seus tipos como Person1, Person2com um número de versão que é incrementado cada vez que a definição é alterada. Para ter usos desses nomes de tipo numerados espalhados por todo o código nas definições de método, você pode temporariamente alias a definição mais recente para um nome comum não numerado.

Suponha, por exemplo, que você tenha uma primeira implementação do seu Persontipo, com apenas um nome:

# 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

Agora, suponha que você queira alterar a definição do Persontipo para adicionar um 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
fonte
2
Eu realmente gosto da sua resposta. Ele responde à pergunta, explica os antecedentes e fornece uma solução alternativa realmente boa. Muito obrigado.
Georgery 15/03
5

Não, isso não é possível sem reiniciar Julia.

fredrikekre
fonte
Desculpe, o que essa frase deveria dizer?
Georgery 15/03
2
Eu acho que "isso não é possível sem reiniciar Julia".
DNF
Desculpe, estraguei minha edição. Corrigido, obrigado.
fredrikekre 15/03