I discovered that Microsoft Visual Studio compiler and gcc preprocess the following small snippet differently:
# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)
'gcc -E' gives the following:
a + {a + b}
, while 'cl /E' issues a warning about missing macro argument and produces the following output:
a + {a, b} +
It seems that commas that came from nested macro expansions are not considered to be argument separators. Unfortunately, I found no description of the algorithm implemented in cl preprocessor, and so I'm not sure that my suggestion is correct. Does anyone know how cl preprocessor works and what's the difference between its algorithm and gcc's? And how the observed behaviour can be explained?
# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)
Let us roll this out manually, step by step:
M(a, b)
--> M2(a, P(a, b))
--> M2(a, {a, b})
The standard says:
The individual arguments within the list are separated by comma
preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate
only parentheses are mentioned, so ...
--> M3(a, {a, b})
--> a + {a + b}
Important:
M3(a, {a, b})
Here, according to the previous quote from the standard, three "arguments" are passed to M3 (using single-quotes to describe tokens/arguments):
M3('a', '{a', 'b}')
which are expanded to
'a' + '{a' + 'b}'
And this is what cpp (4.6.1) gives verbatim:
# 1 "cpp.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpp.cpp"
a + {a + b}
cpp (or gcc and g++) are correct, MSVC isn't.
As a nobleman make sure a bug report exists.
The only logic that explains such a behavior looks like this.
CL way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> M3 gets 2 arguments ( 'a' and '{a,b}') instead of 3.
| \ /
arg1 |
arg2
Gcc way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> Gcc probably thinks there are 3 arguments here ('a', '{a', 'b}').
| | |
arg1 | |
arg2 |
arg3
I think gcc gets it right, what Microsoft does is incorrect.
When macro substitution is done for the line
M2(a, P(a, b))
the standard (section 6.10.3.1) requires that before replacing the second parameter ("y") in the macro's replacement list ("M3(x, y)") with its argument ("P(a, b)"), macro replacement is to be performed for that argument. This means "P(a, b)" is processed to "{a, b}" before it is inserted, resulting in
M3(a, {a, b})
which is then further replaced to
a + {a + b}
Related
How to translate this Clojure code to Hy, so it prints 2?
It doesn't need to be like Clojure, i just want to hide + and replace it with - in local environment.
(defmacro q [expr]
`(let ~'[+ (fn [x y] (- x y))]
~expr))
(print (q (+ 3 1)))
In Clojure it prints 2 (let creates a local environment).
In Hy it prints 4.
How to make Hy print 2 also, by replacing the + with - ?
I need those local environments because i am making a DSL.
This doesn't do what you expect in Hy because + is a macro, and macro calls take precedence over function calls:
(defmacro x [] 1)
(defn x [] 2)
(print (x)) ; => 1
Your options are:
Instead of +, use a name doesn't have the same name as a core macro, like my+ or +2.
Only use your new + in contexts other than the head of an Expression (which is the only place Hy expands macro calls), such as (map + (range 10)).
In q, replace the symbol + in the input instead of just setting the variable +, as in something like
(defmacro q [expr]
(import hyrule [coll?])
(defn f [x]
(cond
(= x '+) '-
(coll? x) ((type x) (map f x))
True x))
(f expr))
(print (q (+ 3 1)))
Use defmacro to define a new macro named +. This is a bad idea because you lose access to the original + in this module, including in the expansions of macros you didn't write that expect + to have its usual meaning. Local macros are not yet implemented (#900).
For expressions like
a1 := sin(1+a/b);
a2 := log(1+ a*b);
a3 := abs(a^2+b);
how can I get expressions of respective functions. For example
someCommand(a1) # should get an output 1+a/b
someCommand(a2) # should get an output 1+a*b
someCommand(a3) # should get an output a^2+b
I have tried to get related topics from maple documentation but unfortunately am not able to get exactly.
edited: Also how is it possible to get list (in sequence)of functions used
let
a :=sin(log(abs(a+b)));# functions can be of more than two
someCommand(a) # have to return [{sin, log, abs}, a+b]
You can use the op() command, which breaks down expressions into their operands. For instance:
f := sin(1+a/b);
g := op(0,f); # sin
h := op(1,f); # 1+a/b
That's not complicated to construct. (More thoughts on that, below...)
restart;
W := (ee,nm::name) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
And now to test it,
a1 := sin(1+a/b):
a2 := log(1+ a*b):
a3 := abs(a^2+b):
W( a1, sin );
[[ a]]
[[1 + -]]
[[ b]]
W( a2, ln );
[[a b + 1]]
W( a3, abs );
[[ 2 ]]
[[a + b]]
Now a slightly longer example,
foo := cos(1+a/b)/abs(a^2+b)
+log(1+ a*b)*cos(s-v)
+sin(c+d/r);
/ a\
cos|1 + -|
\ b/ / d\
foo := ---------- + ln(a b + 1) cos(s - v) + sin|c + -|
| 2 | \ r/
|a + b|
W( foo, sin );
[[ d]]
[[c + -]]
[[ r]]
W( foo, cos );
[[ a] ]
[[1 + -], [s - v]]
[[ b] ]
W( foo, abs );
[[ 2 ]]
[[a + b]]
W( foo, ln );
[[a b + 1]]
With no other context to judge by, I personally prefer to have the items above be returned within lists, to be able to handle them later more easily.
But it looks even simpler, if one leaves out the encapsulating lists,
Y := (ee,nm::name) -> op(map(op,indets(ee,':-specfunc'(nm)))):
Y( foo, cos );
a
1 + -, s - v
b
Now a few opinions. The reason that there is no dedicated command for doing precisely this is because there are so very many tasks in a similar vein. A programming language that is crammed full of hundreds of distinct commands to do too similar things can be awkward (or worse) to use.
To use Maple effectively it helps to learn the basic building blocks very well. Those include at least things like,
op, map, map[n], zip, select, remove, selectremove,
table, indices, entries, type, indets, subsindets,
normal, radnormal, simplify, evalc, evala, rationalize
In your followup comment to another Answer you gave the further example of sin(log(abs(a+b))). I suspect that you want to be able to slice and dice even more complicated examples.
You haven't really told use what your final goal is. Perhaps you're trying to build an expression tree. Or perhaps you're evenutally planning on doing something else with this analysis. It'd really help if you told us the final goal.
Having said that, the following might be of some use to you.
restart;
ee := "sin(log(abs(a+b))) + sin(s+t) + abs(log(v+w))":
P:=InertForm:-Parse(ee):
lprint(P);
`%+`(%sin(%log(%abs(`%+`(a,b)))),%sin(`%+`(s,t)),
%abs(%log(`%+`(v,w))))
It may be that the above inert form is something you can work with, for whatever your goal might be.
indets(P, specfunc(name,`%+`));
{a %+ b, s %+ t, v %+ w}
indets(P, specfunc(anything,%abs));
{%abs(a %+ b), %abs(%log(v %+ w))}
indets(P, specfunc(specfunc(name,`%+`),%abs));
{%abs(a %+ b)}
indets(P, specfunc(specfunc(name,`%+`),%log));
{%log(v %+ w)}
Using a routine limke from my earlier Answer,
W := (ee,nm) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
W( indets(P, specfunc(specfunc(name,`%+`),%log)), `%+` );
[[v, w]]
W( indets(P, specfunc(specfunc(name,`%+`),%sin)), `%+` );
[[s, t]]
W( indets(P, specfunc(specfunc(name,`%+`),%abs)), `%+` );
[[a, b]]
There are other ways to get those last results (using something like W on an actual expression and not its inert form, say). I'm just trying to show you how you can do a bit more with it all.
What is the purpose of the # operator, called the stringizer operator,
and how can it be used?
My book describes # in the following way, the bald part is what I do not understand.
The stringizer operator # must be followed by a parameter and they are replaced with a string literal contructed from the argument's tokens, which are not first replaced That is, the following input:
#define W 124
#define str(a) (#a)
str(W)
produces the output:
"W"
If we would like to have a string literal with the definition of a macro, we must use two function-like macros:
#define W 124
#define xstr(a) (#a)
#define str(b) (xstr(b))
which produces the output
"124"
The reason for this is that the argument of the parameter b is completely replaced before the parameter is replaced in the replacement-list of str, which means that the invocation of xstr will use 124 as the argument which is then stringized in xstr
So to understand this, think of how the preprocessor will treat these things. In the first example we can see that
#define W 124
#define str(a) (#a)
str(W)
would get processed as follows str(W) -> #W -> "W".
Now if we take the second example this
#define W 124
#define xstr(a) (#a)
#define str(b) (xstr(b))
str(W)
Would be processed as follows: str(W) -> xstr(124) -> #124 and finally "124"
#a forces the compiler to put the value of a, which in this case is a macro argument, in double quotes. This quoting of the string happens before substitution within the macro. Thus you get the "W".
You can see this by passing your source through the C preprocessor; you do not need to have a valid C program here. On Linux hosts, ignoring the "#" and blank line fluff produced by cpp, we get:
cpp macro-strings.c
("W")
Adding a level of indirectness allows the expansion the value of W. Since there is no "#" in the outer macro the substitutions occurs within that macro before the inner macro is expanded, which creates the string.
If you comment out the xstr definition it may become more visual:
#define W 124
/* #define xstr(a) (#a) */
#define str(b) (xstr(b))
cpp macro-strings.c
(xstr(124))
Removing the comment produces the proper (("124"))
And do remember, that adjacent double-quoted strings are combined by the compiler into a single string:
"Hello," " " "world!" is the same as "Hello, world!"
This can become quote important when one or more strings are generated within macros.
If time is not that much an issue, understanding often comes from a "do it yourself" approach. Here, if the question is "what is preprocessor doing?", why not write a simplified toy-preprocessor and study the results. I forgot the name, but there is a "law", saying "You only really understood if you can implement it".
Of course, writing a full fledged C/C++ preprocessor is not really attractive. So, the following code tries to get a sufficiently large, yet minimalist implementation of a simplified model, which is just so able to showcase what is basically going on. A compact language has been chosen to keep the line count low. No parser is needed if you resort to abstract syntax tree level instead of using a syntax.
type MacroExpr =
| MacroDef of string * string list * MacroExpr
| MacroCall of string * (string * MacroExpr) list
| String of string
| Stringize of MacroExpr
| ArgRef of string
let rec run (macros : MacroExpr list) (call : MacroExpr) : MacroExpr =
let value_of arg_name =
match call with
| MacroCall(n,args) -> snd (List.find (fun a -> fst a = arg_name) args)
| _ -> failwith "bla bla"
match call with
| MacroCall(n,al) ->
let m = macros |> List.find (fun m -> match m with | MacroDef(n1,_,_) -> n1 = n | _ -> false)
let mname,margs,mbody =
match m with
| MacroDef(a,b,c) -> a,b,c
| _ -> failwithf "macros argument contains something else: %A" m
let rec x_to_string = function
| String s -> s
| Stringize x -> x_to_string x
| ArgRef(an) -> x_to_string (eval (snd(al |> List.find (fun (n,_) -> n = an))))
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,_) -> n
and eval = function
| String s -> String s
| Stringize x -> String (x_to_string x)
| ArgRef(an) -> String (x_to_string (snd(al |> List.find (fun (n,_) -> n = an))))
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,al1) ->
run macros (MacroCall(n, al1 |> List.map (fun (an,ax) -> an,eval ax)))
match mbody with
| ArgRef(an) -> snd(al |> List.find (fun (n,_) -> n = an))
| Stringize(x) -> String(x_to_string x)
| String s -> String s
| MacroCall(mn,al1) ->
run macros (MacroCall(mn, al1 |> List.map (fun (an,ax) -> an,eval ax)))
| MacroDef(_,_,_) -> failwithf "No nested macros supported. Found one in %s: %A" n mbody
| _ -> failwithf "'call' argument shall be a MacroCall expression but is a %A" call
let macros =
[
MacroDef ("W", [], String "124")
MacroDef ("str1", ["a"], Stringize (ArgRef "a"))
MacroDef ("str2", ["a"], MacroCall("str1", ["a",ArgRef "a"]))
]
let calls =
[
MacroCall("W",[])
MacroCall("str1",["a",MacroCall("W",[])])
MacroCall("str2",["a",MacroCall("W",[])])
]
calls
|> List.map (fun c -> run macros c)
The macros variable contains the list of predefined macros we want to explore. They are defined in terms of the (minimal, low tech) MacroExpr type.
The calls variable contains a list of macro invocations, using the same technique.
Even if we ignore the implementation of the function run for now, we see something interesting:
The macro definition for "str2" forwards its argument 'a' to a macro call to str1. An ArgRef - a reference to the argument list of "str2". Languages which follow the eager evaluation principle will not pass that ArgRef down to the next macro evaluation but instead attempt to resolve it first. After all, else the evaluation of "str1" would have to know about the arglist of the caller "str2".
Hence, the argument for the call of str1 from str2 is ["a",MacroCall("W",[])], whereas a direct invocation of macro str1 with ["a",MacroCall("W",[])] is first resolved by evaluating the macro "W" to String "124".
The last 2 lines in the code run all calls and the results yielded are not as expected:
val it : MacroExpr list = [String "124"; String "124"; String "W"]
Now, as an exercise, you could try to change the run function such, that it behaves as the c preprocessor does. Tip: sub-functions x_to_string and eval are the culprits ;)
The fixed version of those 2 sub-functions is:
let rec x_to_string = function
| String s -> s
| Stringize x -> x_to_string x
| ArgRef(an) -> x_to_string ( (*eval*) (snd(al |> List.find (fun (n,_) -> n = an)))) // disabled eval
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,_) -> n
and eval = function
| String s -> String s
| Stringize x -> String (x_to_string x)
| ArgRef(an) -> String (x_to_string (eval (snd(al |> List.find (fun (n,_) -> n = an))))) // added eval
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,al1) ->
run macros (MacroCall(n, al1 |> List.map (fun (an,ax) -> an,eval ax)))
... and now the result is as expected:
val it : MacroExpr list = [String "124"; String "W"; String "124"]
How can we prove a program in repeat until using Hoare Logic?
I've found a rule like this:
{P} S {R}, {R ^ ~B -> P}, {R ^ B -> Q}
For {P} repeat S until B {Q}
But I still can't find any explanatiom how I can use this rule
For example in this question:
{x > 0 ^ y > 0}
z:=0; u:=x; REPEAT
z:=z+y;
u:=u-1;
UNTIL u=0;
{z = x * y}
How I can use the rule to prove this program?
Let's suppose I want to minimize a function:
x<-seq(-4.5,4.5,by=.2)
y<-seq(-4.5,4.5,by=.2)
f <- function(x1,x2){(x1^2 + x2)^2 }
z <- outer(x,y,f)
Where z is a matrix of dimension 46 x 46:
> class(z)
[1] "matrix"
> dim(z)
[1] 46 46
So I make a graph of the result with:
persp(x,y,z,phi=-45,theta=45,col="yellow",shade=.65 ,ticktype="detailed")
If I write the previous, it works, but since I want to minimize the function using optim, if I use that I get:
optim(c(-4,-4), f, df)$par
> Error in fn(par, ...) : argument "x2" is missing, with no default
So I need to use an array in order to use optim after all. So if I write:
f <- function(x) (x[1]^2 + x[2])^2
x <- seq(-4.5,4.5,by=.2)
y <- seq(-4.5,4.5,by=.2)
s<-data.frame(cbind(x,y))
I can use optim:
optim(c(-4,-4), f, df)$par
But outer gives an error:
z <- outer(s,f)
Error in as.vector(x, mode) : cannot coerce type 'closure' to
vector of type 'any'
I don't know how to solve it.
I believe the goal here is to not have to write the function two different ways, right?
f0 <- function(x1,x2) ( x1^2 + x2 )^2
f <- function(x) ( x[1]^2 + x[2] )^2
Similarly, maybe you just want to use just s<-data.frame(cbind(x,y)) (without x and y).
Here's what I would consider doing:
outer(s[[1]],s[[2]],Vectorize(function(xi,yi) f(c(xi,yi))))
This way you only have to write the function once, in the way amenable to using optim (with a single argument).
Note: If you want the grids x and y to have a different number of points, you should store s <- list(x,y) instead. The code will work the same.