Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
pp:2026:scala:l02 [2026/03/04 18:25]
ldaniel created
pp:2026:scala:l02 [2026/03/05 13:46] (current)
ldaniel
Line 2: Line 2:
  
 Objectives: Objectives:
-  * implement and use **higher-order** functions. A **higher-order** function takes other functions as parameter ​or returns ​them+  * implement and use **higher-order** functions. A **higher-order** function takes other functions as arguments ​or returns ​a function as its result.
   * implement **curry** and **uncurry** functions, and how they should be properly used (review lecture).   * implement **curry** and **uncurry** functions, and how they should be properly used (review lecture).
  
Line 36: Line 36:
 </​code>​ </​code>​
  
-===== 2.2 Custom high order functions =====+===== 2.2 Curry vs Uncurry ===== 
 +**2.2.1** Modify the function below so that it's curry and use it to compute ''​5*3''​ 
 +<code scala> 
 +def multiply(x:​Int,​ y:Int): Int = x * y 
 +</​code>​ 
 + 
 +**2.2.2** Write a definition for the function doubler at 2.1.2 using multiply. 
 + 
 +**2.2.3** Modify the function below so that it's curry and use it to compare 3 numbers and return the maximum 
 +<code scala> 
 +def compare(x: Int, y: Int, z: Int): Int = 
 +
 +  if (x > y && x > z) x 
 +  else if (y > x && y > z) y 
 +  else z 
 +
 +</​code>​ 
 + 
 +===== 2.3 Custom high order functions =====
  
-**2.2.1** Define the function ''​foldWith''​ which uses an operation ''​op''​ to reduce a range of integers to a value. ''​foldWith''​ starts with an initial value ''​acc''​ supplied by the programmer. For instance, given that ''​op''​ is addition (+), the result of folding the range 1 to 3 will be acc+1+2+3=6. ''​foldWith''​ should be curried (it will take the operation and return another function which expects the bounds).+**2.3.1** Define the function ''​foldWith''​ which uses an operation ''​op''​ to reduce a range of integers to a value. ''​foldWith''​ starts with an initial value ''​acc''​ supplied by the programmer. For instance, given that ''​op''​ is addition (+), the result of folding the range 1 to 3 will be acc+1+2+3=6. ''​foldWith''​ should be curried (it will take the operation and return another function which expects the bounds).
 <code scala> <code scala>
 def foldWith (acc: Int)(op: (Int,Int) => Int)(start: Int, stop: Int): Int = { def foldWith (acc: Int)(op: (Int,Int) => Int)(start: Int, stop: Int): Int = {
Line 46: Line 64:
 </​code>​ </​code>​
  
-**2.2.2** Suppose $math[x_1, x_2, x_3] are the only values from a given range. What is the order in which $math[+] is performed, in ''​foldWith(acc)( (x,y) => x+y) ''​ ? Write an alternative implementation for ''​foldWith''​ which would compute: $math[x_1 + (x_2 + (x_3 + acc))], in this particular order.+**2.3.2** Suppose $math[x_1, x_2, x_3] are the only values from a given range. What is the order in which $math[+] is performed, in ''​foldWith(acc)( (x,y) => x+y) ''​ ? Write an alternative implementation for ''​foldWith''​ which would compute: $math[x_1 + (x_2 + (x_3 + acc))], in this particular order.
  
-**2.2.3** Define the function ''​foldConditional''​ which extends ''​foldWith''​ by also adding a predicate ''​p:​ Int => Boolean''​. ''​foldConditional''​ will reduce only those elements of a range which satisfy the predicate. The accumulator should not be filtered.+**2.3.3** Define the function ''​foldConditional''​ which extends ''​foldWith''​ by also adding a predicate ''​p:​ Int => Boolean''​. ''​foldConditional''​ will reduce only those elements of a range which satisfy the predicate. The accumulator should not be filtered.
  
 <code scala> <code scala>
Line 54: Line 72:
 </​code>​ </​code>​
  
-**2.2.4** Write a function ''​foldMap''​ which takes values $math[a_1, a_2, \ldots, a_k] from a range and computes $math[f(a_1)\;​op\;​f(a_2)\;​op\;​\ldots f(a_k)].+**2.3.4** Write a function ''​foldMap''​ which takes values $math[a_1, a_2, \ldots, a_k] from a range and computes $math[f(a_1)\;​op\;​f(a_2)\;​op\;​\ldots f(a_k)].
 Use the ''​apply''​ and ''​foldWith''​ methods. The accumulator should not be transformed by ''​f''​. Use the ''​apply''​ and ''​foldWith''​ methods. The accumulator should not be transformed by ''​f''​.
 <code scala> <code scala>
Line 61: Line 79:
 </​code>​ </​code>​
  
-**2.2.5** Write a function ''​sum''​ which takes values start, end and computes the sum of numbers between start and end.+**2.3.5** Write a function ''​sum''​ which takes values start, end and computes the sum of numbers between start and end.
 Use the curry function ''​foldWith''​ defined before. Use the curry function ''​foldWith''​ defined before.
 <code scala> <code scala>
 def sum(start: Int, stop: Int): Int = ??? def sum(start: Int, stop: Int): Int = ???
-</​code>​ 
- 
-===== 2.3 Curry vs Uncurry ===== 
-**2.3.1** Modify the function below so that it's curry and use it to compute ''​5*3''​ 
-<code scala> 
-def multiply(x:​Int,​ y:Int): Int = x * y 
-</​code>​ 
- 
-**2.3.2** Modify the function below so that it's curry and use it to compare 3 numbers and return the maximum 
-<code scala> 
-def compare(x: Int, y: Int, z: Int): Int = 
-{ 
-  if (x > y && x > z) x 
-  else if (y > x && y > z) y 
-  else z 
-} 
 </​code>​ </​code>​
  
Line 113: Line 115:
 As a result, by executing intense computation on this branch, we would delay other functionalities or would lock into a specific task instead of scheduling. As a result, by executing intense computation on this branch, we would delay other functionalities or would lock into a specific task instead of scheduling.
  
-To solve this limitation, programmers have created ways ('''​functional closures'''​) in which the main thread injects all the needed parameters to functions and then passes them to other threads, from where they can be unpacked and run. +To solve this limitation, programmers have created ways (''​functional closures''​) in which the main thread injects all the needed parameters to functions and then passes them to other threads, from where they can be unpacked and run.  
 + 
 +For a better understanding,​ compare the implementation of ''​curry_for_thread''​ with the one for ''​apply''​ at 2.1.1.
  
-Such an implementation for functional closures is represented by '''​zero-parameter lambdas'''​ where the evaluation is delayed by currying such a function over our method:+Such an implementation for functional closures is represented by ''​zero-parameter lambdas''​ where the evaluation is delayed by currying such a function over our method:
  
 <code scala> <code scala>