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