Ruby: Multi-line conditional syntax: how do I do it? - ruby

What I'm trying to do:
result = (not question?) \
and ( \
condition \
or ( \
comparer == compared and another_question? \
) \
)
The goal is to have complicated and / or logic and still have it be readable.
The problem with the above attempted syntax is that it some how messes up parenthesis in ruby's parser, so console says that the error is in a file that this code isn't in. (though it's in the call stack)
without the back slashes, I get these:
syntax error, unexpected kAND, expecting kEND (SyntaxError)
and
syntax error, unexpected kOR, expecting ')'
any ideas on how to properly do this?

Remove the space after the backslash in another_question? \. You're escaping the space rather than the newline, which causes a syntax error.
Note you don't need to escape every newline.
result = (not question?) \
and (
condition \
or (
comparer == compared and another_question?
)
)

For logical expression, you should use &&, ||, !, not and, or, not.
and, or, not should only be used for control-flow.
One reason is that &&, ||, ! have higher precedence than and, or, not.
Read more about this in this blog post.

Make sure each line (except the last) ends with an operator so the interpreter "knows" there will be more operands coming, e.g.
result = (not question?) and (
condition or
(comparer == compared and another_question?)
)
(tested with MRI 1.8.7)

Try this:
sub = (comparer == compared and another_question?)
result = (not question?) and (condition or sub)
No need to make the whole thing one expression.

Related

How exactly does this work string.split(/\?|\.|!/).size?

I know, or at least I think I know, what this does (string.split(/\?|\.|!/).size); splits the string at every ending punctuation into an array and then gets the size of the array.
The part I am confused with is (/\?|\.|!/).
Thank you for your explanation.
Regular expressions are surrounded by slashes / /
The backslash before the question mark and dot means use those characters literally (don't interpret them as special instructions)
The vertical pipes are "or"
So you have / then question mark \? then "or" | then period \. then "or" | then exclamation point ! then / to end the expression.
/\?|\.|!/
It's a Regular Expression. That particular one matches any '?', '.' or '!' in the target string.
You can learn more about them here: http://regexr.com/
A regular expression splitting on the char "a" would look like this: /a/. A regular expression splitting on "a" or "b" is like this: /a|b/. So splitting on "?", "!" and "." would look like /?|!|./ - but it does not. Unfortunately, "?", and "." have special meaning in regexps which we do not want in this case, so they must be escaped, using "\".
A way to avoid this is to use Regexp.union("?","!",".") which results in /\?|!|\./
(/\?|\.|!/)
Working outside in:
The parentheses () captures everything enclosed.
The // tell Ruby you're using a Regular Expression.
\? Matches any ?
\. Matches any .
! Matches any !
The preceding \ tells Ruby we want to find these specific characters in the string, rather than using them as special characters.
Special characters (that need to be escaped to be matched) are:
. | ( ) [ ] { } + \ ^ $ * ?.
There is a nice guide to Ruby RegEx at:
http://rubular.com/ & http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm
For SO answers that involve regular expressions, I often use the "extended" mode, which makes them self-documenting. This one would be:
r = /
\? # match a question mark
| # or
\. # match a period
| # or
! # match an explamation mark
/x # extended mode
str = "Out, damn'd spot! out, I say!—One; two: why, then 'tis time to " +
"do't.—Hell is murky.—Fie, my lord, fie, a soldier, and afeard?"
str.split(r)
#=> ["Out, damn'd spot",
# " out, I say",
# "—One; two: why, then 'tis time to do't",
# "—Hell is murky",
# "—Fie, my lord, fie, a soldier, and afeard"]
str.split(r).size #=> 5
#steenslag mentioned Regexp::union. You could also use Regexp::new to write (with single quotes):
r = Regexp.new('\?|\.|!')
#=> /\?|\.|!/
but it really doesn't buy you anything here. You might find it useful in other situations, however.

thymeleaf eq with spring variables bug?

I'm trying to run the following th:if:
th:if="${camelContext.getRouteStatus( route.id )} &eq; 'Hey'
but I get this error:
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "${camelContext.getRouteStatus( route.id )} &neq; 'Hey' " (camel:92)
However, if I try
th:if="${camelContext.getRouteStatus( route.id )} > 41 "
I get a different error, but now indicating that it's able to parse the expression, its just that it cannot compare Strings and numbers:
Cannot execute GREATER THAN from Expression "${camelContext.getRouteStatus( route.id )} > 41". Left is "Started", right is "41" (camel:92)
That's fine, I just wanted to check if I was writing the syntax correctly, and I don't want to compare numbers anyways, I want to compare the RouteStatus string.
Anyways, maybe someone can help me with this problem? Basically I want to do a if-else on the contents of a string, but I can't get this to work..
Cheers
Have you tried this:
th:if="${camelContext.getRouteStatus( route.id )} == 'Hey'"
Maybe it will work like this?
The example on the thymeleaf shows something similar:
Values in expressions can be compared with the >, <, >= and <= symbols, as usual, and also the == and != operators can be used to check equality (or the lack of it). Note that XML establishes that the < and > symbols should not be used in attribute values, and so they should be substituted by < and >.
th:if="${prodStat.count} gt; 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
Even though textual aliases exist for some of these operators: gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=), it is sometimes still better to stick with the old fashion operators.
It seems that your expression is malformed, but maybe this a copy paste issue.
Could you try: th:if="${camelContext.getRouteStatus( route.id ) eq 'Hey'} ?

Ruby: Why does equals sign in literal regexp cause parsing error?

These parse and execute fine:
"=".scan(/=/)
"=".scan (/=/)
This causes "unterminated regexp meets end of file":
"=".scan /=/
If I insert something before the = the error goes away:
"=".scan /^=/
What's going on?
I'm guessing that you're hitting this in the parser:
case '/':
if (IS_BEG()) {
lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
return tREGEXP_BEG;
}
if ((c = nextc()) == '=') {
set_yylval_id('/');
lex_state = EXPR_BEG;
return tOP_ASGN;
}
Note the nextc() check in the second if. For reference, tOP_ASGN is:
%token <id> tOP_ASGN /* +=, -= etc. */
so it is used for operator-assign tokens.
This suggests that that /=/ in
'='.scan /=/
is being seen as the divide-assign operator (/=) followed by a start-regex-literal (/).
You'll have trouble (of a slightly different sort) with this:
' ='.scan / =/
but not this:
' ='.scan(/ =/)
There is often ambiguity when a method call doesn't have parentheses. In this case, I think operator precedence rules apply and that's not what you're expecting.
I tend to put parentheses on all my method calls because I'm too old and cranky to want to worry about how the parser is going to behave.

If statement not working - what is wrong with this syntax?

I get an "Expected Identifier" message against the if line. Any ideas why?
if ([inputA.text isEqualToString:#""]) && ([inputB.text <> isEqualToString:#""]) {
c = 1;
}
I'm trying to say it both inputs are empty...
I presume there isn't an easier way to say if the text is null in Obj C++?
An if statement requires that its condition expression be enclosed in parentheses. You have a compound expression. You've used parentheses around the subexpressions of the logical AND operation (&&), but you haven't surrounded the entire expression in parentheses. (The subexpressions don't actually require parentheses in this case, but they don't hurt.)
Next, you have a random <> in the second subexpression. What is that doing in there? In some languages that is the "not equal" operator, but a) it's not an operator in C or Objective-C, b) it wouldn't go inside a message-send expression like that, and c) you claim you were trying to check that both inputs are empty, so I wouldn't expect you to try to negate the test for equality with the empty string.
So, fixing just those problems yields:
if ([inputA.text isEqualToString:#""] && [inputB.text isEqualToString:#""]) {
c = 1;
}
That said, pie's answer is good, too. It also works if either of the inputs has a nil text property, too.
if ([inputA.text length]==0 && [inputB.text length]==0)
{
c = 1;
}

Converting a string to a condition in Ruby

I actually have a string called "cond". This is the content of that string:
"20 < 50"
I would like to insert it into a condition like this: (example)
if 20 < 50
return "Hello"
But that condition is a string, so I can't write this:
if cond
return "Hello"
So I would like to know if it is possible to convert a string to a condition to set in an "if" condition. And if it is possible, how can I do it ?
Thank you.
eval might just be your friend here:
>> eval('20 < 50')
=> true
However, eval will execute the arbitrary code inside its argument; you should be sure that your cond can't contain anything detrimental to your system's health!
One alternative to using eval is perhaps to write an evaluator (or use/modify an existing one, like this one by Sterling Camden).
As is his code requires you to write lt, gt, eq, and so on, instead of <, >, ==, ... . As noted in a comment in calc.rb:
# Equality and its clan (note we cannot use '==' or other two-character
# non-word operators, because of the way we parse the string. Non-word
# characters come in one at a time.
If you know the condition will always be basic like the example you provided, you can do this:
left, op, right = "20 < 50".split
cond = left.to_i.send(op.to_sym, right.to_i)

Resources