Why does the + function work with tuples?

Using the + function in a tuple of two Int64s returns the sum:

julia> +((1, 2)) 3 

However, using the + function for a variable that refers to a tuple gives the following error:

 julia> a = (1, 2) (1,2) julia> +(a) ERROR: MethodError: no method matching +(::Tuple{Int64, Int64}) 

I am having trouble understanding why it behaves this way, especially when the following code returns true.

 julia> typeof(a) == typeof((1, 2)) 
+7
syntax julia-lang
source share
1 answer

Please note that, contrary to what you think,

 julia> :(+((1, 2))) :(1 + 2) 

This is a single function call equivalent to (+)(1, 2) . There is no tuple, although the syntax may look like there is a tuple. (The + function, as you have noticed, does not work with tuples.) Is this behavior desirable? Well, this was reported as bug No. 12755 , but then fixed. But the fix caused error # 12771 , as a result of which the fix was returned by pull # 12772 .

The solution to this problem is to avoid calling operators as functions without explicitly writing parentheses. That is, always write (+)(1, 2) instead of +(1, 2) . You can check that (+)((1, 2)) produces the expected error.

(This problem only occurs with unary operators, so why | and * do not obey it.)


If you're interested, the essence of this problem is the fundamental ambiguity between the syntax of the functions +(x, y) and the syntax of a unary operator. Here are a few situations that motivate parsing of + and - as unary operators, even if followed by ( :

  • In -(x+y)^2 , it is very likely that this means (-)((x+y)^2) , and not ((-)(x+y))^2 . Therefore, we cannot simply unconditionally parse -( as a function call.
  • Instead, you need to do what is after - parsed to a certain priority, so -x * y parsed as (-x) * y , -x + y as (-x) + y , but -x^y as -(x^y) .
  • Exception: But this would make -(1, 2) syntax as (-)((1, 2)) , that is, a function called a tuple. For one reason or another, it was decided to add an exception when the thing after - looks like a tuple of a function. This means that +(1, 2) will work, but in reality it is just a hack.
  • But from the point of view of the parser ((1, 2)) looks exactly like (1, 2) ; only the first is enclosed in parentheses.

My personal opinion is that the notation -(1, 2) stupid (and generally does not work in all cases, for example, in -(1, 2)^2 ). If there was no exception, and -(1, 2) sequentially analyzed as a unary function call on a tuple, then more consistency could be achieved without (I think) a lot of loss. It's not so bad to just write 1 - 2 or (-)(1, 2) when you need to call a binary function.

+6
source share

All Articles