Date: Fri, 26 May 2006 17:21:58 +0000
Reply-To: toby dunn <tobydunn@HOTMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: toby dunn <tobydunn@HOTMAIL.COM>
Subject: Re: enterprise guide peculiarities - %str()
In-Reply-To: <052620061644.18051.4477305F0008F2D700004683220073483005029A06CE9907@comcast.net>
Content-Type: text/plain; format=flowed
Ian ,
Okay I can live with the explaination so far. We havent had a spirited
round of posts in quit some time. Kind of refreshing even if you do end up
kick me all over the SAS-L school yard. But then I wouldnt expect my 7
years of programming experience to hold up to your 20 or 30 years. So I get
to learn something and I hope others do too.
I will make one comment here you stated:
NO! That is the mistake. You told the macro facility to hide the
meaning of the slash as divide in arithmetic expressions. You
did not tell it to change the symbol and you can find nothing in
the documentation that would even hint that is what you did.
Well actually the online docs do talk about this under the section "How
Macro Quoting Works".
/*Snippet*/
When the macro processor masks a text string, it masks special characters
and mnemonics within the coding scheme, and prefixes and suffixes the string
with a hexadecimal character, called a delta character. The prefix character
marks the beginning of the string and also indicates what type of macro
quoting is to be applied to the string. The suffix character marks the end
of the string. The prefix and suffix characters preserve any leading and
trailing blanks contained by the string. The hexadecimal characters used to
mask special characters and mnemonics and those used for the prefix and
suffix characters may vary and are not portable.
There are more hexadecimal combinations possible in each byte than are
needed to represent the symbols on a keyboard. Therefore, when a macro
quoting function recognizes an item to be masked, the macro processor uses a
previously unused hexadecimal combination for the prefix and suffix
characters.
Macro functions, such as %EVAL and %SUBSTR, ignore the prefix and suffix
characters. Therefore, the prefix and suffix characters do not affect
comparisons.
When the macro processor is finished with a macro quoted text string, it
removes the macro quoting-coded substitute characters and replaces them with
the original characters. The unmasked characters are passed on to the rest
of the system.
/*Snippet End*/
As a secondary thind to note a lady from SI (I dont have the paper in front
of me wrote about macro quoting) which covers the physical act of quoting.
So did I tell it to change the character? One could say that it is implict
when I choose to use the quoting function. But to say that is to say that I
know how SAS is physically masking the meaning of the characters when
quoting is used and ignoring what the intent of masking. Now whether or not
you agree with that statement is another story.
Toby Dunn
From: iw1junk@comcast.net
To: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
CC: toby dunn <tobydunn@HOTMAIL.COM>
Subject: Re: enterprise guide peculiarities - %str()
Date: Fri, 26 May 2006 16:44:16 +0000
Toby,
I will embed comments your message below.
Ian Whitlock
Date: Fri, 26 May 2006 04:01:20 +0000
Reply-To: toby dunn <tobydunn@HOTMAIL.COM>
Sender: "SAS(r) Discussion"
From: toby dunn <tobydunn@HOTMAIL.COM>
Subject: Re: enterprise guide peculiarities - %str()
Comments: To: iw1junk@COMCAST.NET
In-Reply-To:
<052620060122.20439.4476584F000C067000004FD7220730003305029A06CE9
907@comcast.net>
Content-Type: text/plain; format=flowed
Ian ,
I think you read a little more into some of what I wrote than I
intended. Guess that is what i get for not writing a book as I
normally do.
The first problem you noted was truelly an error on my part for
thinking one thing and writing another, then not double checking
what I wrote close enough. I actually forced the error you
mentioned before I wrote the post, just as a sanity check for
myself.
The use of %bquote was just something I threw in for giggles.
*****Ian
I consider the use of %BQUOTE in open code to act like a
compile time quoting function a serious offense because when
adopted by someone not fully understanding the consequences they
can get mysterious macro compile time errors. Now you say that
you do it for giggles! Did you get a degree in psychology by any
chance?
*****
I could have just as easily put %str(), but then again you
already know that.
*****Ian
The point not that you could have easily used %STR(), but that it
should have been very hard for you to use %BQUOTE() in this
example.
*****
Nice explaination of the %eval and the use of quotes. However, I
think my true quable here is getting lost.
You once said (forgive me if I mangle this) that in the data step
language words have meaning and as such we as programmers have to
distinguish between what we want SAS to interprete as having
meaning and what we dont. So we put quotes around those words
that we dont want SAS to interprete as haveing meaning. The
macro language is somewhat different, in that everything is text
and we as SAS programmers give meaning to words by prefixing them
with &'s and %'s.
*****Ian
Except for typos and perhaps understanding, it looks reasonably
close to something I have said. The intent was to consider two
distinct languages, SAS and macro. In SAS the data is usually
external to the language, hence quoting is only needed for the
odd bits of character data that may appear inside SAS code. The
system is common to many languages that make the same assumption
that data is generally external to the code. In contrast, macro
is a language in which the data (SAS code) is integrally part of
the macro program. Hence it is the programming instructions that
are distinguished rather than the data. Percent signs and
ampersands are used to distinguish some macro instructions but
there are other forms of text that also have meaning. For
example, in
%do i = 1 %to &fini + 1 ;
the "+ 1" has meaning. On the other hand, in
%let x = &fini + 1 ;
the "+ 1" has no meaning. Consequently it is important to know
the context and the time (i.e. macro compile, macro execute, SAS
compile, SAS execute) in order to make precise statements of what
symbols have meaning to whom when.
*****
( there is more meaning in those statements than one at first
thinks and I still ponder those words today). However, this &
and % business raises a problem in that sometimes we want the &'s
and %'s to be interpreted by the macro facility as just text.
*****Ian
True and that means when we write an & we mean it to be the
symbol &. If the macro facility chooses to store that symbol
some other way, it still should treat that symbol as an &. That
is the point I was trying to make in the message below and that
is the point that you seem to have overlooked.
The fact that macro uses "010F02" to store the instruction
%NRSTR(&) gives you no right to expect that the symbol to be
manipulated is not an ampersand! In fact, if your wish were true
macro quoting would be completely useless. I note that nowhere
in the documentation will you find a statement of how %NRSTR(&)
is stored since it is not the programmer's business. Moreover,
I assume that SI feels free to change this internal method of
accomplishing this task at any time. Hence you would be very
unwise to try and make use of it in any macro code that you wish
to work with.
In short, you seem to have interpreted the words "just text" (I
suspect that I use "just data") in some absolute manner without
regard to the fact that I was talking about programming and that
as a programmer, when I write
%put %nrstr(&) ;
I expect to see an ampersand and not some dump from memory.
*****
Thus, arise the need for macro quoting.
Now if I quote some macro value I as the programmer have
specifically told SAS not to interpret those as having
significant meaning to the macro facility. In otherwords forget
any possible meaning for these characters other than as just
text. Programmatically this can be some what tricky to
implement, so SI decided when quoting is used it would change the
underlying value of the characters to be quoted to a non-
printable character.
So when we get to the %eval I was thinking it did a literal
character by character comparison of the underlying value in each
expression.
*****Ian
Yes, it does compare character by character, the "underlying
value" rather than the internal means of referencing that
"underlying value". Now take a moment to ponder on wisdom
of not choosing to insist that you know every intenal detail of
how your code is executed before allowing you to use SAS.
*****
But if it did that then the example of %put %eval( "/" = "&Y" ) ;
would evaluate to a false statement. Because the underlying
value of a '/' would be different than the value on the right
hand side of the equals sign which is a nonprintable character.
However, if it translated the nonprntable characters of 'Y' back
to a '/' (in some fashion) in this case then it would it would
evaluate to a true statement.
This in some way irks me as I explicitly told SAS to change the
value of '/' to a non printable character when I told it to quote
the string
*****Ian
NO! That is the mistake. You told the macro facility to hide the
meaning of the slash as divide in arithmetic expressions. You
did not tell it to change the symbol and you can find nothing in
the documentation that would even hint that is what you did.
Well, you are not the first "programmer" to not understand what
he did with some piece of code. Incidentally, the use of
'"programmer"' in the previous sentence is completely different
from and not to be confused with quoting the word "programmer",
which I didn't quote in the last part of this sentence.
*****
and I havent yet at the time of the %eval told it to unquote the
string and translate it back to the '/'.
*****
That is also wrong. To be precise, you haven't told it to give
the character back it's meaning in an arithmetic expression. But
you did by reference explicitly ask that it be compared with a
slash.
*****
But this would lead to printing problems if it followed this
philosophy making macro quoting more unwieldy, also it make for a
higher user error rate. So %eval is attempting to use the quoted
string in context, choosing to see the values as they would
translate too rather than as they really are nonprintable
characters.
*****Ian
I see nothing in what you have written to lead me to think that I
have misinterpreted what you meant. As an exercise, write a
simple macro that essentially uses macro quoting to accomplish
something useful. Then analyse how many times in that code you
should have been thankful that the language didn't work the way
you thought it should.
Here is a portion of a log to show that you can have what you
want in SAS, while the rest of us can be thankful that it doesn't
take less work.
80 %let x = %str(/) ;
81 data _null_ ;
82 set sashelp.vmacro ;
83 where name = "X" ;
84 if value ^= "/" then put "Toby is satisfied" ;
85 else put "Toby is irked" ;
86 test = symget ( "x" ) ;
87 if test = "/" then put "Programmers are satisfied" ;
88 else put "Programmers have a big problem" ;
89 put value= " %nrstr(&)x=&x " test= ;
90 run ;
Toby is satisfied
Programmers are satisfied
value= &x=/ test=/
*****
Toby Dunn
From: Ian Whitlock <iw1junk@COMCAST.NET>
Reply-To: iw1junk@COMCAST.NET
To: SAS-L
Subject: Re: enterprise guide peculiarities - %str()
Date: Fri, 26 May 2006 01:22:24 +0000
Subject: Re: enterprise guide peculiarities - %str()
Summary: Another subtlety of macro quoting is discussed
Respondent: Ian Whitlock
In part in answer to Paa K <sas.paa@GMAIL.COM> Toby Dunn
<tobydunn@HOTMAIL.COM> a lot of errouneous information by writing
in part
the following:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Now what I was refering to is that when you put the quoted value
inside of
double quotes it acts atleast like the quoting is removed.
17 %let Y = %str(/) ;
18
19 %put %eval( %bquote(/) = &Y ) ;
1
20 %put %eval( "/" = &Y ) ;
0
21 %put %eval( "/" = "&Y" ) ;
1
The first %eval evaluates to a true value which makes perfect
sense given I
have the same value quoted on either side of the equals sign.
But notice I
did not suround the &Y with double quote marks. If the %str()
macro
quoting were removed then %eval would return a false statement.
Now in the second %eval I get a false value. So even though the
first
slash is in double quote marks it isnt equal to the macro quoted
value of
&Y.
In the last %eval I enclosed both sides in Double quotes. When I
do that I
get a true value. Which using inductive reasining shouldnt
happen given
the first two examples. Unless the macro quoting is removed when
&Y is
enclosed in the double quotes.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
We consider each of the three basic claims to explain the results
produced
by lines 19-21.
In reference to line 19 Toby suggested that if the action of %STR
were
removed from the value of Y the result of the %EVAL would be
false. It is
wrong for two reasons. First consider:
9 %let Y = / ;
10
11 %put %eval( %bquote(/) = &Y ) ;
ERROR: A character operand was found in the %EVAL function or %IF
condition
where a numeric
operand is required. The condition was: / = /
We did not get false; we got a message saying that the request
could not be
handled. The problem is that when %EVAL sees an arithmetic
operator it
expects to do arithemtic and it couldn't.
The second reason is more philosophical, since it involves what
would
happen if %EVAL didn't work the way it does, but it still is very
important
to understanding the way macro works. The expression %BQUOTE(/)
and the
expression / are the same because quoting removes the meaning, it
does
not change the symbol. The point is confused becasue the method
of
implementation does actually change the stored value, but the
method
of implementation does not change the logical circumstance that a
symbol
macro quoted or not it is logically the same symbol. SAS/macro
treats it
that way, and it is not a bug for SAS/macro to treat it that way.
It is also worth remarking that had line 19 been in a macro the
%BQUOTE
functuion would not have hidden the /-mark at the time the %PUT
statement
was compiled. In this case it doesn't matter, but the habit of
using
%BQUOTE to hide typed symbols does matter because sometimes the
distinction
is important.
In reference to line 20, Toby hints that there is some difference
in
symbols between a macro quoted /-mark and a macro unquoted /-mark
that is
causing the evaluation to false. This is not true. One must
remember that
double quote marks are part of the expression as well as
indicators of
quoting. Thus the reason line 20 produces a 0 is becasue the set
of symbols
to the left of the equal sing begin wht a double quote and the
the set of
sybols to the right does not. It has nothing to do with the
nature of the
/-mark. Another way to put it, is that the expression on the left
is three
characters and the expression on the right is one character which
happens
to match one of the lefthand characters, but that does not make
the
expressions equal.
Now line 20 produces 1, i.e. true, becasue the expression on the
left has
three symbols (two double quotes and a /-mark) and the expression
on the
right also has the same three symbols. Here the confusion is
compounded by
the fact that meaning of the /-mark is hidden from %EVAL by two
different
techniques, but that is irrelevant to the conclusion that the
marks on the
left are the same as those on the right.
In other words, lines 19 and 20 both produce a 1 for the same
reason, a
/-mark is a /-mark whether its meaning is hidden or not.
Now to really confuse things, consider
"/" = '/'
In SAS code the logical expression is true because the quote
marks are not
part of the expressions (they are indicators of how to treat the
objects
contained between them) and the symbol inside is the same on both
sides of
the equaality. In macro the logical expression is false becasue
single
quotes and double quotes are different symbols. They hide, but
they are
also part of the expression.
I hope that somebody is interested and helped by this
explanation.
Ian
|