Check multiple conditions at once using m4 preprocessor - preprocessor

There is any m4 syntax that is equivalent to this C preprocessor one?
#if defined A || defined B
do something
#endif

The short answer is no.
The long answer:
Checking if macros are defined
define(`defined', `ifelse($1()$1, `$1()$1', ``0'', ``1'')')
ifelse(eval(defined(`A') || defined(`B')),
1,
``At least one is defined'',
``Neither are defined'')
There are no sensible ways to check for a defined macro in m4, so you would have to resort to hacks like the above.
How it works
ifelse checks for equality of two strings. In the defined macro, I've expanded the macro in $1 twice (once as $1(), once as $1). I'm comparing it against $1()$1 as a string, so if it doesn't expand then it will compare true. The reason for specifying the macros in two different ways is because A could be defined as ``A'' or ``A()'' which would otherwise cause false negatives when using this method to check whether or not it is defined.
I'm then using that defined macro within an eval to throw the || logic on top.
Caveats
If you use the word defined in your document already, you might want to give the macro a different name.
The defined macro will not work on macros defined to expand to unquoted syntactic markers like (, ,, or ).
If the macro to be checked is infinitely recursive, the defined check will also never return. (Essentially, realize that a hack like this is still actually executing the macro.)
Though the last 2 points there are something you'd expect from any ifelse check on a macro, it might not be intuitive to expect it from a macro purporting to check for whether another macro is defined.
A better way
I would much rather suggest that you define the variables with some default value first, and just avoid the problem of checking whether it is defined or not altogether.
This is much easier to do:
# Define this right off the bat:
define(`A', ``0'')
# Maybe later this line will come up...
# Quotes around the A are mandatory
define(`A', ``1'')
# Then soon after that, you can check:
ifelse(A, `0', , ``hey, A is nonzero!'')

Related

Check values existence using spss syntax

I should check existence of values based on some conditions.
i.e. i have 3 variables, varA, varB and varC. varC should not be empty only if varA>varB (condition).
i normally use some syntax to check any of the variables and run a frequency of any of them to see if there are errors:
if missing(varC) and (varA>varB) ck_varC=1.
if not(missing(varC)) and not(varA>varB) ck_varC=2.
exe.
fre ck_varC.
exe.
I had some errors when the condition became complex and when in the condition there are missing() or other functions but i could have made a mistake.
do you think there is an easier way of doing this checks?
thanks in advance
EDIT: here an example of what i mean, think at a questionnaire with some routing, you ask age to anyone, if they are between 17 and 44 ask them if they work, if they work ask them how many hours.
i have an excel tool where i put down all variables with all conditions, then it will generate the syntax in the example, all with the same structure for all variables, considering both situations, we have a value that shouldn't be there or we don't have a value that should be there.
is there an easier way of doing that? is this structure always valid no matter what is the condition?
In SPSS, missing values are not numbers. You need to explicitly program those scenarios as well. you got varC covered (partially), but no scenario where varA or varB have missing data is covered.
(As good practice, maybe you should initialize your check variable as sysmis or 0, using syntax):
numeric ck_varC (f1.0).
compute ck_varC=0.
if missing(varC) and (varA>varB) ck_varC=1.
if not(missing(varC)) and not(varA>varB) ck_varC=2.
***additional conditional scenarios go here:.
if missing(varA) or missing(varB) ck_varC=3.
...
fre ck_varC.
By the way - you do not need any of the exe. commands if you are going to run your syntax as a whole.
Later Edit, after the poster updated the question:
Your syntax would be something like this. Note the use of the range function, which is not mandatory, but might be useful for you in the future.
I am also assuming that work is a string variable, so its values need to be referenced using quotation signs.
if missing(age) ck_age=1.
if missing(work) and range(age,17,44) ck_work=1.
if missing(hours) and work="yes" ck_hours=1.
if not (missing (age)) and not(1>0) ck_age=2. /*this will never happen because of the not(1>0).
if not(missing(work)) and (not range(age,17,44)) ck_work=2. /*note that if age is missing, this ck_work won't be set here.
if not(missing(hours)) and (not(work="yes")) ck_hours=2.
EXECUTE.
String variables are case sensitive
There is no missing equivalent in strings; an empty blank string ("") is still a string. not(work="yes") is True when work is blank ("").

DLV Rule is not safe

I am starting to work with DLV (Disjunctive Datalog) and I have a rule that is reporting a "Rule is not safe" error, when running the code. The rule is the following:
foo(R, 1) :- not foo(R, _)
I have read the manual and seen that "cyclic dependencies are disallowed". I guess this is why I am being reported the error, but I am not sure how this statement is so problematic to DLV. The final goal is to have some kind of initialization in case that the predicate has not been defined.
More precisely, if there is no occurrence of 'foo' with the parameter R (and anything else), then define it with parameters R and 1. Once it is defined, the rule shouldn't be triggered again. So, this is not a real recursion in my opinion.
Any comments on how to solve this issue are welcomed!
I have realised that I probably need another predicate to match the parameter R in the body of the rule. Something like this:
foo(R, 1) :- not foo(R, _), bar(R)
Since, otherwise there would be no way to know whether there are no occurrences of foo(R, _). I don't know whether I made myself clear.
Anyway, this doesn't work either :(
To the particular "Rule is not safe" error: First of all this has nothing to do with cyclic or acyclic dependencies. The same error message shows up for the non-cyclic program:
foo2(R, 1) :- not foo(R,_), bar(R).
The problem is that the program is actually not safe (http://www.dlvsystem.com/html/DLV_User_Manual.html#SAFETY). As mentioned in the section on negative rules (anchor #AEN375, I am only allowed to use 2 links in my answer):
Variables, which occur in a negated literal, must also occur in a
positive literal in the body.
Observe that the _ is an anonymous variable. I.e., the program
foo(R,1) :- not foo(R,_), bar(R).
can be equivalently written as (and is equivalent to)
foo(R,1) :- not foo(R,X), bar(R).
Anonymous variables (DLV manual, anchor #AEN264 - at the end of the section) just allow us to avoid inventing names for variables that will only occur once within the rule (i.e. for variables that only express "there is some value, I absolutely do not care about it), but they are variables nevertheless. And since negation with not is "negation" and not "true negation" (or "strong negation" as it is also often called), none of the three safety conditions is satisfied by the rule.
A very rough and high-level intuition for safety is that it guarantees that every variable in the program can be assigned to some finite domain - as it is now the case with R by adding bar(R). However, the same also must be the case for the anonymous variable _ .
To the actual problem of defining default values:
As pointed out by lambda.xy.x, the problem here is the Answer Set (or stable model) semantics of DLV: Trying to do it in one rule does not give any solution:
In order to get a safe program, we could replace the above problems e.g. by
foo(1,2). bar(1). bar(2).
tmp(R) :- foo(R,_).
foo(R,1) :- not tmp(R), bar(R).
This has no stable model:
Assume the answer is, as intended,
{foo(1,2), bar(1), bar(2), foo(2,1)}
However, this is not a valid model, since tmp(R) :- foo(R,_) would require it to contain tmp(2). But then, "not tmp(2)" is no longer true, and therefore having foo(2,1) in the model violates the required minimality of the model. (This is not exactly what is going on, more a rough intuition. More technical details could be found in any article on answer set programming, a quick Google search gave me this paper as one of the first results: http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)
In order to solve the problem, it is therefore somehow necessary to "break the cycle". One possibility would be:
foo(1,2). bar(1). bar(2). bar(3).
tmp(R) :- foo(R,X), X!=1.
foo(R,1) :- bar(R), not tmp(R).
I.e., by explicitly stating that we want to add R into the intermediate atom only if the value is different from 1, having foo(2,1) in the model does not contradict tmp(2) not being part of the model as well. Of course, this no longer allows to distinguish whether foo(R,1) is there as default value or by input, but if this is not required ...
Another possibility would be to not use foo for the computation, but some foo1 instead. I.e. having
foo1(R,X) :- foo(R,X).
tmp(R) :- foo(R,_).
foo1(R,1) :- bar(R), not tmp(R).
and then just use foo1 instead of foo.

how to suppress simplification of formulas to True or False?

is it possible to disable automatic simplifications of boolean expressions in Z3?
For example, the expression 2 > 1 becomes True automatically while I would like it to stay 2 > 1:
>>> t = 2 > 1
>>> t
True
I found several options by calling help_simplify() in Z3Py. However, none of them seems to relate to my problem.
In another tutorial (http://citeseerx.ist.psu.edu/viewdoc/download?rep=rep1&type=pdf&doi=10.1.1.225.8231) an option "CONTEXT SIMPLIFIER" was mentioned: "This setting can be used to simplify sub-formulas to true or false." However, I could not find this option in Z3Py.
Background: I would like to be able to use expressions like And(2>1, 1!=2) where 2>1 and 1!=2 are automatically generated earlier and sometimes contain no variables (constants). Z3Py simplifies this to And(True, False) which is not accepted, because "At least one of the arguments must be a Z3 expression or probe". Therefore, I would like to suppress the simplification. Or is there a way to make And(True, False) an accepted expression?
Thanks in advance!
Indeed, this is because simple expressions like 2>1 are simplified to True/False by Python. Most operators (like Implies, Xor, ...) were fine with this, but the And and Or operators were not. They had a different implementation because they can be used for probes as well as expressions. I have now added a little bit more code to make them behave like the other Boolean operators (for fix see here). I hope this fixes this problem while not introducing any new problems with probes. I'd be grateful if other could test this some more.

How does one define C/C++ style macros in ruby/rails

I have noticed that ruby on rails has some small macros that have a c feel.
__FILE__ and __LINE__
For instance. This makes debugging and generating unique cache keys much easier.
store = Rails.cache.fetch("#{__FILE__}|#{__LINE__}|#{self.store_id}")...
Most handy when I am likely to get the same store over and over for a given set of orders.
What I'm wondering though is; can I create my own MACROS/defines? Precompiled code while not a good idea sometimes, does have its place.
QUESTION: Is there a way to create c style macros in ruby/rails?
They look like C but they are not macros, they are just objects, like everything else in ruby, these in particular having the power to determine the name and line number of the file currently being interpreted.
C macros are just references to compile-time executable code. Ruby is ... like, totally, completely opposite from this :-) Compilation in ruby is really syntax evaluation and then interpretation. If some languages like C, C++ and Java are early-binding and others like PHP and Python are late-binding, ruby has missed the bus and will get there at the last possible moment.
So if you want to create your own stuff, create a module and/or class having something inside. What you create inside will be a variable, symbol, constant, or method, perhaps local, of the instance, or of the class, perhaps public, protected or private. It's generally not good form to use the special naming conventions __FOO__ or others (even if they are valid names).
(end of answer... if I am hearing what you're asking, perhaps this will help you make the mental leap that is needed)...
I went from C, to C++, to Java, then to Ruby. After a brief time in the clinic for reformed Java programmers, I was able to understand how amazingly powerful ruby is. But you really have to think about how to solve problems differently.
I highly recommend the book Eloquent Ruby, linked here to Amazon.
__FILE__ and __LINE__ aren't macros per se, they're keywords (that return String values).
Having said that, you are allowed to define constants and methods that start with an underscore or _ character. For example:
__MICKEY__ = :mouse
Now, a constant can refer to anything—a String, an expression, even a code block (a Proc or lambda) or a whole Class.
That means that instead of compile-time macro expansion (Ruby, being an interpreted language, doesn't really have a 'compile phase') you can take advantage of (arguably more powerful) run-time code execution.
For instance, the C++ macro:
#define SUM(a, b, c) a + b + c
Can be suitably approximated in Ruby as
def SUM(a, b, c); a + b + c; end
I say 'approximated' because a) in this case we're defining a method, not a constant or a macro, and b) C++ macros can still work when evaluated with a different number of arguments than they expect (because C++ macros are expanded, meaning, it's as if we did find and replace), whereas Ruby method call semantics come into play, such as checking arity of methods and arguments.
To get around that, in our particular example, we can do (something arguably even more flexible)
def SUM(*args); args.inject(:+); end
SUM(1, 2) # => 3
SUM(1, 2, 3, 5) # => 11
As you can see, you can achieve a similar (possibly even greater) level of expressiveness that C++ macros provide by leveraging Ruby's dynamic nature.

m4 does not obey expansion?

I use m4 for a little text preprocessing here, and it behaves in a way I don't understand.
This is the portion in question:
ifdef(`TEST',
define(`O_EXT', `.obj'),
define(`O_EXT', `.o'))
This macro will always be expanded to .o, regardless whether TEST is defined (m4 -DTEST) or not.
What am I doing wrong?
You're not quoting the other arguments to ifdef. Try this:
ifdef(`TEST', `define(`O_EXT', `.obj')', `define(`O_EXT', `.o')')

Resources