I have a macro (!DashStr) that takes an input string and returns a string the same length except all dashes. (The motivation for this is to produce simple text tables in Markdown with pandoc.) I want to call this macro multiple times within another macro. I don't know how to access the local value (here named !D) returned from the !DashStr macro in the outer !MarkTable macro that calls it. Below is a simplified example.
*************************************************. DEFINE !DashStr ( !POSITIONAL = !CMDEND ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !DashStr !1. PRINT /!QUOTE(!D) /!1. !ENDDEFINE. DATA LIST FREE /X. 1 END DATA. PRESERVE. SET MPRINT ON. !MarkTable X. RESTORE. *************************************************. You can see that the resulting command is [PRINT /'!D' /X] and I want it to be [PRINT /'-' /X]. So how do I access !D in the !MarkTable macro? Or in other words, how do I return a macro variable to be used outside of that local macro environment. |
Administrator
|
Andy,
Macro doohickies/'variables' are completely LOCAL. However the following approach can yield favorable outcomes in some situations. ;-) Note changes in BOLD. DEFINE !DashStr ( !POSITIONAL = !TOKENS(1) ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !CONCAT(!QUOTE(!D)) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) . PRINT /!DashStr !1 /!1. !ENDDEFINE. DATA LIST FREE /X. BEGIN DATA 1 END DATA. PRESERVE. SET MPRINT ON. !MarkTable X. EXECUTE. RESTORE. <Output> - 1.00
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me. --- "Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis." Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?" |
Thank you, I will be able to work with that to get where I want. What I had originally wanted was to use it on the right hand side of a !LET statement. It doesn't seem to behave the same way in both instances.
****************************************************. DEFINE !DashStr ( !POSITIONAL = !ENCLOSE("(",")") ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !QUOTE(!D) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) ECHO !DashStr(!1). !LET !A = !DashStr(!1) ECHO !A !ENDDEFINE. !MarkTable 333. ****************************************************. I thought instead of using [!LET !A = !DashStr(!1)] if you used [!LET !A = !EVAL(!DashStr) (!1)] that would do the trick, but this causes SPSS to forever expect a command that isn't supplied (it says "Running EVAL parameter 1 COMMAN..." in the footer of all the windows). Also was there a special reason for the !CONCAT in your original proposal? (It doesn't seem to be needed as far as I can tell.) |
Administrator
|
Andy, I got an error message when I ran your code. To make it run without any errors, I had to remove the period from the first ECHO line in your !MarkTable macro.
HTH.
--
Bruce Weaver bweaver@lakeheadu.ca http://sites.google.com/a/lakeheadu.ca/bweaver/ "When all else fails, RTFM." PLEASE NOTE THE FOLLOWING: 1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above. 2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/). |
Sorry if I wasn't clear - the error message is to be expected (although I'm not sure if I can replicate the behavior you describe). Here is perhaps a more clear example. Basically I was just showing that
And here is what my output (V15) says:
If you
Maybe a more general question, but I can't find a single example (besides the trivial one in the Help) of using |
Administrator
|
Ah, okay. My mistake. Sorry about that. I'll defer to David on this one! ;-)
--
Bruce Weaver bweaver@lakeheadu.ca http://sites.google.com/a/lakeheadu.ca/bweaver/ "When all else fails, RTFM." PLEASE NOTE THE FOLLOWING: 1. My Hotmail account is not monitored regularly. To send me an e-mail, please use the address shown above. 2. The SPSSX Discussion forum on Nabble is no longer linked to the SPSSX-L listserv administered by UGA (https://listserv.uga.edu/). |
Administrator
|
In reply to this post by Andy W
Can't spend time now trying to dig that one out...
On Eval: Basically it forces macros to be expanded. -- Consider: DEFINE !Const () X !ENDDEFINE . DEFINE Evaltest () . ECHO "1". ECHO !QUOTE(!Const). ECHO "2". ECHO !QUOTE(!EVAL(!Const)). ECHO "3" . !ENDDEFINE. SET MPRINT OFF. EvalTest . --Output-- 1 !Const 2 X 3
Please reply to the list and not to my personal email.
Those desiring my consulting or training services please feel free to email me. --- "Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis." Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?" |
In reply to this post by Andy W
So it may be a good idea to always use !eval (along with all the !quote, !concat, !blanks and what not calls), just in case the caller passes a macro as one of the arguments (?). Without !eval, the first macro call would fail (or at least not give the desired outcome).
define !x () "x" !enddefine. define !y (!pos !cmdend). echo !quote(!eval(!1)). !enddefine. !y !x. !y 'x'. Regards, Albert-Jan ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -------------------------------------------- On Thu, 1/16/14, David Marso <[hidden email]> wrote: Subject: Re: [SPSSX-L] Accessing a local macro value in an outside macro To: [hidden email] Date: Thursday, January 16, 2014, 12:41 AM Can't spend time now trying to dig that one out... On Eval: Basically it forces macros to be expanded. -- Consider: DEFINE !Const () X !ENDDEFINE . DEFINE Evaltest () . ECHO "1". ECHO !QUOTE(!Const). ECHO "2". ECHO !QUOTE(!EVAL(!Const)). ECHO "3" . !ENDDEFINE. SET MPRINT OFF. EvalTest . --Output-- 1 !Const 2 X 3 Andy W wrote > <p> > Sorry if I wasn't clear - the error message is to be expected (although > I'm not sure if I can replicate the behavior you describe). Here is > perhaps a more clear example. Basically I was just showing that > <code> > !DashStr(!1) > </code> > is fine when passed to the first echo command, but for some reason is not > valid when passed on the right hand side of > <code> > !LET > </code> > . > </p> > <p> > <pre> > <code> > ****************************************************. > DEFINE !DashStr ( !POSITIONAL = !ENCLOSE("(",")") ) > !LET !D = !NULL > !DO !j = 1 !TO !LENGTH(!1) > !LET !D = !CONCAT(!D,"-") > !DOEND > !QUOTE(!D) > !ENDDEFINE. > > DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) > ECHO !DashStr(!1). > ECHO "Both Above and Below me should be dashes". > !LET !A = !DashStr(!1) > ECHO !A. > !ENDDEFINE. > > ECHO !MarkTable 333. > ****************************************************. > </code> > </pre> > </p> > > <p> > And here is what my output (V15) says: > </p> > > <p> > <pre> > <code> > ECHO !MarkTable 333. > >>Warning # 48 in column 256. Text: (End of Command) >>The ECHO command requires a single parameter - a quoted string. > > --- > Both Above and Below me should be dashes > >>Error # 1. Command name: ( >>The first word in the line is not recognized as an SPSS command. >>This command not executed. > </code> > </pre> > </p> > > <p> > If you > <code> > SET MPRINT ON > </code> > you can see that the > <code> > !1 > </code> > parameter from > <code> > !MarkTable > </code> > is submitted within the parenthesis, but not expanded. I've tried various > code with and without a command terminator after the > <code> > !LET > </code> > . This does make it expand to the next line, but still not work as > expected. > </p> > > <p> > <pre> > <code> > SET MPRINT ON. > ECHO !MarkTable 333. > 489 M> ECHO > 490 M> . > >>Warning # 48 in column 256. Text: (End of Command) >>The ECHO command requires a single parameter - a quoted string. > > 491 M> ECHO '---' > 492 M> . > --- > 493 M> ECHO 'Both Above and Below me should be dashes'. > Both Above and Below me should be dashes > 494 M> ( 333 ) ECHO '' > >>Error # 1. Command name: ( >>The first word in the line is not recognized as an SPSS command. >>This command not executed. > > 495 M> . > </code> > </pre> > </p> > > <p> > Maybe a more general question, but I can't find a single example (besides > the trivial one in the Help) of using > <code> > !EVAL > </code> > , so I'm not exactly sure how you are supposed to use it anyway. > </p> ----- Please reply to the list and not to my personal email. Those desiring my consulting or training services please feel free to email me. --- "Nolite dare sanctum canibus neque mittatis margaritas vestras ante porcos ne forte conculcent eas pedibus suis." Cum es damnatorum possederunt porcos iens ut salire off sanguinum cliff in abyssum?" -- View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Accessing-a-local-macro-value-in-an-outside-macro-tp5723922p5723931.html Sent from the SPSSX Discussion mailing list archive at Nabble.com. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
Can someone give an example of using !EVAL when the expanded macro actually takes an argument? All examples I have been able to dig up are the macros which take no arguments (which I understand are useful for those hacky write an outfile meta programming thing - but doesn't translate to this situation).
*********************************************. DEFINE !DashStr ( !POSITIONAL = !ENCLOSE("(",")") ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !QUOTE(!D) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr(!1)) . ECHO !QUOTE(!A). !ENDDEFINE. *This macro fails to compile - error message. *>In a macro expression, a left parenthesis immediately follows an operand. *>This command not executed. *********************************************. Here are a few more versions which compile as valid macro's, but when running produce a message "Running EVAL parameter 1 COMMAN..." in the footer and just hang. After these I have to kill the SPSS process to even exit - so beware! So !EVAL doesn't appear be amenable to expanding a macro that takes arguments. *********************************************. DEFINE !DashStr ( !POSITIONAL = !TOKENS(1) ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !QUOTE(!D) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr) !1. ECHO !A. !ENDDEFINE. *This compiles, but when it runs it hangs forever expecting a command. *MarkTable 333. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr) !EVAL(!1) . ECHO !A. !ENDDEFINE. *Ditto with prior. *MarkTable 333. *********************************************. |
* fails.
define !x (!pos !enclose("(", ")")). !quote(!concat("tadaah: ", !1)) !enddefine. define !y (!pos !enclose("(", ")")). echo !quote(!eval(!1)). !enddefine. set mprint = on. !y(!x(I hate macros)). * works. set mprint = off. begin program. import spss def x(v): return "tadaah: " + v def y(v): spss.Submit("echo '%s'." % v) y(x("I love Python")) end program. Regards, Albert-Jan ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -------------------------------------------- On Thu, 1/16/14, Andy W <[hidden email]> wrote: Subject: Re: [SPSSX-L] Accessing a local macro value in an outside macro To: [hidden email] Date: Thursday, January 16, 2014, 2:40 PM Can someone give an example of using !EVAL when the expanded macro actually takes an argument? All examples I have been able to dig up are the macros which take no arguments (which I understand are useful for those hacky write an outfile meta programming thing - but doesn't translate to this situation). *********************************************. DEFINE !DashStr ( !POSITIONAL = !ENCLOSE("(",")") ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !QUOTE(!D) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr(!1)) . ECHO !QUOTE(!A). !ENDDEFINE. *This macro fails to compile - error message. *>In a macro expression, a left parenthesis immediately follows an operand. *>This command not executed. *********************************************. Here are a few more versions which compile as valid macro's, but when running produce a message "Running EVAL parameter 1 COMMAN..." in the footer and just hang. After these I have to kill the SPSS process to even exit - so beware! So !EVAL doesn't appear be amenable to expanding a macro that takes arguments. *********************************************. DEFINE !DashStr ( !POSITIONAL = !TOKENS(1) ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !QUOTE(!D) !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr) !1. ECHO !A. !ENDDEFINE. *This compiles, but when it runs it hangs forever expecting a command. *MarkTable 333. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) !LET !A = !EVAL(!DashStr) !EVAL(!1) . ECHO !A. !ENDDEFINE. *Ditto with prior. *MarkTable 333. *********************************************. ----- Andy W [hidden email] http://andrewpwheeler.wordpress.com/ -- View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Accessing-a-local-macro-value-in-an-outside-macro-tp5723922p5723933.html Sent from the SPSSX Discussion mailing list archive at Nabble.com. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
In reply to this post by Andy W
At 08:40 AM 1/16/2014, Andy W wrote:
>Can someone give an example of using !EVAL when the expanded macro >actually takes an argument? I've written a little utility called !MacEcho, use to test and display macro expansions: * Macro /* !MacEcho */ is used to display the macro expansion . DEFINE !MacEcho(!POS !NOEXPAND !CMDEND) ECHO !QUOTE(!CONCAT(' Call : ',!1)). ECHO !QUOTE(!CONCAT(' Result: ',!EVAL(!1))). !ENDDEFINE. Here's an illustration, from some time past(*), where I used it to pass a macro with an argument: * This is the test macro .......................................... . DEFINE !Mystery(Help=!DEFAULT(No) !TOKENS(1)) !IF (!UPCASE(!HELP) !NE Y) !THEN ECHO 'Sorry, it is a mystery. There is no help for you'. !IFEND !IF (!UPCASE(!HELP) !EQ Y) !THEN ECHO 'Yes! You can be helped! Mystery is solved!'. !IFEND *. !ENDDEFINE. !MacEcho !Mystery . Call : !Mystery Result: ECHO 'Sorry, it is a mystery. There is no help for you' * !MacEcho !MYSTERY Help=Y . Call : !MYSTERY Help=Y Result: ECHO 'Yes! You can be helped! Mystery is solved!'* --------------------------------------------------------------- (*) This is taken from posting Date: Sun, 25 Jun 2006 20:49:50 -0400 From: Richard Ristow <[hidden email]> Subject: Re: Macro expansion / Ultimate string parsing problem To: [hidden email] X-ELNK-Info: spv=0; X-ELNK-AV: 0 X-ELNK-Info: sbv=0; sbrc=.0; sbf=0b; sbw=000; ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
Albert,
You can feel free to assume I already know that you can replicate whatever functionality I am trying to accomplish in the MACRO facility in Python. The day has not yet come that I decide to write some simple code in Python over plain vanilla SPSS. I've already written the program I was interested in, at this point I'm just trying to learn about the macro facility and its limitations for future reference. Richard, Interesting, but I can't figure out how to apply it to my situation. This is just a very simple case of functional programming. Consider a macro called !F that takes one token within parentheses. Why is this valid: !F(!Input) And this is valid: ECHO !F(!Input). But this is not: !LET !Output = !F(!Input) The answer I've been getting is that when !F follows another macro "operand" like !LET, I need to use !EVAL to expand it. However, !EVAL only appears to expand a macro that takes no arguments (or has default arguments as you've shown). If I want to pass in an !Input and get an !Output I don't see how the example you've shown would allow me to accomplish that. The first example !F(!Input) Doesn't work, because whatever stuff it produces is only local. I can't hack !F to return stuff to the global environment nor will it allow you to change objects outside of its scope. Hence why I would like to assign what the function returns to an object. If you could do this it would allow you to basically make your own string manipulation functions in the macro facility, e.g. you could implement a more general !REPLACE function for string tokens. Using some of the string manipulations Richard just shown as motivation, I came up with this. **********************************************. DEFINE !DashStr ( !POSITIONAL = !TOKENS(1) ) !LET !D = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !D = !CONCAT(!D,"-") !DOEND !D !ENDDEFINE. DEFINE !MarkTable ( !POSITIONAL = !CMDEND ) ECHO !QUOTE(!1). !LET !A = !EVAL(!UNQUOTE("!DashStr !1")) ECHO !QUOTE(!A). !ENDDEFINE. !MarkTable 3334. **********************************************. You will see with this though that !DashStr is expanded and correctly takes the next string as its argument, but !1 is unfortunately not expanded! That is, the result of when !DashStr !1 is called ends up being "--" because it pretends like !1 is a text input for the !DashStr macro instead of expanding !1 to be "3334". So close, but no cigar so far. I tried several other ways to make !1 expand as well (by nesting seperate !EVAL statements for !DashStr & !1 and trying to concatenate the two together) but was unable to get any to work. Andy |
In reply to this post by Andy W
Andy,
In my experience, !EVAL() function scans its argument, and if the argument contains some macro call of another macro, the function runs (expands) it immediately. !EVAL is needed when the macro call is "hidden" in a string function or in a macro expression as its operand. Example1. !quote(!EVAL(!macrocall)) !EVAL is needed if you want !macrocall to expand inside !quote. Example2. !EVAL('!macrocall BlahBlah') !EVAL is needed if you want !macrocall to expand inside quotes. Example3. !do !i !in (!EVAL(!macrocall)) !EVAL is needed if you want !macrocall to expand inside the expression. Also, !EVAL is practically very useful to drop a trailing point and/or to cut out excessive spaces from a string. In this case, !EVAL can be used not only with macrocalls but with any strings. Example4. !EVAL("A B C.") returns string: A B C Thus, !EVAL("A B C")=!EVAL("A B C")=!EVAL("A B C.") etc. which is handy. |
In reply to this post by Andy W
At 02:17 PM 1/16/2014, Andy W wrote:
>Consider a macro called >!F that takes one token within parentheses. Why is this valid: > >!F(!Input) > >And this is valid: > >ECHO !F(!Input). > >But this is not: > >!LET !Output = !F(!Input) > >!EVAL only appears to expand a macro that takes no arguments (or has >default arguments as you've shown). OK. To answer your last question first, !EVAL can indeed expand a parametrized macro; see the *second* call in my last posting, where it (correctly) expands the call "!MYSTERY Help=Y". (I posted that for a reason!) Second, you aren't asking about passing a macro with a parameter; you're asking about *returning* a value *from* a macro. I didn't answer this question at first, because you didn't ask it. You're asking a macro to return a value, into the macro text. Macros don't *return* values; they *generate* values, which go into the (SPSS) code space. Normally, a macro doesn't 'see' what any macro is calls generates; that has nothing to do with whether or not the called macro takes parameters. >I would like to assign what the function returns to an object. If >you could do this it would allow you to basically make your own >string manipulation functions in the macro facility, e.g. you could >implement a more general !REPLACE function for string tokens. Tell me about it. Tell any of us about it. Yes, it is (would be) very useful. I'd taken for granted that this was impossible; that there was no way to make a macro's generated text available to a calling macro. I haven't time for a proper investigation now, but check David Marso's postings. I thought that he'd found a way for a macro to generate a value that gets assigned to a variable belonging to a calling macro, though if so, I can't find it at the moment. All I can say is, (a) yes, it would be very useful; (b) it is *not* something the macro facility is designed to offer; and (c) I'd expect David to find a way, if anybody can. But, again, it has nothing to do with how !EVAL works; it has to do with how macro results are (not) passed back to the caller. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
This is starting to remind me of dialogue in Alice in Wonderland. While I can accept the fate that what I want to do is impossible, I'm having a hard time understanding why the compiler is fine and dandy to accept
!F(!Input) But !LET !Output = !F(!Input) is impossible. Where does !LET go if not "code space" - outer space? Rural Idaho? The moon? I type !LET in the syntax window the same as I do any other command. |
Andy,
Try this, to force macro at the right hand side of !LET. define !F(!pos= !enclose('(',')')) !conc('Andy ',!1) !enddefine. !F(Weeler). *The F macro works. define !MAIN() !let !output= !F(Weeler) echo !quote(!output). !enddefine. !MAIN. *The F macro doesn't work correctly inside another macro when put in right hand side of macro expression. define !MAIN() !let !output= !eval('!F(Weeler)') echo !quote(!output). !enddefine. !MAIN. *But with the help of !EVAL and being put in apostrophes, it works allright. 17.01.2014 0:44, Andy W пишет:
This is starting to remind me of dialogue in Alice in Wonderland. While I can accept the fate that what I want to do is impossible, I'm having a hard time understanding why the compiler is fine and dandy to accept !F(!Input) But !LET !Output = !F(!Input) is impossible. Where does !LET go if not "code space" - outer space? Rural Idaho? The moon? I type !LET in the syntax window the same as I do any other command. ----- Andy W [hidden email] http://andrewpwheeler.wordpress.com/ -- View this message in context: http://spssx-discussion.1045642.n5.nabble.com/Accessing-a-local-macro-value-in-an-outside-macro-tp5723922p5723952.html Sent from the SPSSX Discussion mailing list archive at Nabble.com. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
In reply to this post by Andy W
At 03:44 PM 1/16/2014, Andy W wrote:
>I'm having a hard time understanding why the compiler is fine and >dandy to accept > >!F(!Input) > >But > >!LET !Output = !F(!Input) > >is impossible. Where does !LET go if not "code space" - outer >space? I type !LET in the syntax window the same as I do any other command. The SPSS code space I was talking about is the stream of code that the SPSS processor executes. It's what you get by expanding all the macros in the original file. Macros write to this code space -- that's what they're for. When you run !F(!Input) then whatever the macro emits is written to the code space. It is *not* a value that's accessible in the macro space, i.e. to the same or another macro. If I write a really simple macro like DEFINE !Freq1() FREQUENCIES A. !ENDDEFINE. then "FREQUENCIES A." is the *output* of the macro, and goes to the SPSS code space; it is not a *value* that can be returned to a calling macro. And when you write !LET !Output = !F(!Input) you're expecting whatever !F produces to be text accessible to the macro, so it can be assigned to a macro variable; but !F's output has gone to the SPSS code space, or code stream, and the calling macro has no access to it. When you write ECHO !F(!Input). then ECHO is a native SPSS statement, not a macro statement; it's in the SPSS code space, and it can 'see' the output of !F. !LET is in the macro code space, and can't see anything any macro produces, except macro variables defined in the same macro. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
Richard Ristow wrote:
And when you write !LET !Output = !F(!Input) you're expecting whatever !F produces to be text accessible to the macro, so it can be assigned to a macro variable; but !F's output has gone to the SPSS code space, or code stream, and the calling macro has no access to it. +1, Richard. But it is possible to make the text !F() produces a value accessible to the parent macro via !EVAL + quoting, - as I've shown above. !LET !Output = !EVAL('!F(!Input)') |
In reply to this post by Andy W
Andy,
Try also this.
define !F(!pos= !enclose('(',')')) !conc('Andy ',!1) !enddefine. define !MAIN(!pos= !token(1)) !let !output= !eval(!conc('!F(',!1,')')) echo !quote(!output). !enddefine. !MAIN Wheeler. *Here, the argument "Wheeler" for the child macro is supplied by the parent macro. |
There we go! Thank you Kirill! (And everyone else for travelling down the rabbit hole with me).
!let !output= !eval('!F(!1)') It treats "!1" like it is text and not a macro variable/pointer. But when you do !let !output= !eval(!conc('!F(',!1,')')) It points to !1 AND expands !F. Here is an example that does the markdown tables but instead of having a macro replace the string with dashes it takes a second argument (and so you can replace it with any string you want). It should be obvious how you could use this to make your own REPLACE function in the macro parser if you wanted to. *******************************************. DEFINE !MarkTable ( !POSITIONAL = !CMDEND) !LET !Stub = !HEAD(!1) !LET !Header = !Stub !LET !Align = !EVAL(!CONCAT("!REP ",!Stub," -")) !DO !i !IN (!TAIL(!1)) !LET !Stub = !CONCAT(!Stub," ",!QUOTE("|"),!i) !LET !Header = !CONCAT(!Header,"|",!i) !LET !Temp = !EVAL(!CONCAT("!REP ",!i," -")) !LET !Align = !CONCAT(!Align,"|",!Temp) !DOEND DO IF $casenum = 1. PRINT EJECT /!QUOTE(!Header) /!QUOTE(!Align). END IF. PRINT / !Stub. !ENDDEFINE. DEFINE !REP ( !POSITIONAL = !TOKENS(1) /!POSITIONAL = !TOKENS(1) ) !LET !A = !NULL !DO !j = 1 !TO !LENGTH(!1) !LET !A = !CONCAT(!A,!2) !DOEND !A !ENDDEFINE. *Example Use. DATASET CLOSE ALL. DATA LIST FREE / Xa Ya (2F1.0) Za (A1). BEGIN DATA 1 2 a 3 4 b 5 6 c 7 8 d END DATA. *SET MPRINT ON. !MarkTable Xa Ya Za. *SET MPRINT OFF. EXECUTE. ********************************************. Which then produces the output Xa|Ya|Za --|--|-- 1 |2 |a 3 |4 |b 5 |6 |c 7 |8 |d |
Free forum by Nabble | Edit this page |