Defining a custom constructor for a type alias?

This snippet is invalid:

boo = Array{Stuff,1}

function boo(x,y,z)
    someStuff = .....
    return someStuff
end

It returns this error:

cannot define function boo; it already has a value

Would you have any idea about defining a custom constructor for a type alias?
Would it be possible, or doesn’t it make any sense?

Thanks

Michel

You can’t define constructors for aliases. This is because aliases aren’t a new type. They’re just a new name. As such, if you want to define this constructor, you would have to define a constructor for 1 dimensional arrays of Stuff. What you probably want is

struct boo
    stuff::Array{Stuff}
end

Then you’re actually making a separate thing which can have it’s own methods.

Thanks Oscar
This is what I did, but this makes the data one step (dot) further away.
I can’t understand why this is not possible.
Thanks,
Michel

You can, they just need to be const, but then they can return anything, e.g. this works:

struct Stuff end
const boo = Array{Stuff,1}
boo(x,y,z) = "boo"
boo(1,2,3) # returns "boo" 

As long as you’re not commiting type piracy by say defining a new constructor for Array{Int,1}, I think this is reasonable to use.

2 Likes

BAM !!!

So I just had to add a const to the snippet and it works!

const boo = Array{Stuff,1}

function boo(x,y,z)
    someStuff = .....
    return someStuff
end

I like Julia! Looks so logical.
But in this case, why does the const make all the difference?
At least a (potentially) “variable” type would make little sense.

Thanks

Michel

1 Like

What is the use case you have? I do not understand where that can be useful.

Thanks to ask, leandrom, it makes me thing again!

First, I like to use alias, just to improve readability.
When specifying type in method signature, having a familiar name is more readable than having thing like

Array{Stuff,1} where stuff can also be “complicated”

Second, the default constructor for an alias can be sufficient, but of course it might happen that I need a more specialize constructor. In my last example, it was simply constructing from a dictionary with some selection.

Before I learned that an alias must be const , I had to use the solution proposed by Oscar_Smith which add a layer.

What is your point of view? Would you suggest to avoid using an alias?

Michel

I would not be pretentious to “have a point of view” that deserves really to be taken into consideration because I am still learning. Nevertheless, I would mention these points below.

First, I just realized that there are cases where aliases are created with the purpose you have in mind. For example in StaticArrays, we have const SVector{S, T} = SArray{Tuple{S}, T, 1, S}.

Nevertheless, I was thinking in the following points:

  1. Using the alias will make the code less clear to everyone else and, in the future (when you forget why the alias was defined), to you as well. The standard syntax everyone understands. Unless, of course, if the purpose of the package is to provide the new type, such as in the example above.

  2. You do not really need an alias just for creating a complicated type. Just write a function with the name you want, for instance. In many cases that will be more clear than the alias, probably.

julia> struct A
         x 
       end

julia> function initialize_vector_of_A(n) 
         return Vector{A}(undef,n)
       end
initialize_vector_of_A (generic function with 1 method)

julia> a_vec = initialize_vector_of_A(10)
10-element Array{A,1}:

  1. It is common to use aliases when the types become long, for example with unions const MyTypes = Union{MyTypeA,MyTypeB,MyTypeC}, but that is for simplifying the annotations of function dispatch mosty. For example:
julia> struct A x end

julia> struct B x end

julia> struct C x end

julia> const MyTypes = Union{A,B,C}
Union{A, B, C}

julia> f(a::MyTypes) = a.x
f (generic function with 1 method)

julia> a = A(1);

julia> f(a)
1

julia> f(1)
ERROR: MethodError: no method matching f(::Int64)

  1. Specialized constructors can be defined as you wish, using functions as I mentioned above, or if you have a new type, like Stuff, using new constructors Stuff(...) = or new(..) inside the definition of Stuff.

  2. Just to point that Vector is an alias for Array{T,1}, which simplifies that the notation a little to Vector{Stuff}, and it is important that the meaning of that is very transparent.

1 Like

Thanks a lot, Leandro.
For a beginner, like me, such discussions help build more self-confidence, which is as useful as the documentation.
Michel

2 Likes