Aliases for `=` and `==`

I’d be, for once, surprised if writing: x = -5; x <-4 would return -4 or nothing instead of true, because I missed a space there, and there may be existing code that does miss it.

2 Likes

These operators exist on R (in both directions) and as I have never seen an assignment with an omitted space, I had never thought about this problem (and I wonder how they handle it on R and if such a mistake is common…). At least, no problem with a hypothetical one-character Unicode operator.

R 4.0.3

> x = -5
> x<-4
> x
[1] 4
> x < -4
[1] FALSE

Julia usually raises a syntax error for ambiguous parses.

4 Likes

could be an alias of ==, but I don’t think I’d ever want to use unicode for that specifically. I could see some value in creating a unicode alias for copy and deepcopy with assignment. That is, if the alias is then b ≍ a could mean b = copy(a) or perhaps b = deepcopy(a). Not sure if I would use that either.

The reason why python needs := is simple: python is not an expression-first language, which means that you cannot use assignment statements inside expressions. Hence, an extra syntax for Python is required to bind variables inside expressions.

Julia is born an expression-first language and has no such inconsistency – simply = is enough.

6 Likes

Python could have lifted = into an expression (and it has done for other statements) but wisely did not.

In Julia, using = for assignment makes it possible to confuse

value = false
if (value == x) # depends on equality

with

value = false
if (value = x) # depends on x

Python doesn’t have this problem, which is good because in Python it would be much more severe, since everything behaves like a boolean under if. This danger is the reason that people use Yoda conditions in some languages. (Yoda conditions aren’t generally used in Python because they’re not necessary.)

It’s not quite as widespread a problem as it looks since Julia will catch the case without parentheses, but = and == are nonetheless uncomfortably close and it would be better to have more visual distinction.

In particular, see the section “Can this feature be a problem in Julia?”

6 Likes

I don’t think it’s so unlikely to have two boolean variables in a condition.

Edit: Nor is it uncommon to want parentheses for clarity.

Have you read the post at all?

I think this consideration is well covered by Julia.

Julia firstly needs the expressiveness. Unlike giving many syntactic restrictions to programmers by default, Julia needs to consider the convenience of metaprogramming, so that making inconsistent syntax rules for = or := is not that appealing in Julia.

If you want the same functionality(i.e., syntactic checking of =) as Python’s, I think it should be implemented as a macro and provided by a library.

2 Likes

Yes, it says that writing if (a == b) is unlikely (but I disagree), and points out (as I did above) that not using parens avoids the problem.

[Edited to fix “not”]

Maybe jzr means not only “top-level” = in a condition?

Yeah

if (a == b) & (c = d) & (e == f); 4 end

doesn’t do what I want for example. (If that’s what you mean @thautwarm ?)

It is often helpful to use parentheses to avoid confusion in, say,

a == b && c == d  

to distinguish between

(a == b) && (c == d)

and

a == (b && c) == d

but the parentheses allow a bug to go unnoticed.

On reflection I think @giordano’s point that

it is kind of useless to test equality with a Bool as a condition, since you can use the Bool itself.

mostly obviates my earlier link to Yoda conditions: they aren’t usually helpful in Julia since if true == x can just write if x, and when the left-hand side is a variable Yoda conditions mostly won’t help anyway. One exception is a const Bool, like if (COND = x) || ... which would error for reassignment of const variable and hence be a useful case for the Yoda condition.

Yes, and that’s what this proposal is meant to address. While getting rid of = completely would be a hugely breaking change and require throwing out a lot of old code, asking programmers to get into the habit of using := and =? instead of = and == could prevent a lot of bugs like this.

It seems like your guess is that this situation – (a == b) where a::Bool b::Bool – is common but that @giordano’s guess is that it isn’t. I think we need some data to resolve that question.

2 Likes

I don’t expect cases that completely slip through the compiler without generating an error or some kind of warning are exceptionally common, but I don’t doubt they . I assume they happen from time to time simply because of the size of the community, though. In addition, accidentally using = when == is meant is an extremely common error, and whenever I read if (x = y) in someone else’s code, my brain immediately parses it as the more common if x == y. I don’t see a reason to encourage this when we could essentially eliminate these kinds of errors by asking people to use := and =? instead.

I think the first part could be fixed pretty easily by using something like =?= or =?? to test for identity.

I also think you made my point for me in terms of the low costs of adding this – \equiv has already been added to Julia, yet nobody who likes to use === instead has suddenly forgotten how to use ===, gotten very confused by it, or referred to it as “Useless.” It’s just a more legible version of ===, much like how := is a version of = that won’t get confused with ==. Something like \triangleq doesn’t really seem to have any kind of obvious use.

I don’t think anyone would expect >? because > is already unambiguously a check. People instinctively assume = means a test for equality when they start programming because it looks like that’s what it means, and think that assignments like x = x+1 are unnatural and should just return false. Nobody comes to programming thinking > will increase the number on the left until it becomes bigger than the number on the right.

I’m not suggesting people modify their own Julia code to implement this, which would obviously be a pretty dumb idea. I just think implementing := and recommending it over = would improve readability and make things make more sense. (Much like how <- is much more common than = in R, despite = existing to keep programmers from getting confused.)

All languages have these kind of problems (bugs introduced by a typo), unless they are incredibly verbose or full of special cases. It is a trade-off.

A linter may be the best place to catch a problematic = in an if.

7 Likes