Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I was a complete Nube an hour ago... I understand info from Nubes has special value, so I'll be as explicit as I can.

I must be slow, being an old fart... I've been at it for 53 minutes and got about 1/2 way before all the questions in my brain stacked up to "full".

I'd add a recommendation at the top of this to have a Rust compiler handy.

{} were called braces when I learned programming, [] were brackets... this tripped me up, Unicode calls these {} curly brackets ?!? (Why did it trip me up? Because on my screen in non-dark mode, { and [ look identical due to my eyesight, and I assumed I was looking at [ because the text said that's what it was... as you get older, you'll understand)

I don't understand why b=a; c=a; <-- doesn't work because a is "used up"???

I'll get a Rust compiler and start again.

I'm allergic to "macros" as they have had a special place in hell because of their misuse in C... I hope Rust is more sane.



It's definitely a lot to take in, you have the right idea — the compiler is here to help, the diagnostics are wonderful and improving every week thanks to the work of Esteban Kuber and others.

Re macros: try to keep an open mind if you can, C macros and Rust macros are completely different. You can get very far without reaching for them, so don't worry too much!


> I'd add a recommendation at the top of this to have a Rust compiler handy.

If you haven't already, check out the Playground: https://play.rust-lang.org/

It's reasonably full-featured for a web IDE (much more so than the Go playground), and it includes many commonly used packages.

> Because on my screen in non-dark mode...

The little sun icon in the lower left corner of the page turns on dark mode! Hopefully that helps.

> I don't understand why b=a; c=a; <-- doesn't work because a is "used up"???

This is something called "linear typing", and it's admittedly pretty unusual in a mainstream language.

The core idea is that the assignment operator _only ever_ creates a "shallow" (bitwise) copy of data; it never invokes anything like C++'s copy assignment operator. For types that are "plain old data" (like primitives), the old and the new values are fully independent, so the assignment works the same way it would in most languages, i.e., `a` is not "used up". This is what other commentors mean when they say that primitives "implement `Copy`". But if the old value has pointers or references, then the two values are not independent: after the bitwise copy, they both have pointers to the same data. Since data can only ever be shared explicitly in Rust, and the assignment operator never performs a deep copy, the old value, `a`, is considered invalid and cannot be re-used.

If you're familiar with C++11 or later, one way to think of it is that `=` in Rust always behaves somewhat like `std::move` in C++:

`b = std::move(a);`

The details are substantially different (this will call `a`'s move-assignment operator if one exists, which has no equivalent in Rust, and C++ offers no support for ensuring that `a` is no longer used if its move-assignment operator invalidates it). But the general idea that "move semantics are on by default" is essentially accurate.


Regarding a getting used up, the Rust compiler enforces a single-ownership principle where all values must have a single owner. If you move ownership of a to b, you cannot use a anymore as it no longer has ownership of the value.

The only exception to the above is if a type "is Copy". This means that values of this type can be copied very cheaply, and in this case the compiler will allow you to use it multiple times, which is implemented by it being duplicated on each use.

As for macros, they are nothing like C macros.


Rust is tricky. Took me about a year to grok decently.

Regarding references, the compiler does flow analysis and tries to enforce a sort of static rwlock semantic on variable level. You either have a single mutable reference xor N readable references to the same variable.

If b is a mutable reference to a, c cannot point to a until b reliquishes the "lock", which happens when b goes out of scope.


>I don't understand why b=a; c=a; <-- doesn't work because a is "used up"???

You know how C has a problem with aliases? (multiple variables referencing the same thing)? Which introduce bugs, prevent optimizations, etc?

Well, Rust tries to prevent this, and make more explicit (and known to the compiler) when you do this...


I've only had a passing acquaintance with C and C++, so I've never used aliases.

I just googled it... why the heck would you copy pointers? That's insane!

In my example, a, b, and c were variables, not pointers.


You keep using this word, variables. I don't think it means what you think it means.

At least in my book pointers are still variables (as in "a pointer variable"), and a variable is any named value, whether it's a scalar or a pointer or a nth-pointer, or what its storage is.

But you mean that in your example there is no way to affect the previous value, right?

>I just googled it... why the heck would you copy pointers? That's insane!

Well, copying values and passing them around would be too costly on memory (for larger structs especially), and would prohibit several techniques.


Variables can be varied... you can increment, decrement, do whatever you want with them. They keep track of things.

Pointers are used reference things allocated from the heap, and never anything else, unless you're insane. Pointers get directly handled in linked lists, trees, etc.

If at all possible, pointers should be avoided otherwise.

Values passed to a procedure can be done by value (the default in Pascal), or by reference (VAR parameters).

I don't see why anyone wouldn't copy values by default... it is the only sane way to do things.


> Pointers are used reference things allocated from the heap, and never anything else, unless you're insane.

People routinely use pointers to things on the stack in several languages. Rust even makes it safe to do that, using lifetimes - a pointer to something on the stack can't outlive the stack frame it points into.

> I don't see why anyone wouldn't copy values by default...

Because not everything is safe to copy. In particular, Rust has a few kinds of pointers which come with special rules.

Firstly, it has boxes, which always point to something on the heap, and have a rule that that when the pointer dies, the thing it points to gets freed. If you copied a box, then when one of the copies died, the thing would be freed, and then the other copy would have a pointer to invalid memory, which would be bad.

Secondly, it has mutable references, which come with a guarantee that a mutable reference is the only pointer to a given thing. If you copied a mutable reference, you would break that guarantee.

Thirdly, it has reference-counting pointers (these are in the standard library, not the language). You can make duplicates of those, but they have to increment their reference count when you do so. Copying is always just a bitwise copy, so there is no chance to increment the reference count. Instead, duplication is an explicit operation.

There are a few other things it doesn't make sense to copy. Like, what would it mean to copy a mutex?

So, in Rust, you can't copy by default. However, it is really easy to mark a type as being copyable (the compiler will check that it really is, ie doesn't contain any non-copyable things), and then you can copy it.


>Variables can be varied... you can increment, decrement, do whatever you want with them. They keep track of things.

You can do the same to a pointer in languages that have them, either directly (e.g. in C) or through some "unsafe" construct (e.g. in Rust, C#, Go).

>I don't see why anyone wouldn't copy values by default... it is the only sane way to do things.

When resources are ample, yes. Not the case historically, or in many use cases today.

And not all values make sense to copy.

But also in Rust, we're talking in the context of C performance needs, memory models, and concepts, and Rust expands and makes those safe.


> Variables can be varied... you can increment, decrement, do whatever you want with them.

Variables by themselves are not much. They inherit the properties of the type they are bound to. So what you can do with them can be as restrictive or as permissive as the type allows. That type can be a pointer/reference as well.


> why the heck would you copy pointers?

Pointer aliasing is not always obvious.


"I don't understand why b=a; c=a; <-- doesn't work because a is "used up"???"

Had the same issue a few months ago.

The pointer can only be referenced by one variable at a time.

If you "move" the pointer from a to b then a is figuratively "used up" because a is now blocked from doing anything with the pointer anymore.

I guess, for Rust itself the pointer is still referenced by a, Rust just blocks you from using it. But thinking you moved it to another variable helped me a bit.


if I say

a = 2; b = a; c = a;

There's no pointer in there, just 2.


That will work fine, because 2 is 'Copy', so it can be copied trivially (as are structs consisting only of Copy members which are marked as Copy). Roughly speaking anything with a pointer in it isn't Copy, though many objects will implement Clone, which basically just means you need to explicitly call .clone() to make a copy instead of it happening implicitly.


2 is Copy? It's an integer, could be 2.0 if you wanted to make it a float.

Someone needs to explicitly nail down the mission statement of Rust... because to me it seems to be

"Rust will introduce pointers where they don't need to be, and then try to protect you from the results with obsessive rules"


I wrote a piece that tries to explain Rust's memory management strategy, compared to C: https://fasterthanli.me/articles/declarative-memory-manageme...

Hope it helps!


Yes, primitive types all implement Copy.

Maybe playing around with the code would help you better, because that last line doesn't make any sense: https://play.rust-lang.org/?version=stable&mode=debug&editio...


You need to seriously read more on Rust before making judgments. You're clearly confused.

What '2 is Copy' means precisely that Rust WILL NOT 'introduce pointers where they don't need to be' - 2 is fine to 'alias' because it's a primitive type and so a copy is made when you do that, (i.e. the type implements the 'Copy' trait). However when you do that with complex types that do not implement Copy, you're moving ownership to the new variable so cannot use the old one any more.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: