How does one refer to the last argument in a given list of arguments in an m4 macro? I have a requirement to pull the last argument and generate macro expansion based on that.
This is not particularly elegant, but it works:
define(`last',`ifelse(`$#',`0',`',`$#',`1',`$1',`last(shift($#))')')dnl
last(foo,bar,baz)
# more elegant solution:
changequote([,])
define([LEN], [$#])
define([LAST], [pushdef([$0], $LEN($#))$0($#)[]popdef([$0])])
define([LAST_BUT_ONE], [pushdef([$0], $decr(LEN($#)))$0($#)[]popdef([$0])])
LAST(foo, bar, baz)
LAST_BUT_ONE(foo, bar, baz)
Related
Reading the docs of the m4 macro language I have found that example:
changequote([,])dnl
define([gl_STRING_MODULE_INDICATOR],
[dnl comment
GNULIB_[]translit([[$1]], [a-z], [A-Z])=1dnl
])dnl
gl_STRING_MODULE_INDICATOR([strcase])
which produces:
GNULIB_STRCASE=1
But if one omits to quote strcase we have the same result:
gl_STRING_MODULE_INDICATOR(strcase)
produces
GNULIB_STRCASE=1
Why quoting strcase?
The quotes are required in case strcase is defined as a macro. For example, if we have define(strcase, foo), then gl_STRING_MODULE_INDICATOR(strcase) will expand first into gl_STRING_MODULE_INDICATOR(foo) and then into GNULIB_FOO=1.
In general, well-written m4 input will continue to function when certain words unexpectedly happen to be defined as macros.
I'll start with my code:
macro example(args...)
local s = __source__
println(s) # This part works, showing macro is called on line 9
quote
println(s) # Julia tells me this variable "s" is not defined
println(__source__) # Likewise, "__source__" is not defined here either
end
end
#example 42 # Line 9 of my file
In my macro above I want to record the line number that is calling the macro and use it within my quote block. Both capturing it in a variable outside the quote block and using it within, or using it directly in the quote block don't work. My understanding is the code outside the quote block runs at parse-time, and the expression returned from the quote block is evaluated at run-time.
I feel like there must be a way to capture that variable and inject it right into the expression that will be evaluated later, but I haven't figured out how to do that. Any help here is appreciated. If there is a better way to do this let me know.
I ended up finding out an answer on my own. In the second line if I changed __source__ to __source__.line or __source__.file it worked fine as long as I then used $ to interpolate the result into the expression the macro returned. I'm still not sure why __source__ on its own didn't work, but using either .line or .file methods is working for me now.
I'm experiencing a similar problem trying to use __source__.
I think I can offer insight into why source.line, etc worked though.
The value of source.line is an integer. The value of source.fike is a string. Numbers and strings evaluate to themselves.
A symbol, on the other hand, evaluates to whatever value it has in the environment.
Can any one explain this format?
${name:-$devi}
Example:
"${1+"$#"}" will check for that first variable to be set , if not it will use that
command line argument.
What is the difference between :- and + between those variables?
${var:-val}
is the same as ${var} if var is set and non-null, otherwise it expands to val. This is used to specify a default value for a variable.
${var+val}
expands to nothing if var is unset, otherwise it expands to val. This is used to supply an alternate value for a variable.
"${1+"$#"}"
is a workaround for a bug in old shell versions. If you just wrote "$#", it would expand to "" when no arguments were supplied, instead of expanding to nothing; the script would then act as if a single, empty argument had been supplied. This syntax first checks whether $1 is set -- if there's no first argument, then there are obviously no arguments at all. If $1 is unset, it expands to nothing, otherwise it's safe to use "$#".
Most modern shell versions don't have this bug, so you can just write "$#" without the special check. I'm not sure if there are any other common use cases for the + construct in shell variable expansion.
I would like to define a macro that can define more macros as:
define(`master_macro',
`foreachq(`slave_macro', `$*',
define(`slave_macro', ...)'
then I can use master_macro to define more similar slave_macros as:
master_macro(m1, m2, m3, ...)
The reason why I need this is that the number and names of slave_macro are unknown when I write M4 macros.
What you are asking for can certainly be done. Here's an example:
$ cat file
changequote(`[',`]')dnl
define([factory],[dnl
define($1,banana)dnl
define($2,split)dnl
])dnl
factory(hello,world)dnl
hello world
$ m4 file
banana split
I think the problem is your usage of the undefined macro foreachq.
I'm learning Scala and lift at the same time and I got stuck on understanding the syntax used to inintialize the SiteMap in the Boot.scala:
val entries = Menu(Loc("Home", "/", "Home")) ::
Menu(Loc("Foo", "/badger", "Foo")) ::
Menu(Loc("Directory Foo", "/something/foo", "Directory Foo")) :: Nil
LiftRules.setSiteMap(SiteMap(entries:_*))
What exactly is the meaning of the SiteMap parameter?
I see that the value entries is a list of Menu. What is the colon, underscore, star?
At first I thought it is a method on the List, but I am unable to find such definition...
OK, after my colleague mentioned to me, that he encountered this secret incantation in the Programming in Scala book, I did a search in my copy and found it described in Section 8.8 Repeated parameters. (Though you need to search with space between the colon and underscore :-/ ) There is a one sentence to explain it as:
... append the array argument with a colon and an _* symbol, like this:
scala> echo(arr: _*)
This notation tells the compiler to pass each element of arr as its own argument to echo, rather than all of it as a single argument.
I find the description offered here more helpful.
So x: _* is like a type declaration that tells the compiler to treat x as repeated parameter (aka variable-length argument list — vararg).