Zulip Chat Archive
Stream: lean4
Topic: confused about nesting namespaces
Paige Thomas (Feb 11 2025 at 05:46):
If I have the following in one file
namespace Chapter2_
/--
The type of formulas.
-/
inductive Formula_ : Type
| false_ : Formula_
| true_ : Formula_
| atom_ : String → Formula_
| not_ : Formula_ → Formula_
| and_ : Formula_ → Formula_ → Formula_
| or_ : Formula_ → Formula_ → Formula_
| imp_ : Formula_ → Formula_ → Formula_
| iff_ : Formula_ → Formula_ → Formula_
deriving Inhabited, DecidableEq, Repr
and I import it into a file containing this
namespace Chapter2_
open Formula_
...code...
Can I make the code that follows open Formula_
belong to an additional nested namespace under Chapter2_
called Prop_
without making changes to that code? That is, make the code in the first file just in the namespace Chapter2_
and the code in the second file in the namespace Chapter2_.Prop_
? I tried adding namespace Prop_
in various locations in the second file, but it seems to break the code that follows it. I think maybe I'm confused about how namespaces work. My thought was that everything under namespace blah
essentially gets blah.
prepended to it.
Kyle Miller (Feb 11 2025 at 05:53):
If you add namespace Prop_
anywhere after namespace Chapter2_
, then the code that follows will be in the Chapter2_.Prop_
namespace.
You can use the #where
command to see where you are
Paige Thomas (Feb 11 2025 at 05:57):
If I do this
namespace Chapter2_
namespace Prop_
open Formula_
and later on have
def Formula_.is_tautology
(F : Formula_) :
Prop :=
∀ (V : Valuation), satisfies V F
and then
def is_logical_consequence
(P Q : Formula_) :
Prop :=
(P.imp_ Q).is_tautology
the last gives
invalid field 'is_tautology', the environment does not contain 'Chapter2_.Formula_.is_tautology'
P.imp_ Q
has type
Formula_
Paige Thomas (Feb 11 2025 at 05:59):
why does the last not see it as Chapter2_.Prop_.Formula_.is_tautology
?
Kyle Miller (Feb 11 2025 at 06:01):
If you define Formula_.is_tautology
inside this nested namespace, you've defined Chapter2_.Prop_.Formula_.is_tautology
, but dot notation is looking in the namespace for Formula_
, which is Chapter2_.Formula
.
Kyle Miller (Feb 11 2025 at 06:01):
If you want to use dot notation, you'll have to define is_tautology
in that namespace.
Kyle Miller (Feb 11 2025 at 06:02):
You should see that is_tautology (P.imp_ Q)
is fine, since it'll find is_tautology
in the current namespace.
Paige Thomas (Feb 11 2025 at 06:07):
I see. Thank you.
Paige Thomas (Feb 11 2025 at 06:15):
Hmm. It seems I need to do Formula_.is_tautology (P.imp_ Q)
.
Kyle Miller (Feb 11 2025 at 06:16):
Oh right, I forgot you defined it as that. Yes, that's expected.
Kyle Miller (Feb 11 2025 at 06:18):
@David Thrane Christiansen has a defmethod
macro for being able to define functions meant to be used with dot notation from within another namespace. This would be convenient here! (code)
Paige Thomas (Feb 11 2025 at 06:19):
Oh? That would be nice!
Kyle Miller (Feb 11 2025 at 06:20):
That file I linked is self-contained, and you could drop it into your project.
Paige Thomas (Feb 11 2025 at 06:22):
Should I try to import the project?
Paige Thomas (Feb 11 2025 at 06:23):
I guess it seems a little odd to copy the file.
Paige Thomas (Feb 11 2025 at 06:25):
Is there a chance the macro might get moved into something like mathlib?
Yaël Dillies (Feb 11 2025 at 06:26):
Kyle Miller said:
David Thrane Christiansen has a
defmethod
macro for being able to define functions meant to be used with dot notation from within another namespace. This would be convenient here! (code)
Oh! That would have been great for @Hannah Scholz in #19760
Kyle Miller (Feb 11 2025 at 06:27):
Copying the file is what I'd do. Verso is a relatively large dependency for just this feature.
The risk is if Lean changes and it needs fixing, you wouldn't be able to just update the dependency. However, if you keep track of the source of the file, you can manually update it.
"Vendoring dependencies" is an age-old development method.
Kyle Miller (Feb 11 2025 at 06:29):
I'll mention that an alternative (and what mathlib does) is instead either (1) manage carefully which namespace you're in or (2) use _root_
like so to temporarily go back to the root namespace:
def _root_.Chapter2_.Formula_.is_tautology
(F : Formula_) :
Prop :=
∀ (V : Valuation), satisfies V F
Paige Thomas (Feb 11 2025 at 06:33):
Hmm. I'm not sure how to apply this here. There are two different definitions of is_tautology
that both use the same definition of Formula_
.
Paige Thomas (Feb 11 2025 at 06:35):
If I did that for both they would clash right?
Paige Thomas (Feb 11 2025 at 06:36):
The _root_
approach that is.
Paige Thomas (Feb 11 2025 at 06:39):
Would the macro work in that case?
Paige Thomas (Feb 11 2025 at 06:45):
That is, if I do def _root_.Chapter2_.Formula_.is_tautology
in two different namespaces, will the definitions clash?
Kyle Miller (Feb 11 2025 at 06:46):
The macro is equivalent to this _root_
approach
Kyle Miller (Feb 11 2025 at 06:46):
Yes, they will clash.
Paige Thomas (Feb 11 2025 at 06:48):
I guess the only option is to drop the dot notation then?
Paige Thomas (Feb 11 2025 at 06:51):
If I have
namespace Chapter2_.Prop_
open Formula_
the open Formula_
somehow knows to use the definition of Formula_
from the Chapter2_
namespace and not try to find it in the Chapter2_.Prop_
namespace?
Kyle Miller (Feb 11 2025 at 06:55):
namespace Chapter2_.Prop_
makes all the names in Chapter2_
and Chapter2_.Prop_
available, so when you do open Formula_
, it can resolve that Formula_
refers to Chapter2_.Formula_
, and then makes the names in there available.
Paige Thomas (Feb 11 2025 at 06:57):
Oh. And I assume namespace Chapter2_.Prop_
is the same as
namespace Chapter2_
namespace Prop_
?
Kyle Miller (Feb 11 2025 at 06:57):
Yeah
Paige Thomas (Feb 11 2025 at 06:57):
Thank you!
David Thrane Christiansen (Feb 11 2025 at 07:50):
Yeah, that macro is there mostly to complain if the name before the dot doesn't resolve, and partly to help with maintenance when I move things around. It helped a lot with early iterative development, but in the long run I'd like to eliminate it.
Edward van de Meent (Feb 11 2025 at 18:40):
David Thrane Christiansen said:
... but in the long run I'd like to eliminate it.
Could you elaborate on why? it seems to me like this is a nice language feature to have?
David Thrane Christiansen (Feb 11 2025 at 19:45):
I think it's fine as an idiomatic language feature, but it doesn't make the Verso codebase easier to understand. It's been very helpful during rapid development, but the core of Verso is getting pretty stable, so I'd rather optimize for being less surprising, easier to maintain, and not so clever when possible. That said, this is not something I feel strongly about :)
Last updated: May 02 2025 at 03:31 UTC