Skip to content

Instantly share code, notes, and snippets.

@bionicles
Created July 20, 2024 16:45
Show Gist options
  • Save bionicles/04a474a6390b61a2ca56622e19014734 to your computer and use it in GitHub Desktop.
Save bionicles/04a474a6390b61a2ca56622e19014734 to your computer and use it in GitHub Desktop.
Enhanced Variable Printing in println! and dbg! Macros - Iteration 2
  • Title: Enhanced Variable Printing in println! and dbg! Macros
  • Author(s): bionicles with help from Mistral Au Large & codestral
  • Iteration: 2
  • Status: Draft

Abstract: This RFC proposes a new shorthand syntax for Rust's println! and dbg! macros, inspired by Python's f-string {x=} syntax. The goal is to reduce redundancy and improve ergonomics when printing variables and their values, especially for long or nested identifiers. This RFC aims to enhance both println! and dbg! macros to provide a more flexible and convenient way to print variables and their values.

Motivation: The discussion revealed that using Rust's println! and dbg! macros to print variables and their values can be redundant and time-consuming, particularly with long or nested identifiers. The proposed shorthand syntax addresses this issue, making it more convenient to print variables and their values without sacrificing readability.

The discussion also highlighted the limitations of the current dbg! macro. Users expressed the need for more flexibility in terms of formatting, output destination, and verbosity level. The proposed shorthand syntax aims to address these limitations and improve the overall usability of dbg!.

Proposed solution: The proposed shorthand syntax for println! and dbg! allows using {x=} to print the variable x and its value. The macros expand this to the longer form x={x}. This syntax is valid in any position where named arguments are currently supported, including formatting strings and write! macros.

Example:

let a_really_long_name = 42;
println!("{a_really_long_name=}"); // Prints "a_really_long_name = 42"
dbg!("{a_really_long_name=}"); // Prints "a_really_long_name = 42"

let module::nested::variable = "hello";
println!("{module::nested::variable=}"); // Prints "module::nested::variable = hello"
dbg!("{module::nested::variable=}"); // Prints "module::nested::variable = hello"

let x = 3.14;
let y = 2.71;
println!("The values are: x={x=}, y={y=}"); // Prints "The values are: x=3.14, y=2.71"
dbg!("The values are: x={x=}, y={y=}"); // Prints "The values are: x=3.14, y=2.71"

To avoid potential confusion with the existing {:?} and {:#?} syntax for Debug and pretty-printed Debug output, the shorthand syntax does not support using {x=?} or {x=#?}. Instead, users should use the longer form x={x:?} or x={x:#?}.

The shorthand syntax also does not support custom formatting specifiers, such as {x=:.2}. In these cases, the longer form x={x:.2} should be used.

Alternatives: The discussion mentioned several alternatives to the proposed solution, including using dbg!, log::debug!, or introducing a new macro, such as print_var!. The proposed solution was chosen over these alternatives due to its compatibility with existing code, simplicity, and integration with the existing println! and dbg! macros.

Compatibility: The proposed shorthand syntax does not affect backward compatibility, as it introduces a new syntax that doesn't conflict with existing code. However, it's essential to consider the potential for confusion or misinterpretation of the new syntax, especially for users who are not familiar with Python's f-string syntax.

Implementation: The implementation of the proposed shorthand syntax involves modifying the println!, write!, and dbg! macros' expansion rules to recognize and handle the {x=} syntax. This change is relatively localized and should not have a significant impact on the overall codebase.

A key challenge is to correctly parse and expand the shorthand syntax in all cases, including when used in combination with other named arguments, dot accessors, function calls (maybe skip this), custom formatting specifiers, or Debug output.

Improving dbg!: The discussion highlighted the need for improvements to the dbg! macro. Suggestions included making it more flexible in terms of formatting, output destination, and verbosity level. The proposed shorthand syntax aims to address these limitations and improve the overall usability of dbg!.

References:

Discussion:

  • Tim Kurdov (its-the-shrimp): is it really that confusing to have {x=:?} in a print!()? I think most uses of this new proposed syntax would in fact involve Debug formatting.
  • Peter Jaszkowiak (pitaj): This use case seems to be covered by the dbg!() macro.
  • Josh Triplett: I don't think it is; sometimes you want to print several things, plus some explanatory text or similar, and you do want println/eprintln. I also think this should be combinable with :? or with arbitrary other formatting.
  • Kevin Reid (kpreid): In my experience, dbg! is too inflexible because it always prints each value on a new line, even in a single dbg!(a, b), which frequently makes it harder to comprehend how values relate when you look at debug output than it would if they were together on a single line.
  • Jacob Lifshay: plus dbg! always uses the verbose debug format, so if you wanted to print v: (u32, u32) it would take 4 lines instead of just 1.
  • Peter Jaszkowiak (pitaj): Are there ways we could make dbg less annoying to use? We're allowed to change it, right? Maybe we could make it work like this:
    • dbg!(x) print non-verbose
    • dbg!(@x) print verbose
    • dbg!(x, y) print on the same line
    • dbg!(x; y) print on different lines
  • Kevin Reid (kpreid): If I were doing what was most useful for me, I would make it so dbg!(a, b) printed all arguments on one line, and used {:?} format rather than {:#?}, and not bother with adding any other formatting options.
  • scottmcm: I'd like to change dbg! to try to :? into a limited width buffer, and only use :#? if it doesn't fit. Because yeah, (1, 2) needing three lines is annoying.
  • scottmcm: But note that customization options for dbg! were in the original RFC, and that was declined. This is one of those places where the simple thing being available without anything is important -- for examples and such -- but if you really need customized stuff then a crate is fine.
  • Josh Triplett: I think there are several improvements we could make to dbg, but I still think there's value in the = modifier as well.
  • Bion Howard: my main use case for this is stdout so hopefully upgrades can be portable across dbg and println.

Conclusion: The proposed shorthand syntax for println! and dbg! macros aims to improve ergonomics when printing variables and their values, especially for long or nested identifiers. This syntax is inspired by Python's f-string {x=} syntax and does not conflict with existing code. The RFC also discusses the limitations of the current dbg! macro and proposes improvements to make it more flexible and useful. The implementation involves modifying the println!, write!, and dbg! macros' expansion rules to recognize and handle the {x=} syntax. The proposed shorthand syntax does not support using {x=?} or {x=#?}, and it does not support custom formatting specifiers. The RFC encourages further discussion and improvements to both dbg! and println! to make them more flexible and convenient for printing variables and their values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment