5
$\begingroup$

I'd like to have both a safe navigation operator and monad unwrapping operator.

Safe navigation is like the feature in TypeScript:

fn() => print(Some(k)?.property) // prints Some(k.property)
fn() => print(None?.property) // prints None

This is very useful for transversing nested structures with members that may or may not exist.

However, I'd also like a monad unwrapping operator like rust has:

fn() => print(Some(k)?.property) // prints k.property, function returns Some(())
fn() => print(None(k)?.property) // prints nothing, function returns None

Note that monad unwrapping works at a function level while safe navigation works at a expression level. Ideally I'd have both, but both contractually use the ? symbol creating ambiguity.

Both of these work on many other monads besides Option

I already use ?? for null coalescing.

What other syntax can I use to disambiguate these 2 concepts? Ideally I'd like something that is already used in some other language.

$\endgroup$
3
  • $\begingroup$ I’m not really sure what the question is asking. Could you give a longer example where the difference is more obvious? Swift has implicit wrapping, so Optional.some(1) can just be written 1, which might be making it a bit harder for me. $\endgroup$
    – Bbrk24
    May 17, 2023 at 15:53
  • $\begingroup$ @Bbrk24 I expaned the examples a bit more, does it make sense now? $\endgroup$
    – mousetail
    May 17, 2023 at 15:56
  • $\begingroup$ Yes it does, thank you! $\endgroup$
    – Bbrk24
    May 17, 2023 at 15:56

3 Answers 3

4
$\begingroup$

Ruby uses the &. token for safe navigation, which can safely coexist with a ? for monads.

foo&.bar # Safe navigation a la Ruby
foo?.bar # Monadic unwrap a la Rust

If you don't like the asymmetry between ? for monad unwrapping and ?? for null coalescing, I'm quite fond of Perl's // for null coalescing. It looks like || (which is similar) but is clearly a different operator. Only downside is it won't work if you're using C-style comments as well.

$\endgroup$
3
$\begingroup$

Asterisk

If you're not already using it and it works with your current syntax, you could use *. for monad unwrapping.

Some(k)*.property = k.property
None(k)*.property = return None
$\endgroup$
3
  • $\begingroup$ Thanks, do you know any language that uses that syntax? I'm specifically looking for a established convention $\endgroup$
    – mousetail
    May 17, 2023 at 15:49
  • $\begingroup$ @mousetail I don't, but that might just be because no languages have had these two features before. You might get to be a trendsetter! $\endgroup$
    – Ginger
    May 17, 2023 at 15:51
  • 1
    $\begingroup$ (I'm mostly asking for established conventions to avoid being closed as opinion based, I don't actually care) $\endgroup$
    – mousetail
    May 17, 2023 at 15:52
3
$\begingroup$

.map method

This is what Swift does. Using the example from your question:

func printSafe(_ x: T?) {
  print(x?.property)
}

func printMonad(_ x: T?) -> Void? {
  x.map { print($0.property) }
}

If you provide functional interfaces on collection types, this runs the risk of confusing arr?.map with arr.map.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .