https://github.com/JuliaLang/Formatting.jl might help.
— Mike
Anyways… I started to tackle this problem
As an interesting/entertaining hack you can “lift” the formatting string out of @printf
with a staged function:
immutable Formatter{format} end
fmt(str) = Formatter{symbol(str)}()
@generated function printf{format}(io :: IO, :: Formatter{format}, args...)
xs = [:(args[$i]::$(args[i])) for i = 1:length(args)]
quote
$(Expr(:meta, :inline))
@inbounds $(Expr(:macrocall, symbol("@printf"), :io, string(format), xs...))
nothing
end
end
julia> printf(STDOUT, fmt("%f"), pi)
Though, of course, the normal warnings with relying heavily on @generated
should be noted.
Performance and resulting code seems to be roughly the same as using @printf
with
hard-coded formatting strings, and faster that what Formatting.jl is able to get.
and what you’d ideally like to see in a formatter.
http://www.gigamonkeys.com/book/a-few-format-recipes.html… but maybe that’s just me :)
— Mike
julia> const fmt = "%05d %-5s %5.2f\n""%05d %-5s %5.2f\n"julia> @eval formatter(i, s, x) = @printf($fmt, i, s, x)formatter (generic function with 1 method)julia> formatter(123, "flux", pi)00123 flux 3.14
julia> ccall(:printf, Cint,(Cstring, Cint, Cstring, Cdouble),"%05d %-5s %5.2f\n", 123, "flux", pi)00123 flux 3.1418
If anything I wrote came off as a "thinly veiled 'fuck you'", I am sincerely sorry; that's nowhere near what I meant to say.
Then, you replied that "Formatting.jl looks next to useless" and "I really don't understand why sprintf is such a big deal. If C can have one, why can't Julia?" I interpreted that, apparently wrongfully, as implying not only that you disliked the currently available implementations, but also that you thought it couldn't be so hard to do better, so my second answer had a different solution to the problem. (Note also that the two posts aren't directed at the same person.)
Re-reading the thread I think both our tones are harsher than necessary, and I apologize for my part in that.
Responding with a solicitation for help in an open source project is not a rhetorical ploy – it's a legitimate request for contribution.
A lecture on the importance of printing numbers is also not helpful and pretty irritating. Yes, printing things is important, especially numbers. Everyone is well aware, myself included – that's why I spent a month implementing our generic printf in the first place. It will get fixed.
In the mean time, several viable solutions have been provided (repeatedly), including...
2. Use Formatting.jl. If you don't care for the interface, help improve it. Help could take the form of pull requests, of just polite issues opened to suggest how the interface could be enhanced. Calling it "next to useless" and dismissing out of hand is rude and not particularly constructive.
3. Use C's printf. Since this seems to be what you want and you can easily call C from Julia, what's stopping you?julia> ccall(:printf, Cint,(Cstring, Cint, Cstring, Cdouble),"%05d %-5s %5.2f\n", 123, "flux", pi)00123 flux 3.1418It's not the most convenient interface in the world, but a little wrapping would solve that. (It may also be incorrect since printf is a varargs function – I was a little surprised that it worked – but using vprintf would address that.)
using Formatting
macro fmt(args...)
expr = Expr(:block)
expr.args = [:(print(fmt($(esc(arg))), "\t\t")) for arg in args]
push!(expr.args, :(println()))
expr
end
x = 1010101
y = 555555.555555555
fmt_default!(width=15)
@fmt x y
fmt_default!(Int, :commas)
fmt_default!(Float64, prec=2)
@fmt x y
1010101 555555.555556 1,010,101 555555.56
I think that before any further discussion takes place of how easy or hard implementing a high-performance printf is, anyone who'd like to comment should spend some time perusing GNU libc's vfprintf implementation. This code is neither easy nor trivial – it's batsh*t crazy.
And we want to match its performance yet be much more flexible and generic. The current printf implementation does just that, while being somewhat less insane GNU's printf code. If someone has bright ideas for how to also allow runtime format specification without sacrificing performance or generality, I'm all ears.
I have some thoughts, but they're just that – thoughts. One option is to change the design and avoid printf-style formatting altogether. But then I'm sure I'll never hear the end of it with people kvetching about how we don't have printf.
printf(fmt::AbstractString, args...) = @eval @printf($(bytestring(fmt)), $(args...))
That depends on what you do in your “production work” ;)
0.4 RC2 is good enough that it would become 0.4 if no serious bugs or regressions are found. There’s currently one issue tagged with milestone 0.4.0, and another one tagged backport pending 0.4, and I don’t know if there are other places you should look to find things that need to be fixed before the RC cycle is considered finished, but I guess there’s at least going to be an RC3 too.
It’s very possible that, for the areas of 0.4 that you would use, nothing will change between now and the final release. It’s also very possible that 0.4 is unusable to you in its current state - it depends entirely on your specific needs. But I would encourage you to try it out - there’s nothing that says you have to uninstall 0.3.11 yet :)
// T
PS:
I have tried to learn macros, but I still think they are basically black magic.
No matter what Julia concept we speak of, I could re-phrase that and apply it to myself, as
I think I have a pretty good understanding of [Concept X], but in the hands of Tim Holy it is still black magic…
But Michael Hatherly’s showed code above that uses a generated function to solve this.
What am I missing?
It’s probably because the thread was getting quite long and what I wrote simply got missed.
— Mike
That depends on what you do in your “production work” ;)
May this lazy-good-for-nothing request a link?
Of course, https://groups.google.com/forum/#!msg/julia-users/hBbEGEopi0A/fKQcqDEVBgAJ. Took me a while to actually find it again myself…
Implementation-wise they were pretty similar. I was dispatching of an instance Formatter{...}()
rather than the FormatString{...}
type itself, though the resulting generated code is identical as far as I can tell.
— Mike
But we could also do code caching with @printf by just maintaining a dict mapping format strings to generated code
Sorry I wasn't expecting you to run it... just comment. You'll have to do:Pkg.rm("Formatting")Pkg.clone("https://github.com/tbreloff/Formatting.jl.git")Pkg.checkout("Formatting", "tom-fmt")Let me know if that works.On Tue, Sep 22, 2015 at 5:52 PM, lawrence dworsky <ma...@lawrencedworsky.com> wrote:I'm afraid my beginner status with Julia is showing:I ran Pkg.add("Formatting"), and then using Formatting came back with a whole bunch of warnings, most about Union(args...) being depricated, use Union(args....) instead.When all is said and done, fmt_default! gives me a UndefVarError.Help!On Tue, Sep 22, 2015 at 2:45 PM, Tom Breloff <t...@breloff.com> wrote:Thanks Larry, that's helpful. Just for discussions sake, here's a quick macro that calls my proposed `fmt` method under the hood, and does something similar to what you showed. What do you think about this style (and what would you do differently)?
using Formatting
macro fmt(args...)
expr = Expr(:block)
expr.args = [:(print(fmt($(esc(arg))), "\t\t")) for arg in args]
push!(expr.args, :(println()))
expr
endAnd then an example usage:In:
x = 1010101
y = 555555.555555555
fmt_default!(width=15)
@fmt x y
fmt_default!(Int, :commas)
fmt_default!(Float64, prec=2)
@fmt x yOut:
1010101 555555.5555561,010,101 555555.56
On Tuesday, September 22, 2015 at 3:08:35 PM UTC-4, lawrence dworsky wrote:Hi TomWhat I like about it is that you can just use print *, dumbly and it always provides useful, albeit not beautiful, results. When I'm writing a program, I use print statements very liberally to observe what's going on - I find this more convenient than an in-line debugger.As the last line in my program below shows, it's easy to switch to formatted output when you want to. The formatting capability is pretty thorough, I'm just showing a simple example.This Fortran program doesn't do anything, it just illustrates what the print statement produces:real x, yinteger i, jcomplex zcharacter*6 namex = 2.6y = -4.i = 36j = -40z = cmplx(17., 19.)name = 'Larry'print *, x, y, i, j, zprint *, 'x = ', x, ' and j = ', jprint *, 'Hello, ', name, jprint '(2f8.3, i5)', x, y, jstopendThe output is:2.60000 -4.00000 36 -40 (17.0000, 19.0000)x = 2.60000 and j = -40Hello, Larry -402.600 -4.000 -40Is this what you are looking for?LarryOn Tue, Sep 22, 2015 at 11:57 AM, Tom Breloff <t...@breloff.com> wrote:Larry: can you provide details on exactly what you like about Fortran's print statement? Did it provide good defaults? Was it easy to customize?On Tue, Sep 22, 2015 at 12:55 PM, LarryD <larryd...@gmail.com> wrote:Something I miss from Fortran is the very convenient default "print *, ..... " It handled almost 100% of my needs while working on a program and was easily replaced by real formatting when the time came. Is there any chance that Julia could get something like this?Thanks
On Monday, September 21, 2015 at 3:46:31 AM UTC-5, Ferran Mazzanti wrote:Dear all,
I could use some help here, because I can't believe I'm not able to easily print formatted numbers under Julia in a easy way. What I try to do is to write a function that, given a vector, prints all its components with a user-defined format. I was trying something of the form
function Print_Vec(aux_VEC,form_VEC)
form_VEC :: ASCIIString
str_VEC = "%16.8f"
for elem_VEC in aux_VEC
str_VEC += @sprintf(form_VEC,elem_VEC)
end
return str_VEC
end
However, that doesn't work because it looks like the first argument in @sprintf must be a explicit string, and not a variable.
Is there anything I can do with that?
Thanks a lot for your help.
Chill guys.Anyways... I started to tackle this problem, but didn't get any (much needed) comments on whether I was on the right track. Here's some sample preliminary usage of what I was working on. Please let me know if you think it's worth continuing, and what you'd ideally like to see in a formatter.On Tue, Sep 22, 2015 at 10:05 AM, Daniel Carrera <dcar...@gmail.com> wrote:Coding sprintf() is beyond my skill, I tried. My contributions to Julia have to lie elsewhere (recently I've been putting a lot of time making mockups of a Julia IDE, and helping a new user port his Matlab code). I think it is rude to say "if you don't like it, fix it yourself"; especially after you wrote a post claiming that the non-implementation of sprintf() was an intentional omission because developers weren't sure how to do it right. I showed, correctly, that that argument is nonsense; so you spinned around and changed it to "if you don't like it, fix it yourself". That answer is only a way to reject valid complaints, and it feels like a thinly veiled "fuck you". Imagine if that's how people responded in bug reports. This is not the type of answer that Julia developers normally give, and it is not the type of answer that I expect in Julia; especially after giving a very different answer to the same question. I do try to contribute to Julia, and it is rude and unreasonable to hold me personally responsible for fixing everything that does not work in Julia. A healthy community needs room for receiving legitimate complaints.Daniel.On 22 September 2015 at 15:49, Tomas Lycken <tomas....@gmail.com> wrote:> If C can have one, why can't Julia?The hard truth, and nothing but it: If Julia is missing a feature, or has one that works in a way that's not the way you want, it's because no-one has wanted what you want enough to actually implement it.
That's it. There's no "it can't be done" - Julia is Turing complete, so "everything" can be done. There's no "it's not allowed" - no-one is stopping you from writing your own package, with your own implementation that does what you want the way you want it done, putting it in the package repository and seeing it take off. Chances are that if you write something that it turns out many others want as well, it will be included in the default package distribution in the future (or even in base Julia). Or it might not take off, but at least be there for your own enjoyment.But the entire language, with all tooling, packages, etc - everything that is Julia - is very much a community-built product. Everything that is there, is there because someone at some point said hey, this is so important to me that I'm going to put it at the very top of my priority list. Creating a sprintf function that fulfills your needs might not have made it there for anyone yet. If it's that important to you, maybe that's your next contribution?// T
On Tuesday, September 22, 2015 at 3:17:55 PM UTC+2, Daniel Carrera wrote:I might be wrong, but to me Formatting.jl looks next to useless. The "sprintf" functions it provides only accept one parameter. The main function provided is `sprintf1()`, but even the very clumsy `generate_formatter()` function fails at the most basic tasks:julia> fmtrfunc = generate_formatter( "%10.3f %6d %3d" )ERROR: Only one AND undecorated format string is allowedin generate_formatter at /home/daniel/.julia/v0.3/Formatting/src/cformat.jl:23I really don't understand why sprintf() is such a big deal. If C can have one, why can't Julia? I understand the argument that you might want to rewrite the implementation later. Fine. Just call the function "__temp_sprintf()" and put it in a package called "FunctionThatWillGoAwayLater". I don't care. I just want to be able to print formatted strings without a ton of needless hassle.
On Tuesday, 22 September 2015 10:03:52 UTC+2, Tomas Lycken wrote:By the way, you might also note that the Formatting.jl package is written and maintained by people who are all active contributors to the main language repo, and very active members of the community. Even if it's "external" in terms of how you install it, it's by no means external "in spirit".// T
On Tuesday, September 22, 2015 at 10:01:24 AM UTC+2, Tomas Lycken wrote:Julia is a young language.
This comes with a lot of benefits - for example, it's possible to do things *right* from the start. We're currently in a phase where there is a multitude of possible solutions to every problem that arises, and we honestly don't know which solution proves to be the best one. Testing various solutions out in packages, outside of the base distribution, where they can compete for popularity, and keep building on top of each-other until we reach something which we believe not only is adequate, but *really* hits the sweet spot. In other words: sure, formatting numeric output is fundamental, but it's a problem with a large solution space, and we don't want to lock in on one path yet.
But Julia's young age also means that there are lots of problems that aren't really solved yet, or that have solutions proposed but not implemented, etc. For the future, there are plans to include some packages (which ones have not been decided, or AFAIK really even discussed) in a sort-of "base distribution", so they will be installed upon installation of Julia, and available with a single `using` statement. But the infrastructure for this is not in place yet, and even if it were, there would still be lots of reasons not to make a final decision on which packages make the cut until we approach a 1.0 release of the language.
So yeah, it might seem silly to have to install a package just to get fine-grained control of numeric output formatting, but, at least for now, that's part of what one could call Julia's "Package Deal" ;)// T
On Tuesday, September 22, 2015 at 9:43:05 AM UTC+2, Ferran Mazzanti wrote:Thanks, that seems to work.
Still it amazes me how Julia, being a language made for numerical calculations, does not natively support a simple mechanism to print/write
large bunches of numbers. I've been in the numerical world for 20+ years and I know printing lots of numbers is something you get on a daily
basis. I know now the formatting package can help on that (thanks :), what I do not like is the idea of having to install every time a new package
to get added functionality. I understand there are things that have to go to external packages because of its limited or specialized use, but
come on... printing number os definitely not one of those.
Just my 2cents :)
On Monday, September 21, 2015 at 10:52:52 AM UTC+2, Michael Hatherly wrote:https://github.com/JuliaLang/Formatting.jl might help.
— Mike
did you see the format function in the last part of Formatting.jl's readme?