Zulip Chat Archive
Stream: lean4
Topic: Code generation
Calvin Lee (Mar 11 2021 at 01:25):
Would there be any easy way to generate a lot of constants automatically at once with random values?
Mario Carneiro (Mar 11 2021 at 05:55):
In lean 3 you can do that by calling add_decl
to create new definitions, where the definition is a random value turned into a literal expression
Mario Carneiro (Mar 11 2021 at 06:12):
Here's some code that should work, and currently works in the command line but crashes the server for me:
import Lean
open Lean
def test : CoreM Unit := do
let decl := Declaration.defnDecl {
name := `foo,
levelParams := [],
value := toExpr (← IO.rand 0 100),
type := mkConst ``Nat,
hints := ReducibilityHints.regular 0,
safety := DefinitionSafety.safe
}
match (← getEnv).addAndCompile {} decl with
| Except.ok env => setEnv env
| Except.error kex => pure ()
#eval test
#print foo
-- def foo : Nat :=
-- 77
Calvin Lee (Mar 11 2021 at 22:26):
Hmm, is there any way to do this without the #eval?
Leonardo de Moura (Mar 11 2021 at 22:52):
Here is an example using the macro system.
/- Helper syntax for defining the real macro. -/
syntax "gen_random_defs%" ident num num num : command
/-
`gen_random_defs id n s` creates `n` declarations of the form
``
def id_<idx> : Nat := <random value>
``
The "random values" are generated using the function `stdNext` and "seed" `s`
-/
macro "gen_random_defs" id:ident n:num s:num : command =>
`(gen_random_defs% $id $n $s 1) -- s and 1 are the "seeds" for the random number generator
macro_rules
| `(gen_random_defs% $id $n $s1 $s2) =>
open Lean in
let (val, ⟨s1, s2⟩) := stdNext ⟨s1.toNat, s2.toNat⟩
let n := n.toNat
let currId := id.getId.appendIndexAfter n
if n == 0 then
return mkNullNode
else
`(def $(mkIdentFrom id currId) := $(quote val)
gen_random_defs% $id $(quote (n-1)) $(quote s1) $(quote s2))
gen_random_defs foo 4 10 -- Creates `foo_1` ... `foo_4` using random seed 10
#print foo_1
#print foo_2
#print foo_3
#print foo_4
Calvin Lee (Mar 17 2021 at 20:40):
Is there any way to access IO in term or command macros in order to get rid of the seed argument here? I'm trying to write something like
/- `rand_nat_const` creates a random `Nat` in the StdGen range -/
macro "rand_nat_const" : term => do
`($(quote (<-(IO.rand (stdRange.fst) (stdRange.snd)))))
but it seems I can only use the reader monad here
Mario Carneiro (Mar 17 2021 at 21:05):
It looks like no
Mario Carneiro (Mar 17 2021 at 21:05):
macros live in the MacroM
monad which is pure
Mario Carneiro (Mar 17 2021 at 21:10):
Although you might not need it since MacroM
implements MonadRef
Calvin Lee (Mar 17 2021 at 21:10):
I see, if I have : command
does it live in CommandM instead? and does that include IO?
Mario Carneiro (Mar 17 2021 at 21:11):
No, all macros live in MacroM
Mario Carneiro (Mar 17 2021 at 21:12):
but that just means that it is pure during macro expansion, you can just do your computation after macro expansion
Calvin Lee (Mar 17 2021 at 21:14):
Indeed
the issue is I would like to avoid the randomness on runtime
Mario Carneiro (Mar 17 2021 at 21:14):
I'm not sure what you mean. It's the same either way
Mario Carneiro (Mar 17 2021 at 21:16):
It's not really clear what counts as "runtime" here
Mario Carneiro (Mar 17 2021 at 21:17):
If you have a command-like that adds definitions to the environment, that will run when the lean file is processed. The olean files will contain the resulting definitions
Mario Carneiro (Mar 17 2021 at 21:17):
if this is then used in a dependent lean file, it will be as if you wrote all those definitions, so I guess it's "compile time"?
Mario Carneiro (Mar 17 2021 at 21:18):
That said, a lean file that elaborates differently depending on the phase of the moon seems like a bad idea
Calvin Lee (Mar 17 2021 at 21:36):
indeed but it's awfully convenient for this case where I want an algorithm to have some random parameters (for efficiency reasons) but I don't want it to be random on runtime (I don't want one of my runs to get some bad seed)
Also it's nice because I don't have to worry about threading a reader through everything, especially if I want to prove things about this (which I want to be immutable)
Last updated: Dec 20 2023 at 11:08 UTC