Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
pp:2026:scala:l02 [2026/03/04 18:29] ldaniel |
pp:2026:scala:l02 [2026/03/05 13:46] (current) ldaniel |
||
|---|---|---|---|
| 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> | ||