I am trying to build a macro with 2 arguments:
- one of them is being passed when calling the macro,
- the 2nd one is a transformation of the first.
Basically, I am trying to do a string transformation on the 1st argument, and use the result to run some syntax.
Define !MyMacro (arg1=!tokens (1), arg2=!DEFAULT(SomeValue) !tokens(1))
/*what I am trying to achieve is to
replace all "-" in arg1 with "_", but the syntax does not work with macro arguments:
compute !arg2 = replace(!arg1,"-","_").
/*I need arg 2 to be available further down the syntax, as a variable name:
fre !arg2.
!Enddefine.
Any suggestions on to work around this ?
"-" being a special character divides strings into separete tokens in the macro parser. For this reason you can not read a string that contains "-" as a macro argument using !TOKENS(1) (like you did in your example).
This can cause problems in other cases but here we can turn the bug into a feature: the following macro runs through the separate tokens in !ARG1 and replaces "-" with "_". If there is no "-", there will only be one token in !ARG1 and nothing will change.
Define !MyMacro (arg1=!cmdend)
!let !arg2=""
!do !i !in(!arg1)
!if (!i="-") !then !let !arg2=!concat(!arg2,"_") !else !let !arg2=!concat(!arg2,!i) !ifend
!doend.
title !quote( !arg2).
freq !arg2 .
!enddefine.
!MyMacro arg1=turn-into_.
The previous macro will only work with "-" and similar special characters, the following one can be used for any character (though I still set it up for "-"):
Define !MyMacro (arg1=!cmdend)
!let !arg2=""
!do !i = 1 !to !length(!arg1)
!if (!substr(!arg1,!i,1)="-") !then !let !arg2=!concat(!arg2,"_") !else !let !arg2=!concat(!arg2,!substr(!arg1,!i,1)) !ifend
!doend.
title !quote(!arg2).
freq !arg2 .
!enddefine.
!MyMacro arg1=turn-into_.
If you review the Macro Directives (DEFINE-!ENDDEFINE command) documentation, you'll find in the String Manipulation section that it is !SUBSTR that you require to make such replacements.
Given there is not a "REPLACE" string manipulation function within DEFINE/!ENDDEFINE you will have to use the combination of various other functions and so for which you may also find this link useful, to carry out arithmetic.
(I have stopped coding in SPSS MACRO language for this purpose, as it is very, very ugly and given the use of Python within SPSS, I now prefer to code in Python which this would be extremely trivial to do).
Related
I understand that both suppress evaluation of a symbol or expression. But the backtick is used for macro definitions while the apostrophe is used for symbols (among other things). What is the difference, semantically speaking, between these two notations?
Backticks allow for ,foo and ,#foo to interpolate dynamic parts into the quoted expression.
' straight up quotes everything literally.
If there are no comma parts in the expression, ` and ' can be used interchangeably.
A standard quote is a true constant literal and similar lists and list that end with the same structure can share values:
'(a b c d) ; ==> (a b c d)
A backquoted structure might not be a literal. It is evaluated as every unquote needs to be evaluated and inserted into place. This means that something like `(a ,#b ,c d) actually gets expanded to something similar to (cons 'a (append b (cons c '(d)))).
The standard is very flexible on how the implementations solves this so if you try to macroexpand the expression you get many different solutions and sometimes internal functions. The result though is well explained in the standard.
NB: Even though two separate evaluation produces different values the implementation is still free to share structure and thus in my example '(d) has the potential to be shared and if one would use mutating concatenation of the result might end up with an infinite structure.
A parallel to this is that in some algol languages you have two types of strings. One that interpolates variables and one that don't. Eg. in PHP
"Hello $var"; // ==> 'Hello Shoblade'
'Hello $var'; // ==> 'Hello $var'
I'm very very new in elisp and just started learning it. I have seen the following expressions in the document:
(1+ (buffer-size))
(+ 1 (buffer-size))
What do they mean? As I know elisp use prefix notation, so the second one should be correct one. But both of them can be executed without any errors. The first one is from the documentation of point-max function.
Thanks.
The token 1+ is an identifier which denotes a symbol. This symbol has a binding as a function, and so (1+ arg) means "call the 1+ function, with the value of arg as its argument). The 1+ function returns 1 plus the value of its argument.
The syntax (+ 1 arg) is a different way to achieve that effect. Here the function is named by the symbol +. The + function receives two arguments which it adds together.
In many mainstream programming languages popular today, the tokenization rules are such that there is no difference between 1+ and 1 +: both of these denote a numeric constant followed by a + token. Lisp tokenization is different. Languages in the Lisp family usually support tokens that can contain can contain digits and non-alpha-numeric characters. I'm looking at the Emacs Lisp reference manual and do not see a section about the logic which the read function uses to convert printed representations to objects. Typically, "Lispy" tokenizing behavior is something like this: token is scanned first without regard for what kind of token it is based on accumulating characters which are valid token constituents, stopping at a character which is not a token constituent. For instance when the input is abcde(f, the token that will be extracted is abcde. The ( character terminates the token (and stays in the input stream). Then, the resulting clump of characters abcde is re-examined and classified, converted to an object based on what it looks like, according to the rules of the given Lisp dialect. Across Lisp dialects, we can broadly depend on a token of all alphabetic characters to denote a symbol, and a token of all digits (possibly with a leading sign) to denote an integer. 1+ has a trailing + though, which is different!
When I read some elisp code, I found something like:
(\,(* 2 \#1))
\,(format "%s %s id%d %s" \1 \2 (+1 \#) \3)
#'(bla bla)
What does the symbol like "\,", "#", "#'" mean? Which session should I look into for those kind of things?
\, is special in replacements when using query-replace-regexp. It means "evaluate the following elisp expression, and use the resulting value in the replacement".
n.b. It's not special elsewhere (that I'm aware of), so that should be the usage you've seen.
\# is also special in the replacement string, and is substituted with the number of replacements made thus far. (i.e. an incrementing counter).
\#N (where N is a number) is a variant of \N which treats the group in question as a number rather than a string, which is useful when the expression you're evaluating requires a number.
So (\,(* 2 \#1)) would be a replacement which evaluates the expression (* 2 \#1), multiplying the number matched by the first group of the regexp by 2 to produce some value N, such that the final replacement is (N).
You can find these detailed in the manual.
C-hig (emacs) RET followed by a search for the syntax in question. e.g. C-s \, with a repeated C-s if the search fails (as it will) to find a match in the subsequent nodes.
#'... is short-hand for (function ...) which is a variant of '... / (quote...) which indicates that the quoted object is a function.
As this is elisp syntax, you find it in the elisp manual:
C-hig (elisp) RET
You can either use C-s #' or in this case it's indexed, so I #' RET also works.
(In general check the index first, and then use isearch.)
For info on backquotes, see http://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html.
# starts the reader syntax, for instance #' is a reader alias for function.
For more info see http://definitelyaplug.b0.cx/post/emacs-reader/
The #' is a short hand for using functions, for more details see here: http://www.gnu.org/software/emacs/manual/html_node/elisp/Anonymous-Functions.html
Backslash \ has two functions: it quotes the special characters (including ‘\’), and it introduces additional special constructs. More here: https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html#Regexps
I am trying to compare the objects of two triples in a knowledgebase. I have connected the knowledgebase through ACL client (Allegro CL Enterprise edition 9.0) and written the following code:
(select (?s ?threshold ?NameMatch)
(q- ?s !mynamespace:hasNameMatch ?NameMatch)
(q- !mynamespace:hasNameMatch !mynamespace:hasThresholdValue ?threshold)
(setq return (if (>= (?NameMatch ?threshold "true" "false")))
(pprint ret))
My Knowledgebase includes the following triples
Subject Predicate Object
ns:hasAddressMatch ns:hasThresholdValue "60"
<../729277> :hasNameMatch "70"^^xsd:double
I am trying to compare the ?threshold with value "60" and ?NameMatch with value "70"^^xsd:double, and I expect the result "true". How can I do this?
In RDF data, things that aren't blank nodes or IRIs are literals. Literals may be a plain literal (a string with no additional information), a string with a language tag, or a lexical form (string part) with a datatype (an IRI).
In your data, the literal with lexical form "70" has a datatype which you've censored, but I assume is supposed to be xsd:double. I.e., the value is "70"^^xsd:double, which is the double precision floating point number 70. Your other literal value "60" is just a plain literal. It doesn't really make sense to compare those two values, since one is a number and one is a string.
You have two options though:
You could do a string comparison with the plain literal "60" and the lexical form of "70"^^xsd:double, in which case you'd use string< or string-lessp, depending on whether you want case sensitivity or not (since these are strings of digit characters, it probably doesn't matter).
You could assume that the plain literal "60" has a lexical form that's legal for an xsd:double, do the appropriate conversion, and then compare "60"^^xsd:double and "70"^^xsd:double as numbers with <.
I'd suggest that, if possible, you clean up your data (but this might not be an option if it's coming from somewhere else) so that you can do a numeric comparison with < as in (2), but without needing to do the conversion at comparison time.
In addition to those RDF concerns, your Lisp code also has some issues. if takes three arguments (the third is optional, though). The first is a test condition, and the second and third are forms that get evaluated depending on whether the first evalutes to true or not. In your code, if is only getting one argument:
(if (>= (?NameMatch ?threshold "true" "false")))
-------------------------------------------
This is trying to call >= with one argument, and that's the
(?NameMatch ?threshold "true" "false")
which would be a function call to the function named ?NameMatch with three arguments (?threshold, "true" and "false"). What you probably want here is:
(if (>= ?NameMatch ?threshold) "true" "false")
(Of course, you may still need to modify the test as described above.)
I'm working on a system that uses M4 to expand some files out, but I'm getting a problem with the expansion in certain cases. The convention for definition / macro naming (which I'd rather not change if possible) is __<name>__ (i.e. double leading and trailing underscores.) So this expands correctly:
define(`__ROOT__', `/home/mydir')
...
__ROOT__/bin
gives
/home/mydir/bin
but,
define(`__PREFIX__', `App_Mnemonic')
...
__PREFIX___some_service
should give:
App_Mnemonic_some_service
but gives
__PREFIX___some_service
(i.e. it missed the expansion)
I presume the lack of space between the trailing underscore of the macro and the valid underscore of the underlying text is confusing m4. Is there anything I can do about this? Can I delimit the macro with silent braces, for example, like enviromnment variables?
Deceptively simple really, all I had to do in the underlying text was change this:
__PREFIX___some_service
for this:
__PREFIX__()_some_service
It looks a bit clunky perhaps, but it is a macro after all and there's no need to change the macro definition. So this can stay as it is:
define(`__PREFIX__', `App_Mnemonic')