Sotto è la funzione repeat
scritta usando un paradigma funzionale, in modo tale che quando chiamata come repeat(square, 2)(5)
applicherà la square
funzione 2
volte sul numero 5
, qualcosa come square(square(5))
.
def repeat(f, n):
def identity(x):
return x
def apply_n_times(n):
def recursive_apply(x):
return apply_n_times(n - 1)(f(x))
if n < 0:
raise ValueError("Cannot apply a function %d times" % (n))
elif n == 0:
return identity
else:
return recursive_apply
return apply_n_times(n)
def square(x):
return mul(x, x)
Riguardo all'astrazione, vedo che repeat(square, 2)
restituisce un dettaglio di implementazione sotto forma di apply_n_times(n - 1)(f(x))
più volte prima di fornire il risultato effettivo.
Per quanto riguarda l'incapsulamento, per l'espressione f = repeat(square, 2)
si potrebbero mutare i membri dell'oggetto funzione, ad esempio: f.__name__='garbage'
Il concetto di higher order function
consente di supportare l'astrazione e l'incapsulamento? Perché restituiscono i dettagli dell'implementazione e forniscono l'accesso per la mutazione.
Tali implementazioni esistenti nei software di grandi dimensioni sono molto noiose da usare, in quanto l'utente deve avere un'idea dell'implementazione prima di utilizzarla.