Why does the + function appear to work on tuples?

孤人 提交于 2020-01-14 08:30:15

问题


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

julia> +((1, 2))
3

However, using the + function on a variable that references a tuple gives the following error:

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

I'm having trouble understanding why it behaves like this, especially when the following code returns true.

julia> typeof(a) == typeof((1, 2))

回答1:


Note that, contrary to what you might 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 noted, does not work on tuples.) Is this behavior desirable? Well it was reported as a bug #12755, but then fixed. But the fix caused bug #12771 which resulted in the fix being reverted by pull #12772.

The solution to this mess is to avoid calling operators as functions without explicitly writing parentheses. That is, always write (+)(1, 2) instead of +(1, 2). You can verify that (+)((1, 2)) throws the error that you expect.

(This problem only occurs with unary operators, hence why | and * are not subject to it.)


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

  • In -(x+y)^2, it is highly likely that (-)((x+y)^2) was meant, not ((-)(x+y))^2. So we cannot simply unconditionally parse -( as a function call.
  • Instead what must be done is the thing after - parsed up to a certain precedence, so that -x * y is parsed as (-x) * y, -x + y as (-x) + y, but -x^y as -(x^y).
  • Exception: But this would make -(1, 2) parse as (-)((1, 2)), that is, a function called on a tuple. For whatever reason or another, it was decided to add an exception for when the thing after - looks like a function call tuple. This is so that +(1, 2) would work, but this is really mostly just a hack.
  • But from the parser's perspective, ((1, 2)) looks exactly like (1, 2); just the former is wrapped in parentheses.

My personal opinion is that the -(1, 2) notation is silly (and doesn't work in all cases anyway; e.g. in -(1, 2)^2). If that exception weren't around, and -(1, 2) consistently parsed as a unary function call on a tuple, then more consistency could be had without (I think) much loss. It's not too bad to just write 1 - 2 or (-)(1, 2) when a binary function call is desired.



来源:https://stackoverflow.com/questions/43262045/why-does-the-function-appear-to-work-on-tuples

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!