Coming from C#, that syntax looks completely alien to me. I need to write a very small monitoring app to run on a tiny armel box so I may try Go. I will still miss Visual Studio's debugger, though.
When I tried to write my first program in Rust, I failed miserably. With a strong background in C# as well, I tried to write a function that returns an interface (a trait in Rust), which was apparently not something you do in Rust. (With an unboxed trait that is, but there are some proposals to add support for this.) The compiler diagnostics have improved tremendously since then. I don’t think the syntax is that much…
Three months of Rust
31–40 of 120 posts
Re: Three months of Rust
#32> The Rust community seems to be populated entirely by human beings. :D Regarding your borrow checker example, note that your code is now prone to blowing up if `step` is modified too much. You have created the necessity of an invariant (step should not pop out of the vector) which may be broken by later cleverness. See http://manishearth.github.io/blog/2015/05/17/the-problem-wit... for more details. Note that in thi…
> Note that in this specific case you could just use `&str` over `&String` everywhere It's an awkwardly construed example. Here is the actual code - https://gist.github.com/jamii/ae46e8e0c9757330e9ea . There the borrow makes more sense since the value is being created by calling a function on the current solver state. I've edited the post to include a solution that was suggested in the reddit discussion - replace &'a…
> Here is a list of limitations with the current bounds syntax that are overcome with the where syntax:
The list is of the limitations of normal bounds, not the limitations of where clauses. This was actually the RFC that added where clauses, and that list was the rationale for doing so.
Re: Three months of Rust
#33> The Rust community seems to be populated entirely by human beings. :D Regarding your borrow checker example, note that your code is now prone to blowing up if `step` is modified too much. You have created the necessity of an invariant (step should not pop out of the vector) which may be broken by later cleverness. See http://manishearth.github.io/blog/2015/05/17/the-problem-wit... for more details. Note that in thi…
> Note that in this specific case you could just use `&str` over `&String` everywhere It's an awkwardly construed example. Here is the actual code - https://gist.github.com/jamii/ae46e8e0c9757330e9ea . There the borrow makes more sense since the value is being created by calling a function on the current solver state. I've edited the post to include a solution that was suggested in the reddit discussion - replace &'a…
Agreed. And yes, a Cow is better in this case though of course there's a slight runtime cost. In such a case I would heavily document the new invariants with warning comments though :P
> I linked to an active rfc about constraints that cannot currently be expressed in where clauses
Those are the constraints that cannot currently be expressed in bounds, not where clauses. Bounds are the stuff within , where clauses were the new thing proposed to supplement them.
> In cases where a function takes two arguments it isn't always obvious which argument should be self.
I'm not sure why you seem to be troubled by self (here and in the post). It might be due to you looking at method dispatch as a sugar for function calls -- it sort of is (because of UFCS), but it really isn't.
The second argument can never be self. It's always the first. (nitpick: functions can't have self args, methods can, but that's just terminology).
For direct impls, you do a method without `self` when you wish it to be a static method. Eg `impl Foo {fn x(){}}` will be a method called as `Foo::x()` and will work independently of any instance of the type. `impl Foo{fn x(self){}}` needs to be called as `foo.x()`, where `foo` is a `Foo`. Here, the method is able to access the state of `foo`.
The behavior so far is the same for most languages like python or java (java has implicit self and uses `static` to say "no self").
Now, traits just let you provide a way to classify objects based on what methods -- both self and nonself/static -- they have. So, a trait `Cloneable` would be `trait Cloneable { fn clone(&self) -> Self}`, and its implementation would be `impl Cloneable for Foo {fn clone(&self) -> Foo {....}}`. This would mean that "given a `Foo`, I should be able to get another `Foo` out of it by calling `foo.clone()`". On the other hand, sometimes you want to run an operation on the type itself. I.e. `trait TypeName {fn type_name() -> &'static str}` and is implemented as `impl TypeName for Foo {fn type_name() -> &'static str {"Foo"}}`. In this case, it's no longer "given a `Foo`, do X", it's "given a type that implements TypeName, do X".
Generally nonself methods on traits don't make much sense unless you're doing type gymnastics (in fact, Java doesn't even allow static methods in interfaces). For example, they're used in hyper for dynamic dispatch on strongly typed headers (http://hyper.rs/hyper/hyper/header/trait.Header.html)
Also, `where Foo` doesn't make sense, where clauses need a colon; `where Something: SomethingElse`.
Re: Three months of Rust
#34Earlier quoted context omitted.
> Note that in this specific case you could just use `&str` over `&String` everywhere It's an awkwardly construed example. Here is the actual code - https://gist.github.com/jamii/ae46e8e0c9757330e9ea . There the borrow makes more sense since the value is being created by calling a function on the current solver state. I've edited the post to include a solution that was suggested in the reddit discussion - replace &'a…
I think you may have misread that RFC. With my emphasis: > Here is a list of limitations with the current bounds syntax that are overcome with the where syntax: The list is of the limitations of normal bounds, not the limitations of where clauses. This was actually the RFC that added where clauses, and that list was the rationale for doing so.
So, I half-remembered the actual problem I ran into and found something that half-looked like it mentioned it. Not my finest hour :S
I dug up the IRC exchange for the problem I actually ran into:
jamii
How do I write the type of a byte iterator:
fn next_path(nibbles: &mut N) -> u32 where ::Item = u8 {
That gives me 'equality constraints are not yet supported'
FreeFull
jamii: >
Equality constraints seem to still be unimplemented ( https://github.com/rust-lang/rust/pull/22074) but I can write this instead where N : Iterator
So that whole section of the post is incorrect. I've removed it and linked to this discussion instead.Re: Three months of Rust
#35"For our 2400 loc it takes 20s for a dev build and 70s for a release build. " I have played with rust, but not written any large amounts of code. This makes me a bit sad though, I have 7000 lines of go which takes less than a second. I think there is a bunch of bloat in software compilation which the plan9/Go people were wise to stamp out. Compare gcc/clang/rustc build times from source with building go 1.5 from sour…
If I remember properly, when Go was first developed, compilation time was one of the primary metric that Rob Pike et al were optimizing for, and drove major aspects of its design. It shouldn't be surprising that Go blows other systems out of the water in this regard. Here he is talking about it: https://www.youtube.com/watch?v=rKnDgT73v8s#t=8m53
You could have a more C-like language that isn't so dependent on expensive optimization passes like multi-level inlining and SROA, granted, but I think most any high-level language—i.e. one that isn't a bare-metal language like C and Pascal—is going to have lots of opportunity for expensive optimizations.
Re: Three months of Rust
#36Earlier quoted context omitted.
> Note that in this specific case you could just use `&str` over `&String` everywhere It's an awkwardly construed example. Here is the actual code - https://gist.github.com/jamii/ae46e8e0c9757330e9ea . There the borrow makes more sense since the value is being created by calling a function on the current solver state. I've edited the post to include a solution that was suggested in the reddit discussion - replace &'a…
> There the borrow makes more sense since the value is being created by calling a function on the current solver state. Agreed. And yes, a Cow is better in this case though of course there's a slight runtime cost. In such a case I would heavily document the new invariants with warning comments though :P > I linked to an active rfc about constraints that cannot currently be expressed in where clauses Those are the con…
Yeah, I got that whole thing totally wrong. I've removed that part of the post and linked to this discussion instead. Thankyou for de-confusing me :)
> The second argument can never be self. It's always the first.
I think we are talking past each other on this point. I'm thinking of the design-time choice between eg:
trait Observe {
fn observe(self, observee: Observee);
}
trait Observe {
fn observe(self, observer: Observer);
}
trait Observe {
fn observe(observer: Observer, observee: Observee);
}
Analogous to the typical OO problem where it's not clear which class a method should belong too.Because I mistakenly believed that where clauses are less powerful I thought that the above choice had additional significance beyond code organisation, because it would affect the kind of constraints I could write. But they aren't so it doesn't matter :)
Re: Three months of Rust
#37Earlier quoted context omitted.
The truth is that rust is in its infancy its all guesses at this point. Go didn't attract c++ people as people first guessed.
I saw them talking about that, but it's completely obvious. Nobody today is running C/C++ unless they need either A) complete speed or B) bare metal. Go can't do either, so there was going to be very little transfer from C/C++ to Go.
There aren't many other good options: Java: UI looks terrible; it's annoying living in Noun-land when CPUs are, if anything, more about verbs than nouns; and running properly on Windows is not trivial.
C#: Up until recently, not cross-platform unless you're ok with Mono. (But, might be worth looking in to now)
Python: great for scripts and experiments. The lack of static typing is a real problem when working with code other people wrote. Also, UI is not a strong point.
Go: what UI libraries? (I'm sure they exist)
Objective-C: even on iOS/Mac-only projects, I still prefer C++, because it's so much easier to use STL objects than NS data structures.
C++: you can pretty much get it done, and often you can use Qt to get it done quickly and cross-platformy.
I'm hoping Rust will be the C++ I always wanted.
Re: Three months of Rust
#38"Modern machines are a huge pile of opaque and unreliable heuristics and the current trend is to add more and more layers on top. The vast majority of systems are built this way and it is by all accounts a successful strategy. That doesn’t mean I have to like it." This is a really valuable observation. "Smart" compilers seem great for letting you write code without thinking too hard when performance requirements are…
Forget about clever compilers; forget even about smart JITs; even if you look at such a big abstraction as GCs and only consider large pauses (say anything over a few tens of milliseconds), it is now the case that in a well-tuned application using good a GC, most large pauses aren't even due to GC, but to the OS stopping your program to perform some bookkeeping. Careful control over the instruction stream doesn't even let you avoid 100ms pauses, let alone trying to control nanosecond level effects.
[1]: http://www.infoq.com/presentations/click-crash-course-modern...
Re: Three months of Rust
#39Earlier quoted context omitted.
> There the borrow makes more sense since the value is being created by calling a function on the current solver state. Agreed. And yes, a Cow is better in this case though of course there's a slight runtime cost. In such a case I would heavily document the new invariants with warning comments though :P > I linked to an active rfc about constraints that cannot currently be expressed in where clauses Those are the con…
> Those are the constraints that cannot currently be expressed in bounds, not where clauses. Yeah, I got that whole thing totally wrong. I've removed that part of the post and linked to this discussion instead. Thankyou for de-confusing me :) > The second argument can never be self. It's always the first. I think we are talking past each other on this point. I'm thinking of the design-time choice between eg: trait Ob…
Yeah, any of these choices will work^. Well, the last choice shouldn't be a trait, really, just a standalone function.
Associated types would also help simplify this (note, if you have a trait Foo, the trait can be implemented multiple times on the same type, with different A. If you have a trait Foo with associated type A, only one implementation will be allowed, the associated type is a property of the implementation)
^ In more complicated situations coherence may disallow one or more of those choices.
Re: Three months of Rust
#40"For our 2400 loc it takes 20s for a dev build and 70s for a release build. " I have played with rust, but not written any large amounts of code. This makes me a bit sad though, I have 7000 lines of go which takes less than a second. I think there is a bunch of bloat in software compilation which the plan9/Go people were wise to stamp out. Compare gcc/clang/rustc build times from source with building go 1.5 from sour…
If I remember properly, when Go was first developed, compilation time was one of the primary metric that Rob Pike et al were optimizing for, and drove major aspects of its design. It shouldn't be surprising that Go blows other systems out of the water in this regard. Here he is talking about it: https://www.youtube.com/watch?v=rKnDgT73v8s#t=8m53
For any developer that never used Turbo Pascal, Modula-2, Oberon compilers, just to cite a few examples among many possible ones.
Those that did, can not comprehend why companies invested in languages like C and C++, which created this notion all compilers should be slow.