Unexpected behavior defining a function on one line with semi-colons

EDIT: I was trying to confirm Taylor’s “barbaric” what would (or wouldn’t) happen similar to here; ran into other unexpected:

julia> f(x) = a=x; a=1; a="P"; # Why not last expression returned?

julia> f(2)
2

julia> f(x) = a=x; a=1; a="P"; return a;
ERROR: unsupported or misplaced expression return # Why?

julia> f(x) = begin a=x; a=1; a="P"; return a end # First version that does what I expected, still "barbaric"?

julia> f(2)
"P"

julia> f(x) = (a=x; a=1; a="P")

julia> f(2)
"P"

Not sure what you mean by ‘barbaric’, but in your first example

f(x) = a=x; a=1; a="P"

the last two assignments are not part of the function declaration. If you want to include them you have to have to put e.g. parentheses around them. What you have written is equivalent to this:

f(x) = a=x;  # defines function
a=1;  # defines variable
a="P" # reassigns variable
7 Likes

Thanks, I see it now… and will not make that mistake again (on the same line)… This should arguable (when on the same line) be an error (at least a warning). The “barbaric” comes from the link and is about assigning different types (I can see the value for that - but mostly in the REPL).

Note:

julia> a=1 a="P"
ERROR: syntax: extra token "a" after end of expression

I see the value in this, and also allowing with a ; separator, just not after a function definition.

Unless someone disagrees, I could try to make a PR disallowing for disallowing expressions, on the same line after a function definition, or at least open an issue.

About the “barbaric” part. Note:
julia> a=[1 1.0 “Palli”]
1×3 Array{Any,2}:
1 1.0 “Palli”

Julia is clever, but if you assign these three types to a scalar it changes types, should Julia infer the most general Any, (Or Float64 for just the first two?)?

Hold up for a moment. What are you suggesting? Disallowing multiple statements on the same line as a function definition? But not disallowing multiple statements otherwise?

A. Like I said, I will not make this error again, but is this useful (or something similar; not unlikely from beginners and/or people migrating from say C):

julia> a=1
1

julia> already_defined(a)=a
already_defined (generic function with 1 method)

julia> f(x) = a=x+1; already_defined(a); # Good result here: ERROR (or WARNING?) "Do not do more after a function definition on the same line"

Yes, I’m not proposing disallowing ; in general as separators. If I make a PR or an issue for the above case it would be to help others.

B. Nor, at least for now, changes to reassignment of variables with new types. Maybe that is very well thought out and has a reason. At least it’s helpful in the REPL to change your mind. Maybe not for code in functions, possibly a Linter is better for that case.

[I was quoting Gary Taylor’s “barbaric”, if people are sensitive to quoting others, I could stop… He’s saying languages like Julia, dynamic ones are barbaric, or people might say that.]

I’m no expert, but I’m a bit skeptical to this suggestion. It seems like the sort of “special casing” that the developers don’t like too much, where you replace a consistent, logical rule, with special case exceptions, for aesthetic reasons.

Right now, you can put as many statements on the same line as you like, but with your suggestion, this would break down a bit arbitrarily.

I don’t think there’s anything wrong with quoting in general. It’s just that, the way you did it, it made me think that ‘barbaric’ was some sort of well-known computer science expression I hadn’t heard before, but then turns out to be an offhand remark by someone in a Quora post. It was more confusing than illuminating.

Then I’ll not look into it much more, with no more support.

I did say or WARNING. It’s still mostly as much work to implement. I said I could look into making a PR, is that more welcome (would still need reviewing) than an issue?

I don’t know. I’m just offering an opinion and an argument to support it. If you disagree with my argument, and since you have no feedback from real experts, don’t let me stop you :slight_smile:

This doesn’t make sense in C because C is not a functional language. But Julia has functional constructs, so defining and using a function in one line is natural. I don’t think throwing an error or warning for something that is very natural in Julia because it’s not natural in C is the right direction to go. To many people who do not come from C, that error/warning would be very unnatural.

Because of this, syntax should never be argued from “naturality”. Instead, one core principle in Julia syntax is to be consistent. To error or warn here would be inconsistent, since ; just ends lines and lets you start a new one in the same line. There’s no magic there, and learning everything you need to know about how that syntax will work is contained in that statement (it works in arrays/matrices the same way for the same reason).

2 Likes

Wasn’t/am not aware it’s common; Ok, then people will just adjust to that possibility. I meant people are used to ; as separators, as i C, just an example language. There’s usually no harm in adding them (you shouldn’t), I guess many people will, at least at first.

julia> f(x) = (a=x; a=1; a="P") # Is this ever useful (inside tuples)or just dangerous to allow? Compared to below, as arrays unlike tuples can be 2D.

julia> f(2) # Compared to:
"P"

julia> f(x) = [a=x; a=1; a="P"]

julia> f(2)
3-element Array{Any,1}:
 2   
 1   
  "P"

julia> f(x) = (a=x, a=1, a="P")
ERROR: syntax: assignment not allowed inside tuple  # Good that this is an error; compared to similar in the array case would be possible (as it should).

I’d say that’s pretty useful. I have myself done this several times. It’s a compound statement, which is a pretty ordinary thing, Without this you could never define functions in short form with more than a single statement.

2 Likes

Yeah compound, I meant is it ever useful in this specific tuple context (clarified that), as shown, not in general: I have noting against:

`julia> f(x) = begin a=x; a=1; a=“P” end # Not the same thing.

Already the array context means a different thing, not “compound” there. And since assignments with commas disallowed for tuples there are restrictions.

Yes, I use it a lot. Here’s one example off the top of my head:

https://github.com/JuliaDiffEq/ODE.jl/blob/master/src/common.jl#L24

It builds an anonymous function which changes a user’s in-place updating f(t,u,du) ODE function to one which is not in-place updating du=f(t,u) since ODE.jl cannot handle the in-place form. Sure, I make that multiple lines, but this is nice, succinct, and easy to read. And again, there’s no special casing here: understanding how it works is just following the rules set out by Julia for what ; means.

2 Likes

No it doesn’t.

A = [0 2
     3 4
     5 6]

creates a matrix. ; causes new lines, so

A = [0 2 ; 3 4 ; 5 6]

is the same matrix.

To continue:

A = 1:2
B = 3:4
C = [A
     B]

is vertical concatenation of vectors (vcat). So it makes sense that

C = [A;B]

is vertical concatenation.

1 Like