Constructor takes Integer but not String

Viewed 2063

This works:

struct Comic
    endpoint::String
end

function Comic(id::Int)
    url = "https://xkcd.com/$id/info.0.json"
    Comic(url)
end


Comic(1)

It returns Comic("https://xkcd.com/1/info.0.json").

This doesn't work:

struct Comic
    endpoint::String
end

function Comic(id::String)
    url = "https://xkcd.com/$id/info.0.json"
    Comic(url)
end


Comic("1")

It kills the Julia process.

Why doesn't the second example work?

2 Answers

In your code Comic("1") calls Comic(id::String).

Comic(id::String) calls Comic(url) which again means calling Comic(id::String)

So you simply end up with an endless recursive loop.

The other answer explains why this crashes the Julia process; now, to make this work the way you intended, you can simply use an inner constructor:

julia> struct Comic
           endpoint::String
           Comic(id::String) = new("https://xkcd.com/$id/info.0.json")
       end

julia> Comic("1")
Comic("https://xkcd.com/1/info.0.json")

This works because new doesn't recursively call this constructor (which would lead to the crash). Instead it creates the object directly with the given string as its element.

Another option to consider is the URIs.jl package.

julia> using URIs

julia> struct XComic
          endpoint::URI
       end

julia> XComic(id::String) = XComic(URI("https://xkcd.com/$id/info.0.json"))
XComic

julia> XComic("4")
XComic(URI("https://xkcd.com/4/info.0.json"))

Related