Zulip Chat Archive

Stream: lean4

Topic: mix and match matching on Syntax


Damiano Testa (May 04 2024 at 14:02):

Below, you can see the two ways in which I typically match on syntax. Is there a way of mixing the two matchings in a single pattern?

import Lean

open Lean Elab Command

-- works and can be extended by more `(...)
example : Syntax   Syntax
  | s@`(a + b) => s
  | s => s

-- works and can be extended by more .atom, .node, ...
example : Syntax   Syntax
  | .ident _ _ v _ => mkIdent v
  | s => s

-- does not work
example : Syntax   Syntax
  | s@`(a + b) => s
  | .ident _ _ v _ => mkIdent v
  | s => s
/-
match (syntax) : unexpected pattern kind .ident _ _ v _
-/

Eric Wieser (May 04 2024 at 14:08):

(and similarly for TSyntax with ⟨.ident _ _ _ _⟩)

Damiano Testa (May 04 2024 at 14:10):

I am comforted that one of the native Lean-speakers does not know of this feature! :smile:

Eric Wieser (May 04 2024 at 14:11):

I'm pretty sure it's just missing, for the same reason that I think you can't match on syntax and other arguments at the same time?

Damiano Testa (May 04 2024 at 14:11):

Ah, that I never tried!

Eric Wieser (May 04 2024 at 14:12):

I bet you can trick it by adding a ~q match to the same match

Damiano Testa (May 04 2024 at 14:14):

I am not sure that I understand what you have in mind, but both of these work:

-- works
example : Syntax  Unit   Unit
  | s, t => t

-- works
example (s : Syntax) (u : Unit) :  Unit :=
  match s, u with
    | .node .., t => t
    | _, t => t

Eric Wieser (May 04 2024 at 14:14):

Does the one with a syntax antiquotation match work?

Damiano Testa (May 04 2024 at 14:15):

I think so:

-- works
example (s : Syntax) (u : Unit) :  Unit :=
  match s, u with
    | `(a + b), t => t
    | _, t => t

seems to work.

Damiano Testa (May 04 2024 at 14:15):

I wonder what happens if you match on two syntaxes, one with anti-quotations on one with constructors...

Damiano Testa (May 04 2024 at 21:59):

Ok, for completeness, this is what happens:

open Lean

-- does not work
example : Syntax  Syntax  Unit
  | `(a + b), .node .. => ()
  | _, t => ()

-- does not work
example : Syntax  Syntax  Unit
  | .node .., `(a + b) => ()
  | _, _ => ()

-- works
example : Syntax  Syntax  Unit
  | .node .., .node .. => ()
  | _, _ => ()

-- works
example : Syntax  Syntax  Unit
  | `(a * b), `(a + b) => ()
  | _, _ => ()

Mario Carneiro (May 04 2024 at 22:01):

This will require rearchitecting the way match works to fix

Damiano Testa (May 04 2024 at 22:02):

Ok, it is not that important: the constructor matching works, it is just more verbose at times.

Mario Carneiro (May 04 2024 at 22:03):

you can usually refactor it into separate matches to get the desired mix and match

Eric Wieser (May 04 2024 at 23:07):

Eric Wieser said:

I bet you can trick it by adding a ~q match to the same match

Yep:

import Qq
open Lean Qq

-- works
example (s1 : Syntax) (s2 : Syntax) : MetaM Unit :=
  match s1, s2, q(trivial) with
  | `(a + b), .node .., ~q(trivial) => return ()
  | _, t, _ => return ()

-- works
example (s1 : Syntax) (s2 : Syntax) : MetaM Unit :=
  match s1, s2, q(trivial) with
  | .node .., `(a + b), ~q(trivial) => return ()
  | _, _, _ => return ()

Eric Wieser (May 04 2024 at 23:09):

Damiano Testa said:

I think so:

-- works
example (s : Syntax) (u : Unit) :  Unit :=
  match s, u with
    | `(a + b), t => t
    | _, t => t

seems to work.

This fails if you replace t => with () => ()(or any other pattern that actually does work); so I think my original claim is basically correct


Last updated: May 02 2025 at 03:31 UTC