A semi-colon madness

i can't help it seems to me. i always type a semicolon at the end of every block.

so instead of this:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    let sum = add(1, 2);

    println!("Sum = {}", sum);
}

i have to include a "return" when coming or exiting from a function call so that i can have this:

fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

fn main() {
    let sum = add(1, 2);

    println!("Sum = {}", sum);
}

at this early, i can't see any disadvantage except additional typing.

One major disadvantage is that it's unidiomatic.

8 Likes

Your code will be considered unidiomatic.

The "block is an expression" quality shows up in other places in Rust, including those without the equivalent of a return.

let x = if y == z { a } else { b };

And you will also see it all the time for closure "one-liners".

for x in iter.map(|y| y.bar()) { ... }

So as you get more use to Rust, you'll get more use to the quality. I wasn't used to it when I started Rust, but now it looks bad to me when I see an unnecessary trailing return.


P.s. Please read the pinned formatting guide.

```
code here
```
12 Likes

Another disadvantage is that now your return's mean nothing.

In the idiomatic code, where returns are only used for early returns then mean, well… early returns: if you see them you know that execution flow diverges and text after that point may not be executed. Something to pay attentin for.

With your approach they no longer mean anything, they just clutter the source code.

13 Likes

maybe its too early in my learning stage. at this point, of all the replies i only understood the formatting guide.

to me, im using return like in C.

edit: just encountered

Option<T>

another data type. can never find any tutorials that teaches only how to use the language itself. like the K&R book.

The Rust language is more tightly coupled to parts of the standard library than many other languages. I suggest thinking of the things introduced in "the book" as just being part of Rust, for practical purposes, whether or not they're in the standard library.

12 Likes

Almost all Rust programs use std and the types within. Of those that don't, many still use alloc and the types within. Of those that don't, almost all use core and the types within. Practically no one writes no_core Rust, and those that do have to supply much of core.

Why? Parts of the language are built around traits and types that are in core. For example, a for loop is build around trait-based iterators that return Option<_>s. Most operators including indexing and dereferencing are also trait based, outside of the implementations for a few primitive or otherwise special types. Box<_> is one such special type that doesn't look like a primitive, but has so much special behavior it sort-of is, despite not being part of core.

So some of these things you're encountering are effectively part of the language.

You can use The Reference in a sort-of targeted way, e.g. to see how if expressions work. But it's not introduced in a prose-based, front-to-back manner like K&R, that's true. Reading the std documentation can also be useful, but again it's meant more as a reference than as learning material per se. E.g. you're not going to memorize all of those methods on your first visit.

12 Likes

just understanding how to read Box<> or Option<> or maybe not dealing with them until i've become accustomed to the language. but existing docs are sprinkled with such advanced references that i have to jump all over the web to find their meaning.

anyway, i'll stick with youtube instead.

fn main() {
   println!("let's get rusty!");
}

If you have any specific section in the book that you feel is'nt very understandable or uses concepts that haven't been introduced, feel free to comment here or open an issue

3 Likes

it's all the text based rust tutorials. they all mix rust concepts with explaining the language tutorial.

also, it seems rust syntax are confusing. for example, why use the boolean OR operator in closure (and lambda functions)? among other things.

but, i blame myself for being a noob that's why im having a hard time reading the book.

is all about context...
|| is not boolean "or" in closure, - as you know the closure term, i assume you must know that closures can also have no arguments... :wink:

// pseudo-code
|| { println!("no-arg closure"); }

vs

// pseudo-code
|arg| { println!("closure with 1 arg being: {arg}"); }
3 Likes

I'm not entirely certain what you mean by "mix rust concepts with explaining the language tutorial", but any Rust tutorial is going to need to explain most Rust concepts, otherwise it would only be a tutorial on part of the language. As far as I can see, the Rust book generally does a good job of introducing concepts in order, and mentioning when something is used that will be explained in more detail later.

The bars in the closure syntax are not the Boolean OR operator, but just unusual brackets enclosing the arguments of the closure and marking the start of a closure. As to the reason for using them, I suppose they are the least ambiguous brackets to use there, since binary operators can't occur at the start of an expression.

Closures are also something you shouldn't need to worry about at this stage in your learning. Your comment about Option earlier indicates you may be in section 6 of the book, and closures are introduced in section 13.

Note that Option and Result are pretty core Rust concepts. It's not an advanced feature at all.and is baked into the language in various ways.

The core concept is fairly understandable I think. For example, if you have a File then it's always an open file. It's never closed or not yet opened. The way you express a maybe open file is by using an Option<File>. This contrasts with some other languages that allow a "null" file to be created or let you hang on to a file after it's been closed, which means that the programmer has to be constantly vigilant when using files (or else risk subtle bugs).

3 Likes

What do you mean by "language itself"? I don't think that's even the case for K&R -- after all, printf("Hello World"); is just as much "the library" as Option is.

10 Likes

If you can point to one (or more) sections or paragraphs, I can try to rewrite it to make it more clear.

4 Likes

one doesn't need to know how a car engine works in order to drive a car.

no i don't. im a noob in rust. only chap 3 in the rust book.

in any other languages, | | is the OR boolean operator.

oh yes very noob am i.

im just looking for a tutorial to teach me how to "drive a car without having to learn how a car engine works".

No, not in any other language, just the very few you happen to have encountered so far[1].

It's really important not to fall into the trap of believing that the first language you encounter is normal, and anything you meet later, that differs from it, is weird. Falling into this trap is a huge disservice to yourself, as it will make learning new things much more frustrating and much less productive for you.

You should studiously avoid conflating syntax and semantics. The way something is written in one particular programming language and the concept that that particular sequence of characters represents, are two distinct (albeit related) things. It is crucial that you understand the idea that the syntax represents independently of the syntax itself.

For example, here is a bunch of ways of saying "I want add to name a function which returns the sum of its two arguments":

int add(int a, int b) { return a + b; }
auto add = [](auto a, auto b) { return a + b; }
def add(a, b): return a + b
add = lambda a, b: a + b
from operator import add
add a b = a + b
add = \a b -> a + b
add = (+)
(defun add (a b) (+ a b))
fn add(a: i32, b: i32) -> i32 { a + b }
let add = |a, b| { a + b };
: ADD + ;

I could go on and on, but this should be enough to make the point.

All of the above examples mean the same thing[2].

If you think that some of them are more logical or natural or correct than others, then you are deeply mistaken. Do yourself a favour and disabuse yourself of this misconception! Understand that the syntax and the concept the syntax represents are separate things, and learn to understand the concept in itself, liberating yourself from the syntax. That way, a number of important and hugely beneficial to you, things will happen:

  • You'll have a far firmer, deeper, better understanding of the meaning of programs you read and write.
  • You'll be able to reason more clearly about the ideas you want to express, because you will be able to decouple thinking about what it is that you want to say, from thinking of how to say it in whatever language you happen to be using.
  • You'll be able to learn new languages far more efficiently.

  1. Python and most of the Lisps are two examples of languages in which boolean or is not spelt ||; Ruby and Smalltalk are just a couple of languages in which the meaning of |...| is similar to its meaning in Rust. ↩︎

  2. Ignoring details like polymorphism, dynamic/static typing, type inference, currying, etc. ↩︎

23 Likes

Writing non-trivial programs is infinitely more difficult than driving a car. I suggest that you adjust your expectations to this reality.

Option is fundamental to programming in Rust. It would be a mistake to believe that Option is some implementation detail of Rust's 'engine', that can be ignored while learning Rust.

4 Likes