Why does this code set the variable a to 9? - loops

I am confused by this piece of code:
| a b c| a := 1. b := [a := a + 1]. c := [a := a - 2. b].
10 timesRepeat: (a even ifTrue: b ifFalse: c). a
My assumption was that this piece of code would set a to -19. Each iteration would test if a was even, but a would be odd so c would be called, substracting 2 from a without affecting its parity. c would not call b because, if my understanding of blocks is correct, the last element of the block is returned instead of evaluated; so c would return b, but timesRepeat discards whatever is returned anyway so this b in c has no effect.
My assumption was proven to be wrong: this piece of code sets a to 9 instead. To see what's going on I modified this piece of code slightly:
| a b c| a := 1. b := [Transcript show: (a displayString). a := a + 1]. c := [Transcript show: (a displayString). a := a - 2. b.].
10 timesRepeat: (a even ifTrue: b ifFalse: c). a
This is what gets printed:
1-1012345678
So it would seem b is called after all? Was my assumption wrong that b is returned instead of called?
Let's try to check this:
jkl := [Transcript show: 'I am called too.'].
asdf := [Transcript show: 'I am called!'. jkl].
10 timesRepeat: asdf
Nope, asdf does not call jkl here:
I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!I am called!
And anyway, if c was always just calling b, its effect would be to effectively substract 1 from a; but this doesn't happen. Instead, the first iteration seems to call c and then, mysteriously, each iteration seems to call b instead, even if a is odd!!
What's going on here??

The timesRepeat: selector wants a block as an argument. You are calling it with an expression inside of parentheses:
10 timesRepeat: (a even ifTrue: b ifFalse: c).
It just so happens, though, that c is defined as the block [a := a - 2. b] which returns the value of b and that happens to be a block. So timesRepeat: is happy, and it executes the block b on each iteration in which a is odd. If you write it correctly as:
10 timesRepeat: [a even ifTrue: b ifFalse: c].
Then at the end, a will be -19 as expected.
Regarding your statement: if my understanding of blocks is correct, the last element of the block is returned instead of evaluated, this isn't really the case. There's no special treatment for the last statement in a block other than it's result is indeed returned as the value of the block when that block is executed. Your last statement in the block is just the name of a variable. The value of the variable just happens to be a block, but no matter what it is, just having a variable name by itself as a statement in Smalltalk just returns the value of the variable. If the variable happens to be a block, you get the block. The block is not executed.
Consider the following blocks:
[a := 1. b := 2. c := a+b]
When this block is executed, then a will have the value 1, b the value 2, and c the value 3. The value the block will return is the value of c, which is 3.
[a := 1. b := 2. a]
If you execute this block, the result will be the value of a, which is 1.
[a := 1. b := 2. c := [a+b]. c]
If you execute this block, the result will be the block that the variable c represents. It does not execute the block c. This is consistent with the prior example.
So, when you execute the block, [Transcript show: 'I am called!'. jkl]., the jkl at the end is not executed. It's value is just returned. If you want to execute it, you could write asdf := [Transcript show: 'I am called!'. jkl value]. A block will execute when sent the value message. The result of executing block [Transcript show: 'I am called!'. jkl value]. will be the result of executing the block jkl.

I may be the only one, but I find the second sentence below a little bit obscure:
It just so happens, though, that c is defined as the block [a := a - 2. b] which returns the value of b and that happens to be a block. So timesRepeat: is happy, and it executes the block b on each iteration in which a is odd.
The semantics of Smalltalk is:
Evaluate the receiver
Evaluate the arguments
Send the message
The order is crucial because evaluations may have side effects.
So, what actually happens is:
Receiver 10 evaluates to 10
Argument a even ifTrue: b ifFalse: c evaluates to b. Side effect a = -1.
The message 10 timesRepeat: b or 10 timesRepeat: [a := a + 1] is sent
Hence, a = 9.

Related

make sub-expressions based on addition(+) operator MAPLE

Arbitrary expression be
test := a*b*c+x+a*y+c*z;
output := SomeCommand(test, `+`);
output
[a*b*c,x,a*y,c*z];
Is there any command to do it as a expression.
I did this by converting it into string and using StringSplit command. converting each element from list to expression and in for loop.
test := convert(test, string)
with(StringTools):
output:=StringSplit(test, "+")
["a*b*c", "a*y", "c*z", "x"]
InertForm:-Parse(output[1])
value(output[1])
a*b*c
but, My interest is to get this done as a expression. is there any possibility??
You're question has input but no output. You should observe that the expression that you've assigned to test may have its addends stored in a different order from which they are typed in the input.
It is possible to pick off the addends of a sum, and put them in a list. The very simple code for this is below.
The order in which the addends appear in the list match the order in which they are stored internally.
restart;
f := proc(expr)
if type(expr, `+`) then
[op(expr)];
else
expr;
end if;
end proc:
test := a*b*c+x+a*y+c*z;
test := a b c + a y + c z + x
f( test );
[a b c, a y, c z, x]
Are you the same fellow who's asked all these (somewhat related) questions? Or taking the same course? Q1 Q2 Q3 Q4
If so then could you just tell use what you're really trying to accomplish?

Code not working: sorting array in ocaml

I am new to Ocaml and I have a problem with this code (below). I am trying to write a program to sort array. I divided array into two halfs, and then I used Array.sort on those two arrays ( I am gonna fix that later, so i wont use Array.sort). And then I wanted to compare elements from those two arrays, but my code is not working.
Can anybody tell me where is the problem?
let a =[|5;4;2;6;1;3|] ;;
let n = Array.length a;;
let l= Array.sub a 0 (n/2);;
Array.sort compare l;;
l;;
let ll= Array.length l;;
let r= Array.sub a (n/2) (n/2);;
Array.sort compare r;;
r;;
let lr=Array.length r;;
let merge l r a =
let k =ref 0 in
let i = ref 0 in
let j =ref 0 in
while( !i<ll && !j< lr) do
if(l.(!i) <= r.(!j)) then
a.(!k) <- l.(!i)
i:= !i+1
else begin
a.(!k) <- r.(!j)
j:= !j+1;
k:= !k+1
end;
while (!i<ll) do
a.(!k)<-l.(!i)
i:= !i+1;
k:=!k+1;
done;
while (!j<ll) do
a.(!k) <-r.(!j)
j:= !j+1;
k:= !k+1
done;
done;;
merge l r a;;
Your problem comes from your misunderstanding of what instructions are. Let's try to explain it in a easy and short way :
If your expression returns a value, it's an expression (a bool, an int, a function ...)
If it doesn't return a value (which means it does a side effect), it's an instruction (and we say it returns unit because actually, that's what it does).
When you have a sequence (this is how multiple instructions executing one after another are called), you separate them with a ;.
So, for example, if I write this
let f x = x := 1; print_int !x; print_newline ()
I have a sequence and I have to separate my instructions with ;.
If I wrote :
let f x = x := 1 print_int !x print_newline ()
You can easily understand that OCaml can't know where the instructions are separated (is it x := 1 print_int; !x? Or anything else?) That's why you need ;.
Now comes the problem with if.
If you write
if cond then instr1; instr2
What is parsed is
(if cond then instr1); instr2
Yes, if cond then instr1 is an instruction because, well, it returns unit, no? So instr2 is not in your then block.
But if you write
if cond then let e1 = e2 in instr1; instr2
Then instr2 is in the then block because the construction let ... in creates a block under which all instructions are nested.
If you're starting with OCaml, my precious advice would be this : always writebegin ... end in your conditionnals. You'll be assured that what you write is what you think is parsed.
I'm too new to comment but will point out that every block needs either parentheses () or begin ... end. Thus, your very first if statement should have then begin at the end of the line. The statements between the begin and else need semi-colons to separate them as in:
if(l.(!i) <= r.(!j)) then begin
a.(!k) <- l.(!i);
i:= !i+1
end else begin
a.(!k) <- r.(!j);
j := !j+1;
k:= !k+1
end;
The first two lines of the while loops also need semi-colons because they are also a block of statements. Note that you do not need a semi-colon for the last statement in a block. They are separators, not end-of-statement. Also, as a shortcut, you can use incr i for i := !i + 1 and similar statements. Also, never use l or ll as variable names. :-)

Using an "or" operator between variables for a loop in Stata

I have a set of variables that are string variables. For each value in the string, I create a series of binary (0, 1) variables.
Let's say my variables are Engine1 Engine2 Engine3.
The possible values are BHM, BMN, HLC, or missing (coded as ".").
The values of the variables are mutually exclusive, except missing.
In a hypothetical example, to write the new variables, I would write the following code:
egen BHM=1 if Engine1=="BHM"|Engine2=="BHM"|Engine3=="BHM"`
replace BHM=0 if BHM==.
gen BMN=1 if Engine1=="BMN"|Engine2=="BMN"|Engine3=="BMN"`
replace BMN=0 if BMN==.
gen HLC=1 if Engine1=="HLC"|Engine2=="HLC"|Engine3=="HLC"
replace HLC=0 if HLC==.
How could I rewrite this code in a loop? I don't understand how to use the "or" operator | in a loop.
First note that egen is a typo for gen in your first line.
Second, note that
gen BHM=1 if Engine1=="BHM"|Engine2=="BHM"|Engine3=="BHM"
replace BHM=0 if BHM==.
can be rewritten in one line:
gen BHM = Engine1=="BHM"|Engine2=="BHM"|Engine3=="BHM"
Now learn about the handy inlist() function:
gen BHM = inlist("BHM", Engine1, Engine2, Engine3)
If that looks odd, it's because your mathematics education led you to write things like
if x = 1 or y = 1 or z = 1
but only convention stops you writing
if 1 = x or 1 = y or 1 = z
The final trick is to write a loop:
foreach v in BHM BMN HLC {
gen `v' = inlist("`v'", Engine1, Engine2, Engine3)
}
It's not clear what you are finding difficult about |. Your code was fine in that respect.
An bug often seen in learner code is like
gen y = 1 if x == 11|12|13
which is legal Stata but almost never what you want. Stata parses it as
gen y = 1 if (x == 11)|12|13
and uses its rule that non-zero arguments mean true in true-or-false evaluations. Thus y is 1 if
x == 11
or
12 // a non-zero argument, evaluates as true regardless of x
or
13 // same comment
The learner needs
gen y = 1 if (x == 11)|(x == 12)|(x == 13)
where the parentheses can be omitted. That's repetitive, so
gen y = 1 if inlist(x, 11, 12, 13)
can be used instead.
For more on inlist() see
articles here
and
here Section 2.2
and
here.
For more on true and false in Stata, see this FAQ

Assigning array elements based on elements in another array

First time post here, and I had a (likely very simple) question.
I wanted to assign the values of elements in one array (A) based on the corresponding values in another array(B), eg if A(1)=2 assign 4 to B(1).
I imagined this would be achieved using DO loops and some if statements. However the If staments I'm using seem to refering to the loop index rather than the specific element at that point.
Can anyone point me in the right direction ?
You could also try a construct with merge... merge constructs a new array from two existing arrays using a mask to choose the correct value:
program test
integer,parameter :: LENGTH=5
integer :: A(LENGTH)
integer :: B(LENGTH)
real :: R(LENGTH)
integer :: i
call random_number(R)
A = int( R*3 )
B = [ ( i,i=1,LENGTH) ]
print *,'A:',A
print *,'B:',B
B = merge( 4, B, A == 2 )
print *,'B:',B
end program
Output:
A: 2 1 2 2 1
B: 1 2 3 4 5
B: 4 2 4 4 5
Explanation:
B = merge( 4, B, A == 2 )
A == 2 constructs a temporary logical array which is .true. at i if A(i) == 2
4 in this case is a temporary array with the same length as B
So, merge choses the value from 4 if the temporary logical array is .true., and the correspond value from B, otherwise.
The resulting vector is written back to B (=)
You might be able to use masked array assignment. Given two arrays, A and B, of the same shape (ie same number of ranks, same size in each dimension), and if you wanted to set elements of B to 4 where the corresponding element of A equals 2 you could simply write
where(A==2) B = 4
where teams up with elsewhere, rather like if and else if, and there is an end where too. Consult your favourite documentation for further details.
If you can't express your operation with where you might (if you have an up to date compiler) be interested in the do concurrent construct. And, if all else fails, there are good old-fashioned do and if to fall back on.

Are there any languages that have a do-until loop?

Is there any programming language that has a do-until loop?
Example:
do
{
<statements>
}
until (<condition>);
which is basically equivalent to:
do
{
<statements>
}
while (<negated condition>);
NOTE: I'm looking for post-test loops.
Ruby has until.
i=0
begin
puts i
i += 1
end until i==5
VBA!
Do-Until-Loop
Do-Loop-Until
Although I think quite a number of people here would doubt if it is a real language at all, but well, BASIC is how Microsoft started (quite weak argument for many, I know)...
It is possible in VB.Net
bExitFromLoop = False
Do
'Executes the following Statement
Loop Until bExitFromLoop
It is also possible in SDF-P on BS2000 (Fujitsu/Siemens Operating System)
/ DECLARE-VARIABLE A
/ DECLARE-VARIABLE SWITCH-1(TYPE=*BOOLEAN)
/ SET-VARIABLE A = 5
/ SET-VARIABLE SWITCH-1 = ON
/ REPEAT
/ A = A + 10
/ IF (A > 50)
/ SET-VARIABLE SWITCH-1 = OFF
/ END-IF
/ UNTIL (SWITCH-1 = OFF)
/ SHOW-VARIABLE A
A = 55
Is is also possible is C or C++ using a macro that define until
Example (definition):
#define until(cond) while(!(##cond))
Example (utilisation):
int i = 0;
do {
cout << i << "\n";
i++;
} until(i == 5);
In VB we can find something like:
Reponse = InputBox("Please Enter Pwd")
Do Until Reponse = "Bob-pwr148" ...
Eiffel offers you an until loop.
from
x := 1
until
x > 100
loop
...
end
There is also an "across" loop as well. Both are very powerful and expressive.
The design of this loop has more to offer. There are two more parts to its grammar that will help us resolve two important "correctness" problems.
Endless loop protection.
Iteration failure detection.
Endless Loop Protection
Let's modify our loop code a little by adding a loop variant.
from
x := 1
v := 1_000
until
x > 100
variant
v
loop
...
v := v - 1
end
The loop variant is (essentially) a count-down variable, but not just any old variable. By using the variant keyword, we are telling the compiler to pay attention to v. Specifically, the compiler is going to generate code that watchdogs the v variable for two conditions:
Does v decrease with each iteration of the loop (are we counting down). It does no good to try and use a count-down variable if it is (in fact) not counting down, right? If the loop variant is not counting down (decreasing by any amount), then we throw an exception.
Does v ever reach a condition of less than zero? If so, then we throw an exception.
Both of these work together through the compiler and variant variable to detect when and if our iterating loop fails to iterate or iterates too many times.
In the example above, our code is communicating to us a story that it expects to iterate zero to 1_000 times, but not more. If it is more, then we stop the loop, which leaves us to wonder: Do we really have cases were we iterate more than 1_000 times, or is there something wrong that our condition is failing to become True?
Loop Invariant
Now that we know what a loop variant is, we need to understand what a loop invariant is.
The invariant is a set of one or more Boolean conditions that must hold True after each iteration through the loop. Why do we want these?
Imagine you have 1_000_000 iterations and one of them fails. You don't have time to walk through each iteration, examining it to see it is okay or not. So, you create a set of one or more conditions that are tested upon completion of each iteration. If the one or all of the conditions fail, then you know precisely which iteration (and its deterministic state) is causing the problem!
The loop invariant might look something like:
from
x := 1
y := 0
v := 1_000
invariant
y = x - 1
until
x > 100
variant
v
loop
...
x := x + 1
y := y + 1
v := v - 1
end
In the example above, y is trailing x by 1. We expect that after each iteration, y will always be x - 1. So, we create a loop invariant using the invariant keyword that states our Boolean assertion. If y fails to be x - 1, the loop will immediately throw an exception and let us know precisely which iteration has failed to keep the assertion True.
CONCLUSION
Our loop is now quite tight and secure—well guarded against failure (bugs, errors).

Resources