Stream: helpdesk (published)

Topic: Creating parallel types in order to dispatch


view this post on Zulip Davi Sales Barreira (Jan 25 2022 at 14:49):

I have a struct in which I'd like to create a "parallel" or "auxiliary" type, in order to make use of multiple dispatch, and I was wondering how this could be done... Here is a non-working example with the gist of what I'd like to do:

abstract type ShapeParameter end
abstract type SizeParameter end
struct Example
 x :: Real <: ShapeParameter
 y :: Real <: SizeParameter
end

Now, I can of course just do:

struct ShapeParameter
 shape::Real
end
struct SizeParameter
 size::Real
end
struct Example
 x ::ShapeParameter
 y ::SizeParameter
end

But this solution has the down side that now I cannot just do Example().x.

And since it's related. I was wondering if it would be possible to similarly create "alternate" types such as PositiveReal, NegativeReal and so on. Such that 1.0 <: Real is true and so is 1.0 <: PositiveReal.

view this post on Zulip Sundar R (Jan 25 2022 at 15:08):

Would this work for you? Edit: this is wrong :cross_mark:

julia> ShapeParameter = Real
Real

julia> SizeParameter = Real
Real

julia> struct Example
         x :: ShapeParameter
         y :: SizeParameter
       end
julia> ex = Example(4.5, 3.14)
Example(4.5, 3.14)
julia> f(r::Real) = "real arg"
f (generic function with 1 method)

julia> f(s::ShapeParameter) = "shape arg"
f (generic function with 1 method)

julia> f(ex.x)
"shape arg"

view this post on Zulip Sundar R (Jan 25 2022 at 15:12):

You can also use the solution in your post, and fix

But this solution has the down side that now I cannot just do Example().x

by defining getproperty and setproperty! methods for the Example type that pass the operations through to the underlying Real value

view this post on Zulip Davi Sales Barreira (Jan 25 2022 at 15:21):

Sundar R said:

Would this work for you?

julia> ShapeParameter = Real
Real

julia> SizeParameter = Real
Real

julia> struct Example
         x :: ShapeParameter
         y :: SizeParameter
       end
julia> ex = Example(4.5, 3.14)
Example(4.5, 3.14)
julia> f(r::Real) = "real arg"
f (generic function with 1 method)

julia> f(s::ShapeParameter) = "shape arg"
f (generic function with 1 method)

julia> f(ex.x)
"shape arg"

@Sundar R , your example didn't work :(

view this post on Zulip Davi Sales Barreira (Jan 25 2022 at 15:22):

I mean, it's actually just calling the function that was more recently defined.

view this post on Zulip Davi Sales Barreira (Jan 25 2022 at 15:24):

Can you expand on the solution with getproperty?

view this post on Zulip Sundar R (Jan 25 2022 at 15:32):

Davi Sales Barreira said:

Can you expand on the solution with getproperty?

julia> import Base: getproperty

julia> function getproperty(ex::Example, sym::Symbol)
         if sym == :x
           getfield(ex, :x).shape
         elseif sym == :y
           getfield(ex, :y).size
         else
           getfield(ex, sym)
         end
       end
getproperty (generic function with 47 methods)

julia> ex = Example(ShapeParameter(4.5), SizeParameter(3.14))
Example(ShapeParameter(4.5), SizeParameter(3.14))

julia> ex.x
4.5

julia> ex.y
3.14

view this post on Zulip Davi Sales Barreira (Jan 25 2022 at 15:43):

Thanks!

view this post on Zulip Sundar R (Jan 25 2022 at 15:54):

That's kind of a problematic solution too though, now that I think about it. Any time you access the fields, we're throwing away the type information, so in most circumstances this would be similar to them being just Real types (for the purpose of dispatch).


Last updated: Oct 02 2023 at 04:34 UTC