Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:2025:scala:l02 [2025/03/05 10:56]
pdmatei
pp:2025:scala:l02 [2025/03/16 01:35] (current)
cata_chiru
Line 48: Line 48:
 **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.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.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.+**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.
  
 <code scala> <code scala>
-def foldConditional(op:​ (Int,Int) => Int, p: Int => Boolean)(start:​ Int, stop: Int): Int = ???+def foldConditional(acc: Int)(op: (Int,Int) => Int, p: Int => Boolean)(start:​ Int, stop: Int): Int = ???
 </​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.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)].
-Use the ''​apply''​ and ''​foldWith''​ methods+Use the ''​apply''​ and ''​foldWith''​ methods. The accumulator should not be transformed by ''​f''​.
 <code scala> <code scala>
-def foldMap(op: (Int,Int) => Int, f: Int => Int)(start: Int, stop: Int): Int = ???+def foldMap(acc: Int)(op: (Int,Int) => Int, f: Int => Int)(start: Int, stop: Int): Int  
 += ??? 
 +</​code>​ 
 + 
 +**2.2.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. 
 +<code scala> 
 +def sum(start: Int, stop: Int): Int = ???
 </​code>​ </​code>​
  
 ===== 2.3 Curry vs Uncurry ===== ===== 2.3 Curry vs Uncurry =====
-**2.3.1** Modify the function below so that it's curry and use it to calculate ​''​5*3''​+**2.3.1** Modify the function below so that it's curry and use it to compute ​''​5*3''​
 <code scala> <code scala>
-def multiply(x:​Int,​ y:Int): Int =x * y+def multiply(x:​Int,​ y:Int): Int = x * y
 </​code>​ </​code>​
  
Line 99: Line 106:
 } }
 </​code>​ </​code>​
 +
 +===== 2.5 Nice to know =====
 +
 +In a computer, we would like the central processing unit / thread to have predominantly a managerial role.
 +
 +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. 
 +
 +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>
 +// Variation 1 - using zero-parameter lambdas
 +// the type of the target function
 +type Result = Int
 +
 +// a closure is represented as a function that takes zero parameters
 +type Closure = () => Result
 +
 +// type of a demo function
 +type TFun = (Int, Int) => Result
 +
 +// run in thread will call that function to evaluate
 +def run_in_thread(f:​ Closure): Result = f()
 +
 +// Dummy method used to illustrate the power of currying
 +// "​f"​ in curry_for_thread
 +def process_data(x:​ Int, y: Int): Int = {
 +  println("​Hello"​)
 +  x + y
 +}
 +
 +// creates a lambda with zero parameters, thus "​delaying"​ the call of f
 +// "​f"​ in run_in_thread
 +def curry_for_thread(f:​ TFun, somex: Int, somey: Int): Closure =
 +  () => f(somex, somey)
 +
 +val close = curry_for_thread(process_data,​ 0, 1)
 +
 +// If you run this code into a Scala Worksheet you will see that "​Hello"​ gets printed when calling the function bellow.
 +// This is thanks to the 0 parameter lambda in curry_for_thread that "​forces"​
 +//                   ​another call of the function for it to execute its body.
 +run_in_thread(close)
 +</​code>​
 +
 +Keep this example in mind! We will meet with it again in a future laboratory! :-)
 +
 +