Zulip Chat Archive

Stream: lean4

Topic: clean syntax for initializing associative lists?


Dillon Huff (Feb 21 2021 at 22:37):

I need to initialize some associative lists to test some lean4 code I've been running. I know that if the list is empty you can do:

def mylist : (Std.AssocList Int Int) := {}

But if I want a list with elements in it I don't see another syntax for this (besides actually calling Std.AssocList.cons which is very verbose. Is there something akin to the python map initialization syntax:

def myList : (Std.AssocList Int Int) := { 1 : 2, 3 : 4}

or could I create this via the macro system?

Leonardo de Moura (Feb 21 2021 at 22:52):

Here is a macro that uses List.toAssocList

import Std

syntax assocEntry := term ":" term
syntax "{" assocEntry,* "}" : term

macro_rules
  | `({ $[$k:term : $v:term],* }) => `([$[($k, $v)],*].toAssocList)

#check { 1 : 2, 3 : 4, 4 : 5 }

Here is one that expands the notation using AssocList.cons and AssocList.nil

import Std

syntax assocEntry := term ":" term
syntax "{" assocEntry,* "}" : term

macro_rules
  | `({ $es:assocEntry,* }) => do
    let r  `(Std.AssocList.nil)
    es.getElems.foldrM (init := r) fun e r =>
      `(Std.AssocList.cons $(e[0]) $(e[2]) $r)

#check { 1 : 2, 3 : 4, 4 : 5 }

Dillon Huff (Feb 21 2021 at 22:57):

Thanks! That was just what I was looking for. One clarification: when I copy that code in and #check {} like so:

import Std

syntax assocEntry := term ":" term
syntax "{" assocEntry,* "}" : term

macro_rules
  | `({ $[$k:term : $v:term],* }) => `([$[($k, $v)],*].toAssocList)

#check { 1 : 2, 3 : 4, 4 : 5 }

macro_rules
  | `({ $es:assocEntry,* }) => do
    let r  `(Std.AssocList.nil)
    es.getElems.foldrM (init := r) fun e r =>
      `(Std.AssocList.cons $(e[0]) $(e[2]) $r)

#check {}

I get an error message from vscode:

ambiguous, possible interpretations
  Std.AssocList.nil

  EmptyCollection.emptyCollectionLean 4 server

Can the macro syntax be tweaked to avoid this?

Leonardo de Moura (Feb 21 2021 at 23:01):

You can define the notation for non-empty lists only. We have to replace * with +

syntax "{" assocEntry,+ "}" : term

The following still works

#check ({} : Std.AssocList Nat Nat)

because we have the instance

instance : EmptyCollection (AssocList α β)

Dillon Huff (Feb 21 2021 at 23:02):

Makes sense. Thanks!


Last updated: Dec 20 2023 at 11:08 UTC