Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

If you change a type from T to Option<T>, yes, all the other code has to change to take the option into account.


Yeah that's not good design. Lowering a requirement should not make callers complying to a stricter one have to change anything. But, ohhh.. right only the type changed. so everybody stop what you're doing and start over.


I strongly disagree, but this is why it's great we have a ton of languages! To me, forcing you to handle it is the exact point of an option type.

The type wasn't the only thing that changed, the possible values have changed. You may be getting more values than you were previously. This means that some of your assumptions may be incorrect. Of course your code needs to change.


I might be misunderstanding, but I think you are talking about slightly different points here. It seems to me that the critique of an explicit Option type (that acts sort of like a box, in contrast to Kotlin's T? vs T) applies to when you pass in the Option as a function parameter to a function that previously expected it to always be T instead of Option<T>. In that case you as a caller are never "getting more values than you were previously", but you can now certainly pass in more values than you could before.

Forcing callers to refactor their calls to use a new Option<T> type as a parameter simply amounts to a change in the type signature, but since the function is more liberal than before, it cannot break your assumptions (at least not assumptions based on the function type signature).

(For what it's worth, I do find Kotlin's T? to be more elegant than the Haskell/Rust-style Option/Some type. But then again, Kotlin is not fully sound, so there's that. Dart's implementation of T? will be fully sound though, so there are definitely examples of languages going that route.)


That is true! You're right that the perspective can be different.

You could write <T: Into<Option<i32>> if you wanted, and your callers wont change.

Frankly, using options as parameters is just not generally good design, so this issue doesn't really come up very often, in my experience. There are exceptions, but it's exceedingly rare.


Frankly, using options as parameters is just not generally good design

That's true. Even in annotated Python, I want to ensure all parameters are set before calling my functions/methods. Saves a lot of complications.


Ah, I see where the misunderstanding is. You can make it so you change only the function signature and behaviour or you can make it so you have to also change the function call site.

Ever since https://github.com/rust-lang/rust/pull/34828 you can transform any `f` that takes a `T` into an `f` that takes an `Option<T>` without any of the call sites changing.

For instance, look at this playground https://play.rust-lang.org/?version=stable&mode=debug&editio...

Your function `get_string_raw` which just handles `i32` can be transformed into a function `get_string` which handles `Option<i32>` without the thing calling changing how it calls the function. And the new `get_string` can accept `Some(i32)` or `None` or just `i32`.

Of course, this is slightly broad for brevity: you can now pass in anything that can become an `Option<i32>` but you can just define a trait to restrict that if you wanted.

You can get that sort of covariant effort that you wanted.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: