News for hackers. Stuff that matters.
Re:Gnirehtet rewritten in Rust by im_down_w_otp on Sunday September 24, 2017 @06:04PM (#15326731)
When I write Rust I tend to do so using functional/procedural patterns instead of object-oriented ones, and it doesn't seem like I run into issues like the ones described here very often.

Much of this write-up seems to cover things that were/are complicated because of OOP's tight coupling of state and actions on that state & the intersection of that with the additional constraints and controls Rust places on state management.

I'm not entirely sure which style/patterns are more idiomatic. I just know which ones keep me out of trouble.

Re:Gnirehtet rewritten in Rust by bluejekyll on Sunday September 24, 2017 @08:30PM (#15327275)
I don’t know about this. I think the trait system is so powerful of a concept for genetics and such that I find that I practice OO pretty regularly. I avoid dynamic polymorphism, but most OO practices translate really well into Rust.
Re:Gnirehtet rewritten in Rust by sixbrx on Sunday September 24, 2017 @08:54PM (#15327352)
Sounds closer to type classes usage a la Haskel than what I'd call OO (late binding)?
Re:Gnirehtet rewritten in Rust by bluejekyll on Sunday September 24, 2017 @09:09PM (#15327407)
I try to capture data in a enum or struct, then define the operations available to that type. A trait allows me to capture common functionality across different types which implement that trait. With generics it allows me to be polymorphic.

If that’s not OO, I don’t know what is :)

Re:Gnirehtet rewritten in Rust by Tarean on Monday September 25, 2017 @05:57AM (#15329134)
Well, technically traits dispatch based on type and not on value. As long as you aren't wrapping everything into trait objects that is much closer to functional programming. Seems like a mostly semantical difference, though.

I guess there is a philosophical difference in whether you pass a large struct into a function or select the needed data at the call side and only pass that, though. Former might be easier to extend, latter is probably easier to test?

Re:Gnirehtet rewritten in Rust by solidsnack9000 on Sunday September 24, 2017 @03:52PM (#15326207)
The discussion of how borrowing impacts encapsulation, abstraction with private methods, and the observer pattern was informative and interesting.
Re:Gnirehtet rewritten in Rust by moomin on Sunday September 24, 2017 @05:37PM (#15326615)
It's interesting, but overstated. It's more a description of how some Java patterns don't translate. For instance, the first example "encapsulation" demonstrates exactly no encapsulation.

In general terms although sometimes you need to do things like this, shared mutable state is something you should be avoiding in any language and you should thank Rust for making it harder on you.

Re:Gnirehtet rewritten in Rust by solidsnack9000 on Sunday September 24, 2017 @05:59PM (#15326706)
> ...the first example "encapsulation" demonstrates exactly no encapsulation.

It demonstrates a kind of getter, but a weird one since it returns a mutable field. These are not the most encapsulated thing.

Re:Gnirehtet rewritten in Rust by oconnor663 on Sunday September 24, 2017 @07:10PM (#15327009)
I think the part where they're trying to abstract out a `content` method could be made to work by adding braces, so that the `&self` borrow goes away earlier than the end of the function. I think "nonlexical lifetimes" are also going to make more cases like that work automatically without braces soon.
Re:Gnirehtet rewritten in Rust by rom1v on Monday September 25, 2017 @02:33AM (#15328464)
> I think the part where they're trying to abstract out a `content` method could be made to work by adding braces, so that the `&self` borrow goes away earlier than the end of the function.

Not in that case. It helps when dropping a borrow earlier avoids to violate the borrowing rules, like in this case:

    let mut a = [0; 20];
    {
        let b = &mut a[2..4];
    }
    let c = &mut a[6..8];

In the example from the blog post, content borrows the whole struct, and you can't drop the borrow earlier since it is used in the next line.
Re:Gnirehtet rewritten in Rust by oconnor663 on Monday September 25, 2017 @10:22AM (#15330705)
Right, you'd have to split up the following line so that `sum` is computed inside the block but assigned after it.
Re:Gnirehtet rewritten in Rust by bluejekyll on Sunday September 24, 2017 @09:13PM (#15327423)
Yes. I use that often. It’s ugly though, and lexical lifetimes should help fix this.
Re:Gnirehtet rewritten in Rust by w4tson on Sunday September 24, 2017 @04:37PM (#15326382)
I found it useful.

I think there’s a missing guide out there for people like myself who have an OO background, are looking to write some rust but can’t reconcile the borrow-checker with how they normally design software

Re:Gnirehtet rewritten in Rust by juanpotato on Sunday September 24, 2017 @05:07PM (#15326507)
Re:Gnirehtet rewritten in Rust by viraptor on Sunday September 24, 2017 @06:03PM (#15326726)
I think in the encapsulation / content example they missed the possibility of creating an explicit block on your own. I believe something like this would solve it:

    let new_sum = { calculate it from self.content() }
    self.sum = new_sum;
Since the sum value itself doesn't borrow anymore.
Re:Gnirehtet rewritten in Rust by rom1v on Monday September 25, 2017 @02:38AM (#15328480)
Yes, you're right, this particular (artificial) example could be rewritten easily so that it compiles.

But the point was to show that a compiling program may not compile anymore after factoring some code into a private method.

Re:Gnirehtet rewritten in Rust by mathw on Monday September 25, 2017 @04:26AM (#15328799)
It's a useful lesson in that Rust's correctness relies on certain notions of borrowing dependencies which don't necessarily match what you assume. Especially that the lifecycle dependency across a function call is essentially opaque to the compiler.

Which is how it has to be, or you could never state anything sane about the lifecycle when you return a reference.

Re:Gnirehtet rewritten in Rust by fnord123 on Monday September 25, 2017 @05:55AM (#15329121)
Is the purpose of encapsulation to wrap all data fields in functions offering mutable references to data? I thought it was the exact opposite.
Re:Gnirehtet rewritten in Rust by rom1v on Monday September 25, 2017 @06:05AM (#15329177)
The purpose was to show that something lifetime-bound to a part of a struct becomes lifetime-bound to the whole struct when returned from a function.

Using mutable references is the minimal way to get this.

Re:Gnirehtet rewritten in Rust by steveklabnik on Sunday September 24, 2017 @03:51PM (#15326203)
Apparently the name is "tethering" backwards.
Re:Gnirehtet rewritten in Rust by saghm on Sunday September 24, 2017 @04:08PM (#15326279)
Embarrassingly, it took me until halfway thorough the article to notice this
Re:Gnirehtet rewritten in Rust by akavel on Sunday September 24, 2017 @05:33PM (#15326607)
Is there some valuable disscussion of the article on rust subreddit? If yes, could somebody please link it here?
Re:Gnirehtet rewritten in Rust by txru on Sunday September 24, 2017 @05:39PM (#15326618)
Re:Gnirehtet rewritten in Rust by mathw on Monday September 25, 2017 @04:31AM (#15328816)
The "encapsulation" example is an interesting one, because it sits right in the fundamental difference between a Rust reference and a Java one, and the lifecycle considerations of a garbage-collected language vs one where lifecycles are statically determined by the compiler.

I guess one way to explain it, if one needed to, is to say that the Java object is effectively a collection of Rc<RefCell<T>>, and getters return copies of those Rc<>s. (Okay I know, garbage collection is not the same as refcounting, but in this kind of analysis it's effectively the same).

Makes me sit back and think how much work Java the language is doing for you here.

Re:Gnirehtet rewritten in Rust by pjmlp on Sunday September 24, 2017 @06:45PM (#15326906)
> ... I introduced Gnirehtet, a reverse tethering tool for Android I wrote in Java.

> At Genymobile, we wanted Gnirehtet not to require the Java Runtime Environment, so the main requirement was to compile the application to a native executable binary.

While it is nice to see new projects adopting Rust, I really don't get the point of having a tool targeted to Android developers not depending on Java.

Re:Gnirehtet rewritten in Rust by harrisi on Sunday September 24, 2017 @07:50PM (#15327137)
As far as I can tell it's not necessarily targeted at Android developers. It seems like the primary use case is if you have some device with cell service and you're out of WiFi range but want to use your Android device with an internet connection.

They must have customers that are in that situation somewhat regularly (traveling business people?) and keeping the overhead low is desired.

Re:Gnirehtet rewritten in Rust by tango25 on Sunday October 08, 2017 @02:28PM (#15429308)
Hello Gnirehtet is really a great tool.

Is there a possibility to have the RUST Version compiled for an ARM architecture?

I'm running it on a Raspi3 as a tether box. Obviously less CPU consumption would be an enormous advantage. , since with the java version transmit speed only reaches arround 50 kbit/s.

Thank you very much for your great work!

Re:Gnirehtet rewritten in Rust by steveklabnik on Sunday October 08, 2017 @04:32PM (#15429863)
It should work, yeah.
Re:Gnirehtet rewritten in Rust by tango25 on Monday October 09, 2017 @12:21PM (#15435186)
Awesome! will you put a executable at GitHub like the others? Thank you very much!
Re:Gnirehtet rewritten in Rust by steveklabnik on Monday October 09, 2017 @02:49PM (#15436405)
I'm not the maintainer of the project, so I can't do that. Rust can cross-compile to that architecture though, so it should be possible, hence my reply.

You probably should file an issue so the maintainer actually sees it.

Re:Gnirehtet rewritten in Rust by tango25 on Wednesday October 11, 2017 @11:51AM (#15450702)
Re:Gnirehtet rewritten in Rust by matt_wulfeck on Sunday September 24, 2017 @03:52PM (#15326206)
> At Genymobile, we wanted Gnirehtet not to require the Java Runtime Environment, so the main requirement was to compile the application to a native executable binary.

While I think that rust is a great choice, if multi platform static executables is your goal then I think you missed a language that does such a thing extrmely well. I’m surprised the author didn’t even consider Go for this purpose.

Re:Gnirehtet rewritten in Rust by stouset on Sunday September 24, 2017 @03:59PM (#15326238)
You may have missed these three points the author listed, favoring Rust:

  * memory safety without garbage collection,
  * concurrency without data races,
  * abstraction without overhead
Go has garbage collection, doesn’t statically prevent data races, and somewhat infamously allows for only minimal abstraction.
Re:Gnirehtet rewritten in Rust by lossolo on Sunday September 24, 2017 @04:41PM (#15326399)
You should reread article again:

> But at that time (early May), I was interested in learning Rust, after vaguely hearing what it provided, namely:

And then he listed what you listed in your comment.

As he wrote the main requirement was not to include JRE. This could also be achieved by using Go.

Re:Gnirehtet rewritten in Rust by Ruud-v-A on Sunday September 24, 2017 @04:25PM (#15326337)
Haskell is another language that compiles to native executables with minimal dependencies (binaries do link against libc, libz, and libgmp by default) which I think deserves more attention. It has great build tooling too (Stack).

I have been responsible for building and deploying Python, JVM, and Haskell projects to production servers. For Haskell projects it was pretty much painless, Python and JVM were "challenging". The main advantage comes from having native binaries and a good build system that does the right thing, which Rust is also good at.

Re:Gnirehtet rewritten in Rust by masklinn on Sunday September 24, 2017 @05:05PM (#15326497)
> Haskell is another language that compiles to native executables with minimal dependencies (binaries do link against libc, libz, and libgmp by default) which I think deserves more attention.

OCaml hits most of the boxes and would be more convenient/familiar to most users since it's strict and impure.

Re:Gnirehtet rewritten in Rust by steveklabnik on Sunday September 24, 2017 @04:20PM (#15326326)
Rust is also pretty good at this, not quite as good as Go, but still generally pretty solid. Main related points:

Rust code is statically linked by default. C code you link to may not be. Many -sys packages (that wrap C libraries) give you an option to link statically or dynamically.

libc isn't statically linked by default, so that's usually the only thing not-statically linked in a pure-Rust program. You can use musl instead if you'd like.

Re:Gnirehtet rewritten in Rust by dimfeld on Sunday September 24, 2017 @04:00PM (#15326244)
I suspect that "But at that time (early May), I was interested in learning Rust" was a big consideration there. But I can also vouch for Go's excellent cross-compilation support.