Hacker News new | ask | show | jobs
by general_failure 4684 days ago
Why do people keep reinventing syntax? Quick tell me what the following mean:

struct Digest { digest: ~[u8] } // what's ~ here?

for self.digest.iter().advance |&byte| { acc = acc.append(fmt!("%02x", byte as uint)); } acc

What does the above mean? acc as a separate line and nothing else

I hate it when people reinvent the same construct that can be found in other languages but differently. I guess they want to do something different in their language, is it?

5 comments

Rust does have some new syntax, but I think most of it is justified for making programming in it nicer.

The `~[u8]` would be written `std::unique_ptr<u8>` in C++. They're used everywhere in Rust, and having to write out unique_ptr would get awfully tiresome.

The `acc` on its own line is a result of "the last statement gets returned" like many functional languages do. If you were writing C++, you'd write `return acc;` instead. This one is more of a convenience, and you could get away without it.

> The `~[u8]` would be written `std::unique_ptr<u8>` in C++.

Wouldn't it be `std::unique_ptr<std::vector<u8>>`?

Indeed, it would.
I agree that C++ broke the syntax terseness of C and become verbose for the sake of being explicit enough. This gets inconvenient sometimes, but the good thing is that it is a technical solvable problem - just redefine the long keywords or configure your editing tools to help you out typing.
It indicates ownership. If you know C++, ~T in Rust is similar to std::unique_ptr<T> in C++ (ensures that there is only one owner of given value) and @T is similar to std::shared_ptr<T> (ensures that there are one or more owners of given value and the value would be deallocated when the last owner vanishes). But you can't check the correctness of these "smart pointers" in the compile time in C++ while keeping the efficiency; Rust has both the correctness and efficiency (1) by making these important types to built-in constructs.

(1) Still being worked on.

Note that that loop function now looks like (the for loop has changed since 0.7):

    fn hexdigest(&self) -> ~str {
      let mut acc = ~"";
      for &byte in self.digest.iter() { 
        acc.push_str(fmt!("%02x", byte as uint));
      }
      acc
    }
Nothing in the syntax is fundamentally new, especially the semicolon turning an expression into a statement.

~[T] is just a vector.

just offhand, from my understanding, ~ signifies rust's pointer type. It's different from C's pointer type in subtle ways, so the symbol is different, to force reader to actually look into it, and understand what it does different instead of just assuming it's just like C's.

There's also the advantage that there's no way to conflict with the * multiplication operator.

`~` is just one pointer type; there's & and * also built-in to the language (and @, but that's moving to the standard lib); and Rust provides the control required for implementing arbitrary "smart-pointers" (e.g. reference counting is a library pointer).

~ is an owned pointer (like unique_ptr in C++); & is a "reference" or borrowed pointer (allowing access to data without taking ownership); * is a raw/unsafe pointer, and is identical to C's pointers.

Also, the * pointer doesn't conflict with multiplication because they can never occur in an ambiguous context:

  foo * bar = NULL; // C

  let bar: *Foo = std::ptr::null(); // Rust

  let bar = std::ptr::null(); // Rust, using type inference