Assignment and named tuples

I love the (a=4) syntax which both assigns a variable and returns its value, for example:

vector = [(a=1+2+3)+4+5, a+4+5]

there is also a very similar syntax used in named tuples, (a=4,) which creates a tuple with a named element a. this is also useful since it lets you use keyword arguments:

function sample(a, b; word1, word2)
    [word1, a, word2, b]
end
sample(word2=3, 2, 4, word1=1)

however, these two syntaxes fight with eachother, and the second usually wins:

sample(word2=3, (a=2), a+2, word1=1)
#error: unsupported keword argument a

it appears that the parens are interpreted as precedence clarification, but since commas are already the lowest precedence, it doesn’t do anything, and ‘simplifies’ itself down to sample(word2=3, a=2, a+2, word1=1), which is an error. if someone actually meant to clarify precedence intent, they would likely do

sample(word2=3, a=(2), a+2, word1=1)

since this currently does nothing, could ‘parens assignments’ in function calls be fixed, or would that be considered a breaking change?

I think (a = 2) is meant to be equivalent to a = 2. If you need the result, use (a = 2;).

2 Likes

I personally am neither a fan of “hiding” the assignment a=2 in a function call nor “mixing“ keyword and positional arguments.

But one thing that does work is beyond storing the result, also returning it from the bracket (extending Vasily’s answer) as (a=2; a),
because otherwise even in the structured form

ample(a=2, a+1; word1=7, word2=3)

complains in the a+1 that a is not defined (in the parent scope) but

ample( (a=2; a), a+1; word1=7, word2=3)

does actually work, even in your order, “mixing” positional and keyword args

sample(word2=3, (a=2; a), a+1, word1=3)

I personally would actually prefer the slightly more readable form (IMHO)

a=2
sample(a, a+1; word1=3, word2=7)
1 Like

wait, what is the benefit of the second a? assignment statements already return their value, right?

sample(word2=3, (a=2;), a+2, word1=1)

does not error for me

Oh, that is interesting, then I confused something there. Note that on REPL

Julia>a=2;

suppressed the output (prints nothing). Then I was not careful enough and assumed the same for the term in brackets, but you are right, even on REPL

Julia>(a=2;)

returns 2, since the ; then acts as a “divider” between expressions, just there is not even a second expression following. So, sure, your variant works as well. The second a explicitly returns a (so you could also assign a and return 2a or so like in (a=2; 2*a) for example).

the parens only fail to assign when they don’t effect precedence; so if I wanted to return 2a I would do

sample(word2=3, (a=2)*2, a+2, word1=1)

as long as you’re using infix operators, the parens work on their own