Επιρροές συναρτησιακού προγραμματισμού σε κυρίως προστακτικές γλώσσες
- Λάμδα συναρτήσεις (ανώνυμες συναρτήσεις)
- Συναρτήσεις υψηλότερης τάξης (higher order functions)
- Περιφραστικές λίστες (list comprehensions)
- Μερικές συναρτήσεις (partial functions)
- Οκνηρή αποτίμηση (lazy evaluation)
- Κλειστότητες (closures)
Παραδείγματα απλών λάμδα συναρτήσεων σε C++, Java, Python
simple_lambda.cpp |
---|
| #include <functional>
#include <iostream>
int main() {
auto f = [](double x, double y) {
return x * y;
}; // δήλωση της λάμδα συνάρτησης και ανάθεσή της σε μεταβλητή
std::cout << f(2, 21) << std::endl; // κλήση της λάμδα συνάρτησης
std::cout << [](double x, double y) { return x * y; }(3, 21)
<< std::endl; // δήλωση και άμεση κλήση της λάμδα συνάρτησης
return 0;
}
|
$ g++ simple_lambda.cpp -o simple_lambda
$ ./simple_lambda
42
63
SimpleLambda.java |
---|
| package simple_lambda;
// 1 abstract function
interface MyFunctionalInterface {
int fun(int x, int y);
}
class SimpleLambda {
public static void main(String[] args) {
MyFunctionalInterface f = (int x, int y) -> x * y;
System.out.println(f.fun(2, 21));
}
}
|
$ javac SimpleLambda.java
$ java SimpleLambda
42
simple_lambda.py |
---|
| f = lambda x, y: x * y # δήλωση της λάμδα συνάρτησης και ανάθεσή της σε μεταβλητή
print(f(2, 21)) # κλήση της λάμδα συνάρτησης
print((lambda x, y: x * y)(3, 21)) # δήλωση και άμεση κλήση της λάμδα συνάρτησης
|
$ python simple_lambda.py
42
63
Notebook με παραδείγματα lambdas σε Python
Συναρτήσεις υψηλότερης τάξης σε C++, Java, Python
Ταξινόμηση λεκτικών με βάση το μήκος τους (χρησιμοποιείται ως παράμετρος ανώνυμη συνάρτηση)
sort_with_lambda.cpp |
---|
| #include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> cities{"arta", "ioannina", "preveza", "igoumenitsa"};
sort(cities.begin(), cities.end(),
[](auto a, auto b) { return a.length() < b.length(); });
for (auto city : cities) {
cout << city << endl;
}
}
|
$ g++ sort_with_lambda.cpp -o sort_with_lambda
$ ./sort_with_lambda
arta
preveza
ioannina
igoumenitsa
SortWithLambda.java |
---|
| package sort_with_java;
import java.util.*;
public class SortWithLambda {
public static void main(String[] args) {
List<String> cities = new ArrayList<>(List.of("arta", "ioannina", "preveza", "igoumenitsa"));
cities.sort((a, b) -> a.length() - b.length());
for (String city : cities) {
System.out.println(city);
}
}
}
|
$ javac SortWithLambda.java
$ java SortWithLambda
arta
preveza
ioannina
igoumenitsa
sort_with_lambda.py |
---|
| cities = ["arta", "ioannina", "preveza", "igoumenitsa"]
cities.sort(key=lambda a: len(a))
for city in cities:
print(city)
|
$ python sort_with_lambda.py
arta
preveza
ioannina
igoumenitsa
Περιφραστικές λίστες (list comprehensions) στην Python
Οι περιφραστικές λίστες είναι μια ιδέα που πρωτοεμφανίστηκε στην Haskell αλλά πλέον και άλλες γλώσσες όπως οι Scala, F# και Python έχουν ενσωματώσει τις περιφραστικές λίστες.
Notebook με παραδείγματα περιφραστικών λιστών στην Python
Μερικές συναρτήσεις στην Python
partial_function_example1.py |
---|
| import functools
from operator import add
add5 = functools.partial(add, 5)
print(add5(15))
|
$ python partial_function_example1
20
partial_function_example2.py |
---|
| import functools
def my_func4(a, b, c, d):
return a + b + c + d
my_func3 = functools.partial(my_func4, 1)
my_func2 = functools.partial(my_func3, 2)
my_func1 = functools.partial(my_func2, 3)
print(my_func4(1, 2, 3, 4))
print(my_func3(2, 3, 4))
print(my_func2(3, 4))
print(my_func1(4))
|
$ python partial_function_example2
10
10
10
10
Οκνηρή αποτίμηση (lazy evaluation) στην Python
Στην Python, range είναι μια ακολουθία που δεν μπορεί να τροποποιηθεί (immutable) και η οποία αποτιμάται οκνηρά. Τα στοιχεία της ακολουθίας δεν δημιουργούνται παρά μόνο όταν απαιτούνται.
ranges_are_lazy.py |
---|
| values = range(0, 1_000_000, 1000)
print(values)
print(values[5])
|
$ python ranges_are_lazy.py
range(0, 1000000, 1000)
5000
generators_are_lazy.py |
---|
| # Δημιουργία "άπειρης" ακολουθίας Fibonacci με generator
def a_simple_generator():
a = b = 1
yield a
yield b
while True:
yield a + b
b += a
a = b - a
gen = a_simple_generator()
for _ in range(20):
print(next(gen))
|
$ python generators_are_lazy.py
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
Notebook με παραδείγματα generators στην Python
Κλειστότητες στην Python
closure1.py |
---|
| def outer_func():
message = "Hi"
def inner_function():
print(message) # free variable
return inner_function()
outer_func()
|
closure2.py |
---|
| def outer_func():
message = "Hi"
def inner_function():
print(message) # free variable
return inner_function # αλλαγή σε σχέση με το closure1.py, επιστρέφει το όνομα της εμφωλευμένης συνάρτησης
my_func = outer_func()
my_func()
|
closure3.py |
---|
| def outer_func(msg):
message = msg
def inner_function():
print(message) # free variable
return inner_function
hi_func = outer_func("Hi")
hello_func = outer_func("hello")
hi_func()
hello_func()
|
$ python closure3.py
Hi
Hello
closure4.py |
---|
| import logging
logging.basicConfig(level=logging.INFO)
def logger(func):
def log_func(*args):
logging.info(f'Running "{func.__name__}" with arguments {args}')
print(func(*args))
return log_func
def add(x, y):
return x + y
def sub(x, y):
return x - y
add_logger = logger(add)
sub_logger = logger(sub)
add_logger(3, 3)
sub_logger(3, 3)
|
$ python closure4.py
INFO:root:Running "add" with arguments (3, 3)
6
INFO:root:Running "sub" with arguments (3, 3)
0