Удалить структуру в Юлии - PullRequest
8 голосов
/ 15 марта 2020

Я создал составной тип

mutable struct Person
    id::Int64
end

Все прошло нормально, поэтому я хочу расширить тип как этот

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

, но мне сказали, что это invalid redefinition of constant Person .

Как удалить тип? Есть ли другой способ, кроме перезапуска REPL? (Пожалуйста, скажите да.)

Ответы [ 2 ]

17 голосов
/ 15 марта 2020

Это, к сожалению, одно из немногих ограничений из Revise.jl (и если бы был способ сделать это, он, вероятно, был бы реализован в Revise). Поэтому, даже используя Revise, вы в настоящее время должны перезапустить julia, чтобы изменить определение типа.

Позвольте мне просто попытаться проиллюстрировать причину, по которой это в настоящее время невозможно:

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

Иногда я использую следующий трюк на этапе разработки нового типа. Однако это отчасти хак, и я не уверен, что должен посоветовать: использовать на свой страх и риск.

Идея состоит в том, чтобы нумеровать ваши фактические определения типов, называя ваши типы как Person1, Person2 с номером версии, который увеличивается каждый раз при изменении определения. Чтобы использовать эти нумерованные имена типов во всех кодах в определениях методов, вы можете временно присвоить псевдониму последнее определение общему ненумерованному имени.

Предположим, например, что у вас есть первая реализация вашего * Тип 1021 *, только с именем:

# 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

Теперь предположим, что вы хотите изменить определение типа Person, добавив поле id:

# 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
5 голосов
/ 15 марта 2020

Нет, это невозможно без перезапуска Джулии.

...