Zulip Chat Archive
Stream: mathlib4
Topic: rotate
Arthur Paulino (Feb 06 2022 at 21:05):
I just found out that we already have rotate_left n
and rotate_right n
tactics. Should I open a PR removing the rotate_goals
tactic?
Arthur Paulino (Feb 06 2022 at 23:57):
Feel free to close it: https://github.com/leanprover-community/mathlib4/pull/185
Johan Commelin (Feb 07 2022 at 05:21):
Would rotate_up
and rotate_down
be more intuitive? The goal state displays the goals in a vertical list...
Arthur Paulino (Feb 07 2022 at 12:43):
But then we'd have it changed in the core code, right?
Mario Carneiro (Feb 07 2022 at 12:45):
the polarity was also not what I expected: mathlib rotate n
, which moves the nth goal to the front and rotates everything else around that, is rotate_left n
in lean 4
Arthur Paulino (Feb 07 2022 at 12:48):
What do you mean by "the polarity was also not what I expected"?
Mario Carneiro (Feb 07 2022 at 12:55):
I had guessed that rotate_right
did that
Mario Carneiro (Feb 07 2022 at 12:57):
in hindsight, and especially if you think about the goals laid out in a left-to-right list, it makes sense, but I agree with Johan that the directionality here is a bit confused
Mario Carneiro (Feb 07 2022 at 12:57):
maybe rotate n
and rotate -n
is a better idea after all
Gabriel Ebner (Feb 07 2022 at 13:12):
FWIW, I would expect rotate_right to rotate in clockwise direction.
Arthur Paulino (Feb 07 2022 at 13:16):
pull_goals
and push_goals
might be a bit more explicit
Gabriel Ebner (Feb 07 2022 at 13:16):
Looking through mathlib3, most occurrences of swap n
are followed by exact
or { ... }
.
I think it would make more sense to add case n => ...
instead of adding all kinds of obscure goal permutations. (We already have pick_goal
, this is enough to get any permutation that you want. :smirk:)
Arthur Paulino (Feb 07 2022 at 13:21):
for case n => ...
we have on_goal n => ...
, which doesn't restrict the incoming tactics to close the goal
Stuart Presnell (Feb 07 2022 at 13:22):
Perhaps rotate_to n
, which suggests rotating the carousel of goals to the n
th entry (and for negative values we count from the end of the list)?
Johan Commelin (Feb 07 2022 at 13:23):
I think on_goal
is all I would need.
Gabriel Ebner (Feb 07 2022 at 13:23):
which doesn't restrict the incoming tactics to close the goal
This restriction is often desired though. Even adding just a macro which expands case $n => $seq
to on_goal $n => { $seq }
seems useful.
Johan Commelin (Feb 07 2022 at 13:23):
If it could take a list of goals that would be a nice cherry.
Stuart Presnell (Feb 07 2022 at 13:24):
I'm less keen on _left
, _down
, etc. since they depend on the particular on-screen representation of the list of goals.
Johan Commelin (Feb 07 2022 at 13:24):
I sometimes want something between all_goals
and on_goal
.
Arthur Paulino (Feb 07 2022 at 13:28):
@Gabriel Ebner why is the restriction desired?
Johan Commelin (Feb 07 2022 at 13:29):
It makes proof scripts more robust. As proof author you promise "the next block will close this goal". So when the proof breaks 7 months later, it's easier to figure out where to tweak things.
Johan Commelin (Feb 07 2022 at 13:29):
Instead of suddenly staring at a 57 line long script that has 5 open goals left at the end.
Gabriel Ebner (Feb 07 2022 at 13:30):
Because that makes tactics proofs more reliable. That is, whenever you see case ... => ...
you can be certain that the case closes that goal. Lean 4 can even continue executing the proof if the case fails, because it's clear how the goals need to look afterwards.
Sebastian Ullrich (Feb 07 2022 at 13:31):
Modulo instantiation of metavariables :) ...
Arthur Paulino (Feb 07 2022 at 13:31):
Got it, thanks!
Eric Rodriguez (Feb 07 2022 at 13:37):
I would love to have something that let me focus some specific goals and close them all automatically. I think that is a fantastic idea
Arthur Paulino (Feb 07 2022 at 13:44):
Eric Rodriguez said:
I would love to have something that let me focus some specific goals and close them all automatically. I think that is a fantastic idea
Something like on_goals [1, 2, 3] => try this; try that; etc
?
Johan Commelin (Feb 07 2022 at 13:46):
If you can implement etc
, that would be major!! :wink:
Mario Carneiro (Feb 07 2022 at 14:21):
Arthur Paulino said:
Eric Rodriguez said:
I would love to have something that let me focus some specific goals and close them all automatically. I think that is a fantastic idea
Something like
on_goals [1, 2, 3] => try this; try that; etc
?
lol, I swear mathlib4#187 was invented independently
Mario Carneiro (Feb 07 2022 at 14:24):
Gabriel Ebner said:
Looking through mathlib3, most occurrences of
swap n
are followed byexact
or{ ... }
.I think it would make more sense to add
case n => ...
instead of adding all kinds of obscure goal permutations. (We already havepick_goal
, this is enough to get any permutation that you want. :smirk:)
Heh, great minds think alike: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/.60swap.60.20semantics.20tactics.20names/near/270789014
Mario Carneiro (Feb 07 2022 at 14:27):
To summarize the on_goals
PR: It adds two new tactics: on_goal
is generalized to multiple goals as in on_goal 1 3 5 => simp
will apply simp
to goals 1,3,5 and place the resulting subgoals back where it found them, and on_goals 1 3 5 => tac
will apply tac
to a state consisting of goals 1,3,5, and then placing the resulting goals at the front and all the unselected goals at the end
Mario Carneiro (Feb 07 2022 at 14:28):
so on_goals 1 3 5 => skip
will move goals 1 3 5
to the front
Arthur Paulino (Feb 07 2022 at 14:33):
[This thread no longer matches it title btw]
That difference in behavior is not clear to me just by looking at their names though. I would expect on_goals
to behave just like on_goal
, but accepting multiple goals. And then focus_goals
would be the one that brings the goals up in the queue (if this is a helpful behavior)
Mario Carneiro (Feb 07 2022 at 14:33):
Lean 4 can even continue executing the proof if the case fails, because it's clear how the goals need to look afterwards.
How does this mechanism work anyways? In lean 3 any failure is fatal, and if you are calling setGoals later in the tactic I don't see how you can recover if an embedded tactic fails
Mario Carneiro (Feb 07 2022 at 14:35):
It's true that the names are not very different, but it's not the only tactic like that: intro
vs intros
both introduce multiple variables but intros
keeps going after it has introduced the named ones
Arthur Paulino (Feb 07 2022 at 14:36):
But "goals" is the plural of "goal". And "intros" is... just "intro" + "s"
Mario Carneiro (Feb 07 2022 at 14:36):
no, intros
is definitely the plural of intro
Johan Commelin (Feb 07 2022 at 14:37):
Could on_goals
work in place, and pick_goals
move things to the front?
Arthur Paulino (Feb 07 2022 at 14:38):
Ah, oops (english not my mother tongue)
Mario Carneiro (Feb 07 2022 at 14:38):
I think it is best not to go overboard with disambiguating names because it's supposed to be a language in the linguistic sense. You have to learn the words but the brevity pays off in the long run
Mario Carneiro (Feb 07 2022 at 14:39):
There is a balance to be sure, you don't want it to be impossible to learn, but it is most important that it is not misleading, it's okay if it's vague
Gabriel Ebner (Feb 07 2022 at 14:40):
Mario Carneiro said:
Lean 4 can even continue executing the proof if the case fails, because it's clear how the goals need to look afterwards.
How does this mechanism work anyways? In lean 3 any failure is fatal, and if you are calling setGoals later in the tactic I don't see how you can recover if an embedded tactic fails
I think case foo => tac
does the equivalent of case foo => { tac } <|> sorry
.
Julian Berman (Feb 07 2022 at 14:40):
Is intros
staying in Lean 4?
Mario Carneiro (Feb 07 2022 at 14:40):
yes
Arthur Paulino (Feb 07 2022 at 14:40):
Maybe on_goals
and on_goals'
work better because their difference is very small
Mario Carneiro (Feb 07 2022 at 14:40):
like I said, lean 4 has intro
and intros
and they are different
Gabriel Ebner (Feb 07 2022 at 14:42):
Mario Carneiro said:
so
on_goals 1 3 5 => skip
will move goals1 3 5
to the front
This is super subtle and easy to overlook. How about we have pick_goal 1 2 3 => tac
for the one that moves multiple goals to the front?
Mario Carneiro (Feb 07 2022 at 14:42):
my mnemonic is: on_goal
runs your tactic on 1 goal (multiple times), on_goals
runs on many goals
Gabriel Ebner (Feb 07 2022 at 14:42):
How does on_goal
execute the tactic multiple times? From what I can tell, the only difference between on_goal
and on_goals
is how the goals are permuted afterwards.
Mario Carneiro (Feb 07 2022 at 14:43):
to be fair on_goals ns => skip
is like running a program for its side effects, we should have a macro for that particular use case to make the side effect more central
Arthur Paulino (Feb 07 2022 at 14:43):
Mario Carneiro said:
my mnemonic is:
on_goal
runs your tactic on 1 goal (multiple times),on_goals
runs on many goals
But that's not what the code is doing, right? on_goal
is accepting multiple goals on your PR
Mario Carneiro (Feb 07 2022 at 14:43):
on_goal
is like all_goals
, it runs the tactic in a focused state on each goal
Mario Carneiro (Feb 07 2022 at 14:45):
If you do on_goal 1 2 => simp
, first simp
will run on goal 1, then simp
will run on goal 2. If you do on_goals 1 2 => simp
then simp
will run on goals 1 and 2 together (and it will ignore goal 2 like most tactics run in a multi-goal state)
Mario Carneiro (Feb 07 2022 at 14:46):
by 1 goal I mean that simp
sees a tactic state with 1 goal in it
Mario Carneiro (Feb 07 2022 at 14:47):
The test has a use of on_goals 2 4 => swap
which permutes [1, 2, 3, 4, 5]
into [4, 2, 1, 3, 5]
Gabriel Ebner (Feb 07 2022 at 14:48):
So on_goal 3 5 8 => simp
is like on_goals 3 5 8 => all_goals simp
modulo goal permutation? This is yet one more reason it should get a visibly different name.
Johan Commelin (Feb 07 2022 at 14:48):
The way I understand it is that those two are not the same. (Sorry, I missed that there was no s
in the first on_goal
. Which I guess exactly makes Gabriel's point.)
Mario Carneiro (Feb 07 2022 at 14:48):
Yes. I originally wanted to implement one in terms of the other but it's not possible for on_goals
to have the goal order preservation thing
Mario Carneiro (Feb 07 2022 at 14:49):
I think on_goal
is likely to be much more useful than on_goals
Johan Commelin (Feb 07 2022 at 14:50):
Also, I would intuitively expect on_goals 3 5 8 => simp
to be the same as on_goals 3 5 8 => all_goals simp
.
Mario Carneiro (Feb 07 2022 at 14:50):
it's rare to need to work with multi-goal states directly, but these are goal permutation tactics, that's the point
Mario Carneiro (Feb 07 2022 at 14:50):
@Johan Commelin on_goal
satisfies that
Johan Commelin (Feb 07 2022 at 14:50):
I think we need more to stress the difference then just this s
.
Mario Carneiro (Feb 07 2022 at 14:51):
with_goals
?
Mario Carneiro (Feb 07 2022 at 14:51):
for on_goals
Johan Commelin (Feb 07 2022 at 14:51):
Right, on_goal
does, but on_goals
doesn't. Which is exactly why you wrote on_goals
. I get that now. But it took me a while.
Johan Commelin (Feb 07 2022 at 14:51):
on_goals {3,5,8} => simp
?
Johan Commelin (Feb 07 2022 at 14:52):
To emphasize that you run the tactic once a the "set" of those 3 goals.
Mario Carneiro (Feb 07 2022 at 14:52):
heh, if you write that then I'm going to generalize it
Johan Commelin (Feb 07 2022 at 14:52):
Yeah, that's part of the hint (-;
Johan Commelin (Feb 07 2022 at 14:53):
Is it clear that on_goals
can not place the goals back in the place where they came from?
Johan Commelin (Feb 07 2022 at 14:53):
on_goal 3 5 8
would just be on_goals {3} {5} {8}
.
Mario Carneiro (Feb 07 2022 at 14:53):
"where they came from" is not well defined if they came from a set {3, 5, 8}
Mario Carneiro (Feb 07 2022 at 14:54):
if you get two goals out, where would they go? the first one replaces 3
, the second 5
, ...?
Johan Commelin (Feb 07 2022 at 14:54):
yeah, fair enough.
Mario Carneiro (Feb 07 2022 at 14:55):
Plus, I'm not even sure that's a useful behavior most of the time
Arthur Paulino (Feb 07 2022 at 14:56):
If the user is not attacking the first goal, I don't think there's a clear intent to bring subgoals to the front
Mario Carneiro (Feb 07 2022 at 14:56):
I think the majority of the time that's always what you want to do
Mario Carneiro (Feb 07 2022 at 14:56):
on_goal
is the only exception I know to that
Mario Carneiro (Feb 07 2022 at 14:57):
everything happens at the head of the list
Gabriel Ebner (Feb 07 2022 at 14:57):
If we're letting the user select a goal, it would be nice if you could also use tags in addition to numbers. That is on_goal 3 zero => simp only
.
Mario Carneiro (Feb 07 2022 at 14:57):
wait, do we have non-closing case
?
Mario Carneiro (Feb 07 2022 at 14:58):
I guess it's fine in the on_goal
syntax to support tags
Arthur Paulino (Feb 07 2022 at 14:59):
What is a tag in this context?
Gabriel Ebner (Feb 07 2022 at 14:59):
No, I don't think we have non-closing case
. We also don't have an unstructured case
(which just moves the goal to the front and renames the variables).
Gabriel Ebner (Feb 07 2022 at 14:59):
Arthur Paulino said:
What is a tag in this context?
The succ i ih
in case succ i ih => tac
.
Mario Carneiro (Feb 07 2022 at 15:00):
lean 3 has multiple word tags, are those possible?
Gabriel Ebner (Feb 07 2022 at 15:00):
I think so, but I can't remember the syntax.
Mario Carneiro (Feb 07 2022 at 15:01):
Maybe we should consider how to port the lean 3 case
tactic that is sitting in Syntax.lean
Mario Carneiro (Feb 07 2022 at 15:06):
Hm, I think I can see a decent grammar for on_goal
, by example:
on_goal 1, zero, succ x ih, {3 a, -1 b c} => ...
Arthur Paulino (Feb 07 2022 at 15:07):
Regarding mathlib#187 I wanna suggest a mix of some ideas I saw here:
What if instead of on_goal
and on_goals
we had on_goals
and with_goals
?
with_goals
being the one that brings unsolved goals to the front
My rationale is that "on" reminds me of something that happens as in place as possible
Mario Carneiro (Feb 07 2022 at 15:07):
this grammar could also be used for variations on what to do with the goal, like case
Mario Carneiro (Feb 07 2022 at 15:08):
In the grammar above you wouldn't need with_goals
: on_goal 1 2 3 =>
becomes on_goal 1, 2, 3 =>
and with_goals 1 2 3 =>
becomes on_goal {1, 2, 3} =>
Johan Commelin (Feb 07 2022 at 15:08):
@Mario Carneiro With you on_goal
example, will you just move everything to the front? Or are the singleton goal-sets working "in-place"?
Mario Carneiro (Feb 07 2022 at 15:09):
If you use braces, you get with_goals
behavior: the set gets pulled to the front
Mario Carneiro (Feb 07 2022 at 15:09):
anything not in braces stays where it is
Mario Carneiro (Feb 07 2022 at 15:10):
so on_goal {3} =>
is also useful if you don't want it to stay where it is
Arthur Paulino (Feb 07 2022 at 15:10):
Ah, then you can mix for instance on_goal 3 {5, 7}
and subgoals from 5
and 7
would get pulled up?
Mario Carneiro (Feb 07 2022 at 15:11):
yes
Arthur Paulino (Feb 07 2022 at 15:11):
Okay that's a neat solution IMO
Mario Carneiro (Feb 07 2022 at 15:11):
if the goals were [1,2,3,4,5,6,7]
before then after they would be [57',1,2,3',4,6]
Johan Commelin (Feb 07 2022 at 15:12):
What is the behaviour of on_goal {2,3} {2,3} => skip
? On goal list [1,2,3]
.
Mario Carneiro (Feb 07 2022 at 15:13):
[2,3,2,3,1]
Mario Carneiro (Feb 07 2022 at 15:13):
yes you can copy goals
Johan Commelin (Feb 07 2022 at 15:13):
Ok, so the second {2,3}
doesn't operate on the result of the first {2,3} => simp
.
Johan Commelin (Feb 07 2022 at 15:14):
Of course these are weird edge cases that don't show up in practice (I hope).
Mario Carneiro (Feb 07 2022 at 15:14):
No, but by the time you get around to them they might be solved already
Mario Carneiro (Feb 07 2022 at 15:14):
if you do something other than skip
then the second invocation probably won't see them at all
Arthur Paulino (Feb 07 2022 at 15:15):
Isn't it safer if you take a snapshot and iterate on that instead of unfolding as it goes?
Mario Carneiro (Feb 07 2022 at 15:15):
I do
Arthur Paulino (Feb 07 2022 at 15:15):
(I probably made no sense)
Mario Carneiro (Feb 07 2022 at 15:16):
All goal indexes refer to the goal state at the start, not after half of the tactics have run
Mario Carneiro (Feb 07 2022 at 15:16):
but goals can "expire" due to other goals getting worked on
Mario Carneiro (Feb 07 2022 at 15:16):
especially if you copied a goal
Mario Carneiro (Feb 07 2022 at 15:17):
I'm sure you've seen this in lean 3 when you apply something and it produces a bunch of metavariables and then you equate two things and all the metavariable goals disappear
Arthur Paulino (Feb 07 2022 at 15:22):
I suspect we've reached a thin line between play and actual need, but I'm enjoying to see the power of Lean metaprogramming in action
Arthur Paulino (Feb 07 2022 at 15:26):
Also I'm learning a lot from this process of empowering and cleaning up mathlib3 tactics (and it barely started for me)
Mario Carneiro (Feb 07 2022 at 15:29):
Of course no one will use all of those features simultaneously. But it is useful to have an orthogonal mechanism, here goal selection, in a way that applies to multiple tactics, since it makes skills transferrable
Arthur Paulino (Feb 07 2022 at 15:31):
Yeah, how many times have I wanted something like on_goal 1 2 => intros
...
Yaël Dillies (Sep 27 2023 at 16:16):
Where is the tactic rotate
gone? I found it very practical for proof building.
Adam Topaz (Sep 27 2023 at 16:23):
import Mathlib
open Lean Elab Tactic
example (p q : Prop) : p ∧ q := by
constructor
run_tac do
let goals ← getGoals
setGoals <| goals.rotate 3
sorry
sorry
Adam Topaz (Sep 27 2023 at 16:27):
Sorry, I didn't actually read this thread before posting.
Kyle Miller (Sep 27 2023 at 16:44):
The tactic is now called rotate_left
and rotate_right
Yaël Dillies (Sep 27 2023 at 17:28):
Ah great!
Yaël Dillies (Sep 27 2023 at 17:28):
@Martin Dvořák, another one for your cheatsheet :point_up:
Martin Dvořák (Sep 27 2023 at 18:58):
May I kick apply?
out in order to make space for rotate_left
on the bottom of the page?
https://github.com/madvorak/lean4-cheatsheet/blob/main/lean-tactics.pdf
Yaël Dillies (Sep 27 2023 at 18:59):
Make it two pages? Reduce the font size?
Martin Dvořák (Sep 27 2023 at 19:04):
Then I'd rather make two versions. Let's move this discussion here:
https://leanprover.zulipchat.com/#narrow/stream/187764-Lean-for-teaching/topic/Lean4.20cheatsheet
Patrick Massot (Sep 27 2023 at 19:09):
Martin Dvořák said:
May I kick
apply?
out in order to make space forrotate_left
on the bottom of the page?
https://github.com/madvorak/lean4-cheatsheet/blob/main/lean-tactics.pdf
I think apply?
is infinitely more important than rotate_left
.
Alex J. Best (Sep 27 2023 at 19:10):
Why are you worried about page sizes anyway? Surely this is a digital document that nobody is actually printing
Patrick Massot (Sep 27 2023 at 19:11):
The layout is based on a document that I ask my students to physically have with them when I'm teaching this. And I print it for them.
Alex J. Best (Sep 27 2023 at 19:13):
Ok, thats interesting, do they have laptops at the same time?
Alex J. Best (Sep 27 2023 at 19:14):
Also how come simp
isn't on the list?
Alex J. Best (Sep 27 2023 at 19:14):
I'd kick convert_to out in favour of that any day
Martin Dvořák (Sep 27 2023 at 19:21):
Can we please continue the discussion about priorities for the cheatsheet in the respective thread?
The missing simp
is a mistake and I want to address it.
Eric Rodriguez (Sep 27 2023 at 20:21):
Where is the thread?
Damiano Testa (Sep 27 2023 at 20:26):
I also like the pick_goal
tactic. Maybe we need a pick_thread
now?
Martin Dvořák (Sep 27 2023 at 20:28):
Eric Rodriguez said:
Where is the thread?
https://leanprover.zulipchat.com/#narrow/stream/187764-Lean-for-teaching/topic/Lean4.20cheatsheet
Last updated: Dec 20 2023 at 11:08 UTC