Earlier quoted context omitted.
> Enumerations type myEnum int const ( someValue myEnum = iota anotherValue moreValues ) > Sum types Consider thinking about the types in your sum type and what they have in common, and define an interface that they share. > Recursive types Not sure what you mean. This is valid Go: type tree struct { value int left *tree right *tree } > Parametric polymorphism Yes Go sucks in this area. `sort.Interface` is a good exa…
> Enumerations - those are integers not enumerations. In Golang they have a type Bool which is either true or false. Can I define my own type using the same convention in GoLang? No. I can't. Ideally I want the ability to do this: type Bool = Enum { True False } or type Tri = Enum { True False QuantumTrueFalseDuality } But in Golang I'm locked in with what the creators provided as primitive types. I can't go deeper.…
My favorite Rust function
171–180 of 197 posts
Re: My favorite Rust function
#172Earlier quoted context omitted.
The compiler prevents you from implementing both Copy and Drop (i.e. a destructor). So dropping any copy type is a no-op.
Lesson learned from c++ "rule of five"? Where if you implement a destructor you must also carefully implement a copy constructor so that the two copies of the object don't accidentally refer to each others members in any way. Something that is much harder than it sounds like, leading to the now more recommended "rule of zero" saying just don't.
This rule really helps both the compiler and the programmer to make moving and copying things effortless. It does prevent things like a struct holding internal pointers to it's own state. This is not bad on x86, because you can replace internal pointers with internal offsets, and the instruction set contains a fast reg+reg addressing mode, but can cost an extra instruction on many other cpu architectures. IMHO the rule is well worth it, although it is an example of a situation where Rust chooses to give away a bit of performance for sanity.
Re: My favorite Rust function
#173I haven't used rust, so can you explain this to me: If I do the rust equivalent of: def add1(x): return x + 1 x = 1 y = add1(x) z = add1(x) then will x have been deallocated by the first call to add1 and will the second call to add1 fail? [You can ignore the fact that I'm using numbers and substitute an object if that makes more sense in the context of allocating / deallocating memory in rust.]
If add1 takes ownership of the argument, yes (and x is not implicitly copyable). Compare with C++, in particular types with deleted copy operators (e.g. unique_ptr ). In order to call a function that takes an unique_ptr by value as argument, you must explicitly move the object into the function: void foo(unique_ptr x) { ... } unique_ptr x = ...; foo(move(x)); foo(move(x)); Linters (i.e. clang-tidy) can be configured…
Also and importantly because move() only indicates that the value may be moved from (it's a fancy cast), that doesn't mean it will be moved from. The called function needs to take an rvalue reference (T&&) for a move to possibly happen. That is if you had a
void foo(unique_ptr&& x)
it may or may not move. Likewise you can call move() on things which are not move constructible (or passing the result to functions which don't care) with no ill effects (save to the reader).IIRC what happens here is that since foo() takes a unique_ptr by value the compiler will insert the construction of a temporary unique_ptr and overload resolution will select the move constructor (since we've provided an rvalue reference, and assuming the wrapped type is move-constructible).
> move leaves the object in an unspecified but valid state
Also notes that this is the general semantics, but specific types can define their exact behaviour here. In particular, unique_ptr specifies that a moved-from unique_ptr is "nulled" (equal to nullptr).
Re: My favorite Rust function
#174Earlier quoted context omitted.
> Maybe you're referring to --release compilation? Indeed.
Ok, well, "cargo build --release" took 3 minutes and 55 seconds, which I would consider reasonably fast for compiling and optimizing 300+ libraries. I guess your laptop has only 2 cores in an older processor, which would explain the difference. Kudos to you for keeping good hardware alive.
I currently compile on raspi4 and scp the results there to check.
Re: My favorite Rust function
#175For me, rust is still love & hate, even after 1 year of half-time (most of the free time I have) hacking. It's a wonderful language but there are still some PITAs. For example you can't initialize some const x: SomeStruct with a function call. Also, zero-cost abstraction is likely the biggest bullshit I've ever heard, there is a lot of cost and there's also a lot of waiting for compiler if you're using cargo packages…
> Also, zero-cost abstraction is likely the biggest bullshit I've ever heard, there is a lot of cost and there's also a lot of waiting for compiler if you're using cargo packages. Zero cost refers to runtime cost, not compilation cost. Zero cost abstraction is not bullshit.
Maybe just dig into some sources and see what macros are expanded to to see the overhead.
Re: My favorite Rust function
#176Earlier quoted context omitted.
Interestingly, the type of `x` actually does matter here in Rust! For most types, yes, passing something by value into a function will cause the memory to be "moved", which means that reusing `x` will be a compiler error. That being said, you can also either pass a shared reference (i.e. `&x`), which will allow you to access the data in Rust (provided you don't move anything out from it or mutate it, which would caus…
Is there any kind of compile-time check available for this (e.g. BIG COMPILER WARNING when you pass-by-value something that lacks Copy)? Seems like a lot of unsettlingly Python-esque freedom ("read the docs and don't screw up") for a language like Rust.
It's a very much a "bondage and discipline"-style language in the sense that unless you explicitly use "unsafe", you have to prove to the compiler that everything you do is safe. Moving large things is not unsafe because after you move something to a different scope, the original doesn't exist anymore and can't be used, so if you were to accidentally move something and tried to use it again, the compiler would helpfully tell you that the thing you're trying to refer to isn't there anymore.
There is no warning on every time you pass something without copy because passing things to different scopes is extremely common, normal and desired.
Re: My favorite Rust function
#177> or making the language unacceptably crippled like Go Gotta say, I lost a lot of respect for the author at this point. It’s not like I don’t love Rust - quite the contrary - but if the only takeaway from Go for you is that it is “unacceptably crippled” then I feel you have missed a lot of insight. Go has been one of my languages of choice for over half a decade now, and for good reason.
Re: My favorite Rust function
#178Earlier quoted context omitted.
Is there any kind of compile-time check available for this (e.g. BIG COMPILER WARNING when you pass-by-value something that lacks Copy)? Seems like a lot of unsettlingly Python-esque freedom ("read the docs and don't screw up") for a language like Rust.
It is perfect fine to take by value something that is not Copy to transfer its ownership. It is a compiler error to use the value after it was moved. And the compiler error is quite explicit about how to solve it For example you can explicitly clone let y = add(x.clone()); let z = add(x);
What the chance in real life that a function like that cannot simply use a reference?
In my learning Rust, my life became significantly better and easier when I started to references to borrow as much as possible.
Re: My favorite Rust function
#179> or making the language unacceptably crippled like Go Gotta say, I lost a lot of respect for the author at this point. It’s not like I don’t love Rust - quite the contrary - but if the only takeaway from Go for you is that it is “unacceptably crippled” then I feel you have missed a lot of insight. Go has been one of my languages of choice for over half a decade now, and for good reason.
> > or making the language unacceptably crippled like Go > ... if the only takeaway from Go for you is that it is “unacceptably crippled” then I feel you have missed a lot of insight. Perhaps the author used a poor choice of words and instead could have phrased their intent along the lines of: Go lacks the semantic density needed to express solutions in both a concise and consistent manner. Were this the case, it wou…
That is a difficult statement for a Go user to parse.
It is referring to a lack of language features that result in verbosity or boilerplate?
Re: My favorite Rust function
#180Earlier quoted context omitted.
Hm. Ur right bad examples. The only advantage rust has then is more elegant syntax and safety for JSON. Ur also right about python and ruby. It is effectively the same. Overall though the need for assert is a sign of a crippled type system.
> Overall though the need for assert is a sign of a crippled type system. Given that most (if not all) new applications have to ingest data from third party systems and export outgoing data to other third party systems, the need for assertions and data validation is not going away, even in strongly typed systems. JSON is becoming the de-facto data transfer format, and thus JSON input validation is necessary in both w…
There is a huge difference in guessing a type using assertions or writing handlers within the boundaries of a domain. Alex’s point that writing such code is effectively the same as rust because the amount of code is the same. However safety is lost. There is literally no point of having a type system in place when unmarshalling Json in go because you have no type safety. In go if you assert the wrong type or if your missing a required assert the error may be hidden and if it’s not hidden you can only see it during runtime. In rust there is no type assertion, only type checking, so such a program won’t even compile.