Zulip Chat Archive

Stream: lean4

Topic: different dbg_traces


Damiano Testa (Jun 02 2022 at 07:04):

Dear All,

I am slowly learning my way around Lean 4 and was wondering about the different options that dbg_trace has. I could not tell the difference between them. Below is an example where they give the same output. What are the difference between them?

Thanks!

import Lean.Elab.Tactic

elab "traces" : tactic => do
  let tgt  Lean.Elab.Tactic.getMainTarget
  dbg_trace f!"with f:\n{tgt}"
  dbg_trace s!"with s:\n{tgt}"
  dbg_trace "neither f nor s:\n{tgt}"

theorem trace {a : Nat} : a = 0 := by
  traces
/-  The three traces produce the same outputs:
with f:
Eq.{1} Nat _uniq.588 (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0))
with s:
Eq.{1} Nat _uniq.588 (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0))
neither f nor s:
Eq.{1} Nat _uniq.588 (OfNat.ofNat.{0} Nat 0 (instOfNatNat 0))
-/

Mario Carneiro (Jun 02 2022 at 07:06):

Those aren't options of dbg_trace

Damiano Testa (Jun 02 2022 at 07:06):

Ok, but with those, dbg_trace does not complain, with any other single character it does.

Mario Carneiro (Jun 02 2022 at 07:06):

dbg_trace takes a format string, or an expression that implements ToString

Mario Carneiro (Jun 02 2022 at 07:07):

f!"fmt_string" is the latter

Mario Carneiro (Jun 02 2022 at 07:07):

My guess is that the latter two are equivalent

Damiano Testa (Jun 02 2022 at 07:08):

Ah, are you saying that the f! or s! are attached to the stuff in quotations and have nothing to do with dbg_trace? So, dbg_trace simply prints out the outcome of f!"..." or s!"..."?

Mario Carneiro (Jun 02 2022 at 07:09):

yes

Damiano Testa (Jun 02 2022 at 07:09):

Ok, so is there a difference between s!"..." and f!"..."?

Mario Carneiro (Jun 02 2022 at 07:09):

the same is also true for m!, but MessageData doesn't implement ToString so it doesn't work

Damiano Testa (Jun 02 2022 at 07:10):

or is this what you answered when you said "My guess is that the latter two are equivalent"?

Mario Carneiro (Jun 02 2022 at 07:10):

f! uses ToFormat instead of ToString and produces a Format

Mario Carneiro (Jun 02 2022 at 07:10):

I think dbg_trace s!"str" and dbg_trace "str" are exactly equivalent in terms of the functions that get called

Mario Carneiro (Jun 02 2022 at 07:11):

dbg_trace f!"str" is a bit different since it is being formatted using the ToFormat implementation and then the format is converted to a string

Damiano Testa (Jun 02 2022 at 07:11):

Ok, so in my situation above, ToFormat and ToString produce the same output and dbg_trace traces the same thing on either one of them and also on the plain "...", right?

Mario Carneiro (Jun 02 2022 at 07:11):

But most likely it won't be noticeably different in most cases

Mario Carneiro (Jun 02 2022 at 07:11):

right

Mario Carneiro (Jun 02 2022 at 07:12):

It's possible that the f! version might result in better looking output when the data is large enough to appear on multiple lines ...?

Mario Carneiro (Jun 02 2022 at 07:12):

assuming the type's ToString implementation isn't just defined as x.toFormat.toString

Damiano Testa (Jun 02 2022 at 07:12):

I'll write a longet goal and see if it prints differently.

Mario Carneiro (Jun 02 2022 at 07:13):

I would guess that Expr has a pretty solid formatter implementation so you aren't likely to see a difference there

Mario Carneiro (Jun 02 2022 at 07:13):

I'm thinking something like ToString on a List (String x String) or so

Mario Carneiro (Jun 02 2022 at 07:15):

indeed, take a look:

elab "traces" : tactic => do
  let tgt := (List.range 20).map (fun i => (i, i))
  dbg_trace f!"with f:\n{tgt}"
  dbg_trace s!"with s:\n{tgt}"
  dbg_trace "neither f nor s:\n{tgt}"

theorem trace {a : Nat} : a = 0 := by
  traces
-- with f:
-- [(0, 0),
--  (1, 1),
--  (2, 2),
--  (3, 3),
--  (4, 4),
--  (5, 5),
--  (6, 6),
--  (7, 7),
--  (8, 8),
--  (9, 9),
--  (10, 10),
--  (11, 11),
--  (12, 12),
--  (13, 13),
--  (14, 14),
--  (15, 15),
--  (16, 16),
--  (17, 17),
--  (18, 18),
--  (19, 19)]
-- with s:
-- [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19)]
-- neither f nor s:
-- [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19)]

Damiano Testa (Jun 02 2022 at 07:16):

Ah, thanks! I was fiddling with strings and did not get anywhere!

Mario Carneiro (Jun 02 2022 at 07:16):

The reason for this is that the ToString (List A) instance doesn't really have enough information to do line wrapping correctly

Mario Carneiro (Jun 02 2022 at 07:17):

but if it's ToFormat then it can delay the wrapping decisions to the ToString Format instance

Damiano Testa (Jun 02 2022 at 07:17):

Mario, do you mind if a variation of this goes into the metaprogramming in lean 4 book?

Mario Carneiro (Jun 02 2022 at 07:17):

of course not, please go ahead

Damiano Testa (Jun 02 2022 at 07:19):

Turns out, 15 iterations are sufficient for wrapping!

Mario Carneiro (Jun 02 2022 at 07:21):

you could also do something like List.replicate 5 (List.range 8) which probably looks a bit more tidy

Damiano Testa (Jun 02 2022 at 07:23):

That's great, thanks!

Damiano Testa (Jun 02 2022 at 07:24):

One final detail, then. Is it possible to observe a difference between s! and neither f nor s?

Mario Carneiro (Jun 02 2022 at 07:34):

No, because it macro expands to the same thing

Damiano Testa (Jun 02 2022 at 07:36):

Perfect, thanks!

Damiano Testa (Jun 02 2022 at 07:53):

So, just to make sure that I understand.

  • f!"..." produces a Format out of ... which then dbg_trace prints, thanks for a Format.toString instance.
  • s!"..." produces a String out of ... which then dbg_trace prints.
  • "..." produces a String out of ... which then dbg_trace prints passing it via s! first, since this is how dbg_trace is implemented.

Is this correct?

Damiano Testa (Jun 02 2022 at 07:54):

That is, at a minimum, the string passed to dbg_trace gets an s! applied, unless you specify that you want something else?

Damiano Testa (Jun 02 2022 at 08:31):

#26 :smile:

Mario Carneiro (Jun 02 2022 at 09:00):

The only function of s! is to transform s!"bla {x} bla" to ("bla " ++ toString x ++ " bla")

Mario Carneiro (Jun 02 2022 at 09:00):

f! does the same thing but with toFormat instead of toString and the append instance on Format

Mario Carneiro (Jun 02 2022 at 09:02):

That is, these macros are all just to make it easier to use interpolated strings where possible, since otherwise dbg_trace "foo {x}" would actually print "foo {x}" which isn't what we want

Damiano Testa (Jun 02 2022 at 09:16):

Ok, thanks for the explanation!

I feel very unsure about these things and cannot always understand the source code, so I value and appreciate very much these confirmations and corrections! :smile:


Last updated: Dec 20 2023 at 11:08 UTC