-
Notifications
You must be signed in to change notification settings - Fork 706
doc: write a guideline for tactic docstrings #11406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
f97249b
3f970f0
18c9f27
3ee9165
d9e9981
23a2185
854f806
37a8524
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1123,6 +1123,87 @@ infix:50 " ⇔ " => Bijection | |
| recommended_spelling "bij" for "⇔" in [Bijection, «term_⇔_»] | ||
| ``` | ||
|
|
||
| #### Tactics | ||
|
|
||
| Docstrings for tactics should have the following structure: | ||
|
|
||
| * Short summary | ||
| * Details | ||
| * Variants | ||
| * Examples | ||
|
|
||
| Sometimes more than one declaration is needed to implement what the user | ||
| sees as a single tactic. In that case, only one declaration should have | ||
| the associated docstring, and the others should have the `tactic_alt` | ||
| attribute to mark them as an implementation detail. | ||
|
|
||
| The **short summary** should be 1–3 sentences (ideally 1) and provide | ||
| enough information for most readers to quickly decide whether the | ||
| docstring is relevant to their task. The first (or only) sentence of | ||
| the short summary should be a full sentence in which the subject | ||
| is an example invocation of the tactic, written in present tense | ||
| indicative. If the example tactic invocation names parameters, then the | ||
| short summary may refer to them. The summary should be written as a | ||
| single paragraph. | ||
|
||
|
|
||
| **Details**, if needed, may be 1-3 paragraphs that describe further | ||
| relevant information. They may insert links as needed. This section | ||
| should fully explain the scope of the tactic: its syntax format, | ||
| on which goals it works and what the resulting goal(s) look like. It | ||
| should be clear whether the tactic fails if it does not close the main | ||
| goal and if it creates any side goals. The details may include | ||
Vierkantor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| explanatory examples that can’t necessarily be machine checked and | ||
| don’t fit the format. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should intentional extension points also fit in here? I'm thinking of tactics that are intended to be extended either by giving them additional
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, we should mention extensibility in/next to the details section. For
For tactics like Proposal:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This absolutely makes sense to me and I think it's fine as is. However, I would note that as someone who hasn't done as much proving myself, I'm not familiar with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, the current text for
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think that's more than sufficient, a hyperlink is what you want, and in lieu of hyperlinks I agree just counting on keyword search is better than repeating the same information over and over.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can link to the manual already. Lean rewrites links of the form |
||
|
|
||
| **Variants**, if needed, should be a bulleted list describing different | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems to me that some tactics may have large variants. How would the docs for Perhaps the restriction on having the example as the subject of the sentence can be one option, and a short summary of the syntactic difference be another? Like: (that text isn't the best, but I think it illustrates a reasonable format that's a bit more accessible than sticking the tactic first).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a big fan of
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds great! |
||
| options and forms of the same tactic. The reader should be able to parse | ||
| and understand the parts of a tactic invocation they are hovering over, | ||
| using this list. Each list item should take the format of the **short | ||
| summary** above and describe an individual variant. | ||
Vierkantor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| **Examples** should start with the line `Examples:` (or `Example:` if | ||
| there’s exactly one). The section should consist of a sequence of code | ||
| blocks, each showing a Lean declaration (usually with the `example` | ||
| keyword) that invokes the tactic. When the effect of the tactic is not | ||
| clear from the code, you can use code comments to describe this. | ||
Vierkantor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ##### Example | ||
|
|
||
| ```` | ||
| `rw [e]` uses the expression `e` as a rewrite rule on the main goal, | ||
| then tries to close the goal by "cheap" (reducible) `rfl`. | ||
|
|
||
| If `e` is a defined constant, then the equational theorems associated with `e` are used. This provides a convenient way to unfold `e`. | ||
| If `e` has parameters, the tactic will try to fill these in by unification with the matching part of the target. | ||
| Parameters are only filled in once per rule, restricting which later rewrites can be found. | ||
| Parameters that are not filled in after unification will create side goals. | ||
| If the `rfl` fails to close the main goal, no error is raised. | ||
Vierkantor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| `rw` may fail to rewrite terms "under binders", such as `∀ x, ...` or `∃ x, ...`. | ||
| `rw` can also fail with a "motive is type incorrect" error in the context of dependent types. | ||
| In these cases, consider using `simp only`. | ||
|
|
||
| * `rw [e₁, ... eₙ]` applies the given rules sequentially. | ||
| * `rw [← e]` or `rw [<- e]` applies the rewrite in the reverse direction. | ||
| * `rw [e] at l` rewrites with `e` at location(s) `l`. | ||
| * `rw (occs := .pos L) [e]`, where `L : List Nat`, only rewrites the | ||
Vierkantor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| given occurrences in the target. Occurrences count from 1. | ||
| * `rw (occs := .neg L) [e]`, where `L : List Nat`, skips rewriting the | ||
| given occurrences in the target. Occurrences count from 1. | ||
|
|
||
| Examples: | ||
|
|
||
| ```lean | ||
| example {a b : Nat} (h : a + a = b) : (a + a) + (a + a) = b + b := by rw [h] | ||
| ``` | ||
|
|
||
| ```lean | ||
| example {f : Nat -> Nat} (h : ∀ x, f x = 1) (a b : Nat) : f a = f b := by | ||
| rw [h] -- `rw` instantiates `h` only once, so this is equivalent to: `rw [h a]` | ||
| -- goal: ⊢ 1 = f b | ||
| rw [h] -- equivalent to: `rw [h b]` | ||
| ``` | ||
| ```` | ||
|
|
||
|
|
||
| ## Dictionary | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I adapted this sentence from the section about constants, so I'll make the same change there. (Feel free to revert.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!