[HN Gopher] The Ultimate Conditional Syntax
___________________________________________________________________
The Ultimate Conditional Syntax
Author : azhenley
Score : 42 points
Date : 2024-10-20 12:33 UTC (10 hours ago)
(HTM) web link (dl.acm.org)
(TXT) w3m dump (dl.acm.org)
| huqedato wrote:
| Elixir already has this - "with".
| https://www.openmymind.net/Elixirs-With-Statement/ E.g.:
| with true <- is_email_address?(email), true <-
| String.length(code) === 6, %EmailConfirmation{} <-
| EmailConfirmations.get_email_confirmation(email), nil <-
| EmailAddresses.get_email_address(email), {:ok, user} <-
| Users.create_user(data), {:ok, email_address} <-
| EmailAddresses.create_email_address(user, email) do ...
| else ... end
| ioasuncvinvaer wrote:
| How does this check exhaustiveness?
| clark800 wrote:
| Looks very similar to lambda zero syntax
| (https://github.com/clark800/lambda-zero): def
| getNaturalName(tag, globals) if globals.lookup("0")
| is Just(Global(_, _, term)) if term is Numeral(_,
| type, _) return Just(Name(getTermTag(type)))
| error showSyntaxError("0 must be a numeral to use numerals", tag)
| return Void
|
| Though this ultimate conditional syntax is more general because
| lambda zero only allows one destructuring per conditional to
| simplify parsing.
| mgaunard wrote:
| I don't understand how it's better than traditional pattern
| matching.
| dan-robertson wrote:
| With traditional matching there are up to five different
| things:
|
| - if x then y else z. This is roughly like a match with a true
| and false case but it depends on the language how much that is
|
| - match e with { p -> e }. This is the classic pattern match
| case
|
| - if let p = e then x. This is roughly equivalent to (match e
| with p -> x | _ -> ())
|
| - match e with { p when e -> e }. This is matching with a guard
| but I've counted it as a special case because it doesn't easily
| designate into a match because of the binding/evaluation order,
| and the guard is special because it can only go at the top
| level of the match clause so it isn't just a special kind of
| pattern (though maybe it could be)
|
| - let p = e. This is one-case pattern matching used for binding
| variables or destructuring.
|
| The paper proposes a way to make the first four cases obvious
| parts of one more unified thing, which makes the language
| potentially simpler and may reduce some weird warts like where
| guards can go.
| EPWN3D wrote:
| There's such a thing as too high an abstraction. Sometimes 4
| different operations really are just 4 different operations
| and not cases of some mega-construct.
| 082349872349872 wrote:
| Inspired by duality, I've been trying to work out a language
| where there's a more obvious correspondence/symmetry between
| expressions (which evaluate in an environment of named
| bindings to produce an anonymous value) and patterns (which
| destructure an anonymous value to produce an environment of
| named bindings).
| dan-robertson wrote:
| I like that there is this left-to-right flow. I think it's a bit
| nicer to read than if-let ordering where the pattern comes before
| the thing it will be matched against. I think it's also good for
| ocaml-style constructor disambiguation, which tends to go in
| lexical order.
|
| Another nice aspect of making guards a less special case is that
| it avoids complexities in deciding if a binding is unused. I
| believe this logic was a source of lots of compiler warning bugs
| in ocaml.
|
| This syntax doesn't seem to solve the following problem with
| matching where there are two paths to the same binding, (say you
| have an option in one branch but it isn't optional in the other,
| and maybe you'd like to handle both cases with the same code.
| Currently you can do that with a match (match ...) with ...
| pattern.
|
| I worry that the semantics around exhaustiveness and mutable
| values may be confusing, though I guess OCaml already has that
| problem: type t = { mutable x : bool }
| let n = function true -> 1 | false -> 0 let f t =
| match t with | { x = false } when ( t.x <- true; false)
| -> -1 | { x } -> n x * 2 + n t.x
|
| What does t { x = false } return? Similarly if you changed the
| second case to be two cases instead of binding x?
___________________________________________________________________
(page generated 2024-10-20 23:00 UTC)