Outer constructors for type aliases overwriting each other

56 views
Skip to first unread message

Uri Patish

unread,
Feb 6, 2016, 8:27:04 AM2/6/16
to julia-users
Hi,

I've came across the following scenario and I can't say if the behavior I'm seeing is a matter of design, or if it's bug. I think the simplest way would be to post the code producing the behavior, so here it is, 

julia> type SomeType
         name::ASCIIString
         value::Int
       end

julia> typealias TypeA SomeType
SomeType

julia> TypeA(value::Int) = SomeType("A", value)
SomeType

julia> TypeA(2)
SomeType("A",2)

julia> typealias TypeB SomeType
SomeType

julia> TypeB(value::Int) = SomeType("B", value)
SomeType

julia> TypeB(2)
SomeType("B",2)

julia> TypeA(2)
SomeType("B",2)

The unexpected behvior was the result of the last call, which I expected to be SomeType("A", 2). I'm guessing that the julia parser is replacing whatever code comes his way with the last typealias, thus, the second method definition overwrites the first. 

My goal was to construct a single type, and have constructors with different names to produce different kinds of instances. I don't want to defined types with different names only to distinguish between different instances that are only different in their state but not by the structure of their type. 

Uri


Lutfullah Tomak

unread,
Feb 6, 2016, 9:20:23 AM2/6/16
to julia-users
'typealias' is not for defining new type but calling a type different names. Therefore, TypeA and TypeB names refer to and is replaced by the same type namely SomeType.

Having said that, You may do

type SomeType{T}
value::Int
end

Then, you can use typealias TypeA and TypeB as

typealias TypeA SomeType{:A}
typealias TypeB SomeType{:B}

You can have functions with SomeType{T} in general. When "A" or "B" is needed I guess you can use string(T) to get that.

Uri Patish

unread,
Feb 6, 2016, 10:13:30 AM2/6/16
to julia-users
Indeed, typealias is not for defining a new types, but merly to associate one type with other names. This is exactly the goal I'm trying to achieve here, having a single type, and defining few outer constructors. 

In the example you present, you in fact create two types that are only different in their name. I think this approach is wrong, if two type are exactly alike, having the same structure and costing the same number of bits, then their signature should be the same. 

What I was trying to achieve is to associate outer constructors with some type, and aliasing those constructors. 

Uri

Tim Holy

unread,
Feb 6, 2016, 10:29:13 AM2/6/16
to julia...@googlegroups.com
Int64, Float64, and Complex{Float32} are all effectively defined as

immutable Number64
data::NTuple{8,UInt8}
end

Do you realize that you're proposing that we stop distinguishing between
integers, floating-point numbers, and complex numbers? I don't think that would
make many people very happy.

The type itself is often used to encode differences in intended behavior, even
when the raw information is the same.

Best,
--Tim

Kevin Squire

unread,
Feb 6, 2016, 10:33:38 AM2/6/16
to julia...@googlegroups.com
If you remove the typealias line (typealias TypeB SomeType), you can still define an outer function that is, essentially, a constructor for SomeType.  The name won't also be an alias, of course.

Cheers,
   Kevin

Uri Patish

unread,
Feb 6, 2016, 11:06:31 AM2/6/16
to julia-users
Hi Tim, thanks for chipping in. 

You make a good point, and it goes to show that sometimes one would want to have different names for a types to indicate different behaviors, even though the data layout is exactly the same. 

What I'm wondering about is the case where the behavior is the same as well, and the type parameterization only standard for different groups of instances. In this case, and especially when the grouping is a product of different constructor initializations, it doesn't feel quite right to me to parameterize the type, and maybe a better design is to have few overloaded constructors. The problem that arises with this solution is that the different constructors cannot be aliased to shorter names without losing their association with the type. 

Uri

Lutfullah Tomak

unread,
Feb 6, 2016, 11:20:38 AM2/6/16
to julia-users
I cannot understand you well, I think then. Whenever you 'typealias' a type the new name will always be replaced with the actual type name before it is further compiled.
Your examples always converted to
TypeA(...) -> SomeType(...)
TypeB(...) -> SomeType(...)
Since both have the same argument types and number arguments the last one will be the one used later.
The most closest thing you can do is having 2 methods named TypeA and TypeB
that constructs two different instances of SomeType.

type SomeType
name::ASCIIString
value::Int
end

#No 'typealiase's
TypeA(x)=SomeType("A",x)
TypeB(x)=SomeType("B",x)

But TypeA and TypeB will not be 'type's.

I may have not understood you well but definetely, you cannot achieve what you want with 'typealias'.

Uri Patish

unread,
Feb 6, 2016, 12:31:54 PM2/6/16
to julia-users
I agree, the typealias idea won't work. The solution of having TypeA and TypeB methods indeed works, though its disadvantage is that now the methods aren't associated with the type. 

Reply all
Reply to author
Forward
0 new messages