[go: up one dir, main page]

|
|
Log in / Subscribe / Register

Little things that matter in language design: make it do what it looks like it does

Little things that matter in language design: make it do what it looks like it does

Posted Dec 28, 2014 8:29 UTC (Sun) by maryjmcdermott57 (guest, #100380)
In reply to: Little things that matter in language design: make it do what it looks like it does by neilbrown
Parent article: Little things that matter in language design

A little bit back to your article.
I want to ask one question about Rust.

First of all, I want to say thank you for your article. You have the answer for my question (the section "semicolons & expression"), that I asked when should add ; at the end of whole if/else expression because it's also an expression. I asked that question in many forums but many people either not pay attention to it or thinking that it's as a silly question.

But as you answered my question. This leads to more questions.
As you said, I assume that in Rust, if the expression return the unit-() type then we wouldn't require add ; at the end of that expression.

As before, if the internal of if/else expression (i.e function call return unit-() type then we won't necessary add ; at the end of either each internal function call or the whole if/else expression.

So what about the function call outside of if/else expression.
The rule seems not true anymore
I mean I have this code

fn main() {
println!("hello") // I think don't need add ; at here but it's wrong
println!("world") // I think don't need add ; at here but it's wrong
}

As the code run, compile raise error. Why does that happens when println!() return unit-() type? So as the assumption above, this code should work.

And can I ask you one more question? Is the function declaration is expression or not? Because I don't see the ; at the end of } of function declaration. I mean if it's an expression, it should look like this

fn foo() {
// do something
}; // ; should add in here but in practical, it's not there


to post comments

Little things that matter in language design: make it do what it looks like it does

Posted Dec 28, 2014 9:15 UTC (Sun) by Cyberax (✭ supporter ✭, #52523) [Link] (1 responses)

This works just fine:
>
>fn main()
>{
> println!("Hello, world!")
>}
>

Here you have a 'fn main()' returning the result of 'println!' invocation (a macro).

Little things that matter in language design: make it do what it looks like it does

Posted Dec 28, 2014 13:16 UTC (Sun) by maryjmcdermott57 (guest, #100380) [Link]

Yes. I already know that if there is just 1 function call like your example, I can omit the ; at the end of println!()

But what I want to know is that why although both println!("hello") & println!("world") return unit-() type, we still need separate each of these with ;

Because as you saw in the article, if the return value inside if/else is unit-() type, it don't need to add ; at the end of whole if/else expression. Otherwise we have to.

Little things that matter in language design: make it do what it looks like it does

Posted Dec 29, 2014 9:11 UTC (Mon) by jem (subscriber, #24231) [Link] (4 responses)

"As you said, I assume that in Rust, if the expression return the unit-() type then we wouldn't require add ; at the end of that expression."

No, it's the other way around: if you add a semicolon at the end of an expression it turns the expression into a statement. Doing this throws away the value of the expression and returns () instead.

Rust does not allow an expression to follow another expression, you will have to turn all but the last consecutive expression into statements by inserting semicolons after them. This means that you are only interested in the side effects of all but the last expressions, and return the value of the last expression. If you wish, you can put a semicolon after the last expression too, if the value of the last expression is not useful.

Little things that matter in language design: make it do what it looks like it does

Posted Dec 29, 2014 10:26 UTC (Mon) by maryjmcdermott57 (guest, #100380) [Link] (3 responses)

With your answer, I summed up like this
- with the last expression in a block, add ; is up to me (depend on my intention)

But it's also give me more confusing. So can you explain a little bit more about this code.

if condition {
function1()
} else {
function2()
}
expression3;

With this code above, the if/else is not last expression. And if both function don't return value so we don't need add ; at the end of } of whole if/else. That makes sense (as author said that the language doesn't require that ; if whole if/else doesn't have value). With that knowledge, why we have to add ; at the end of println!("hello"). Because println!("hello") also doesn't return any value

fn main() {
println!("hello") // why we have to add ; at here
println!("world")
}

And if can, please answer me one more question. What about other blocks like match, loop, struct, function declaration? These are also expression as whole or not.

Because I saw function declarations next each other without ; between them. like this

fn foo() {
// ...
} // don't have ; at here
fn bar() {
// ...
}

If they are expression, we have separate them with ; to compile correct, right?

Please bear with me if my questions make you annoying. I'm very confusing about these and I also add question in other places but not get the good answer or some just ignore & vote close topic.

Little things that matter in language design: make it do what it looks like it does

Posted Dec 29, 2014 10:51 UTC (Mon) by Cyberax (✭ supporter ✭, #52523) [Link] (1 responses)

>fn main() {
>println!("hello") // why we have to add ; at here
>println!("world")
>}

You need ';' because you can't just combine two expressions together. What operation should be used for that?

(never mind the fact that units can't be used in _any_ operation)

Little things that matter in language design: make it do what it looks like it does

Posted Dec 29, 2014 11:21 UTC (Mon) by maryjmcdermott57 (guest, #100380) [Link]

Yes, of course I can't combine 2 expressions together. So what about if/else & expression3. Both are expressions, right? But we can omit the ; at if/else expression in some cases. That makes no sense if we can omit ; at if/else expression but can't do that with println!("hello"). If we want consistent, Rust should force add ; at if/else (after the closing } of else) expression too

Little things that matter in language design: make it do what it looks like it does

Posted Dec 29, 2014 12:50 UTC (Mon) by jem (subscriber, #24231) [Link]

"With this code above, the if/else is not last expression. And if both function don't return value so we don't need add ; at the end of } of whole if/else. That makes sense (as author said that the language doesn't require that ; if whole if/else doesn't have value)."

You don't put a semicolon at the end of } of the whole if/else. This has nothing to do with whether the if should return a value or not – you never put a semicolon there. The if/else returns a value if the last expressions in the if and else branches do not end with a semicolon.

"What about other blocks like match, loop, struct, function declaration? These are also expression as whole or not."

Just like in the if/else case, you don't put a semicolon there. As with the if case, this does not mean these constructs have a value. Rust (mostly) borrows this syntax from C.

I think the best way of thinking about this is not to try to minimize the amount of semicolons. Do not focus all the time on whether you can leave out a semicolon, but instead think "do I want to return the value of the last expression in this block as the value of the block?". If that is the case, then you should leave out the semicolon.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds