# Lesson #14. Lambda expressions

## lambda expression Theory

• A lambda expression is some unnamed expression representing a functional dependency.
• Based on lambda expression, the compiler builds a function, identifies it in some way and replaces this lambda expression with this identifier.
• A lambda expression can be stored in procedural variables, or passed as parameters of a procedural type.
• Sample 1: An example of a lambda expression that returns, first, the square of the parameter, and then returns the parameter to the third power. The lambda expression is stored in the procedural variable x.
1. Declaring of a procedural variable, and then binding it to a lambda expression:

begin var x: integer-> integer; x:= t -> t * t; Print(x(7)); // 49 x := t -> t * t * t; Print(x(7)); // 343 end.

2. Declaring and initialization of a procedural variable at the same time:

begin var x: integer-> integer:= t -> t * t; Print(x(7)); // 49 x := t -> t * t * t; Print(x(7)); // 343 end.
IDE PascalABC.NET allows you to use a beautiful arrow → instead of -> (on the keyboard: with the Alt key pressed, we type 26 on the small numeric keypad).
Sample 2: An example of a procedural variable with two parameters that returns the maximum of the parameters using a lambda expression.
begin var f: (integer,integer) → integer :=(x, y) -> if x > y then result:=x else result:=y; print(f(5,13)) end.
If a procedural variable is intended to store procedures (and not functions), then when declaring it, empty brackets must be specified after the arrow -> ().
Sample 3: An example of a procedural variable with two parameters that outputs the maximum of the parameters using a lambda expression.
begin var f: (integer,integer) → () :=(x, y) -> if x > y then print(x) else print(y); f(5,13) end.
Sample 4: An example of a lambda expression that outputs the squared parameter.
begin var x: integer-> () := t -> (t * t).Print(); x(5) // 25 end.
Sample 5: Example of a procedural variable with tuple assignment: the variable is associated with a lambda expression that takes two integers and returns their sum and product:
1. A classic solution using the procedure:

procedure Pr(a,b:integer; var sum,mult:integer); begin sum:=a+b; mult:=(a*b); end; begin var sum,mult:integer; Pr(2,4,sum,mult); print(sum,mult) // (6,8) end.

2. Solution using a procedural variable with tuple assignment and a lambda expression:

begin var f: (integer,integer) -> (integer, integer); f := (a, b) -> (a + b, a * b); print(f(2, 4)) // (6,8) end.
Lambda function as a parameter
Sample: Create a procedure that outputs a list of values of an arbitrary function of one argument on the range [a;b].

The results when a=-5, b=-1 and function x -> x * x:

-5 25
-4 16
-3 9
-2 4
-1 1


✍ Solution:

procedure Lamb(a, b: integer; f: real-> real); begin for var x := a to b do begin Println(x, f(x)); end end;   begin Lamb(-5, 3, x -> x * x); Writeln; end.

{0.5 points} Task 1:

To do: Create a procedural variable with one parameter — a two-digit number that returns a number in which the digits are swapped. Associate the variable with a lambda expression to perform the task. Do the task twice: the procedural variable returns the value and the procedural variable outputs the value. (see samples 2, 3, 4)

expected output:

enter two-digit number please:
>> 72
27


[Program name: 14task-01.pas]

{0.5 points} Task 2:

To do: Calculate the value of the variable y by one of the two branches:

To solve this, create a procedural variable with two parameters — a and b, and associate it with a lambda expression. Complete the task twice: the procedural variable returns the value and the procedural variable outputs the value. (see samples 2, 3, 4)

expected output:

enter two numbers
>>2
>>5
result: 3


[Program name: 14task-02.pas]

{0.5 points} Task 3:

To do: Create a Triangle(a,h) function that calculates the perimeter of an isosceles triangle using its base a and the height h drawn to the base. (see sample 5 solution 2)

1. Declare the procedural variable TriangleP, defining its type as a function that takes two real parameters and returns a real result:

var TriangleP: (real, real) -> real;

2. Then, assign a lambda expression to this variable, which, using two parameters a and h — the base and height of an isosceles triangle — calculates the perimeter of this triangle (P = 2b+a; the side formula: b2 = (a/2)2 + h2)

expected output:

enter two numbers
>>4
>>6
result: 16.6491106406735


[Program name: 14task-03.pas]

{0.5 points} Task 4:

To do: Declase a TrianglePS(a, P, S) procedure that calculates an equilateral triangle’s perimeter P = 3·a and area S = a2·(3)1/2/4 (a — input triangle side, P and S — output parameters; all parameters are real). Using this procedure, output the perimeters and areas of three equilateral triangles with these sides. Solve this problem twice: a classical procedure and a procedural variable associated with a lambda expression. (see sample 5 solutions 1 and 2)

expected output:

>>2
61.73205080756888
>>5
1510.8253175473055
>>6
1815.5884572681199


[Program name: 14task-04.pas]

## Standard functions and procedures and Transformation of an array elements

Lab 1:

To do: Create the function to search x in the array. The function returns -1 if it is not found and index of the element otherwise.

✍ Algorithm:

function IndexOfW<T>(a: array of T; x: T): integer; begin var n := a.Length; var i := 0; while (i < n) and (a[i] <> x) do i += 1; Result := i = n ? -1 : i; end;   begin var a := new integer[10]; a := arrRandomInteger(10, 0, 10); print(a); print(indexOfW(a, 2)) end.
Lab 2:

To do: Print out how many odd elements are in the array.

Expected output:

[18,10,91,47,35]
3


✍ Algorithm:

begin var a := new integer[5]; a := arrRandomInteger(5); // [18,10,91,47,35] print(a); print(a.Count(a->odd(a))) // 3 end.
Lab 3:

To do: Transform the array elements using the rule: if element is even then substruct it by 1, if it is odd then add 1 to it.

✍ Algorithm:

 begin var a := new integer[5]; a := arrRandomInteger(5); // [4,36,93,36,29] a.Transform(a,a -> a mod 2 = 0 ? a-1 : a + 1); print(a) // [3,35,94,35,30] end.
{0.5 points} Task 5:

To do: Create a randomly generated array. Use the standard functions and procedures to implement the following goals. Print out:

1. reversed array (Reverse())
2. the index of x number (x is entered)
3. the last index of x number (x is entered) (LastIndexOf())
4. true if x exists in the array, false if it doesn’t (Contains())
5. index of the first even element (IndexOf())
6. the number of positive elements in the array (Count()). You should create your own function that returns true if the checked number is positive.
7. maximum element and it’s index (Max(), IndexMax()).
8. transformed array with a rule: if element is positive then square it, if it is negative then set it to 0 (Transform()).

Expected output:

1. [1,6,6,4,9,9,1,3,3,10] result: 10 3 3 1 9 9 4 6 6 1
2. [8,10,0,5,10,7,2,9,8,2]  enter x: >>10  the result: 1
3. [8,10,0,5,10,7,2,9,8,2]  enter x: >>10  the result: 4
4. [8,10,0,5,10,7,2,9,8,2]  enter x: >>3  the result: false
5. [7,1,0,3,2,4,2,10,9,4] result: 2
6. [7,-1,0,3,-2,4,2,-10,9,4] result: 7
7. [7,1,0,3,2,4,2,10,9,4] result: max = 10 indexMax= 7
8. [-8,5,1,-5,-8,10,-9,-7,-7,1] result: 0 25 1 0 0 100 0 0 0 1


[Program name: 14task-05.pas]

1. Open taskBook of pascalAbc.net IDE:
2. Choose ArrTransF group in the dropdown menu and click html-page button:
3. Complete the tasks giving the files the proper names (ArrTransf1.pas etc.)
Lab 4, Loop over some indices:

To do: Create an array of integer elements. Pint out the array values in the interval [10,19] and increase by one it’s positive values with even indexes.

Expected output:

array: [41,90,100,12,16,7,69,23,59,37]
array values in the interval [10,19]: 12 16


✍ Algorithm:

begin var a:=arrRandomInteger(10); print(a); // values in the interval [10,19] foreach var i in a.Indices(x -> x.InRange(10,20)) do print(a[i]);   // positive values with even indexes foreach var i in a.Indices((x,i) -> (i mod 2 = 0) and (x > 0)) do a[i] += 1; end.
{0.4 points} Task 6:

To do: Create a randomly generated array. Use indeces method to print out:

• The values of the array with odd indexes.
• The second half of the array elements.

Expected output:

array: [8,41,56,82,8,93,44,70,6,54]
The second half of the array elements: 8 41 56 82 8
The values of the array with odd indexes: 41 82 93 70 54


[Program name: 14task-06.pas]

Lab 5:

To do: Create the procedure to shift circularly the elements to the left

✍ Algorithm:

procedure CircularShiftLeft<T>(a: array of T); begin var v := a[0]; for var i:=0 to a.Length-2 do a[i] := a[i+1]; a[a.Length-1] := v; end;   begin var a := new integer[5]; a := arrRandomInteger(5); // [56,28,33,57,25] CircularShiftLeft(a); print(a)// [28,33,57,25,56] end.
Lab 6:

To do: Create the procedure to shift circularly the elements to the right

✍ Algorithm:

procedure CircularShiftRight<T>(a: array of T); begin var v := a[a.Length-1]; for var i:=a.Length-1 downto 1 do a[i] := a[i-1]; a[0] := v; end;   begin var a := new integer[5]; a := arrRandomInteger(5); // [25,23,74,17,31] CircularShiftRight(a); print(a)// [31,25,23,74,17] end.
{0.3 points} Task 7:

To do: Create a randomly generated array. At first, transform its elements using the rule: a-1, and after, reverse it’s elements and after, make a circular shift it’s elements to the right and to the left.

Expected output:

array:  [93,25,52,74,76,40,54,13,29,65]
transformed:  [92,24,51,73,75,39,53,12,28,64]
Shift left:  [24,51,73,75,39,53,12,28,64,92]
Shift right:  [92,24,51,73,75,39,53,12,28,64]


[Program name: 14task-7.pas]