Add custom chain method

I have comtom struct:

struct Ci
    pre::Union{Ci,String}
    next::String
end

I can add chain method to construct an instance of it:

(::Colon)(x::Vararg{String})=begin
    pre=x[1]
    for next_ in x[2:end]
        pre=Ci(pre,next_)
    end
    return pre
end

"a":"b":"c"

Ci(Ci("a", "b"), "c")

But it can not be added for this method, which is the same as above with just different unicode

(..)(x::Vararg{Union{String}})=begin
    pre=x[1]
    for next_ in x[2:end]
        pre=Ci(pre,next_)
    end
    return pre
end

"a".."b".."c"
syntax: extra token ".." after end of expression

I can not figure out what is going on?

Would I must to write like this:("a".."b").."c"

See this post, which references this post, which contains further references.

1 Like

It do a infix operator well:

"a".."b"
# Ci("a", "b")

while fail to this:

"a".."b".."c"

Maybe it is not a problem of infix operator?

Does it work with spaces between the operators?

You are probably right. I don’t know enough about ::Colon and parser restrictions (.. could clash with the broadcast operator . somehow?), but the following variations seem to work

(&)(pre::Union{String,Ci},next_::String)=return Ci(pre,next_)
    
@show "a"&"b"
@show "a"&"b"&"c"        

(..)(x::Vararg{String})=begin
    pre=x[1]
    for next_ in x[2:end]
        pre=Ci(pre,next_)
    end
    return pre
end

@show ..("a","b")
@show ..("a","b","c")

yielding

"a" & "b" = Ci("a", "b")
("a" & "b") & "c" = Ci(Ci("a", "b"), "c")
"a" .. "b" = Ci("a", "b")
..("a", "b", "c") = Ci(Ci("a", "b"), "c")
Ci(Ci("a", "b"), "c")

Edit: switching the operators doesn’t work in both cases…

(..)(pre::Union{String,Ci},next_::String)=return Ci(pre,next_)
    
@show "a".."b"
@show "a".."b".."c"     

fails with

ERROR: syntax: ".." is not a unary operator

and

(&)(x::Vararg{String})=begin
    pre=x[1]
    for next_ in x[2:end]
        pre=Ci(pre,next_)
    end
    return pre
end

@show "a"&"b"
@show "a"&"b"&"c"

fails with

ERROR: MethodError: no method matching &(::Ci, ::String)
1 Like

No, it does not. It appears the same error as above.

Note that there is no performance advantage to marking a field with a Union type over Any. It’s nice because it’s a bit selfdocumenting, but if you want it to be more performant you’ll want a parametric type. TIL

1 Like

That’s incorrect. Small unions of concrete types may still be stored inline.

Edit: The reason Ci here can’t be stored inline is due to it’s self-recursive definition. Annotating the type as a union will still allow the compiler to do union splitting, so it’s still better than Any performance-wise.

4 Likes