I have a simple function that changes the first element of any matrix to the number 99. It looks like this:

function foo(a)
a[1] = 99
end

Now when I apply the function to a matrix, here’s what I get:

x = [1 2 3 4 5];
y = foo(x);

I’m confused, because applying foo to x has mutated the first element of x as expected, but the output y is just the number 99.

julia> x
1×5 Matrix{Int64}:
99 2 3 4 5
julia> y
99

What exactly is the logic here? How is the function able to mutate x, then seemingly forget about the other elements in x before spitting out a scalar value y?

I would advise against this. It becomes super difficult to read. The oneliner is fine, but since there are no return statements in if blocks, it always takes a while to figure out what points are the final ones.

if x < 0
a = 0
elseif x < 1
a = 1
else
a = 2
end

is a lot better than

a = if x < 0
0
elseif x < 1
1
else
2
end

. And the difference gets bigger the more complicated the statement is.

No, I have not, and I’m increasingly convinced I don’t want to.

With functions it’s mostly obvious where the return value is, and if it’s not you can mark it with return. In an if clause you don’t have that option. Add to that the fact that the major action, the assignment, is all the way at the top, so if I’ve figured out what it returns I now need to scroll all the way back to remind myself where it’s stored. And some but not all if clauses are assignments. Meanwhile, “if x is small, assign 0 to a” is natural.

I recently implemented a feature in JuliaFormatter, but I ironically had to spend most of the time just figuring out heads or tails of all the if-assignments in there. It’s fixed now though.

You can wrap the if clause in a begin block which then allows you to return from there.

For short if-clauses an assignment inside can be nice. For larger ones – as in the example above – I find the assignment outside better as it immediately makes clear where the value of a comes from. In the other case, it could well be that every branch assigns a different variable!

if x < 0
a = 0
elseif x < 1
b = 1 # oops
else
a = 2
end

In any case, if I need to scroll over the if-clause it is probably time to at least move it into its own function or better yet, break the logic into smaller pieces.