Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete Struct in Julia

Tags:

julia

I created a composite type

mutable struct Person
    id::Int64
end

This went fine, so I want to expand the type like this

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

but I am told that this is an invalid redefinition of constant Person.

How do I delete a type? Is there another way besides restarting the REPL? (Please, say yes.)

like image 397
Georgery Avatar asked Mar 15 '20 15:03

Georgery


2 Answers

This is unfortunately one of the few limitations of Revise.jl (and if there was a way to do it, it would probably be implemented in Revise). So even using Revise you currently have to restart julia to change the definition of a type.

Let me just try to illustrate the reason why this is currently not possible:

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




I sometimes use the following trick during the development stage of a new type. It is somewhat of a hack, though, and I'm not sure I should advise it: use at your own risk.

The idea consists in numbering your actual type definitions, naming your types like Person1, Person2 with a version number that is incremented each time the definition changes. In order to have uses of these numbered type names littered all over your code in method definitions, you can temporarily alias the latest definition to a common unnumbered name.

Suppose for example that you have a first implementation of your Person type, with only a name:

# 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

Now suppose you want to change the definition of the Person type to add an id field:

# 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
like image 180
François Févotte Avatar answered Oct 05 '22 03:10

François Févotte


No, this is not possible without restarting Julia.

like image 37
fredrikekre Avatar answered Oct 05 '22 04:10

fredrikekre