Initializing functions important? - function

My teacher said that initializing a function is important. I know why you would initialize a variable, but don't understand why you'd do that with a function.
function f(n: integer):integer;
begin
f := 0; //what my teacher wants me to do
Result := n + 1;
end;

In Delphi function Result is undefined unless you set specific value to it. So you always have to initialize/set function Result at some point in your function.
In your specific example initializing is not important because there is only single execution path that sets value with f := n + 1;
Also Delphi compiler can recognize that value assigned in first line is never used and show you warning message (depending on version and warning settings): H2077: Value assigned to ‘Result’ never used
function f(n: integer):integer;
begin
Result := 0; // not important because it will be set with next line
Result := n + 1;
end;
In more complex functions you can have more execution paths and you have to make sure that each single one sets the function result. Sometimes it is simpler and safer to initialize function result up front to some default value.
function f(n: integer):integer;
begin
Result := 0; // this is important because if n <= 0 Result will be undefined
if n > 0 then Result := n + 1;
end;
Of course, you can write above as
function f(n: integer):integer;
begin
if n > 0 then Result := n + 1
else Result := 0;
end;
Upfront initialization is not necessary. However, it is necessary that function result is set for each possible execution path in your function.
Also, using function name to set function value is obsolete technique. Using Result is preferable.
One important note. Different languages have different rules about returning/seting function results. There is no “one rules them all”. Keep in mind that this is very language specific question.

Related

Is using base case variable in a recursive function important?

I'm currently learning about recursion, it's pretty hard to understand. I found a very common example for it:
function factorial(N)
local Value
if N == 0 then
Value = 1
else
Value = N * factorial(N - 1)
end
return Value
end
print(factorial(3))
N == 0 is the base case. But when i changed it into N == 1, the result is still remains the same. (it will print 6).
Is using the base case important? (will it break or something?)
What's the difference between using N == 0 (base case) and N == 1?
That's just a coincidence, since 1 * 1 = 1, so it ends up working either way.
But consider the edge-case where N = 0, if you check for N == 1, then you'd go into the else branch and calculate 0 * factorial(-1), which would lead to an endless loop.
The same would happen in both cases if you just called factorial(-1) directly, which is why you should either check for > 0 instead (effectively treating every negative value as 0 and returning 1, or add another if condition and raise an error when N is negative.
EDIT: As pointed out in another answer, your implementation is not tail-recursive, meaning it accumulates memory for every recursive functioncall until it finishes or runs out of memory.
You can make the function tail-recursive, which allows Lua to treat it pretty much like a normal loop that could run as long as it takes to calculate its result:
local function factorial(n, acc)
acc = acc or 1
if n <= 0 then
return acc
else
return factorial(n-1, acc*n)
end
return Value
end
print(factorial(3))
Note though, that in the case of factorial, it would take you way longer to run out of stack memory than to overflow Luas number data type at around 21!, so making it tail-recursive is really just a matter of training yourself to write better code.
As the above answer and comments have pointed out, it is essential to have a base-case in a recursive function; otherwise, one ends up with an infinite loop.
Also, in the case of your factorial function, it is probably more efficient to use a helper function to perform the recursion, so as to take advantage of Lua's tail-call optimizations. Since Lua conveniently allows for local functions, you can define a helper within the scope of your factorial function.
Note that this example is not meant to handle the factorials of negative numbers.
-- Requires: n is an integer greater than or equal to 0.
-- Effects : returns the factorial of n.
function fact(n)
-- Local function that will actually perform the recursion.
local function fact_helper(n, i)
-- This is the base case.
if (i == 1) then
return n
end
-- Take advantage of tail calls.
return fact_helper(n * i, i - 1)
end
-- Check for edge cases, such as fact(0) and fact(1).
if ((n == 0) or (n == 1)) then
return 1
end
return fact_helper(n, n - 1)
end

Why are these lines of code in Pascal necessary?

The following example in Pascal was given in a book dedicated to the basics of programming. The function ReadLongint is supposed to check whether the input is 0-9 encoded in a char type. The function then returns true or false depending on the check results, as well as a variable for calculations, rendered into an integer via the operator ord().
Being a newbie I've had hard times figuring out how exactly this code works. But even the bigger mystery for me was the necessity of line 9.
'repeat
read(c);
position := position + 1;
until (c <> #32) and (c <> #10);'
I can see that it's a cycle which repeats itself if you input Space or Enter. However, I've checked the program without these lines, substituting it with a simple read(c); , and the program seems to work just fine. Can somebody please explain the role of this line in the example?
Here is the full program:
function ReadLongint(var check: longint): boolean;
var
c: char;
number: longint;
position: integer;
begin
number := 0;
position := 0;
repeat
read(c);
position := position + 1;
until (c <> #32) and (c <> #10);
while (c <> #32) and (c <> #10) do
begin
if (c < '0') or (c > '9') then
begin
writeln('Unexpected ''', c, ''' in position: ', position);
readln;
ReadLongint := false;
exit
end;
number := number * 10 + ord(c) - ord('0');
read(c);
position := position + 1
end;
check := number;
ReadLongint := true
end;
var
x, y: longint;
ok: boolean;
begin
repeat
write('Please type the first number: ');
ok := ReadLongint(x)
until ok = true;
repeat
write('Please type the second number: ');
ok := ReadLongint(y)
until ok = true;
writeln(x, ' times ', y, ' is ', x * y)
end.
Your readLongInt function wants to (partially) mimic the behavior of read/readLn. The behavior of read/readLn differs slightly if the destination variable is an integer (or real) or char value. The ISO Standard 7185 puts it like that:
c) If v is a variable-access possessing the integer-type (or subrange thereof), read(f, v) shall satisfy the following requirements. No component of s shall equal end‑of‑line. The components of r, if any, shall each, and (s ~t ~u).first shall not, equal either the char-type value space or end‑of‑line. […]
Translated to plain English: Leading spaces and newlines are ignored when interpreting a number (i. e. an integer [or real] variable as the destination). This is quite different to read/readLn in conjunction with a char‑variable where ' ' is a legal value, thus it is not “skipped”, you know.
The until (c <> #32) and (c <> #10) loop is trying to imitate the behavior of read(check) although the actually used read(c) merely reads a single char value, one after another.
PS: It always makes me cringe seeing ok = true. I hope you, unlike the author(s) of the textbook, knows that the = true is redundant, merely an identity.

How can this be the output?

It is simple program, but the output of the program is so unexpected .
Programming language : ActionScript 3.0
So, we have 3 kinds of syntax:
// 1. Variable declaration.
var a:int;
// 2. Assign value to variable.
a = 0;
// 3. Declare variable and assign value in one go.
var b:int = 1;
The tricky moment is that in AS3 variable declaration is NOT an operation. It is a construction that tells compiler you are going to use a variable with a certain name and type within a given context (as a class member or as a timeline variable or as a local variable inside a method). It literally does not matter where in the code you declare your variables. AS3 is, I must admit, ugly from this very perspective. The following code might look weird yet it is syntactically correct. Lets read and understand what it does and why.
// As long as they are declared anywhere,
// you can access these wherever you want.
i = 0;
a = 0;
b = -1;
// The 'for' loop allows a single variable declaration
// within its parentheses. It is not mandatory that
// declared variable is an actual loop iterator.
for (var a:int; i <= 10; i++)
{
// Will trace lines of 0 0 -1 then 1 1 0 then 2 2 1 and so on.
trace(a, i, b);
// You can declare a variable inside the loop, why not?
// The only thing that actually matters is that you assign
// the 'a' value to it before you increment the 'a' variable,
// so the 'b' variable will always be one step behind the 'a'.
var b:int = a;
a++;
}
// Variable declaration. You can actually put
// those even after the 'return' statement.
var i:int;
Let me say it again. The place where you declare your variables does not matter, just the fact you do at all. Declaring variable is not an operation. However, assigning a value is. Your code actually goes as following:
function bringMe(e:Event):void
{
// Lets explicitly declare variables so that assigning
// operations will come out into the open.
var i:int;
var score:int;
for (i = 1; i <= 10; i++)
{
// Without the confusing declaration it is
// obvious now what's going on here.
score = 0;
score++;
// Always outputs 1.
trace(score);
// Outputs values from 1 to 10 inclusive, as expected.
trace(i);
}
}

Scilab not returning variables in variable window

I have created a function that returns the magnitude of a vector.the output is 360x3 dimension matrix. the input is 360x2.
Everything works fine outside the function. how do i get it to work ?
clc
P_dot_ij_om_13= rand(360,2); // 360x2 values of omega in vectors i and j
//P_dot_ij_om_13(:,3)=0;
function [A]=mag_x(A)
//b="P_dot_ijOmag_"+ string(k);
//execstr(b+'=[]'); // declare indexed matrix P_dot_ijOmag_k
//disp(b)
for i=1:1:360
//funcprot(0);
A(i,3)=(A(i,2)^2+A(i,1)^2)^0.5; //calculates magnitude of i and j and adds 3rd column
disp(A(i,3),"vector magnitude")
end
funcprot(1);
return [A] // should return P_dot_ijOmag_k in the variable browser [360x3 dim]
endfunction
mag_x(P_dot_ij_om_13);
//i=1;
//P_dot_ij_om_13(i,3)= (P_dot_ij_om_13(i,2)^2+P_dot_ij_om_13(i,1)^2)^0.5;// example
You never assigned mag_x(P_dot_ij_om_13) to any variable, so the output of this function disappears into nowhere. The variable A is local to this function, it does not exist outside of it.
To have the result of calculation available, assign it to some variable:
res = mag_x(P_dot_ij_om_13)
or A = mag_x(P_dot_ij_om_13) if you want to use the same name outside of the function as was used inside of it.
By the way, the Scilab documentation discourages the use of return, as it leads to confusion. The Scilab / Matlab function syntax is different from the languages in which return specifies the output of a function:
function y = sq(x)
y = x^2
endfunction
disp(sq(3)) // displays 9
No need for return here.

Delphi - for - loop

is there solution in Delphi 7 for deynamically creating for-loop cycles?
for example, i want to have a function that generates 1..n for-cycles
for example:
function generate_binary(var number_of_loops:integer):string
var x:word
begin
for x:=1 to number_of_loops do begin
for ... cycle 1
...
...
...
for ... cycle[x]
//code
end; //cycle n
end; //cycle[x]
end;
end;
is there some code for doing that? Or i must manually set every for.. cycles?
This is not direct answer to the topic question, but an example of particular problem solving. There are more effective methods of generation (especially for numbers, not for strings).
Look at this recursive code to generate all strings with predefined length and number of 1's. Note that output size will very large for big Len (number of combination C(N,K) is exponential function)
procedure Generate01Combination(Len, OnesLeft: Integer; s: string);
begin
if Len = 0 then
Memo1.Lines.Add(s)
else begin
if Len > OnesLeft then
Generate01Combination(Len - 1, OnesLeft, s + '0');
if OnesLeft > 0 then
Generate01Combination(Len - 1, OnesLeft - 1, s + '1');
end;
end;
begin
Generate01Combination(5, 2, '');
end;
outputs
00011
00101
00110
01001
01010
01100
10001
10010
10100
11000
Yes, you can kind of "generate loops" - if you enclose them into procedures and pass those procedures as procedure pointers.
But you said for ... cycle[1] - WHAT is that "..." ? Is it for I := 1 to 4 do cycle[1]() ? Or is it for I := cycle[1] to 10 do ; ? It all fits in!
So, well, - and yes, you indeed came with XYZ problem,- I will make an answer that formally fits, I think, but is hardly to help you with your own problem.
type TLoopProc = procedure(const LoopCount: integer);
procedure Loop1(const LoopCount: integer); var i: integer;
begin
for I := 1 to LoopCount do ShowMessage('Loop1 loop is burning!');
end;
procedure Loop2(const LoopCount: integer); var i: integer;
begin
for I := 1 to LoopCount do ShowMessage('Loop2 loop is burning!');
end;
procedure Loop3(const LoopCount: integer); var i: integer;
begin
for I := 1 to LoopCount do ShowMessage('Loop3 loop is burning!');
end;
procedure Loop4(const LoopCount: integer); var i: integer;
begin
for I := 1 to LoopCount do ShowMessage('Loop4 loop is burning!');
end;
var Loops: array[1..4] of TLoopProc;
function generate_binary(const number_of_loops:integer):string
var x,y:word;
begin
Result := '1234';
for x := 1 to number_of_loops do begin
for y := 1 to x do begin
Loops[y](x+y);
end;
end;
end;
BEGIN
Loops[1] := Loop1;
Loops[2] := Loop1;
Loops[3] := Loop1;
Loops[4] := Loop1;
generate_binary(4);
END.
See, formally that does call that ever increasing number of loops.
Those loops which bodies are contained inside their own procedures.
Not that I think you really can apply that to your real task.
But coming back to your real task, it is very very different.
You are given two numbers: N <= L with N being number of "1" to position in the string of Length L.
To me it looks a slightly hidden example of mathematical induction.
Can you position one single "1" in the string? I think you can.
But if you have all the strings with a single "1" - can you position the second "1" to the right of it? And then the 3rd "1" ?
So we would not search for the strings, we would search for ones' positions, sequences like 4-6-8-9-15-16-29-....
var results: iJclStringList;
// here it is just like TStringList, but interface-based, thus needs no `.Free`
type OnePositions = array of integer;
procedure Error;
begin
raise Exception.Create ('We badly screwed'); // or whatever you would make it do
end;
procedure StoreResult( const L: integer; const P1: OnePositions );
var R: string; i,Prev1,Next1: integer;
begin
R := StringOfChar( '0', L );
Prev1 := 0;
// if those Low/High functions are not yet implemented in Delphi7,
// you may run the loop from 0 to Prev(Length(P1))
// to go through all the P1 array elements
for i := Low(P1) to High(P1) do begin
Next1 := P1[i]; // position for next "1"
if Next1 > Length(R) then Error; // outside of string
if Prev1 >= Next1 then Error; // Next "1" is left of previous "1"
R[Next1] := '1';
Prev1 := Next1; // tracing what was the right-most "1" inserted
end;
Results.Add(R);
end;
// L - string length, thus maximum position of "1"
// StartAt - the leftmost (minimal) position of the 1st left "1" to place
// positions < StartAt already were taken
// Rest1s - how many "1" left to be placed (we still have to place)
procedure PositionRest(var Pos: OnePositions; const L, StartAt, Rest1s: integer);
var Max, idx, NextRest1s, i: integer;
begin
idx := Length(Pos) - Rest1s; // number of "1" we are setting now
NextRest1s := Rest1s - 1; // how many "1"s to be set by next calls
Max := L - NextRest1s; // rightmost part of string we have to leave free for next "1" to be placed
for i := StartAt to Max do begin
Pos[idx] := i; // placing our dear "1" here or there
if NextRest1s = 0 // did we maybe just positioned the last "1" ?
then StoreResult( L, Pos )
else PositionRest( Pos, L, i+1, NextRest1s);
end;
end;
procedure GenerateAll( const L,N: integer );
var Ones: OnePositions;
begin
results := JclStringList();
SetLength(Ones,N);
PositionRest(Ones, L, 1, N);
Memo1.Lines.Text := results.Text;
results := nil;
end;
var L: integer = 20; N: integer = 7;
GenerateAll( L,N );
Here are results at Phenom X3 710 2.6GHz CPU from CodeTyphon 5.60 and Delphi XE2: http://imgur.com/a/22B9b - 4 variants.
Example:
Only single core was used, would have to think how to make it parallelized;
Sources and Win32 EXE: http://rghost.ru/7lYwX2B4Y and http://rghost.ru/8RHmCKF4D
Project1 built by CT 5.60 and Project2 built by Delphi XE2
PS. Some general advices.
Whenever you can - use const parameters to functions. Only use var parameters when you know what it is and why you do need that. It is very rarely needed !
Do not use word for looping. Today CPU runs in 32 bits or 64 bits ( for Delphi 7 - only 32 bits ) - so use CPU-native type integer or cardinal, it would make it slightly easier for the hardware and 65535 maximum value for word might be too small sometimes.
Delphi 7 is good but old. Did you purchased it? Why to stick with it today? I think you better either purchase modern Delphi version or take free Lazarus/FPC suite (i'd stick with CodeTyphon distro, without controversial Orca);
PPS. I implemented OTL-based multithreading approach.
On a somewhat good note, I had to implement exactly dynamic number of loops approach.
As was expected MT-decoupling required extensive memory copying and multiple FastMM calls, which is uni-threaded by design, so multithreading was nothing but illusion and results were even worse than I expected -
still even that crippled MT-ing would provide to "show first 100 results while others are not being calculated yet.
I could enhance it here and there, getting rid of intermediate dynamics arrays (using lists and pointers instead) and switching to MT-oriented Heap Memory Manager, but that would clearly overflow the topic-started experience. It would be challenging to make most fast implementation, but since no one cares, then be it. Still this task was interesting synthetic example for pushing some OTL features and bounds.