POV-Ray : Newsgroups : povray.advanced-users : passing variable to macro for use in #for statement Server Time
28 Mar 2024 20:51:02 EDT (-0400)
  passing variable to macro for use in #for statement (Message 1 to 10 of 12)  
Goto Latest 10 Messages Next 2 Messages >>>
From: Bald Eagle
Subject: passing variable to macro for use in #for statement
Date: 19 Sep 2018 12:00:01
Message: <web.5ba2723e83bd6a1ec437ac910@news.povray.org>
Is it possible to start a loop in a macro using a variable name passed into the
macro?

I think not, but maybe it's one of those #write #read workaround things.

Like so:
#macro Loop (_Var, _Begin, _End, _Step)
 #for (_Var, _Begin, _End, _Step)
 ....
 #end
#end


Along the same lines, is it possible to assign an image_map file type to a
variable
like png, jpeg, etc. ?


Post a reply to this message

From: clipka
Subject: Re: passing variable to macro for use in #for statement
Date: 19 Sep 2018 13:57:47
Message: <5ba28e1b$1@news.povray.org>
Am 19.09.2018 um 17:58 schrieb Bald Eagle:
> Is it possible to start a loop in a macro using a variable name passed into the
> macro?
> 
> I think not, but maybe it's one of those #write #read workaround things.
> 
> Like so:
> #macro Loop (_Var, _Begin, _End, _Step)
>  #for (_Var, _Begin, _End, _Step)
>  ....
>  #end
> #end

That depends on what you actually want to achieve.

If you actually want to pass the /name/ of an identifier into the macro
(presumably as a string), you're pretty much out of luck.(*)

Theoretically you could probably use:

    #macro Loop (VarName, Begin, End, Step)
      #for (Parse_String(VarName), Begin, End, Step)
        ...
      #end
    #end

    Loop("Fnord",0,10,2)

but then the loop will actually use the macro-local variable `Fnord`,
not some global variable.


If however you just pass the variable itself (rather than its name),
then the following should work fine:

    #macro Loop (Var, Begin, End, Step)
      #for (Var, Begin, End, Step)
        ...
      #end
    #end

    #local Fnord = 42;
    Loop(Fnord,0,10,2)
    #debug concat("Fnord is now ", str(Fnord,0,0), "\n")

In this case, the macro-local name `Var` is used as an alias for the
"more global" variable named `Fnord`, and the for loop should use
exactly that same variable.


(* As of v3.8.0-alpha, another approach /may/ be viable; I haven't
tested it, and it may or may not work:

    #macro Loop (VarName, Begin, End, Step)
      #for (global[VarName], Begin, End, Step)
        ...
      #end
    #end

    #declare Fnord = 42;
    Loop("Fnord",0,10,2)
    #debug concat("Fnord is now ", str(Fnord,0,0), "\n")

If this works, it's because along with the introduction of dictionaries,
two pseudo-dictionaries have been added, `global` and `local`, which
allow access to the global and "most local" variables, respectively,
using dictionary-style syntax.

The caveat is that `#for` is specifically designed to use a local
variable as the loop counter, and it may gag on this construct. )


> Along the same lines, is it possible to assign an image_map file type to a
> variable
> like png, jpeg, etc. ?

Only using the `Parse_String` approach (or an equivalent homebrew
`#write`/`#include` workaround; as a matter of fact that's how the
`Parse_String` macro works behind the scenes):

    #declare Format = "png";
    image_map { Parse_String(Format) "foo.png" }

In the case of `image_map` it's probably easier and cleaner to use the
filename extension to convey the type information.

Also reasonably clean would be the following construct:

    #macro FormatKeyword(Format)
      #if (Format = "png")
        png
      #elif (Format = "jpeg")
        jpeg
      ....
      #end
    #end

    #declare Format = "png";
    image_map { FormatKeyword(Format) "foo.png" }


Post a reply to this message

From: Bald Eagle
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 10:10:01
Message: <web.5ba3aa31b6c56d12c437ac910@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:

> If however you just pass the variable itself (rather than its name),
> then the following should work fine:
>
>     #macro Loop (Var, Begin, End, Step)
>       #for (Var, Begin, End, Step)
>         ...
>       #end
>     #end


>     #local Fnord = 42;
>     Loop(Fnord,0,10,2)
>     #debug concat("Fnord is now ", str(Fnord,0,0), "\n")

Hmmm.   yes, that will work just fine.... in most cases...

Though I'm trying to only /initiate/ a loop with the macro - so the #end of the
for loop is what I need to avoid at the present.
I have not yet figured out if there's a syntax trick that's possible.

like so:
Loop(Fnord,0,10,2)
     [loop contents NOT in macro]
#end

> Also reasonably clean would be the following construct:
>
>     #macro FormatKeyword(Format)
>       #if (Format = "png")
>         png
>       #elif (Format = "jpeg")
>         jpeg
>       ....
>       #end
>     #end
>
>     #declare Format = "png";
>     image_map { FormatKeyword(Format) "foo.png" }

Right - o.  That'll be great.   Especially since I can just use a string
function to look at the extension of the filename and avoid the declare
altogether.   :)


Post a reply to this message

From: clipka
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 11:00:09
Message: <5ba3b5f9$1@news.povray.org>
Am 20.09.2018 um 16:09 schrieb Bald Eagle:

> Though I'm trying to only /initiate/ a loop with the macro - so the #end of the
> for loop is what I need to avoid at the present.
> I have not yet figured out if there's a syntax trick that's possible.

Can't do such a thing. The `#end` directives in a macro must always be
balanced - otherwise, how would the parser be able to figure out where
the macro ends.


>>     #declare Format = "png";
>>     image_map { FormatKeyword(Format) "foo.png" }
> 
> Right - o.  That'll be great.   Especially since I can just use a string
> function to look at the extension of the filename and avoid the declare
> altogether.   :)

If the file type can already be inferred from the extension, Why not let
POV-Ray do that job? Just leave out the file format keyword, like so:

    image_map { "foo.png" }

and Bob's your uncle.


Post a reply to this message

From: Kenneth
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 15:00:00
Message: <web.5ba3ed57b6c56d12a47873e10@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> Am 19.09.2018 um 17:58 schrieb Bald Eagle:

> > Along the same lines, is it possible to assign an image_map file type
> > to a variable-- like png, jpeg, etc. ?

>
> ...reasonably clean would be the following construct:
>
>     #macro FormatKeyword(Format)
>       #if (Format = "png")
>         png
>       #elif (Format = "jpeg")
>         jpeg
>       ....
>       #end
>     #end
>
>     #declare Format = "png";
>     image_map { FormatKeyword(Format) "foo.png" }

Hey, that's GREAT! I struggled with this idea years ago, and had to use some
ugly kludges to get this result. Using a macro didn't occur to me (I probably
thought it wouldn't work.) Thanks, it's a really nice construct.

This would be the (longer) way that I would write such a macro (just for
visual/mental clarity):

#macro FormatKeyword(Format)
#if (Format = "png")
png
#else
     #if(Format = "jpeg")
     jpeg
     #else
          #if(Format = "bmp")
          bmp
          #else
          #end
     #end
#end
#end // of macro

#declare Format = "png";
box{0,1
pigment{
image_map{FormatKeyword(Format) "crater demo as PNG.png" interpolate 2}

.... which works very nicely.

A couple of questions/observations, though: The docs say two things at
"3.3.2.6.1 The if...else...end Directives" (in v3.7.1 beta 9's help file--
although I haven't yet checked the online wiki):

"...an optional #elseif clause is now supported."

and

"NOTE: Nesting directives in the following manner has been known to cause
problems during the parse phase.
#if( #if(yes) yes #end ) #end
"

The even shorter keyword  #elif  (for #elseif) is not mentioned there (even
though it works); and, its keyword 'color' in scsne code looks like a
'non'-keyword. Should both of those little errors be fixed?

More importantly, I've never had a problem using nested #if's (when including
all of the #else keywords, anyway.) I *think* my macro is a good demonstration
of what the docs mean by nested #ifs as explained there(?) So are the new
keywords #elseif and #elif designed to eliminate any *possible* nested-#ifs
problems (along with being 'shorthand' versions of such constructs)? Just
curious.


Post a reply to this message

From: Kenneth
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 15:50:00
Message: <web.5ba3f86fb6c56d12a47873e10@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

>
> More importantly, I've never had a problem using nested #if's (when including
> all of the #else keywords, anyway.) I *think* my macro is a good demonstration
> of what the docs mean by nested #ifs as explained there(?)

Hmm, I see now that my macro's nested #if's and the docs' example are different
animals.

The docs'
#if( #if(yes) yes #end ) #end

clause is trying to construct a boolean "yes" within its inner #if (for use
within the outer #if?), which is rather odd-- and different from my macro's
straightforward use of nested #if's.


Post a reply to this message

From: clipka
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 15:58:03
Message: <5ba3fbcb@news.povray.org>
Am 20.09.2018 um 20:56 schrieb Kenneth:

>>     #macro FormatKeyword(Format)
>>       #if (Format = "png")
>>         png
>>       #elif (Format = "jpeg")
>>         jpeg
>>       ....
>>       #end
>>     #end
...

> A couple of questions/observations, though: The docs say two things at
> "3.3.2.6.1 The if...else...end Directives" (in v3.7.1 beta 9's help file--
> although I haven't yet checked the online wiki):
> 
> "...an optional #elseif clause is now supported."

Whoops, my bad: It's `#elseif`. The construct isn't too uncommon in
programming languages, but the languages can't agree on whether it
should be `elseif`, `elsif` or `elif` (or a variation thereof as the
programming language's meta-structure permits, such as POV-Ray's `#elseif`).

Examples of Elseif-Languages:

- Ada
- POV-Ray SDL
- Visual Basic

Examples of Elsif-Languages:

- Perl
- Ruby

Examples of Elif-Languages:

- C/C++ Preprocessor
- Python
- Unix shell scripts


> The even shorter keyword  #elif  (for #elseif) is not mentioned there (even
> though it works); and, its keyword 'color' in scsne code looks like a
> 'non'-keyword. Should both of those little errors be fixed?

Actually, no, it doesn't work: That's a mirage. If you examine it more
carefully, you'll find that the construct only behaves as expected if
both the `#if` condition and `#elif` conditionoid happen to be false;
because in that case the bogus `#elif` statement will simply be skipped.
If the `#if` condition happens to be true, the parser will parse the
`#if` branch and then crash right into the `#elif` like a brick wall,
and if the `#elif` conditionoid happens to be true, the parser will
still skip over it and enter the `#else` branch.


> More importantly, I've never had a problem using nested #if's (when including
> all of the #else keywords, anyway.) I *think* my macro is a good demonstration
> of what the docs mean by nested #ifs as explained there(?) So are the new
> keywords #elseif and #elif designed to eliminate any *possible* nested-#ifs
> problems (along with being 'shorthand' versions of such constructs)? Just
> curious.

Properly nested `#if` statements are not a problem. The problem
described in the docs specifically relates to nesting an `#if` in the
/condition/ of an enclosing `#if`.


Post a reply to this message

From: Kenneth
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 16:45:01
Message: <web.5ba40654b6c56d12a47873e10@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> Am 20.09.2018 um 20:56 schrieb Kenneth:

>
> > The even shorter keyword  #elif  (for #elseif) is not mentioned there (even
> > though it works)...
>
> Actually, no, it doesn't work: That's a mirage. If you examine it more
> carefully, you'll find that the construct only behaves as expected if...

Oh, sorry. I didn't thoroughly test the  #elif  keyword; I used your macro
construct as-is (basically), and it just *happened* to work in my case, or
appeared to.

Caveats noted!!


Post a reply to this message

From: clipka
Subject: Re: passing variable to macro for use in #for statement
Date: 20 Sep 2018 17:25:36
Message: <5ba41050$1@news.povray.org>
Am 20.09.2018 um 22:43 schrieb Kenneth:
> clipka <ano### [at] anonymousorg> wrote:
>> Am 20.09.2018 um 20:56 schrieb Kenneth:
> 
>>
>>> The even shorter keyword  #elif  (for #elseif) is not mentioned there (even
>>> though it works)...
>>
>> Actually, no, it doesn't work: That's a mirage. If you examine it more
>> carefully, you'll find that the construct only behaves as expected if...
> 
> Oh, sorry. I didn't thoroughly test the  #elif  keyword; I used your macro
> construct as-is (basically), and it just *happened* to work in my case, or
> appeared to.

Yeah, been there, done that. When you mentioned that both `#elseif` and
`#elif` seemed to work, I was like "huh? I'm not sure which of the two I
implemented, but I'm pretty darn sure I didn't implement both" - did a
short test myself, and lo and behold - `#elif` didn't produce an error.

So yeah, `#elif` must be what I had implemented, and I must have screwed
up the docs, accidently communicating it as `#elseif`...

Just for funsies and because I always love to double-check even if I
/know/ the results [hah!], let's just replace `#elif` with `#elseif` to
prove my point...

... huh? That didn't produce an error either; did I /really/ implement
both alternatives? Wow, clever me...

... um, wait, WTF?! Didn't that scene behave differently with `#elif`?!

Now I'm officially puzz...
... D'OH! - yeah, THAT is what's happening...


I love the smell of truth dawning on me.


Post a reply to this message

From: dick balaska
Subject: Re: passing variable to macro for use in #for statement
Date: 21 Sep 2018 00:51:03
Message: <5ba478b7$1@news.povray.org>
On 09/20/2018 02:56 PM, Kenneth wrote:

>
> This would be the (longer) way that I would write such a macro (just for
> visual/mental clarity):
>
> #macro FormatKeyword(Format)
> #if (Format = "png")
> png
> #else
>      #if(Format = "jpeg")
>      jpeg
>      #else
>           #if(Format = "bmp")
>           bmp
>           #else
>           #end
>      #end
> #end
> #end // of macro
>


I would write:

#macro FormatKeyword(Format)
    #if (Format = "png") png #end
    #if (Format = "jpeg") jpeg #end
    #if (Format = "bmp") bmp #end
#end

-- 
dik
Rendered 1024 of 921600 pixels (0%)


Post a reply to this message

Goto Latest 10 Messages Next 2 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.