Zulip Chat Archive

Stream: lean4

Topic: Support options with type ``Lean.Name``


Yicheng Qian (May 20 2024 at 05:47):

Is it possible to support options with type Lean.Name? I need this type of options in lean-auto. Currently we can register options of type Lean.Name

register_option foo : Lean.Name := {
  defValue := ""
}

But cannot set_option:

set_option foo ``Nat.add

Seems like the parser is not supporting Name literals

-- Lean/Parser/Command.lean
def optionValue := nonReservedSymbol "true" <|> nonReservedSymbol "false" <|> strLit <|> numLit
@[builtin_command_parser] def «set_option»   := leading_parser
  "set_option " >> ident >> ppSpace >> optionValue

Yicheng Qian (May 20 2024 at 05:49):

Currently I'm using a workaround: register options of type String and use name_str.foldl (fun acc s => Name.str acc s) .anonymous.

Kyle Miller (May 20 2024 at 16:05):

There's a possibility. There are some questions about the implementation.

There are two options:

  1. Have set_option foo `name and set_option foo ``name, where single vs double backquote work like how they do for normal names (the latter would do name resolution)
  2. Have set_option foo name, where either (a) name is not resolved or (b) name always attempts to resolve and either b.1 doesn't throw an error if it doesn't or b.2 throws an error if it does.

Could you mention the use case for name-valued options in lean-auto? Could you also evaluate the difference between this proposed set_option feature and using an attribute?

Yicheng Qian (May 20 2024 at 17:42):

In lean-auto, I sometimes want to leave "hole"s in the code using Lean.evalConst:

  • I want users to be able to customize e.g. the translation from lean-auto's internal representation to Lean. This can be done by leaving a hole in the code.
  • I need to debug code deep in the import tree (long compilation time), and testing lean-auto might require importing mathlib (long loading time). Sometimes I have to make several attempts to get the code right. So, I leave a hole in the code deep in the import tree, and fill the hole directly in the test file.

Yicheng Qian (May 20 2024 at 17:47):

I think set_option foo `name and set_option foo ``name is better within the two options.

Yicheng Qian (May 20 2024 at 17:49):

Using attributes would also be ok, but set_option seems more convenient?

Kyle Miller (May 20 2024 at 18:00):

Is it more convenient than writing something like the following?

@[rebind myFn]
def newFn : ...

That would be rather than

def newFn : ...

setOption myFn ``newFn

Yicheng Qian (May 20 2024 at 18:17):

I'm a bit confused. My intended set_option approach looks like this overall:

register_option hole_func_name : Name := ...

unsafe def foo := do
  ...
  let hole_func  hole_func_name.get ( getOptions)
  <check that hole_func have the correct type>
  let hole  evalConst <expected_type> hole_func
  ...

-- In another Lean file
def newFn := ...
set_option hole_func_name ``newFn

If I understand correctly, the rebind approach only replaces

-- In another Lean file
def newFn := ...
set_option hole_func_name ``newFn

with

@[rebind hole_func_name]
def newFn := ...

Yicheng Qian (May 20 2024 at 18:37):

That would be a little more convenient.

Yicheng Qian (May 20 2024 at 18:41):

However, the set_option approach will allow def newFn := ... and set_option hole_func_name ``newFn to reside in different Lean files, while the rebind approach won't.

Kyle Miller (May 20 2024 at 19:00):

You could use the attribute [rebind hole_func_name] newFn syntax from a different file just fine

Kyle Miller (May 20 2024 at 19:42):

code: Rebind.lean

Example usage (you need to fix the import first):

import /-packagename-/.Rebind

declare_rebindable foo : Nat

def test : Lean.MetaM Nat :=
  eval_rebind% foo

#eval test
-- No implementation exists for rebind foo

@[rebind foo]
def myFoo : Nat := 22

#eval test
-- 22

section
@[local rebind foo]
def myFoo' : Nat := 37

#eval test
-- 37

end

#eval test
-- 22

Kyle Miller (May 20 2024 at 19:51):

Extending the examples:

declare_rebindable f : Nat  Nat
declare_rebindable a : Nat

def test2 : Lean.MetaM Nat := do
  return ( eval_rebind% f) ( eval_rebind% a)

attribute [rebind a] myFoo

@[rebind f]
def myF := (· * 2)

#eval test2
-- 44

Kyle Miller (May 20 2024 at 19:53):

Note that the type of eval_rebind% f in this example is m (Nat -> Nat), for m some monad that supports what evalConst requires.

Note also that since this is being done with a term elaborator like this, we can safely omit unsafe because we can ensure it has the right type.

Yicheng Qian (May 21 2024 at 03:37):

Thanks! I'm using rebind in lean-auto now.


Last updated: May 02 2025 at 03:31 UTC