Thanks Kevin,

Follow the link you've posted found an explanation why

@printf() constant format string is not allowed

https://github.com/JuliaLang/julia/issues/4248

and the useful trick:

julia> const fmt_ = "%4d%4d%4d\n"
"%4d%4d%4d\n"

julia> @eval f(x,y,z) = @printf($fmt_,x,y,z)
f (generic function with 1 method)

julia> f(9,16,25)
   9  16  25


On Monday, February 3, 2014 9:37:59 PM UTC+4, Kevin Squire wrote:
>
> See the discussion in the following issue, which discusses your case and 
> potential solutions:
>
> https://github.com/JuliaLang/julia/issues/4209
>
> Cheers, Kevin
>
>
> On Mon, Feb 3, 2014 at 8:06 AM, Alexander Samoilov <
> [email protected] <javascript:>> wrote:
>
>> Thanks a lot for the hint and for the useful code hack.
>>
>> Let me elaborate a bit about multiple @printf in order to avoid 
>> misunderstanding and explain the use case:
>>
>> I was translating from Fortran
>>
>> ```Fortran
>>     write(50,1001) mptr,level,mx
>>
>>  1001 format(i5,'                 grid_number',/,
>>      &     i5,'                 AMR_level',/,
>>      &     i5,'                 mx')
>> ```
>> The 1st variant of translation with a big format string:
>>
>> ```julia
>> @printf(unit50,
>>             "%5d                 grid_number\n%5d                 
>> AMR_level\n%5d                 mx\n",
>>             mptr,level,mx)
>> ```
>>
>> i.e. is not very pretty-looking as the format string is too big.
>>
>> In C it can be written as
>>
>> ```C
>> printf(unit50,
>>             "%5d                 grid_number\n"
>>             "%5d                 AMR_level\n"
>>             "%5d                 mx\n",
>>             mptr,level,mx);
>> ```
>> due to consecutive tokens pasting.
>>
>> Finally I gave up and just wrote:
>>
>> ```julia
>>     @printf(unit50,"%5d                 grid_number\n",mptr)
>>     @printf(unit50,"%5d                 AMR_level\n",level)
>>     @printf(unit50,"%5d                 mx\n",mx)
>> ```
>>
>> Thanks,
>> Alexander
>>
>> On Monday, February 3, 2014 7:39:04 AM UTC+4, Jake Bolewski wrote:
>>>
>>> I don't think you can do this as a macro, you want to use a function 
>>> instead wrapping multiple @printf's as you stated.
>>>
>>> the behavior you are asking for is to partially evaluate the string 
>>> function at compile time (hack)
>>>
>>> macro myprintf(args...)
>>>     if length(args) == 0
>>>         error("@myprintf: called with zero arguments")
>>>     end
>>>     if isa(args[1], String) || (isa(args[1], IO) && isa(args[1], String
>>> ))
>>>        :(@printf($(args...)))
>>>     else 
>>>         local io, func, fargs
>>>         if isa(args[1], Expr)
>>>             io    = :(Base.STDOUT)
>>>             func  = args[1].args[1]
>>>             fargs = args[1].args[2:end]
>>>         elseif (isa(args[1], IO) && isa(args[2], Expr))
>>>             io    = args[1].args[1]
>>>             func  = args[1].args[2]
>>>             fargs = args[1].args[3:end]
>>>         else
>>>             error("better message here")
>>>         end
>>>         for i in 1:length(fargs)
>>>             if isa(fargs[i], Symbol)
>>>                 fargs[i] = getfield(current_module(), fargs[i])
>>>             end
>>>         end
>>>         fmt_string = apply(getfield(Base, func), fargs...)
>>>         :(@printf($io, $fmt_string, $(args[2:end]...)))
>>>     end
>>> end
>>>
>>> however this does not work at all with local scope.
>>>
>>>  julia> a = "This is "
>>> "This is "
>>>
>>> julia> b = "a test: %d"
>>> "a test: %d"
>>>
>>> julia> @myprintf(string(a, b), 10)
>>> This is a test: 10
>>> julia> let a = "test1 ", b = "test2 %d"
>>>        @myprintf(string(a, b), 10)
>>>        end
>>> This is a test: 10
>>> julia> 
>>>
>>>
>>> Best,
>>> Jake
>>>
>>> On Sunday, February 2, 2014 6:53:04 PM UTC-5, John Myles White wrote:
>>>>
>>>> Hi Alexander, 
>>>>
>>>> I’m not aware of a way to do this, but would also like to know how to 
>>>> do it. 
>>>>
>>>>  — John 
>>>>
>>>> On Feb 2, 2014, at 5:52 AM, Alexander Samoilov <
>>>> [email protected]> wrote: 
>>>>
>>>> > Hello, 
>>>> > 
>>>> > I have a format string - a "%Fmt" literal for @printf() and it is too 
>>>> large, so would like to concatenate it from chunks, 
>>>> > say using string("chunk 1 ", " chunk 2 ", " chunk 3 ") 
>>>> > 
>>>> > @printf() disallow to do it as requires a string literal, but 
>>>> string() is a function and the produced string variable cannot be checked 
>>>> vs. @printf() args. 
>>>> > 
>>>> > julia> @printf(string("abc ", " def ", " ggg ")) 
>>>> > ERROR: first or second argument must be a format string 
>>>> > 
>>>> > Looks this is intentionally to have an opportunity to check format 
>>>> string vs. parameters (at least check number of args). 
>>>> > 
>>>> > BTW, C allows gluing of a few consecutive strings, e.g.  "abc " " def 
>>>> " " ggg " into one string literal, though it doesn't look very aesthetic. 
>>>> > 
>>>> > Is it possible for Julia to construct a format string somehow and 
>>>> feed it to @printf() or this is impossible in principle 
>>>> > and several invocations of @printf() should be used as workaround? 
>>>> > 
>>>> > Thanks, 
>>>> > Alexander 
>>>>
>>>>
>

Reply via email to