Well, there was a debate on the below code between me and my friend. We're a bit confused about the output it produce. Can someone clarify the call-by-reference and call-by value result for the below piece of code?
program params;
var i: integer;
a: array[1..2] of integer;
procedure p(x,y: integer);
begin
x := x + 1;
i := i + 1;
y := y + 1;
end;
begin
a[1] := 1;
a[2] := 2;
i := 1;
p( a[i],a[i] );
output( a[1],a[2] );
end.
The resulting output of this program in the case that the
parameters are transmitted to procedure p by value-result and by reference.
Call by Value
x and y in p are local variables initialized with the actual parameters, while i is a global variable, so the call p( a[i],a[i] ) is equivalent to:
x := 1 /* The value of a[i] */
y := 1 /* The value of a[i] */
x := 2 /* x + 1 */
i := 2 /* i + 1 */
y := 2 /* y + 1 */
and at the end the values 1, 2 are printed since they are the values of a[1], a[2] which weren't changed.
Call by Reference
Both x and y in p are alias for a[1] and (again) a[1] (since i = 1 when the procedure is called), so the call is equivalent to:
a[1] := 2 /* a[1] + 1 */
i := 2 /* i + 1 */
a[1] := 3 /* a[1] + 1 */
and at the end the values 3, 2 are printed.
Call by Name
Call by Name is equivalent to Call by Reference when simple variables are passed as parameters, but is different when you pass an expression that denotes a memory location, like a subscript. In this case the actual parameter is re-evaluated each time it is encountered. So in this case, this is the effect of the call of p( a[i],a[i] ):
a[1] := 2 /* since i = 1, the result is equal to a[1] + 1 */
i := 2 /* i + 1 */
a[2] := 3 /* since i is now 2, the result is equal to a[2] + 1 */
and at the end the values 2, 3 are printed. In practice the implementation calls an anonymous function (a “thunk”), each time it must evaluate a parameter.
Call by Value Result
Just to complete the discussion, here is the case for the value-result parameter passing, in which x and y are initialized at the beginning of the procedure execution with the values of the actual parameters, and, at the end of the execution of the procedure, are copied back to the original variables addresses:
x := 1 /* The value of a[i] */
y := 1 /* The value of a[i] */
x := 2 /* x + 1 */
i := 2 /* i + 1 */
y := 2 /* y + 1 */
a[1] := 2 /* the value of x is copied back to a[1] */
a[1] := 2 /* the value of y is copied back to a[1] (not a[2]!) */
and at the end the values 2, 2 are printed.
For a discussion of the different ways of passing parameters, see for instance this.
procedure p(x, y: integer);
begin
end;
In this case the varaibles passed as parameters are never modified. They are copied either to two registers (likely x: EAX and y: ECX) or to the stack. (depending on the compiler ABI)
procedure p(var x, y: integer);
begin
end;
In this case the original parameters are modified. x and y are pointers to the original variables passed as parameters.
Related
I am programming a procedure in Maple. This procedure receive a list of vector fields (from the ``DifferentialGeometry'' package). I want that in the output they appear, together with the performed computations, the name of the vector fields introduced by the user.
During the procedure I refer to them by the name I have given to the parameter, but I don't actually know the "names of the variables". Is there a way to recover them? I have being looking for in the Maple documentation and in the DGinfo help, but I didn't get anything.
EXAMPLE ADDED
I have simplified the problem to the following. Consider the code:
with(DifferentialGeometry);
DGsetup([x, u], M);
X := evalDG(D_u*x+2*D_x);
myproc := proc (var)
return evalDG(var+D_u)
end proc;
myproc(X)
The output is
But I want modify the code in such a way that the output were something like
X+D_u is 2 D_x + (1+x) D_u
That is, I want to use the name ("X") of the variable in the output, not only the value (2 D_x + x D_u).
Thank you for your time.
Here is one way of handling your example.
restart;
with(DifferentialGeometry):
DGsetup([x, u], M):
myproc := proc(var::uneval) local evar;
evar := eval(var);
return evalDG(var+D_u) = evalDG(evar+D_u);
end proc:
X := evalDG(D_u*x+2*D_x):
myproc(X);
X + D_u = 2 D_u + (1 + x) D_u
Here is a variant on that idea, with two such parameters on the procedure, but also handling then in a more general manner.
restart;
with(DifferentialGeometry):
DGsetup([x, u], M):
myproc := proc(var1::uneval, var2::uneval)
local evars, res;
evars := [var1=eval(var1), var2=eval(var2)];
res := var1 + var2 + D_u;
return res = evalDG(eval(res, evars));
end proc:
X1 := evalDG(D_u*x+2*D_x):
X2 := evalDG(D_u*x+3*D_x):
myproc(X1, X2);
X1 + X2 + D_u = 5 D_x + (1 + 2 x) D_x
I am trying to implement numbering in TRichEdit component, Delphi. Ideally I want to get the same behavior as in these 3rd party component:
As you can see Numbering button works similar way as Bullet button. I mean it sets FirstIdent or LeftIdent (I am not sure) and put the numbers 1,2,3,... instead of bullets. When you move cursor to the left close to number it does not allow to move onto number but jumps one line up.
This is what I got so far:
procedure TMainForm.NumberingButtonClick(Sender: TObject);
var
i: Integer;
s: String;
begin
if NumberingButton.Down then
begin
Editor.Paragraph.Numbering := nsNone;
i := Editor.ActiveLineNo;
s := Editor.Lines[i];
insert(inttostr(i)+'. ', s, 1);
//Editor.Paragraph.LeftIndent := 10;
Editor.Paragraph.FirstIndent := 10;
Editor.Lines[i] := s;
end;
end;
But it does not work as I want. Anybody have any ideas?
This code works exactly how I expected:
procedure TMainForm.NumberingButtonClick(Sender: TObject);
var
i: Integer;
s: String;
fmt: TParaFormat2;
begin
FillChar(fmt, SizeOf(fmt), 0);
fmt.cbSize := SizeOf(fmt);
fmt.dwMask := PFM_NUMBERING or PFM_NUMBERINGSTART or
PFM_NUMBERINGSTYLE or PFM_NUMBERINGTAB;
if NumberingButton.Down then
fmt.wNumbering := 2
else
fmt.wNumbering := 0;
// wNumbering:
// 0 - no numbering
// 1 - bullet list (·, ·, ·, ...).
// 2 - Arabic numbers (1, 2, 3, ...).
// 3 - small letters (a, b, c, ...).
// 4 - capital letters (A, B, C, ...).
// 5 - small Roman numbers (i, ii, iii, ...).
// 6 - capital Roman numbers (I, II, III, ...).
// 7 - Unicode character sequence
fmt.wNumberingStart := 1;
// wNumberingStart:
// The number at which the numbering starts.
fmt.wNumberingStyle := $200;
// wNumberingStyle:
// Numbering Style
// 0 : 1)
// $100 : (1)
// $200 : 1.
// $300 : 1
// $400 : remove list
// $8000 : continues to number the list without changing the style
fmt.wNumberingTab := 1440 div 4;
// wNumberingTab:
// the space between number and paragraph text
Editor.Perform( EM_SETPARAFORMAT, 0, lParam( #fmt ) );
if BulletsButton.Down then
BulletsButton.Down := False;
end;
Thanks to www.decoding.dax.ru
i was "finding Pi" with Monte Carlo Method, but the answer was incorrect. The oryginal code was:
RandomTools[MersenneTwister]: with(Statistics):
tries := 10000:
s := 0;
for i to tries do
if GenerateFloat()^2+GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
It gives answer aroud 2.8-2.85
when I change the code to
s := 0;
x := Array([seq(GenerateFloat(), i = 1 .. tries)]);
y := Array([seq(GenerateFloat(), i = 1 .. tries)]);
for i to tries do
if x[i]^2+y[i]^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
Then the answer is correct. I have no idea why i can't generate number in "for" loop.
I've founded that the mean of it is the same, but the variance is different.
For:
tries := 100000;
A := Array([seq(GenerateFloat(), i = 1 .. 2*tries)]);
s1 := Array([seq(A[i]^2+A[tries+i]^2, i = 1 .. tries)]);
Mean(s1);
Variance(s1);
s2 := Array([seq(GenerateFloat()^2+GenerateFloat()^2, i = 1 .. tries)]);
Mean(s2);
Variance(s2);
output is:
0.6702112097021581
0.17845439723457215
0.664707674135025
0.35463131700965245
What's wrong with it? GenerateFloat() should be as uniform as possible.
Automatic simplification is turning your,
GenerateFloat()^2+GenerateFloat()^2
into,
2*GenerateFloat()^2
before GenerateFloat() is evaluated.
One simple change to get it to work as you expected would be separate them. Eg,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
for i to tries do
t1,t2 := GenerateFloat(),GenerateFloat();
if t1^2+t2^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
Another way is to use a slightly different construction which doesn't automatically simplify. Consider, single right quotes (uneval quotes) don't stop automatic simplification (which is a definition of the term if you want).
'f()^2 + f()^2';
2
2 f()
But the following does not automatically simplify,
a:=1:
'f()^2 + a*f()^2';
2 2
f() + a f()
Therefore another easy workaround is,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
a := 1;
for i to tries do
if GenerateFloat()^2 + a*GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
I get this error on my insertion sort algorithm:
insertionsort.lpr(19,17) Error: Incompatible types: got "Boolean" expected "LongInt"
Here's the line 19 of my code
while j > 0 and A[j]>key do
I have tried googling all over the internet but i couldn't find any syntax errors or anything.
Here's the full code if it helps :
program instert;
uses crt;
const
N = 5;
var
i:integer;
j:integer;
key:integer;
A : Array[1..N] of Integer;
procedure insertionsort;
begin
for i := 2 to N do
begin
key := A[1];
j:= i - 1;
while j > 0 and A[j]>key do
begin
A[j+1] := A[j] ;
j := j-1;
end;
A[j+1] := key ;
end;
end;
begin
A[1]:= 9;
A[2]:= 6;
A[3]:= 7;
A[4]:= 1;
A[5]:= 2;
insertionsort;
end.
I also get the same error on the bubble sort algorithm i did. Here's the error line
bubblesort.lpr(26,14) Error: Incompatible types: got "Boolean" expected "LongInt"
Here's line 26 of my algorithm:
until flag = false or N = 1 ;
Here's the full code:
program bubblesort;
uses crt;
var
flag:boolean;
count:integer;
temp:integer;
N:integer;
A : Array[1..N] of Integer;
procedure bubblesort ;
begin
Repeat
flag:=false;
for count:=1 to (N-1) do
begin
if A[count] > A[count + 1] then
begin
temp := A[count];
A[count] := A[count + 1];
A[count] := temp;
flag := true;
end;
end;
N := N - 1;
until flag = false or N = 1 ;
end;
begin
A[1]:= 9;
A[2]:= 6;
A[3]:= 7;
A[4]:= 1;
A[5]:= 2;
N := 5;
bubblesort;
end.
In Pascal, boolean operators and and or have higher precedence than the comparison operators >, =, etc. So in the expression:
while j > 0 and A[j] > key do
Given that and has higher precedence, Pascal sees this as:
while (j > (0 and A[j])) > key do
0 and A[j] are evaluated as a bitwise and (since the arguments are integers) resulting in an integer. Then the comparison, j > (0 and A[j]) is evaluated as a boolean result, leaving a check of that with > key, which is boolean > longint. You then get the error that a longint is expected instead of the boolean for the arithmetic comparison.
The way to fix it is to parenthesize:
while (j > 0) and (A[j] > key) do ...
The same issue applies with this statement:
until flag = false or N = 1 ;
which yields an error because or is higher precedence than =. So you can parenthesize:
until (flag = false) or (N = 1);
Or, more canonical for booleans:
until not flag or (N = 1); // NOTE: 'not' is higher precedence than 'or'
When in doubt about the precedence of operators, parenthesizing is a good idea, as it removes the doubt about what order operations are going to occur.
I know how to do basic exception handling. So i can raise a message on divide by zero using the 'try except' method.
What i would like to do is, find the variable that causes this error and then change its value on run time.
For Ex:
procedure Calculate();
var
a, b, c : Double;
begin
try
a := 4; //suppose i take this value from user and he enters 4
b := 0; //suppose i take this value from user and he enters 0
c := a/b;
ShowMessage(FloatToStr(c));
except
on E : EZeroDivide do
begin
ShowMessage('Exception message = '+E.Message);
//i am not sure how to identify that its variable 'b' that is causing the error and has to be changed by a default value
get(E....errorVaraiable);
E....errorVaraiable := 0.00001;
c := a/E....errorVariable;
ShowMessage(FloatToStr(c));
end;
end;
Please, can anyone help me with this?
Here's a modified version of your example that does what you want.
procedure Calculate();
var
a, b, c : Double;
begin
a := 4; //suppose i take this value from user and he enters 4
b := 0; //suppose i take this value from user and he enters 0
if IsZero(b) then
begin
ShowMessage('b cannot be 0')
end
else
begin
c := a/b;
ShowMessage(FloatToStr(c));
end;
end;