Zulip Chat Archive
Stream: new members
Topic: why does this array/list pattern match fail?
Alok Singh (Nov 19 2024 at 20:22):
#eval match #[1, 2, 3] with
| #[a, b, c] => a + b + c
| #[a, c] => a + c
| #[a] => a
| #[] => 0
-- | _ => 0
/-
failed to compile pattern matching, stuck at
remaining variables: [x✝:(Array ℕ)]
alternatives:
[a:(ℕ), b:(ℕ), c:(ℕ)] |- [#[a, b, c]] => h_1 a b c
[a:(ℕ), c:(ℕ)] |- [#[a, c]] => h_2 a c
[a:(ℕ)] |- [#[a]] => h_3 a
[] |- [#[]] => h_4 ()
examples:_
-/
#eval match [1, 2, 3] with
| [_,_,_,_] => 4
| [_, _, _] => 3
| [_,_] => 2
| [_] => 1
| [] => 0
-- | _ => 0
-- missing cases: (List.cons _ (List.cons _ (List.cons _ (List.cons _ (List.cons _ _)))))
I have an idea of why but wanted to be sure. Is it that the pattern matcher does not have access to any length info, so it assumes any length array/list can be passed, so there needs to be a catchall for arbitrary length cases?
Edward van de Meent (Nov 19 2024 at 20:23):
yes, that seems right to me.
Edward van de Meent (Nov 19 2024 at 20:24):
if you want to match an exact number of values, you can use match (1,2,3) with |(a,b,c) => a+ b+ c
Edward van de Meent (Nov 19 2024 at 20:24):
i.e. match on a tuple, where lean can tell that indeed there is an exact number of items.
Alok Singh (Nov 19 2024 at 20:25):
makes sense, was curious about specifically array/list after reading that pattern matching supports array literals
Alok Singh (Nov 19 2024 at 20:27):
slight digression, if i wanted to write a custom pattern matcher, is that possible?
say for
structure Vector (a : Type) (n : Nat) where
data : Array a
_len : data.size = n
-- assume some literal syntax like (v[1,2,3] : Vector Nat 3) is defined
match v[1,2,3] with
| v[a,2,b] => b
| v[a,b,c] => 3
-- no catch all needed
Mario Carneiro (Nov 19 2024 at 20:27):
you are matching on an array here, so of course the longer arrays have to be handled?
Mario Carneiro (Nov 19 2024 at 20:27):
No, there is no way to extend the pattern language currently, the match compiler is not extensible
Mario Carneiro (Nov 19 2024 at 20:28):
you can make macros that fire in pattern position though
Mario Carneiro (Nov 19 2024 at 20:29):
Actually, I bet you could make that example work, although it probably won't generate very good code
Mario Carneiro (Nov 19 2024 at 20:41):
dang, so close and yet so far
import Batteries.Data.Vector
syntax (name := vecNotation) (priority := high) "#v[" withoutPosition(sepBy(term, ", ")) "]" : term
namespace Batteries.Vector
open Lean Elab Term in
@[term_elab vecNotation]
def elabVectorNotation : TermElab := fun stx ty => do
match stx with
| `(#v[ $elems,* ]) =>
if (← read).inPattern then
elabTerm (← `(Vector.mk (n := $(quote elems.getElems.size)) ⟨[$elems,*]⟩ _)) ty
else
elabTerm (← `(Vector.mk (n := $(quote elems.getElems.size)) ⟨[$elems,*]⟩ rfl)) ty
| _ => throwUnsupportedSyntax
#check
match #v[1,2,3] with
| #v[a,2,b] => b -- invalid pattern
| #v[a,b,c] => 3
It doesn't work because match
only expands macros, not elabs, and macros are not given access to inPattern
Alok Singh (Nov 19 2024 at 20:48):
i'm very appreciative but a bit apprehensive that you're so nerd-snipable @Mario Carneiro
Mario Carneiro (Nov 19 2024 at 20:48):
what? that's, like, my thing
Edward van de Meent (Nov 19 2024 at 20:49):
it is? i thought that was yaels?
Damiano Testa (Nov 19 2024 at 20:49):
Oh, there are many nerds here...
Alok Singh (Nov 19 2024 at 20:49):
Damiano Testa said:
Oh, there are many nerds here...
understatement of the year
Edward van de Meent (Nov 19 2024 at 20:50):
like sniping nerds in a barrel
Mario Carneiro (Nov 19 2024 at 20:51):
this isn't even full on nerd sniped, it's a few lines of code. Full nerd sniping is writing a fix to lean core, and then belatedly making an RFC for that because that's what you need to do now
Damiano Testa (Nov 19 2024 at 20:52):
I can see where you are headed, Mario.
Alok Singh (Nov 19 2024 at 20:52):
well, he had to do it guys
Edward van de Meent (Nov 19 2024 at 20:53):
at least i never wrote a tool because i felt it was missing... ahem
Mario Carneiro (Nov 19 2024 at 20:53):
TBH I'm not headed there, it's the part of the process that is not fun
Mario Carneiro (Nov 19 2024 at 20:54):
the actual way to do this kind of thing now is to hint to FRO members that it's a worthwhile problem and then maybe later it will show up on the lean commit feed
Edward van de Meent (Nov 19 2024 at 20:54):
transitive nerdsniping?
Mario Carneiro (Nov 19 2024 at 20:55):
remote sniping
Last updated: May 02 2025 at 03:31 UTC