Skip to content
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

Hope to have f-string like in python #67

Closed
zsz00 opened this issue Jan 31, 2024 · 10 comments
Closed

Hope to have f-string like in python #67

zsz00 opened this issue Jan 31, 2024 · 10 comments

Comments

@zsz00
Copy link

zsz00 commented Jan 31, 2024

Hope to have f-string like in python

reference:
https://peps.python.org/pep-0498/
https://realpython.com/python-f-strings/
https://github.com/bicycle1885/Fmt.jl

small example:

a="world"
println(f"hello {a}")    # hello world

b=1.234567
c = f"number {b:.3f}"    # "number 1.235"

d="aaaa"
println(f"{d=}")   # d="aaaa", debug feature

Most important of all f-string enables a compact and expressive syntax which is clean, fast and fun to type.

@ScottPJones
Copy link
Member

There already is such a thing - although not with exactly the same format (for various reasons):
Check out StrFormat.jl (which uses Format.jl):

julia> using StrFormat

julia> b=1.234567
1.234567

julia> f"number \{.3f}(b)"
"number 1.235"

It has a number of extensions over Python f-strings, you can also do more C style formatting, or formatting based on type-specific defaults (which you can add types to, or change the formatting)

C-style:

julia> f"number \%.3f(pi)"
"number 3.142"

Settable defaults, with keywords:

julia> f"\%(pi*10000,20,:commas,:left)"
"31,415.926536       "

This is what I've used for debugging for the past 8 years 😁

@aplavin
Copy link
Contributor

aplavin commented Feb 16, 2024

For syntax that follows Python f-strings directly, use PyFormattedStrings.jl:

julia> f"number {π:.3f}"
"number 3.142"

That package simply transforms the f-string syntax to calling the sprintf function (from base Julia), so it's lightweight.

@ScottPJones
Copy link
Member

@aplavin Are you planning on supporting the rest of the Python formatting functionality, such as ^ (center justification), _ and , for group separators, # for alternate output format?
Also, there is a bug in Printf, when padding strings that have wide characters that have been truncated by the precision, that needs to get fixed in Printf, or worked around in your own code (which is what I did for Format.jl)

It would be nice to have a complete drop in replacement for Python f-strings (my focus was on equivalent functionality, not equivalent syntax)

@aplavin
Copy link
Contributor

aplavin commented Feb 16, 2024

Are you planning on supporting the rest of the Python formatting functionality

I'm going to support whatever functionality is available in the Printf stdlib! For example, when dynamic width/precision was implemented there (in 1.10), I quickly added its support to PyFormattedStrings using Python syntax, like f"{x:{w}.{p}d}".

# for alternate output format

Is that what you mean?

julia> f"{1234:#x}"
"0x4d2"

But I'm not planning to implement any formatting myself in that package, this is what lets it remain lightweight and as reliable as base Julia. If there are missing features or bugs there – would be best to fix them in Printf.jl stdlib directly.
The goal and scope of PyFormattedStrings is specifically to provide Python formatted string syntax in Julia. Nothing more, nothing less :)

@jariji
Copy link

jariji commented Feb 17, 2024

Are you planning on supporting the rest of the Python formatting functionality

The other thing that's missing in PyFormattedStrings.jl is Python's format(x, fmt) which is needed when you're making the formatter before the x is available.

@aplavin
Copy link
Contributor

aplavin commented Feb 17, 2024

Hm, I don't remember exactly why I didn't go with format(), but this functionality is actually present in PyFormattedStrings.jl:

julia> fmtfunc = ff"abc {x:.2f} {y:d}"
#6 (generic function with 1 method)

julia> fmtfunc((x=1, y=2.2))
"abc 1.00 2"

julia> x = 2
2

julia> fmtfunc((y=2.2,))
"abc 2.00 2"

It does require a macro for performance anyway, maybe the interface should be format(x, ff"...")?..

@ScottPJones
Copy link
Member

ScottPJones commented Feb 17, 2024

I suppose if you really wanted to have the syntax more like Python's ("formatstring".format(args)) you could have the macro return a struct, and then define getproperty on that type, i.e. something like py"abc {x:.2f} {y:d}".format((x=1, y=2.2))

@jariji
Copy link

jariji commented Feb 17, 2024

StrFormat.jl doesn't give any usage documentation and says it's a "work in progress" and "I plan on changing it shortly" so it doesn't seem ready for users.

Also, imho the syntax for this stuff is already pretty fiddly and hard to remember, so any divergence from established f-string syntax (of Python, Rust) needs to be significantly better for the user in order to justify learning a new thing.

@ScottPJones
Copy link
Member

I do need to update the docs (it's no longer a work in progress, it's been stable for a long time now).
I do believe that the syntax in StrFormat is less "fiddly" than the Python f-strings though, and Rust f-strings don't have some of the features (such as formatting with thousand separators [, or _] like Python and this do)

@ScottPJones
Copy link
Member

The other thing that's missing in PyFormattedStrings.jl is Python's format(x, fmt) which is needed when you're making the formatter before the x is available.

That is present in JuliaString/Format.jl, i.e.

julia> format("π = {:6.3f}, {:^8.4s}", pi, "🍕")
"π =  3.142,    🍕   "

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants