4 ms·
I have to admit I was really not excited to see this: var answer = if number == 42 The language looks shockingly pleasant in a number of ways, but everyth
by mangeletti 11y ago
I have to admit I was really not excited to see this:
var answer = if number == 42
The language looks shockingly pleasant in a number of ways, but everything being an expression seems odd. Would somebody mind helping me understand the value (semantic, performance, etc.) of such a choice?
- dustingetz 11y agoExpressions compose
- untog 11y agoCoffeeScript (which this is forked from) has some parts like this that I strongly dislike, such as using the unless keyword after an action. For example: doSomeThing() unless person.present For me that utterly destroys readability - in my mind, when I see a (), that function is being called there and then. The fact that you can invalidate that later in the line confuses me deeply - and it doesn't really provide any benefits above an if statement anyway. The rest of CoffeeScript is great though, don't get me wrong. (though ES6 JavaScript has taken the best features anyway)
- applecore 11y agoThe unless keyword is very useful for when you're testing an exit condition, e.g., return unless...
- mangeletti 11y agoTo play devil's advocate, when using Python's ternary operator like this: something() if False else y The `something` function is never called.
- matthewmacleod 11y agoThat's not specific to 'unless' – it's the general postcondition style that's is derived from Ruby. Indeed, for single-line if statement bodies in Ruby, it's the recommended style. It fits the style of Ruby to try and cut down on syntax noise where it's not needed. Contrast: save! if !record.persisted? && !record.invalid? save! unless record.persisted? || record.invalid? Though I do appreciate it's a bit unusual compared with most other languages – CoffeeScript does owe a lot to Ruby's syntax.
- untog 11y agoThat's not really the part of unless that bothers me - it's the order. Why not do: if !record.persisted? && !record.invalid? save! or: unless record.persisted? || record.invalid? save!
- kbenson 11y agoThe behavior here, if it comes from Ruby, almost definitely has it's legacy in Perl, so you can look to Perl for justifications. The main justification is likely to be that's a natural construct of how we think and communicate, so why not allow us to express ourselves that way? Another way to look at it is why do you think the conditional should come before like you've shown? Because C or even older languages started with that? If you didn't have prior experience with that form, would you still think it's inherently better, or would the trade-offs between the two forms seem slightly more balanced?
- matthewmacleod 11y agoI guess it's generally just that it's regarded as fairly idiomatic Ruby. bbatsov's popular style guide, for example (https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier): The same applies to while/until loops, which can lead to quite succinct code. I've been using it for a long time, so I don't find it confusing at all – but I agree it's pretty rare to find, so I'm not surprised to find out some people would rather not see that!
- vlunkr 11y agoWell just don't use the unless keyword then. I've used CS for years and I don't use it.
- untog 11y agoWell sure. But I live in a weird world where I sometimes have to work with code other people wrote, as well as my own.
- kbenson 11y agoAs a Perl programmer, I'm often using contructs like that, and I think they have a place, but you should restrain yourself from using them in places where they can easily be misunderstood. For example, they work really well in loop control statements: for my $i (1 .. 100) { next if $i == 10; next if skippable($i); last if is_what_we_want($i); # Do stuff here } Or more complex param validation sub foo( $arg1, $arg2 ) { return unless $arg1 > 10; die "Invalid argument arg2!" unless defined $arg2 and $arg2 =~ /^(?:CAT|DOG|GERBIL)$/; # Do something } That said, I don't like it for assignment of in that manner (at least where the assigned value comes out of the if), because the main justification for allowing it (it's a natural extension of how we think) doesn't follow. A ternary operator is better in that instance, IMHO.
- Q6T46nT668w6i3m 11y agoTechnically, the language has patterns (e.g. identifiers) too. A major semantic benefit of expression-oriented programming is minimizing state while maximizing composition (e.g. compare and contrast a switch statement to pattern matching).
- matthewmacleod 11y agoThis comes directly from Ruby via Coffeescript. It's aligned with a general approach of reducing syntax noise, and it can result in some really nice, clean code. It leads to a whole class of syntax possibilities, like implicit returns. There are probably some performance arguments against this in the case of Coffeescript, especially wrt constructing expensive return values that are immediately discarded. The consistency is nice, however.
- kbenson 11y agoDoes Ruby allow the value of the if statement to be used as the RHS of an assignment? That's surprising. In Perl, which I assume they got that from (it's a fairly safe bet, Ruby is heavily Perl influenced), postconditionals are not allowed to be used as a statement, they are statement modifiers. You can do this: $v = 1 if $v < 1; return unless defined $param; die "died!" unless $param > 10; But you cannot: $v = if $v; You also cannot use else on postconditionals (if it's that complex, you need a traditional if statement).
- matthewmacleod 11y agoAh, that's interesting – they become expression modifiers instead. x = (:false if true) => :false x = (:false if false) => nil Any other if statement does appear to be treated as a value: x = if true then 5 else 10 end => 5
- kbenson 11y agoAnd that's different than in Perl, where they aren't statement modifiers (I slightly misspoke), they really are just rearranged into single statement if blocks. That is, if the postconditional is false, the statement is not executed at all. my $x = 1; $x = 10 if $x > 1; say $x; # 1 Personally I find the assignment of the if/else statement's return value distasteful, as it's both complex to read and mixes a portion of a natural pattern of thinking while later abandoning it, making it unintuitive. At that level, I prefer a ternary operator.
- 11y ago