108 lines
2.6 KiB
Markdown
108 lines
2.6 KiB
Markdown
# Namespaces
|
|
|
|
Lean provides us with the ability to group definitions into nested, hierarchical *namespaces*:
|
|
|
|
```lean
|
|
namespace Foo
|
|
def a : Nat := 5
|
|
def f (x : Nat) : Nat := x + 7
|
|
|
|
def fa : Nat := f a
|
|
def ffa : Nat := f (f a)
|
|
|
|
#check a
|
|
#check f
|
|
#check fa
|
|
#check ffa
|
|
#check Foo.fa
|
|
end Foo
|
|
|
|
-- #check a -- error
|
|
-- #check f -- error
|
|
#check Foo.a
|
|
#check Foo.f
|
|
#check Foo.fa
|
|
#check Foo.ffa
|
|
|
|
open Foo
|
|
|
|
#check a
|
|
#check f
|
|
#check fa
|
|
#check Foo.fa
|
|
```
|
|
|
|
When we declare that we are working in the namespace ``Foo``, every identifier we declare has
|
|
a full name with prefix "``Foo.``" Within the namespace, we can refer to identifiers
|
|
by their shorter names, but once we end the namespace, we have to use the longer names.
|
|
|
|
The ``open`` command brings the shorter names into the current context. Often, when we import a
|
|
module, we will want to open one or more of the namespaces it contains, to have access to the short identifiers.
|
|
But sometimes we will want to leave this information hidden, for example, when they conflict with
|
|
identifiers in another namespace we want to use. Thus namespaces give us a way to manage our working environment.
|
|
|
|
For example, Lean groups definitions and theorems involving lists into a namespace ``List``.
|
|
```lean
|
|
#check List.nil
|
|
#check List.cons
|
|
#check List.map
|
|
```
|
|
We will discuss their types, below. The command ``open List`` allows us to use the shorter names:
|
|
```lean
|
|
open List
|
|
|
|
#check nil
|
|
#check cons
|
|
#check map
|
|
```
|
|
Like sections, namespaces can be nested:
|
|
```lean
|
|
namespace Foo
|
|
def a : Nat := 5
|
|
def f (x : Nat) : Nat := x + 7
|
|
|
|
def fa : Nat := f a
|
|
|
|
namespace Bar
|
|
def ffa : Nat := f (f a)
|
|
|
|
#check fa
|
|
#check ffa
|
|
end Bar
|
|
|
|
#check fa
|
|
#check Bar.ffa
|
|
end Foo
|
|
|
|
#check Foo.fa
|
|
#check Foo.Bar.ffa
|
|
|
|
open Foo
|
|
|
|
#check fa
|
|
#check Bar.ffa
|
|
```
|
|
Namespaces that have been closed can later be reopened, even in another file:
|
|
```lean
|
|
namespace Foo
|
|
def a : Nat := 5
|
|
def f (x : Nat) : Nat := x + 7
|
|
|
|
def fa : Nat := f a
|
|
end Foo
|
|
|
|
#check Foo.a
|
|
#check Foo.f
|
|
|
|
namespace Foo
|
|
def ffa : Nat := f (f a)
|
|
end Foo
|
|
```
|
|
|
|
Like sections, nested namespaces have to be closed in the order they are opened.
|
|
Namespaces and sections serve different purposes: namespaces organize data and sections declare variables for insertion in definitions.
|
|
Sections are also useful for delimiting the scope of commands such as ``set_option`` and ``open``.
|
|
|
|
In many respects, however, a ``namespace ... end`` block behaves the same as a ``section ... end`` block.
|
|
In particular, if you use the ``variable`` command within a namespace, its scope is limited to the namespace.
|
|
Similarly, if you use an ``open`` command within a namespace, its effects disappear when the namespace is closed.
|