8 ms·
Rust also has (almost) everything being an expression - things like this aren't uncommon: let x = if something { foo() } else { bar()
by vertex-four 10y ago
Rust also has (almost) everything being an expression - things like this aren't uncommon:
let x = if something {
foo()
} else {
bar()
}
Things which don't have a logical value evaluate to `()` (the empty tuple), I believe.
- qznc 10y agoThe if expression is not a persuasive example. C/Java/Algol/etc all have it as well. x = something ? foo() : bar();
- coderzach 10y agoI see two issues with the ternary operator. One, the syntax is much less readable, and two, the consequent and alternate are both single expressions, so you can't do something like: x = if(something) { a = foo(); baz(a); } else { b = bar(); baz(b); }
- heywire 10y agoI've always read ternary statements to myself as a question. some_condition ? this : that some_condition? then this, otherwise that Typing this, I realize how hard it is to explain without speaking it :)
- lawpoop 10y agoIs the color red? If so, this; otherwise, that. It's a little tricky, because in the above, the `if` keyword appears after the question mark. Is the color red? Yes-- this: no-- that. Trying to make a parsimonious English sentence while maintaining the syntax elements : P
- kbutler 10y ago> some_condition ? this : that Just read it as: IF some_condition THEN this ELSE that
- junke 10y agoYou compute baz in both branches, you can refactor. x = baz(if (something) foo() else bar())
- tacostakohashi 10y agoIf you insist on the assignments: x = something ? ((a=foo()), baz(a)) : ((b = bar()), baz(b)); Otherwise: x = something ? baz(foo()) : baz(bar());
- vertex-four 10y agoa and b have to be defined before the statement containing the terniary expression here. And the point is that you can embed arbitrary multi-statement logic in your if expressions in Rust in the same way you'd do it anywhere else.
- kazinator 10y agoIt should work in GNU C: x = (something) ? ({ a = foo(); baz(a) }) : ({ b = bar(); baz(b); }); However, since all your forms are actually expression statements, we can happily just use the ISO C comma operator: x = (something) ? (a = foo(), baz(a)) : (b = bar(); baz(b)); If C provided operators for iteration, selection and for binding some variables over a scope (that scope consisting of an expression), everything would be cool. E.g. fantasy while loop: x = (< y 0) ?? y++ : y; // evaluate y++ while (< y 0), then yield y. Variable binding: x = let (int x = 3, double y = 3.0) : (x++, x*y); The problem is that some things can only be done with statements. The ternary operator is not actually lacking anything; with the comma operator, multiple expressions can be evaluated. What's lacking is the vocabulary of what those expressions can do.
- vertex-four 10y agoThe difference is that C/Java/Algol have different syntaxes for things-as-expressions and things-as-statements, and you can't put blocks in the things-as-expressions. In Rust, blocks are also expressions and so have a result (the result of the last expression in the block), so your expressions inside the if can be as complex as you like. Since functions also have a block, and the return value of the function is the result of the block, this is much more consistent.
- kazinator 10y agoIn GNU C, you can use a brace-enclosed statement block as an expression. Funny story; years before I became a C programmer, and at a time when I didn't yet study ISO C properly, I discovered and used this extension naturally. I wanted to evaluate some statements where only an expression could be used so I thought, gee, come on, can't you just put parens around it to turn it into an expression and get the value of the last expression as a return value? I tried that and it worked. And of course, if it works it's good (standards? what are those?) Then I tried using the code with a different C compiler; oops! Anyway, this GNU C feature doesn't have as much of an impact as you might think.
- mroll 10y agoThis example of "everything as an expression" doesn't take it as far as Tcl, though. In the above code snippet, the conditional body is surrounded by braces, which are syntax. In Tcl, the second argument to the 'if' command is also an expression, which only uses braces as a quoting mechanism, if it needs to.
- wtetzner 10y agoI'm not sure I understand why it matters if the syntax requires braces or not. The things inside the braces are still expressions.
- mroll 10y agoIt matters because if the braces are not syntax, you can decide what code to execute as the condition body at runtime. set condition-body {puts "Hello, world"} if { $condition } $condition-body To get this to run, you need to splice in the condition-body like so, if { $condition } {*}$condition-body But you get the point.
- wtetzner 10y agoBut the "then" and "else" parts of the Rust "if" are expressions. What you're talking about doesn't seem to be related to which things are expressions, it's more like being able to eval code at runtime.
- virtualwhys 10y ago> Things which don't have a logical value evaluate to `()` (the empty tuple), I believe. If Rust follows Scala then `()` is not the empty tuple, but rather Unit (void in C*).
- jimktrains2 10y agoIt's the same thing. It's a type with only a single value.
- virtualwhys 10y agoIt's not the same thing, a value of type Unit can only produce a side effect (or do nothing at all).
- dllthomas 10y agoHow is that different from a value of type "empty tuple"?
- virtualwhys 10y agoTrue, neither are useful as values, though Unit typically conveys programmer intent (to produce a side effect), whereas the empty tuple is, in Scala at any rate, quite rare. The empty tuple: scala> val empty = Tuple1(()) empty: (Unit,) = ((),) vs. Unit: scala> val empty = () empty: Unit = ()
- vertex-four 10y agoIsn't that a tuple containing a unit, and therefore not empty?
- virtualwhys 10y agoIt's the closest you can get in Scala to represent an empty value whose type is `Tuple`.