Live data from Hacker News

Four years with Rust

words.steveklabnik.com

141–150 of 199 posts

Re: Four years with Rust

#141
post #33

Earlier quoted context omitted.

They certainly didn't get unbanned! And btw I vaguely recall other accounts being silly around a similar derangement-point, so perhaps this is a serial troll, which is one of the few cases where we just ban accounts immediately. The comment might have gotten unkilled because of a bug that I might have introduced yesterday. Looking into it now. Edit: yep, it turns out I introduced a bug, with the dismaying but hilario…

He's still posting, so not banned? Or that because of the bug you're referring to? https://news.ycombinator.com/threads?id=cyphreak

Pretty sure that was the bug, but if anyone sees weird behavior around dead comments and banned accounts, please let us know.

Re: Four years with Rust

#142
post #129

Earlier quoted context omitted.

Rust doesn't have a GC in the first place, so there's nothing to turn on. Even then, the fundamental hurdle with GC isn't the effect on your program's runtime, it's the effect that it has on the lifetimes of your data . GC (and RC) are means of dynamic lifetime determination. Manual memory management is static lifetime determination. The latter requires you to structure your code in a specific way, which may be less…

I was just thinking that most languages are either GCed (like Java or Go) or manually curated (C/C++/rust). My idea is that if one could write in a language like Go (which has some kind of GC), but when one wants, say "I'll take care of this memory".

Yes, my above paragraph doesn't imply the impossibility of intentionally mixing manual and automatic memory management. E.g. you can kinda do this in Go, but the language provides no facilities to help you get the manual bits right. And you can kinda opt-in to GC in C++ and Rust (via reference counting), but it's not super ergonomic.

Re: Four years with Rust

#143

Wow, four years already. Maybe you can help settle this question I've had. I'm a rubyist (like you were/are, and wycats, and a bunch of rustaceans), and I think that sort of drove my interest in rust. But after 4-5 years of ruby the dynamism which initially was super cool, has grown a little frustrating and I long for a more sophisticated type system and a compile step, since frustrating bugs crop up from time to tim…

Are you talking about strong typing or static typing? I've been using statically typed languages for 20 years (C++, Java, Objective-C) and I haven't gotten tired of it yet. Especially when working in a large code-base I didn't write, Python is rough. What's a "session"? Who knows, guess I'd better put `print type(session)` and figure out how to get that function executed. Although, the thing that bothers me about Pyt…

> With interpreted and dynamically typed languages, you have to have 100% test coverage, because you have no idea if your code is even syntactically valid until you run it, and of course if it isn't valid, then you throw an exception.

I think you mean _semantically_ valid, e.g. no undefined variables. Most dynamic languages provide file-level syntax checking, rather than line-level. But I completely agree that this is the easiest argument against dynamic languages. Computers are better at bookkeeping than humans, and we should use them as such.

Re: Four years with Rust

#144
post #126

Earlier quoted context omitted.

I've worked primarily in Java and C++ for the past few years, but also with several dynamic languages. I sometimes miss the expressiveness of Python, but I can't say I'm ever frustrated by a strong type system nor does the compile step annoy me as long as my write-compile-test cycle is reasonably quick (usually achievable). With Java 8, and even more so with Rust, I'm less frustrated by the lack of expressiveness, so…

> but I can't say I'm ever frustrated by a strong type system Never? I can't say it happens very often but occasionally the type system get's in the way, usually when you want the function to be type T1 but sometimes it'd be convenient to do a little bit more if the type is also T2.

Rust supports algebraic types and switching over the type, which handles your example quite efficiently. You would simply define an algebraic union of T1 and T2, and switch on the type into the desired code for each branch.

Re: Four years with Rust

#146
post #126

Earlier quoted context omitted.

> but I can't say I'm ever frustrated by a strong type system Never? I can't say it happens very often but occasionally the type system get's in the way, usually when you want the function to be type T1 but sometimes it'd be convenient to do a little bit more if the type is also T2.

Rust supports algebraic types and switching over the type, which handles your example quite efficiently. You would simply define an algebraic union of T1 and T2, and switch on the type into the desired code for each branch.

What does that look like in code? I was using c# so I did the dirty:

T1 arg;

var foo = arg as T2;

if (foo != null)

  ....
Also, how do we format code here?

Re: Four years with Rust

#147

Earlier quoted context omitted.

How do you convert copies to non-mutable references? That involves proving things about aliasing. Even in Rust that is not that easy…

The other way round. Sometimes you want to convert non-mutable references to non-mutable copies. This is almost always a win for int, float, etc., and usually a win for anything up to 8 bits on a modern processor.

I'm going to nitpick and suggest that you almost certainly meant 8 _bytes_.

Re: Four years with Rust

#148
post #119

Earlier quoted context omitted.

The main languages I use with work are: * C * Scheme (Gambit) * Python 3.4 * Pony I find all of them frustrating at times. Python's dynamism is nice, but it's so damn inflexible, requiring my to follow the One True Way. That can be good, and makes it easier to eliminate bad code in reviewing. But it also means that you can fight with the interpreter to do what you want. Scheme gives me both dynamism and flexibility,…

Can you talk more about using Pony in a production environment? What are the performance aspects of it? How do you find writing 'non-actor' code - like just doing some string manipulation? I find the language fascinating but I'm learning Erlang and I don't really want to get started with Pony at the same time. Do you have experience with Erlang? what made you choose Pony? Sorry for the bombardment of questions but I…

I've never met anyone else using Pony in production, so I'll try and give the best answer I can.

> What made you choose Pony?

We wanted a Type Safe language to run a REST API frontend. That is to say, we wanted to have something that could redirect requests to the appropriate servers, at scale, whilst maintaining Type Safety in the server itself. We got hit by so many issues from JSON's weak/absent typing causing runtime errors, we wanted something that could sanely prove that we wouldn't crash.

Whilst we were at it, the same language seemed great for the backend for a couple languages we develop in-house. For example, Owlang is a language developed for teaching with a group of teachers. The first iteration was written in Scheme, today, it runs on top of Pony.

We considered three languages:

* Rust

* Pony

* Erlang

Erlang was a bit odd to throw in the mix, but we couldn't ignore how amazing BEAM is, especially with recovery by dropping and creating thousands of processes without effort.

However, we found Rust was making too many breaking changes, and there was sort of a culture of using Rust Nightly, which doesn't give off a nice solid feel, or didn't back then.

Erlang has this sort of huge cognitive overload with it's syntax, making it take longer to learn, for no obvious benefits.

Pony's Philosophy[0] however, felt damn good, and we investigated their mathematical proof of safety and the like.

> Can you talk more about using Pony in a production environment?

Pony's got a few gotchas. Thankfully, they spell them out. [1]

We have been burned from long running procedures when we've had to tap out to an in-house C library. We went from using around 400mb of RAM for a group of processes, to running out of memory on a 16GB RAM machine.

That was a stupid mistake. However, using a Timer, like the docs tell you to, obliterated that, and we dropped back down to 4-500mb.

The non-preemptive nature of Pony's scheduler has taken a few people, myself included, some time to get used to.

> How do you find writing 'non-actor' code - like just doing some string manipulation?

If you try and avoid the fact you're using Actors, it'll bite you. Pony is designed for concurrency.

However, if we're just talking about methods and classes and so on, and how they feel... Pony feels simple, and easy to use.

Traits and interfaces make subtyping a breeze, especially interfaces.

But, being interested in Erlang, how about some pattern matching?

    fun f(x: (String | None), y: U32): String =>
      match (x, y)
      | (None, _) => "none"
      | (let s: String, 2) => s + " two"
      | (let s: String, 3) => s + " three"
      | (let s: String, let u: U32) if u > 14 => s + " other big integer"
      | (let s: String, _) => s + " other small integer"
      else
        "something else"
      end
One more bonus for something Pony has, that proved unexpectedly useful, is the ability to have multiple, or generate, Environments. In terms of Pony, that means argc, argv, argp. Being able to isolate environment variables between processes has been useful for making some configuration easier.

[0] https://tutorial.ponylang.org/#the-pony-philosophy-get-stuff...

[1] https://tutorial.ponylang.org/gotchas/

Re: Four years with Rust

#149
post #146

Earlier quoted context omitted.

Rust supports algebraic types and switching over the type, which handles your example quite efficiently. You would simply define an algebraic union of T1 and T2, and switch on the type into the desired code for each branch.

What does that look like in code? I was using c# so I did the dirty: T1 arg; var foo = arg as T2; if (foo != null) .... Also, how do we format code here?

I expect Rust should be able to handle this nicely, but I'm more familiar with Pony... So here's how to do it nicely in it:

    fun f(x: (T1 | T2 | None)): ReturnType =>
      match x
      | T2 => /* do something */
      | T1 => /* do something else */
      | None => /* Handle badly behaved. Optional to have, compiler can enforce good behaviour if you want. */
Note: You can see formatting at https://news.ycombinator.com/formatdoc

Re: Four years with Rust

#150
post #146

Earlier quoted context omitted.

Rust supports algebraic types and switching over the type, which handles your example quite efficiently. You would simply define an algebraic union of T1 and T2, and switch on the type into the desired code for each branch.

What does that look like in code? I was using c# so I did the dirty: T1 arg; var foo = arg as T2; if (foo != null) .... Also, how do we format code here?

In Rust, you'd define an `enum` of two types.

    enum Either {
        Type1(T1),
        Type2(T2),
    }
let's say you get a value of type Either

then you can match on them:

    match value {
        Type1(v) => func(v),
        Type2(v) => func2(v),
    }
Post reply on HN