Spin off from #ideas > Unicode code point syntax.
Would it be worth adding some sort of debug printing syntax that is built on top of Inspect.toStr? The base idea for the syntax is to add support for \?(someVar) which is equivalent to \(someVar |> Inspect.toStr). This will enable quick to string conversion for logging and printouts without caring about the type.
Given Inspect.toStr is pretty new, it is not seen that often in string interpolation. That said, seen in many many examples is \(someVar |> Num.toStr) or:
someVarStr = Num.toStr someVar
"\(someVarStr)..."
These two common examples show cases where someone really just wants a generic debug printout. Of course to get a prettier printout, someone may still need to a fancier format function that can take into account many options (base, leading/trailing zeros, decimal places before rounding, etc)
This proposal is just for the common case of debugging where the generic printout for the type is totally acceptable. Given inspect is derived for all types, this will always compile for every single type and never need to panic.
This is probably a hot take, but I don't think the language should support this. I do this all the time in the software I write, but it's a bad habit (always stuff like log("here 1: {foo}")). It's either a poor substitute for line numbers (which Roc's dbg provides), or redundant when you have a facility that provides line numbers. The only other case I can think of is you want to show a debug representation to a user (internal or external). But usually the raw programmer debug representation isn't what you want to show there, or if it is, you probably need to think about it/its so infrequent that spelling it out doesn't hurt.
That's very true. Maybe it is more a sign that it might be useful to also have some sort of display ability for interpolation.
And if that is the case, this probably is a premature proposal cause we should first see the amount of friction or lack there of from just calling functions directly in interpolation for pretty displaying.
For me, the piping to Num.toStr indicates design/restriction smell with regular interpolation. Localization is hard, but even if we had it, having a sensible, unambiguous default representation of basic types will be a common need. For example, numbers with digit-grouping separators do not double-click select well, and then whatever you try pasting them into will not accept non-numeric digits, thus any localization goal would frequently need an opt-out anyways.
If \(...) provides sensible default representations for more types than just strings, then \? would have less value.
I'm not sure. If piping is the default it then makes any sort of more capable library calls makes sense.
Basic
\(x |> Num.toStr)
Medium complicated
\(x |> Float.format {precision: 6, places: 2})
Complex
\(x |> Locale.format Turkish ...)
Just a naive example, but it is directly showcasing the problem rather than hiding behind an automatic formatter/interpolation. Given the complexity will be needed in many cases, may be valid to always make it explicitly called out.
Honestly with expressions that lengthy, I'd just give those names (variables) and just interpolate the variables. Readability suffers when you've got a string literal that's 90% verbose interpolation and 10% actual literal bytes.
I was just trying to consider if we wanted to allow this in modern Roc because we don't currently have a syntax even for formatting numbers, but I agree that we probably don't want it. Luckily, static dispatch will make a lot of this much more terse:
abc = 123
xyz = 0.567
out = "abc is ${abc.to_str()} and xyz is ${xyz.format({ precision: 6, places: 2 })}"
Especially the .format approach prevents people from always getting confused as to which language has which syntax for padding like I do
Last updated: Jun 16 2026 at 16:19 UTC