-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
fmt formatting string can't be a variable #18218
Comments
Here's the discussion on Nim Forum that triggered this issue. |
For JavaScript targets https://juancarlospaco.github.io/nodejs/nodejs/jsstrformat.html |
No and no.
What you should do: Use a custom format proc that supports what you need. Feel free to use |
Ok, thank you. I'll look into jsstrformat, that seems promising and if not try and code a custom format proc. |
A bit of background to support @Araq's comment: Usually in type safe languages, string interpolation supports type safe formatters. For instance in Scala it is a compile time error to use a formatter that is inappropriate for the type: This behavior obviously requires to know the formatting literal at compile time. In contrast dynamic languages like Python cannot find such bugs statically anyway, and thus can allow for dynamically generated format strings. I always felt it is a bit unfortunate that Nim's string formatting has the limitation of not being able to use dynamically generated format strings, while missing the potential of statically checking formatter correctness. For instance, Nim's equivalent to the example above let s = "foo"
echo &"{s:.3f}" unfortunately compiles, and throws an exception at runtime instead. Even semi-valid looking formatters like So rather than going in the direction of allowing dynamic format strings (which may be technically impossible anyway), it would make sense to make strformat fully type safe one day. |
Er, didn't you submit the original implementation of strformat? You could have given us a better initial implementation. ;-) |
I'm pretty sure it was a compilation error in my original implementation using the Scala style formatters, because this was a high priority acceptance criteria of mine. The type safety got lost in the re-implementation towards Python style formatters. I had mentioned the issue on the PR/discussion somewhere. I always wanted to have a look how hard it would be to make the Python style formatters type safe as well, but I never got to it... |
Bummer, I wasn't aware. |
This is a very useful feature and I have an implementation for it:
when true:
import formatutils
block: # D20210615T123026
var x = @[10, 2]
let y = 123
doAssert interpIt("{x} and {y}", (x, y)) == "@[10, 2] and 123" # simplest example
doAssert interpIt("{y} times 2 is {y2}", (y, y2: y*2)) == "123 times 2 is 246" # allow introducing variables on the fly
doAssert interpIt("{x} and {y} using locals") == "@[10, 2] and 123 using locals" # using locals()
var s = "foo {x}"
doAssert interpIt(s, (x, )) == "foo @[10, 2]" # works with runtime strings
doAssert interpIt(s) == "foo @[10, 2]" # ditto
doAssertRaises(ValueError): discard interpIt("foo {badvar}")
doAssertRaises(ValueError): discard interpIt("{y} {bad}", (x, )) # # substitution variable not found: bad
doAssert interpIt("{y} {bad} {bad2}", (y, ), it.toUpper) == "123 BAD BAD2" # use arbitrary expression for variables not found (via `it`)
let z = x[0].addr
doAssert interpIt("variable is {z}", (z: $z[])).tap == "variable is 10" # custom $
IMO this is clearly stdlib territory; I understand there are lots of open discussions at the moment but eventually this should make its way note
|
Thank you timothee ! I'm anxious to try it out. Is formatutils going to be in the nimble package directory ? |
I'd rather it be added to stdlib so it can be used in stdlib and compiler, but maybe I'll make a nimble package in the meantime |
It looks like this is because |
fmt accepts hard coded strings, but no variable strings.
This works :
While the code below throws a compile error "only works with string literals". Isn't the variable format a string literal ? Even when it is declared as const (before the loop), it doesn't work.
Or is it impossible to use a var because the compiler needs to know beforehand ?
However it works with variables as format strings when using a template for sprintf:
I would like to do this:
Note: this is a very simple example. The format strings would be in tables and some would be constructed on the fly during runtime.
If it is something that can be fixed/implemented and if so will it be in the not too distant future ? I should make design decision now, even if I go the sprintf route for the time being, I could already code in parts with when statements.
The project is a game speech system (TTS based), where the format strings have to be more or less created on the fly based on parameters.
Nim fmt with variables as format strings would have great benefits:
The issue has been mentioned before:
https://scripter.co/notes/nim-fmt/#fmt-and-and-formatting-strings-cannot-be-a-variable
The text was updated successfully, but these errors were encountered: