Closed rktjmp closed 1 year ago
Yep, haven't quite gotten to match
yet. Unsure whether to introduce the term unification
or call it implicit pinning
, or instead term pin
as unify
in case
...
I don't think pin
is immediately obvious to a new reader, but I think unification
might also imply more mechanics. It's more like references
or tie
(maybe not tie
...).
Ideally there would be one term, unify operator
unification
or pin operator
pinning
or ... I only call it pin
because I have seen it in Elixir, not sure of other prior art - that might help get the right (or at least traditional) name.
A bit off-topic, but, I've been looking at where
, and in reality, where
actually acts almost like and
, with the exception that it only accepts two arguments, the first being the pattern, and the last being the clause.
Maybe we could lift this and allow multiple patterns/clauses and rename it to and
? As far as I understand we'll get plain or
in match
soon, so it will play nicely. @technomancy WDYT?
Maybe we could lift this and allow multiple patterns/clauses and rename it to and?
Discarding or
for a moment, multiple patterns and clauses, or a pattern and multiple clauses? I assume you could only give multiple patterns with or
.
ex:
A case
clause accepts multiple patterns in an or
form. or
must contain at least
one pattern, as described in the preceeding section.
(case x
(or 1 2 3) true ; x was 1 2 or 3
_ false)
(case x
(or 1) :valid
(or y) :valid
(or (v-1 v-2) [(= key)]) :valid
(or) :invalid
_ false)
case
clauses may also optionally be "guarded" with an and
form. The first
value/form/expression/argument provided to and
must be a pattern or
collection of patterns as described by or
above. Each additional expression
represents a guard. All guard expressions must evaluate to truethy for the
case
clause to match.
Guard expressions may contain any valid Fennel code and have access to any in-scope binding.
(case x
(and (or 1 2 3) (sunday? today)) true ; 1 2 or 3 on a sunday
;; 1 2 or 3 in a leap year and we rolled lucky
;; note that the second `and` is a regular boolean expression
(and (or 1 2 3) (and (leap-year? today) (feeling-lucky?))) true
true :ok
_ false)
(case x
(and 1) :valid ;; (and 1 true) but I think worth supporting
;; for easy of modification when writing code.
(and (or (= x))) :valid
(and {:count c :name (= user-name)} (and (<= limit c)
(authorised? user-name))) :valid
(and) :invalid
(and (or))) :invalid
I think there might be some clarity of intent lost by overloading the terms and
and or
but they do still behave as their regular counter parts, just with some restrictions on what values can go where which can be pointed out with a compiler warning pretty clearly?
Thank you for this thorough patch!
I have some suggestions inline; please let me know what you think. My understanding of how the term unification is used has changed since I did a bit of research, and I now favor the term "pinning" for how we were using "unification" previously.
I have merged the better-match
branch into main. Could you rebase off that and maybe squash this down into one commit?
Thanks again; this is great work.
@andreyorst what you're saying about where
vs and
is really interesting. However, I'd like to keep this thread focused on the docs for the feature as it currently exists; can we start a separate thread about a potential change to case
and flesh it out there first?
I've squashed the old commits but left new changes unsquashed just for review, if all ok I will squash them all down.
Yes, please go ahead and squash this down, then I'll merge. Thanks!
Thanks; I've merged this!
I feel like a more elaborate explanation of the distinction between
case
andmatch
is needed, becausecase macro that skips unification
doesn't explain much. Though the originalmatch
explanation wasn't really clear on that part too.