5 comments

[ 2.8 ms ] story [ 21.9 ms ] thread
The boolean example is particularly bad though; I believe it is even in the Rust API Guidelines to not pass booleans in your APIs precisely for that reason. The advice which I agree with is to make it properly typed

https://rust-lang.github.io/api-guidelines/type-safety.html?...

But the recommendation sounds like it's trying to work around a limitation of the language.

"We don't support named parameters, therefore, create an enum whenever a boolean would have been enough with proper support of named parameters".

I think this is unsound reasoning, but regardless of whether you agree with this or not, the idea of creating an enum for every boolean that gets passed to a function sounds pretty crazy to me.

If you have named parameters, you just don't need to create an enum whenever you are passing a boolean to a function.

I think it's good the way the Rust API guidelines lay it out. It will also introduce additional lightweight documentation (in form of a type) and reduces amount of raw booleans in the code, and will get the benefits of the advanced type system too, and somewhat future proofs it that way too.
(comment deleted)
The constructor example is not really fair. new_with_visibility is useless, you can just call Window { x, y, z}. You can also put your Window struct on one line, like you did in Kotlin. So 7 lines and one function instead of 17 and two functions. There's still a bit of overhead, of course. But far less than you think.

> The lack of overloading is the most baffling to me. First, this forces me to come up with unique names, but mostly because it’s a compiler feature that’s pretty trivial to implement in general, which is why most (all?) mainstream languages created these past twenty years support it.

I'm not sure what you mean by this. Rust has overloading in the form of traits. So if you have a function that does the same thing, it can have the same name. If that's not the case, why do you want it to have the same name? They are doing different things. Rust likes to be explicit about things like this. I'm also not sure why you're so confident that it's trivial to implement. How many mainstream languages created these past twenty years have borrow checking? If the answer is no one, maybe it's not a good idea to compare the Rust compiler with their compiler.

> Without named parameters, calls to the constructor can be ambiguous to a reader:

You could use an enum, WindowColor::BlackAndWhite and WindowColor::FullColor. This way you communicate intent way better than with a named parameter. I'll also add that rust-analyzer has inlay hints that emulate this well, so when you're coding it's not needed. This makes it a bit of a pain when you do code reviews on Github though, but this is part of a larger argument about smart tools and concise code vs explicit plain text. I think your use of Kotlin and lack of fondness for boilerplate already shows where you belong though.

> In the absence of this feature, you will have to define an additional constructor in your Rust structure, one for each combination of parameters that you want to support.

Not exactly, you can get around by using Option<T> as arguments, and give the default argument when Option<T> is None. I agree that Kotlin feels better here, but Rust is not as bad as you make it to be. Usually when the cases in your code start growing at a quadratic rate, that means that you're doing something wrong.

> My solution to this specific problem was to first define all the opcodes as constants and put them in a vector as tuples:

What you could do here is implement the Into<T> trait for the different types that you need. I'm not sure about what you're trying to do and how you use the opcodes, so it's hard to give a good recommendation here for your use case. But the Into<T> would emulate Java's behavior pretty well.

> This was another unpleasant step back, and I still find it routinely painful in Rust to have to write getters and setters for all the fields that I want to expose from a structure. We learned this lesson the hard way with Java, and even today in 2021, getters and setters are still alive and well in this language. Thankfully, Kotlin does it right (it’s not the only one, C#, Scala, Groovy, … get it right too).

I think you should not try to write Kotlin, C#, Scala, Groovy in Rust. All of these are object-oriented programming languages. Rust is not. So you're going to have to use different patterns. Try to read idiomatic Rust code and see how they solve the problems you solve through encapsulation.

> We know better today, and I hope Rust will adopt properties at some point in the future.

Who is "we"? Again, I think you're trying to fit Rust into a Kotlin hole. That won't work, at all. Rust is Rust, and Kotlin is Kotlin. There's also some stuff in the article that betrays a lack of understanding of the language. That's not an issue at all, you can't know everything. But this article should be titled "What I miss from Kotlin in Rust", not "What Rust could learn from Kotlin&...