Created: 2018-09-17 lun 09:30
[polemica on]
[polemica off]
mortale(giovanni). /* giovanni è un mortale */
mortale(massimo)./* massimo è un mortale */
dio(massimo)./* massimo è un dio */
dio(tommaso)./* tommaso è un dio */
semidio(X) :- /* un semidio è sia dio che mortale */
dio(X), mortale(X).
?- dio(massimo).
true.
?- semidio(massimo).
true.
?- mortale(massimo).
true.
?- mortale(tommaso).
false.
?- semidio(tommaso).
false.
?- dio(tommaso).
true.
La funzione fold_left
delle liste, ha bisogno di alcuni valori di input: una funzione da applicare, un valore iniziale ed una lista di qualcosa. Questa espressione avrà un valore di 15, la somma di tutti i numeri della lista. La funzione (+)
viene applicata per ogni elemento.
List.fold_left (+) 0 [1;2;3;4;5]
Definendo due funzioni e combinandole:
let somma a b = a + b;;
let applica_funzione f = List.fold_left f 0 [1;2;3;4;5];;
applica_funzione somma;; (* -> Int: 5 *)
I codici sopra sono in OCaml, ma in Racket (un dialetto LISP):
(foldl + 0 '(1 2 3 4 5))
Scala è un linguaggio multiparadigma a base funzionale e la stessa espressione precedente diventa:
List(1,2,3,4,5).foldLeft(0)(_+_)
// Oppure:
List(1,2,3,4,5).reduce(_+_)
// Oppure:
(1 to 5).reduce(_+_)
In Ruby:
[1,2,3,4,5].reduce(:+)
# Oppure:
(1..5).reduce(:+)
Definiamo una funzione applica_la_funzione_alla_lista_di_numeri
con due valori di input: f
(una funzione) e lista
(una lista di numeri)
def applica_la_funzione_alla_lista_di_numeri(
f: (Int, Int) => Int,
lista: List[Int]) =
lista.reduce(f)
Poi alcune operazioni aritmetiche:
def somma(a: Int, b: Int) = a + b
def sottrazione(a: Int, b: Int) = a - b
def divisione(a: Int, b: Int) = a / b
def resto(a: Int, b: Int) = a % b
def moltiplicazione(a: Int, b: Int) = a * b
Definiamo una variabile con una lista di numeri e poi applichiamo
val lista = List(1, 2, 3, 4, 5)
applica_la_funzione_alla_lista_di_numeri(somma, lista) // => 15
applica_la_funzione_alla_lista_di_numeri(sottrazione, lista)// => -13
applica_la_funzione_alla_lista_di_numeri(divisione, lista) // => 0
applica_la_funzione_alla_lista_di_numeri(resto, lista)// => 1
applica_la_funzione_alla_lista_di_numeri(moltiplicazione, lista) // => 120
divisione
restituisca 0
?Notate una certa somiglianza?
def applica_la_funzione_alla_lista_di_numeri(
f: (Int, Int) => Int,
lista: List[Int]) =
lista.reduce(f)
def applica_la_funzione_alla_lista[T](
f: (T, T) => T,
lista: List[T]) =
lista.reduce(f)
La sintassi è più semplice, ma il concetto non cambia, il valore somma
è una funzione anonima che viene applicata durante l'iterazione della lista:
# literal syntax
somma = ->(a, b) { a + b }
somma_norm_syntax = lambda { |a,b| a + b }
somma_norm_syntax_alt = lambda do |a,b| a + b end
def applica_la_funzione_alla_lista(f, lista)
lista.reduce(&f)
end
applica_la_funzione_alla_lista(somma, [1,2,3,4,5]) # => 15
Se provo a fare la stessa cosa con l'ECMAScript (javascript moderno)
const applyToList = (f, l) => l.reduce(f);
const somma = (acc, valoreCorrente) => acc + valoreCorrente
applyToList(somma, [1,2,3,4,5]) // => 15
applyToList(somma, ["1",2,3,4,5]) // => 12345
Sia l'ECMAScript che Ruby sono linguaggi dinamici (il tipo è determinato a runtime) ma Ruby in questo caso emetterà un'eccezione (non si mischiano le pere con le mele) :
Traceback (most recent call last): ... reduce_test.rb:1:in `+': no implicit conversion of Integer into String (TypeError)
T_PAAMAYIM_NEKUDOTAYIM
Grazie al linguaggio Scala, si possono progettare nuove strutture
def questo_o_quello(test: Boolean) (questo: => Unit) (quello: => Unit) {
if(test) questo else quello
}
val n = 2
questo_o_quello(n > 3) {
println("è questo")
} {
println("è quello")
}
questo_o_quello
diventa un analogo della struttura if then else
ma di tipo imperativo senza restituire quindi valori.a
e b
, si controlla se b
è zero (questa prima fase rientra ovviamente nell'ambito di un uso moderno dell'algoritmo ed era ignorata da Euclide e dai suoi predecessori, che non conoscevano lo zero). Se lo è, a
è il MCD. Se non lo è, si divide a / b
e si assegna ad r
il resto della divisione (operazione indicata con "a modulo b" più sotto). Se r = 0
allora si può terminare affermando che b
è il MCD cercato, altrimenti occorre assegnare a = =b e =b = r
e si ripete nuovamente la divisione. L'algoritmo può essere anche espresso in modo naturale utilizzando la ricorsione in coda.def MCD(number1: Int, number2: Int): Int = {
val rest = number1 % number2
if (rest == 0) number2
else MCD(number2, rest)
}
def mcm(number1: Int, number2: Int): Int = {
(number1 * number2) / MCD(number1, number2)
}
def mcd(number1, number2)
rest = number1 % number2
rest == 0 ? number2 : mcd(number2, rest)
end
def mcm(number1, number2)
(number1 * number2) / mcd(number1, number2)
end