Lambda

Verso la fine dei ruggenti anni ’20 la Lancia Lambda era tra le automobili più belle e innovative. E sì! a Torino non c’era solo la Fiat. Eccola, in versione standard e Dilambda

Ma non è di questa lambda che voglio parlare bens’ di un’altra molto più attuale, quella di Python:

An anonymous inline function consisting of a single expression which is evaluated when the function is called. The syntax to create a lambda function is lambda [arguments]: expression

preso da qui. O, se vogliamo una seconda opinione:

Lambda forms (lambda expressions) have the same syntactic position as expressions. They are a shorthand to create anonymous functions; the expression lambda arguments: expression yields a function object. The unnamed object behaves like a function object defined with

def <lambda>(arguments):
return expression

See section Function definitions for the syntax of parameter lists. Note that functions created with lambda forms cannot contain statements or annotations.

expression_nocond      ::=  or_test | lambda_form_nocond

Che poi alla fine della fiera:

Note that the lambda form is merely a shorthand for a simplified function definition; a function defined in a “def” statement can be passed around or assigned to another name just like a function defined by a lambda form. The “def” form is actually more powerful since it allows the execution of multiple statements and annotations.

Ma serve lambda, e si usa? Sì e no. Io sono immune ma se guardate certi codici la trovate spesso, per esempio in acire.

Proviamo a usarla, con un esempio pratico: il calcolo dell’area del cerchio, dato il diametro e del quadrato, dato il lato. Non è granché ma serve al nostro scopo.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import math

PI = math.pi

def cerchio(diametro):
	area = lambda d: PI / 4 * d * d
	return area(diametro)

def quadrato(lato):
	area = lambda l: l * l
	return area(lato)

def qeq(area):
	""" ritorna il lato del quadrato avente
		l'area data. Sì è particolarmente
		scema come funzione. Fatta solo per scopi
		didattici, se la vedessi in un codice
		reale mi perplimerei (o peggio).
	"""
	return (lambda a: math.sqrt(a)) (area)

#test
print 'cerchio', 10, cerchio(10)
print 'quadrato', 10, quadrato(10)
print 'cerchio', 20, cerchio(20)
print 'quadrato', 20, quadrato(20)
print
print 10, qeq((cerchio(10)))
print 20, qeq(cerchio(20))

Le righe 9 e 13 definiscono, usando lambda, la funzione area() rispettivamente per il cerchio e il quadrato. Sono funzioni locali per cui non c’è conflitto per il fatto che abbiano lo stesso nome. Le stesse funzioni vengono richiamate alle righe 10 e 14.
Le righe 26-29 usano le funzioni cerchio() e quadrato().

È inoltre presente la funzione qeq(), quadrato di area equivalente, in cui lambda viene usata in modo ancora più diretto, senza assegnare un nome alla funzione che viene definita. La qeq() viene utilizzata nelle righe 31 e 32.
Eseguendo lo script otteniamo:

$ python lmbd.py
cerchio 10 78.5398163397
quadrato 10 100
cerchio 20 314.159265359
quadrato 20 400

10 8.86226925453
20 17.7245385091
$

Allora: per un matematico va bene ma per un ingegnere, o una generica persona normale, c’è una ridondanza di precisionismo! Si può fare qualcosa? Cerrrto!

#!/usr/bin/python
# -*- coding: utf-8 -*-

import math

PI = math.pi

def cerchio(diametro):
	area = lambda d: PI / 4 * d * d
	return area(diametro)

# main
d = 10
a = cerchio(d)
print a, format(a, '6.4')

print '\nPI approssimato a 3.14'
e = 3.14 / 4 * d * d
print e, format(e, '6.4')

print '\nformat() non mi piace'
a100 = round(100 * a)
a2 = a100 / 100.0
print a2

print '\nlambdabile?'
print (lambda x: (round(100 * x)) / 100.) (a)

$ python fmt.py
78.5398163397  78.54

PI approssimato a 3.14
78.5   78.5

format() non mi piace
78.54

lambdabile?
78.54
$

Viene calcolata l’area del cerchio di diametro 10 (unità lineari a piacere) e visualizzato il risultato utilizzando la funzione format(), riga 15.
Proviamo a fare come i ragazzi della scuola elementare, con pi-greco approssimato a 3.14, righe 17-19, non tanto buono.

Ma se il tutto è di avere due cifre dopo la virgolail puntodecimali il procedimento delle righe 22 e 23 è OK.

È lambdabile? Sì, riga 27, che se non fosse per la notazione infissa sarebbe quasi Lisp, da dove l’ispirazione per la creazione di lambda proviene 😀

Se qualcuno non ne ha ancora abbastanza c’è questo e quest’altro, da dove copioncollo:

4.15. Q. Is it possible to write obfuscated one-liners in Python?
A. Yes. See the following three examples, due to Ulf Bartelt:

# Primes < 1000
print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,\
map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))

Ops! saltano fuori map() e reduce()

mi viene in mente che devo portare Pico a fare la passeggiata 😉

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • knulp  Il 5 agosto 2010 alle 16:40

    ah, i programmi obfuscated! Ottimo post.

    Io comunque direi anche che l’uso più comune di lambda è per ordinare elementi di una lista o array, passando a sort() una funzione anonima.

    Ecco un esempio.

    Buona estate!

  • juhan  Il 5 agosto 2010 alle 19:48

    Molto bello l’esempio e bellissimo il sito http://stackoverflow.com/ ci ho passato quasi un’ora, poi ho bookmarkato 😀 Mi sa che ne riparlerò. Ma non subito, sono tutti in ferie, tra un po’ anch’io 😀
    E naturalmente buone ferie a tutti.

Trackback

  • Funzioni e liste « Ok, panico su 31 ottobre 2011 alle 08:42

    […] che cos’è una lambda function? Juhan ne aveva già parlato qui. Praticamente è una funzione inlined nel codice. Si elimina il nome (inutile, perché la funzione […]

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: