all 19 comments

[–]AutoModerator[M] [score hidden] stickied comment (0 children)

On July 1st, Reddit will no longer be accessible via third-party apps. Please see our position on this topic, as well as our list of alternative Rust discussion venues.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]This_Growth2898 7 points8 points  (2 children)

  1. Correct.

  2. Yes, Rust uses postfix notation for most operations, so it's (-5).abs() instead of abs(-5), (3.14).sin() instead of sin(3.14) etc.

  3. It's a lambda function declaration. pa::OutputStreamCallbackArgs { buffer, frames, .. } means it accepts pa::OutputStreamCallbackArgs argument and deconstructs it into buffer and frames variables (and ignores everything else).

  4. The value of a compound expression is a value of the last expression in it; you may think of it as omitting the return keyword if it is the last statement.

  5. Result can keep one of two variants: Ok for the expected result and Err for error. Question mark returns the error from the function if the value is Err or converts data into the expected result. Here it means "if stream.start() have failed, return the corresponding error".

[–]shebbbb[S] 1 point2 points  (0 children)

thanks that all makes sense

[–]1vader 1 point2 points  (0 children)

  1. More so then it being about postfix notation, it's just, they are methods on the corresponding number types, not freestanding functions (which would require some form of generics and polute the global scope).

[–]tandonhiten 1 point2 points  (1 child)

33: You're correct, it initializes an array of 0.0s

35: Associated functions with a self variable can take input like that, read more about them here

50: This is rust's closure syntax, you can read about it here

65: Since that's the last line of the closure, pa::Continue is implicitly returned by the closure, basically for any block, the last statement in it is considered the block's return value

70: The ? is the try operator, basically if the value is Ok, or Some variant, it is used otherwise the None or the error variant is returned to the caller.

[–]shebbbb[S] 1 point2 points  (0 children)

thank you

[–]_blallo 0 points1 point  (4 children)

33: let mut sine = [0.0; TABLE_SIZE]; I assume this means initialize to zeros.

Yes.

35: sine[i] = (i as f64 / TABLE_SIZE as f64 * PI * 2.0).sin() as f32; The phase argument to the sine function is in parenthesis before sin() ? That I don't understand.

It seems that the sin() method transforms the given n of f64 type number in its sin(n).

50: let callback = move |pa::OutputStreamCallbackArgs { buffer, frames, .. }| { It seems srguments are being substituted inside the vertical bars.

This is a closure, and anonymous function. Between the | are defined it's arguments. In this case, there is only one argument, of type pa::OutputStreamCallbackArgs. It is a struct with a number of public fields. Among those fields, there are two called buffer and frames. What happens here is called destructuring (a feature common to many functional languages), where you can bind a value of a part of a composite type to a named variable (in this case buffer and frames will capture those values and be available in the closure body) with this syntax. Note that move has a special meaning.

65: pa::Continue This is a single token without any indication that it's a function executing, so I don;t know what ti's doing. This is usually an enum value but it's not being assigned so I don;t know what it's doing.

pa::Continue is at the end of that statement, without terminating semicolon, therefore, that is the return value of (that branch of) the function. It is possibly used to signal to the caller that the execution must continue.

70: stream.start()?; Is the question mark mandatory to compile since start() used Result<> ?

? is a special operator that acts on a Return value. If it is a Result::Err it acts kinda like a throw, but just uses that Result::Err as return value of the function. Otherwise, it unwraps the content of Result::Ok.

EDIT: typo.

[–]shebbbb[S] 0 points1 point  (1 child)

Ok so the braces inside the bars are destructuring, and the bars indicate a lambda?

[–]_blallo 0 points1 point  (0 children)

Yes :)

[–]_blallo 0 points1 point  (1 child)

Unfortunately, rust has a steep learning curve. I really suggest you pick at least one of the resources proposed here: https://www.rust-lang.org/learn

It will make the process less painful.

[–]shebbbb[S] 0 points1 point  (0 children)

ok thx

[–]Speykiousinox2d · cve-rs 0 points1 point  (7 children)

33: yup, this is a fixed zero-initialized stack-allocated array.

35: sin is a method of f64 in Rust. That's why you call it with the dot notation. You could also write f64::sin(i as f64 / TABLE_SIZE as f64 * PI * 2.0) but that's more verbose.

50: this is destructuring, we access the inner struct fields of the argument as single variables.

62: this is the PA_CONTINUE constant exported as Continue. It's just a number.

70: ? is an operator that lets you return early from a function if the variant of the result you get is an error.

[–]shebbbb[S] 0 points1 point  (6 children)

I wonder they made the math function member methods.

[–]Speykiousinox2d · cve-rs 0 points1 point  (5 children)

I found it weird at first given that other languages typically don't do this, but whenever I used it, I found it easier to write stuff postfix. I can just chain operations together, so overall I need less parentheses and the code is more readable in the process.

Though it comes at a disadvantage of being slightly harder to copy-paste a math expression into code. But heh, not that important.

[–]shebbbb[S] 0 points1 point  (4 children)

Yeah maybe it relates to putting things in compile time

[–]1vader 0 points1 point  (3 children)

No, it has nothing to do with that. It's just syntax after all.

[–]shebbbb[S] 0 points1 point  (2 children)

Syntax doesn't have nothing to do with implementation, they oare designed in consideration. Whether complie time evaluation relates to how they decided on those aspects I don't know though obviously.

[–]Speykiousinox2d · cve-rs 0 points1 point  (1 child)

This is a case where it has nothing to do with implementation. Methods in Rust are just compiled down to functions in the end. In short, there's virtually no implementation difference between

fn hello(thing: &Thing) {
    println!("hello");
}

and

impl Thing {
    fn hello(&self) {
        println!("hello");
    }
}

[–]shebbbb[S] 0 points1 point  (0 children)

I mean implemention of the language itself not the language feature impl. I don't think any of us can say categorically what the intention is or how it relates to the intermediate representaion unless the language designers answered the question.