Broadcasting `$` as a binary operator

It’s possible to define $ as a binary operator, but it turns out you can’t use it with broadcasting:

julia> ($)(x, y) = x + y
$ (generic function with 1 method)

julia> 1 $ 2
3

julia> [1, 2] .$ [3, 4]
ERROR: ParseError:
# Error @ REPL[3]:1:7
[1, 2] .$ [3, 4]
#     ╙ ── whitespace is not allowed here

This seems to be intentional, since the old julia-parser.scm file has this code in it, where $ is explicitly excluded from the the add-dots call:

(define prec-plus (append! '($) (add-dots '(+ - # ...

I’m guessing it has to do with a parsing ambiguity related to expression interpolation, or something like that, but I can’t point to exactly what the issue is. Does anyone know why binary $ is excluded from broadcasting?

1 Like

Just as a side note, broadcasting works without the dot fusion:

broadcast($, [1, 2], [3, 4])
1 Like

what

3 Likes

Yeah, it also works with @.:

julia> @. [1, 2] $ [3, 4]
2-element Vector{Int64}:
 4
 6
1 Like

From parse more dot operators, parse .= with assignment precedence by stevengj · Pull Request #17393 · JuliaLang/julia · GitHub :

The exceptions are operators with very special syntactic meanings, like $ and ||. (Some of these could be allowed, but I wanted to be conservative to start with).

The case of $ was never re-visited, apparently.

2 Likes

this by itself is so cursed already, feels like we should have disallowed that (given how $ is used for “interpolation” in many context

2 Likes

Yeah, the meaning of $ is heavily overloaded in that case, but it could be nice for some things, like as a function application operator, which is how $ is used in Haskell and in this Julia package:

I had a use case in mind similar to function application.

1 Like

I assume that $ works this way to mirror :, which is also a syntactic operator in prefix form, but a function operator in infix form. Moreover, : cannot be broadcasted either.

(I don’t like it either :angry: )

Edit: To add to this, the exact ambiguities are the following:

julia> p = :prop; :(obj.$p) # Not broadcasting, but interpolation
:(obj.prop)

julia> julia> :(a.:b) == :(a.b) # not broadcasting either
true
4 Likes