Var &= .method


#1

There are some situations when this code would be great to work:

foo = "foo"
foo &= .upcase if rand > 0.5
pp foo

It works for String and Number concatenation, however, + and - are just methods as well, so why not letting the syntax be more sweet with &=?

Just to be clear, the code above should expand to

foo = foo.upcase if rand > 0.5

#2

WDYT, Crystallers?


#3

Wouldn’t it make code harder to parse at least for humans?

Compare this straightforward to expand example (you don’t need to think about right side here, the &= defines the expansion):

left &= right
left = left & right

This is confusing however (the & and . come from different sides, and if there is . at the right side it expands differently now, and what’s worse the end result is not related to & operator at all):

left &= .right
left = left.right

Just from “looks good” standpoint it feels like your idea to shorten the code can be written as:

left .= right
left = left.right

However the . is not even an operator to begin with.

Using left &.= right probably looks even weirder.


#4

I’m not a fan of foo &= .something as &= is already an operator:

foo &= expr
foo = foo & expr # expanded

It would be confusing to have the same operator for 2 entirely different things… (AND binary operator, and short method calling)


Also left &= .right and @vlazar 's left &.= right looks like a call to left: left(&.=(right)), with the former being a weird typo…

@vlazar left .= right doesn’t look ‘right’, we can’t see the relationship between left & right


Another idea idea would be a = pseudo operator/method that takes a block:

foo = &.upcase
foo = foo.upcase # expanded

I like this syntax because it looks like crystal!! And I think it’s quite easy to guess what it does.


#5

@bew Not sure what you mean by “we can’t see relationship”. Visually it’s exactly the same rules as for left += right or any other operator, just ignore the spaces. Well also ignore that . is not an operator:

left += right
left = left + right # expanded

left .= right
left = left.right # expanded (plus spaces removed)

That being said I’m not sure this is a good idea as removing spaces and ignoring the “not operator” part doesn’t feel very consistent.

For your example with foo = &.upcase it’s easy to guess what it does, but &. now has quite clear semantic for blocks and overloading it with expansion syntax for assignment might not be a good idea as well.

Side note: I never made any language or part of it, I would guess there are tons of ways the introduction of some syntax might look very appealing on the surface but complicate language implementation exponentially.

It would be much more interesting to hear opinion on this matter from someone who has expertise on this. Maybe @asterite can chime in here and tell the kids why this is a terrible idea? :wink:


#6

I think left .= right expanding to left = left.right is the most intuitive syntax.

That said, I’m not sure this is that common or useful. And with this I mean “implementing it might be easy, but without carefully thinking about it it might interact badly with other features or even prevent us from using that syntax or that operator for something else in the future”.


#7

I disagree for left .= right, what I mean by not seeing relationships is that it looks like a call to a top level right method and even worse imo it looks like a call to =: left.=(right), which doesn’t make sense.

I agree .= would be kinda consistent with += expension logic, but to me it’ll do much more bad than good because it’s inconsistent / conflicts with the current call syntax


#8

Yeah. Syntax is very important, that’s why we love Crystal. But it’s also very hard and requires careful thinking.


#9

Just to throw that out there:

Ruby has method + ! as a sytax for I will modify my caller.
This could be interpreted without too much of a stretch as such:

a = a.split 
a.split!

Theoretically this would remove the ! from being a legal character in method names.
Also, major disclaimer, I have no idea of language design, I have not thought this through at all, and I’m not even sure I like it all that much, Just though to mention it as a option.


#10

& reminds me of the bitwise operator in an if statement. then when I see the foo &= .upcase part, it makes my head explode

I really like

foo = foo.upcase if rand > 0.5

it’s just so simple and easier to read (IMO)


#11

IMO this is a non-issue, not worth to solve it. The expanded version is easy to follow, doesn’t require to learn any new concepts and thanks to the postfix-if already short and fast enough to write.


#12

I ditto this statement, I’d need a lot of convincing to include this sugar in crystal, regardless of the syntax.