4 ms·
Reminds me of: https://github.com/roc-lang/roc/blob/main/FAQ.md#why-doesnt-roc-have-a-maybe-or-option-or-optional-type-or-null-or-nil-or-undefined https://githu
by eterps 3y ago
Reminds me of: https://github.com/roc-lang/roc/blob/main/FAQ.md#why-doesnt-roc-have-a-maybe-or-option-or-optional-type-or-null-or-nil-or-undefined https://github.com/roc-lang/roc/blob/main/FAQ.md#why-doesnt-...
- nivertech 3y agoError Handling in Elm https://twitter.com/nivertech/status/1413392990211657729 https://twitter.com/nivertech/status/1413392990211657729 It looks like Maybe/Option is just a Booleans-in-disguise. As I'm in favor of banning Booleans (and if-statements), so it makes sense to ban Maybe/Option-s also.
- mrkeen 3y ago> It looks like Maybe/Option is just a Booleans-in-disguise. This is a unique take. Care to expand?
- 0x457 3y agoNot the person you're asking, but I may have insight. Realistically, it's no different, checking if something is null or None. Yeah, some languages have a lot of sugar around optional thanks to rich type systems. Imagine the following pseudo rust code: if let Some(x) = x {} is not that different from if x != null {} Or any other type of boolean check. I think you have to be around optional long enough to understand the benefits.
- mrkeen 3y ago> Realistically, it's no different, checking if something is null or None. That is correct. However, what languages with null lack is a way to say "See this String here? This is actually a String - not the absence of a String". It is nonsense to encode both A and lack-of-A as A.
- 0x457 3y agoYeah, and it's annoying. One of my most hated things about proto3 - is this string empty or just not set? (they added optional back now, but everything is already optional)
- mathgladiator 3y agoBut it is different because you can't dereference x without the check. In other words, you can't really make an accident. My language has maybe<T>, and I have automatic "re-wrapping" (not sure if there is a better term). where For example, with record R { int x; } maybe<R> r; I can access r.x yet the type is maybe<int>.
- 0x457 3y agoTrue. I'm just playing devil's advocate here. In unsafe rust, technically deref you can for types that have niche optimization.
- Akronymus 3y agoWell, you can have nested options. Some(None) is different from a None It also has nice ergonomics with bind, map and such. And the fact that a None is not even comparable to an 'a.
- 0x457 3y agoOh, I'm not arguing about the usefulness of optional - I love them.
- nivertech 3y agoMainly, there are 3-4 reasons for considering alternatives to using booleans: 1. Booleans are primitive types without rich domain-specific information or context. When using true/false, it can be more beneficial to employ more descriptive options such as AnsweredYes/AnsweredNo, PositiveResult/NegativeResult, LightsOn/LightsOff, or UserOnline/UserOffline. Mixing and matching booleans of different domain types can lead to errors that the compiler may not catch. For instance: bool isLightsOn = true; bool isUserOnline = false; bool isAdmin = true; if(isLightsOn && !isUserOnline && !isAdmin) { ... } compare with Elixir: case {lights_status, connection_status, user_role} do {:lights_on, :user_offline, :unprivileged_role} -> ... ... end The example above is basically a Decision Table [1]. While booleans can still be used in system code or libraries, it is advisable to avoid them in application code. 2. Preemptive pluralization [2] makes it easier to refactor code. Going from two options to three is simpler than transitioning from one option to two. Consider the following examples: bool isLightsOn; or type LightsStatus = Bool vs type LightsStatus = LightsOn | LightsOff Suppose there is a new requirement to support dimmed lights. In the former case, significant code refactoring is necessary. In the latter case, adding a new option to the sum type is straightforward, and the compiler assists in handling the changes: type LightsStatus = LightsOn | LightsOff | LightsDimmed Similarly, let's examine another scenario: boolean isOnline; or type ConnectionStatus = Bool vs type ConnectionStatus = Online | Offline The latter option can easily evolve into: type ConnectionStatus = Online | Offline | BadConnectivity and later: type ConnectionStatus = | OnlineMobile | OnlineFastInternet | Offline | BadConnectivity | IntermittentConnection | ConnectedToMeshnet 3. Booleans encourage the overuse of conditionals and branching, including nested branching. This can increase the cyclomatic complexity [3] of the code. It is important to manage cyclomatic complexity to keep the codebase maintainable and easier to reason about. Also see "Get rid of those boolean function parameters" [4]. 4. Booleans can indicate whether something occurred, but they lack both the necessary context and the timestamp indicating when the event took place. However, by transforming booleans into nullable or optional timestamps, one can achieve a rudimentary implementation of Domain Events or Event Sourcing. user_connected_at: nullable(Timestamp) lights_turned_on_at: nullable(Timestamp) record_deleted_at: nullable(Timestamp) NOTE: I'm not advocating for the pattern above, but it's widely used because of the limitations inherent in booleans. -- References: [1] https://en.wikipedia.org/wiki/Decision_table https://en.wikipedia.org/wiki/Decision_table [2] https://www.swyx.io/preemptive-pluralization https://www.swyx.io/preemptive-pluralization [3] https://en.wikipedia.org/wiki/Cyclomatic_complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity [4] https://mortoray.com/get-rid-of-those-boolean-function-parameters/ https://mortoray.com/get-rid-of-those-boolean-function-param...
- awestroke 3y agoWow, I hope I never have to work with you or anybody who shares your opinions on this topic
- dotancohen 3y ago> I'm in favor of banning Booleans (and if-statements) I would love to hear your reasoning on this. I think that either I'm misunderstanding you, or one of us is crazy ))
- withinboredom 3y agoI've usually seen it expressed as: > instead of accepting a boolean argument, write a new function Which can be expanded to > instead of an if-statement, write a new function You can't remove branching from software (otherwise, just create a jpeg), but you can structure your software in such a way that it appears not to branch. I think it's weird, but I worked with someone like that and learned a few interesting things (for example, I usually do write a new function instead of adding an optional/boolean argument -- unless it makes things worse for the caller because the argument comes from outside the context/domain). But with all due respect to people like this, it's bananas to do it all the time.
- nivertech 3y agohttps://news.ycombinator.com/item?id=35955938 https://news.ycombinator.com/item?id=35955938
- awestroke 3y agoVery strange design. It completely ignores the potential ergonomics of functions over Option<T> like map, unwrap_or, flatten etc that you'd have to implement yourself for every option-imitating enum.
- mathgladiator 3y agoYeah, I agree. My language has both maybe<T> and result<T>, and maybe<T> is exceptionally convenient for all sorts of things. As an example, the result of division is a maybe<double> and I have all the typical operations defined between maybe<double> and double so maybe<double> + double is a maybe<double>. It feels nice to force people to think about the edge conditions of why something isn't present.