Eiffel: classical typecasting switch structure with attached and inspect - casting

What is the best practice to do something such as
local
l_pet: ANIMAL
do
l_pet := catch_it_from_the_sky
inspect l_pet
when attached {DOG} l_pet as l_dog
l_dog.eat (meat)
when attached {FISH} l_pet as l_fish
l_fish.eat (plants)
else
io.put_string ("Strange animal how do I feed him???")
end
do
the compiler is complaining with the attached after when...
Update: why such a need?
because it just happened me to mess up with repeated copy-paste which is what a language tries to help avoiding. In the above case, the l_pet is written one time, with a N times if/else I'd have to write it as much times as ifs...

An inspect statement allows for checking if an expression has a specific value, and can be applied to expressions of integral types (such as INTEGER_64, CHARACTER_32 or NATURAL_8):
inspect age
when 6 .. 16 then ...
when 18 then ...
when 80, 90 then ...
...
end
For discriminating over object types, conditional instructions are used:
if attached {DOG} pet as dog then
dog.eat (meat)
elseif attached {FISH} pet as fish then
fish.eat (plants)
else
io.put_string ("Strange animal how do I feed him???")
end

In a multi-branch instruction
inspect exp when ... then ... else ... end
The exp expression needs to be a character or an integer expression.
In your given example I don't see the need to do that Object-Test,
but if you need to do something like that you need to use the conditional instruction.
if ... then
...
elseif ... then
...
else
...
end

Related

(XQuery/Conditions) Is it possible to declare variables in an if-statement?

I do not find an example for my problem so here is my question.
I get an error that else is an unexpected token in the following example:
let $var1 := 'true'
if ($var1 = 'true') then
let $var2 := 1
let $var3 := $var1 + 1
else ()
As you see I want to declare variables if the if-statement is true. Is this possible in XQuery? I just saw examples where the value of just one variable can depends on a condition. The following does more or less the same I want to realize with the code at the beginning.. and it works but it is a little bit confusing in my opinion and actually I don't want the variables to be created if the condition is not true. Furthermore you have to think around the corner when you realize it like that especially when there are more than just 2 variables that depends on each other.
let $var1 := 'true'
let $var2 := if ($var1 = 'true') then (1) else (0)
let $var3 := if ($var2 = 1) then ($var2 + 1) else (0)
So my question is. Is there a prettier solution to realize that than my solution?
You could add a return clause to put a full flwor expression inside the condition, e.g. something like this:
let $var := 'true'
if ($var = 'true') then
let $var2 := 1
let $var3 := $var1 + 1
return 0
else ()
But it would be pointless: the binding of $var2 and $var3 would not extend outside of the scope of the then clause.
XQuery is a declarative and functional language, which means that variables do not get assigned, but only bound within a certain scope. This is something that should be thought about in term of space, not time, as there is no elapse of time in an XQuery program, like a ticket allows you to visit a museum but not another.
Let clauses are part of FLWOR (acronym for for-let-where-orderby-return) expressions. A variable bound in a let clause can be used in subsequent clauses, up to and including the return clause. As mholstege explains, beyond the return clause, which is required, the variable is not visible any more, like nobody would accept your ticket outside the museum.
Since expressions nest in a "well-parenthesized" way according to the XQuery grammar, any attempt to start a let clause inside an if-then-else expression requires that a return clause be present before the then (or else) expression ends. This means that a variable bound this way will never be visible after this if-then-else expression.
In general, when I program in XQuery (as opposed to, say, Java), I try to remind myself continuously that I have to write down what I want, and resist the temptation to describe how I want it computed.
Having said that, XQuery does have scripting extensions that introduce variable assignments as you describe, but this did not get standardized so far -- also, such a scripting extension should only be used when side effects to the outside world happen, meaning that one needs a notion of time and succeeding snapshots.
You could avoid using if/else altogether by defining sequences for your possible values, and a predicate that calculates the position() to select the desired value from the sequence:
The following uses number() to evaluate the numeric value of a boolean (0 for false, 1 for true) and selects either the first or the second item in the sequence of values:
let $var1 := 'true'
let $var2 := (0, 1)[number($var1 = 'true') + 1]
let $var3 := (0, $var2 + 1)[number($var2 eq 1) + 1]
return ($var1, $var2, $var3)

giving a string variable values conditional on another variable

I am using Stata 14. I have US states and corresponding regions as integer.
I want create a string variable that represents the region for each observation.
Currently my code is
gen div_name = "A"
replace div_name = "New England" if div_no == 1
replace div_name = "Middle Atlantic" if div_no == 2
.
.
replace div_name = "Pacific" if div_no == 9
..so it is a really long code.
I was wondering if there is a shorter way to do this where I can automate assigning values rather than manually hard coding them.
You can define value labels in one line with label define and then use decode to create the string variable. See the help for those commands.
If the correspondence was defined in a separate dataset you could use merge. See e.g. this FAQ
There can't be a short-cut here other than typing all the names at some point or exploiting the fact that someone else typed them earlier into a file.
With nine or so labels, typing them yourself is quickest.
Note that you type one statement more than you need, even doing it the long way, as you could start
gen div_name = "New England" if div_no == 1

if then statement not working asp

I've been trying every combination to make this if then statement work on my ASP page. I've calling fields from 2 access database, then I need to compare both to see if there is a facility that has a report against them.
At first I was using the facility name as the anchor to both database files. It worked pretty good until there was an issue with double quotes in the name. This code worked
<%
for k=0 to y-1
if (B(1,k)) = facility then
%>•<%=B(2,k)%><br /><%
end if
NEXT
%>
So all I did was add a facility id number in the second database (row 12) since the ID already existed in the first database
<%
for k=0 to y-1
response.write(ID)
response.write("\")
response.write(B(12,k))
if (B(12,k)) = ID then
response.write("TRUE")
%>•<%=B(2,k)%><br /><%
else
response.write("FALSE")
end if
response.write("<br>")
NEXT
%>
as you can see, I've tested that the values are acually the same. The results of this If Then is;
2006225\2006225FALSE 2006225\2007101FALSE 2006225\2006225FALSE
2006225\2004245FALSE 2006225\279025FALSE 2006225\2006225FALSE
2006225\2006225FALSE 2006225\2006225FALSE 2006225\2006225FALSE
Since your example code does not show how your variable named ID is assigned, my first guess would be that this may be due to variables being untyped in VBscript and you may not be assigning the type you are expecting to either the above mentioned variable or your array in the above code. You may want to use forced concatenation to make certain the evaluation is based on string types. You can concatenate an empty string in VBscript to force it to evaluate the whole expression as a string (this is what is also happening when you are writing the output). If it works this way, then most likely your variable may actually be getting assigned to a recordset field rather than a string value or something similar.
if ("" & B(12,k)) = ("" & ID) then

How can I avoid over-testing with example

I've been trying to start testing my code more, and I thought I would mimic the style of some of the tests that were autogenerated for by me rails scaffolding (I'm using rspec and rails, but my question is really just general-tdd). However, those methods were very basic, along the lines of do something. then if foo, do something else. I feel like as soon as you get more complex by adding one more 2 more things to condition in your if, things start spiraling and you get nested examples all over the place. Here's an example of what i've been doing that feels like overkill.
First the method
def maybe_blah(foo)
if foo != nil && foos.find_by_id(foo.id) != nil
blah unless bar?(foo)
end
end
this method is pretty simple, here's how I was planning on testing it
describe maybe_blah
shared_examples "what happens when bad input is passed" do
it "doesn't call bar?"...
it "doesn't call blah"...
end
context "when foo is not nil"
context "when foo is in foos"
context "bar? returns true"
it "doesn't call blah" do
some code involving mocking bar? and blah
end
end
context "bar? returns false"
it "does call blah" do
some code involving mocking bar? and blah
end
end
end
context "when foo is not in foos"
include_examples "what happens when bad input is passed"
end
end
context "when foo is nil"
include_examples "what happens when bad input is passed"
end
end
That's noticeably shorter than what the test would be if there was all of the setup and whatever else in there (testing maybe_blah for real like that took me 55 lines), so you can see how it seems to get out of hand. Is there a good way of testing a method that does feel like such overkill.
I don't see a way around having 3-deep nesting when you have 3 conditions you're testing (at least without repeating yourself even more), but it seems like you'd need to do that to make sure you're handling all different cases. Also, it seems dumb to test the fail result for every different bad input, but how else would you know you're actually failing on those bad inputs?
So is this just overkill?
Actually you condition is the same as:
def maybe_blah(foo)
if foo != nil && foos.find_by_id(foo.id) != nil && !bar?(foo)
blah
end
end
Thus you can extract it into separate method using Decompose Conditional and Consolidate Conditional Expression techniques:
def maybe_blah(foo)
blah if can_do_it?(foo)
end
def can_do_it?(foo)
foo != nil && foos.find_by_id(foo.id) != nil && !bar?(foo)
end
After that you can test this method in two contexts
describe '#maybe_blah' do
context 'when can do' do
# stub can_do_it? and returns true
# stould receive :blah
end
context 'when cant do' do
# stub can_do_it? and returns false
# should not receive :blah
end
end
And test condition separately.
And you can omit != nil
def can_do_it?(foo)
foo && foos.find_by_id(foo.id) && !bar?(foo)
end

doctrine2 dql, use setParameter with % wildcard when doing a like comparison

I want to use the parameter place holder - e.g. ?1 - with the % wild cards. that is, something like: "u.name LIKE %?1%" (though this throws an error). The docs have the following two examples:
1.
// Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%'))
public function like($x, $y); // Returns Expr\Comparison instance
I do not like this as there is no protection against code injection.
2.
// $qb instanceof QueryBuilder
// example8: QueryBuilder port of: "SELECT u FROM User u WHERE u.id = ?1 OR u.nickname LIKE ?2 ORDER BY u.surname DESC" using QueryBuilder helper methods
$qb->select(array('u')) // string 'u' is converted to array internally
->from('User', 'u')
->where($qb->expr()->orx(
$qb->expr()->eq('u.id', '?1'),
$qb->expr()->like('u.nickname', '?2')
))
->orderBy('u.surname', 'ASC'));
I do not like this because I need to search for terms within the object's properties - that is, I need the wild cards on either side.
When binding parameters to queries, DQL pretty much works exactly like PDO (which is what Doctrine2 uses under the hood).
So when using the LIKE statement, PDO treats both the keyword and the % wildcards as a single token. You cannot add the wildcards next to the placeholder. You must append them to the string when you bind the params.
$qb->expr()->like('u.nickname', '?2')
$qb->getQuery()->setParameter(2, '%' . $value . '%');
See this comment in the PHP manual.
The selected answer is wrong. It works, but it is not secure.
You should escape the term that you insert between the percentage signs:
->setParameter(2, '%'.addcslashes($value, '%_').'%')
The percentage sign '%' and the symbol underscore '_' are interpreted as wildcards by LIKE. If they're not escaped properly, an attacker might construct arbirtarily complex queries that can cause a denial of service attack. Also, it might be possible for the attacker to get search results he is not supposed to get. A more detailed description of attack scenarios can be found here: https://stackoverflow.com/a/7893670/623685