Anonimne funkcije
U programiranju, anonimna funkcija je funkcija definisana tako da nije vezana za identifikator. Anonimne funkcije su cesto:[1]
- argumenti prosledjeni funkcijama viseg reda, ili
- se koriste za konstruisanje rezultata funkcije viseg reda koja treba da vrati funkciju.
Ako se funkcija koristi jednom, ili ogranicen broj puta, anonimna funkcija moze biti sintaksicki "laksa" od koriscenja imenovane funkcije. Anonimne funkcije su ceste u jezicima funkcionalnog programiranja i jezicima koji podrzavaju funkcije prve klase (first-class funkcije), gde ispunjavaju ulogu tipa funkcije kao sto literali rade za tipove podataka.
Anonimne funkcije je uveo Alonzo Cerc kada je otkrio lambda racun 1936. godine, pre nastanka elektronskih racunara, kada su sve funkcije bile anonimne.[2] U nekoliko programskih jezika, anonimne funkcije su predstavljene kljucnom recju lambda, i anonimne funkcije se cesto nazivaju lambdama ili lambda apstrakcijama***. Anonimne funkcije su deo programskih jezika jos od nastanka programskog jezika Lisp 1958. i sve veci broj modernih programskih jezika podrzava anonimne funkcije. Takodje anonimne funkcije se mogu posmatrati kao forma ugnjezdenih funkcija.
Anonimne funkcije mogu biti koriscenje za funkcionalnost koja ne treba biti imenovana i za kratkotrajnu upotrebu. Neki bitniji primeri su u koriscenju closure i currying funkcija.
Koriscenje anonimnih funkcija je pitanje stila. Njihovo koriscenje nikada nije jedini nacin za resavanje problema; Svaka anonimna funkcija moze biti definisana imenovanom funkcijom i biti pozivana imenom. Neki programeri koriste anonimne funkcije za pisanje kodova koji se nece izvrsavati vise puta, a u sebi sadrzi veliki broj jednolinijskih funkcija.
U nekim programskim jezicima, anonimne funkcije se cesto implementiraju za veoma specificne potrebe kao sto je koriscenje u obliku callback funkcija, ili instanciranje funkcije za konkretne vrednosti, koje mogu biti efikasnije, citljivije i manje sklone greskama nego imenovane funkcije.
Kod u sledecim primerima je napisan u jeziku Python 2.x .
Kad pokusavamo da sortiramo nestandardnim nacinom, koriscenje anonimne funkcije u komparacione svrhe moze biti jednostavnije od koriscenja imenovanih funkcija. Vecina jezika nudi genericku funkciju koja implementira algoritam za sortiranje koji ce sortirati proizvoljne objekte. Ove funkcije obicno primaju proizvolju funkciju poredjenja koja prima dva proizvoljna objekta i vraca vrednosti manje od 0, 0 ili vece od 0 u odnosu na to da li je drugi prosledjen objekat veci, jednak ili manji od prvog prosledjenog.
Sortiranje liste stringova po njihovoj duzini:
>>> a = ['house', 'car', 'bike']
>>> a.sort(lambda x,y: cmp(len(x), len(y)))
>>> print(a)
['car', 'bike', 'house']
Anonimna funkcija u ovom primeru je lambda izraz:
lambda x,y: cmp(...)
Anonimna funkcija prima dva argumenta, x i y, i vraca poredjenje izmedju njih koristeci ugradjenu funkciju cmp().
>>> a = [10, 'number', 11.2]
>>> a.sort(lambda x,y: cmp(x.__class__.__name__, y.__class__.__name__))
>>> print(a)
[11.2, 10, 'number']
Closure funkcije su funkcije koje imaju vrednost u okruzenju koje sadrzi 'bound' promenljive.
Sledeci primer povezuje promenljivu "threshold" sa anonimnom funkcijm koja poredi ulaz sa njom.
def comp(threshold):
return lambda x: x < threshold
Ovo moze sluziti kao generator funkcija poredjenja.
>>> func_a = comp(10)
>>> func_b = comp(20)
>>> print func_a(5), func_a(8), func_a(13), func_a(21)
True True False False
>>> print func_b(5), func_b(8), func_b(13), func_b(21)
True True True False
Bilo bi neprakticno kreirati funkciju za svaku funkciju poredjenja i moze biti neprakticno cuvati vrednost po kojoj se poredi za dalju upotrebu. I pored razloga zasto se closure funkcije koriste, anonimne funkcije su entitet koji sadrzi funkcionalnost koja vrsi poredjenje.
Currying je proces promene funkcije da bi bilo potrebno manje ulaznih vrednosti (u ovom slucaju transformacija funkcije koja izvodi deljenje bilo kog celog broja u onu funkciju koja vrsi deljenje sa skupom celih brojeva).
>>> def divide(x, y):
... return x / y
>>> def divisor(d):
... return lambda x: divide(x, d)
>>> half = divisor(2)
>>> third = divisor(3)
>>> print half(32), third(32)
16 10
>>> print half(40), third(40)
20 13
Koriscenje anonimnih funkcija nije cesta kod currying tehnike, ali se moze koristiti u te svrhe.U primeru iznad, funkcija divisor generise funkciju sa konkretnim deliteljem.Funkcija half i third izvodi funkciju divide sa fiksiranim deliteljiim.
Funkcija divisor takodje primenjuje clousure tehniku tako sto vezuje promenljivu "d".
Python 2.x sadrzi nekoliko funkcija koje primaju anonimne funkcije kao argument.Ovaj odeljak opisuje njih.
Map funkcijavrsi poziv funkcije nad svakim elementom liste. Sledeci primer kvadrira svaki element u nizu anonimnom funkcijom.
>>> a = [1, 2, 3, 4, 5, 6]
>>> print map(lambda x: x*x, a)
[1, 4, 9, 16, 25, 36]
Anonimna funkcija prima argument i mnozi ga sobom (kvadrira ga). Po misljenju kreatora jezika, forma iznad nije preporucljiva, vec predlazu sledecu formu sa istim znacenjem a bolje se uklapa sa namenom jezika:
>>> a = [1, 2, 3, 4, 5, 6]
>>> print [x*x for x in a]
[1, 4, 9, 16, 25, 36]
Filter funkcija vraca sve elemente liste koje imaju vrednost True kad ih prosledimo odredjenoj funkciji.
>>> a = [1, 2, 3, 4, 5, 6]
>>> print filter(lambda x: x % 2 == 0, a)
[2, 4, 6]
Anonimna funkcija proverava da li je prosledjeni argument paran. Isto kao u slucaju sa mapom, kod ispod je preporucljiviji.
>>> a = [1, 2, 3, 4, 5, 6]
>>> print [x for x in a if x % 2 == 0]
[2, 4, 6]
Fold/reduce funkcija prolazi kroz sve elemente liste (obicno s leva na desno), i nagomilava vrednost pri tom prolasku. Cesta upotreba ovoga je kombinovanje elemenata liste u jednu vrednost. Na primer:
>>> a = [1, 2, 3, 4, 5]
>>> print reduce(lambda x,y: x*y, a)
120
Ovo izvrsava sledece
Anonimna funkcija ovde je mnozenje dva argumenta.
Rezultat fold funkcije mora biti jedna vrednost. Umesto toga, i mapa i filter mogu biti kreirani korisnjenjem fold funkcije.U mapi, vrednost koje je nagomilana je zapravo nova lista koja sadrzi rezultate primene funkcije na svaki element originalne liste. U filter funkciji, vrednost koja je nagomilana je nova lista koja sadrzi samo one elemente koji ispunjavaju odredjen uslov.
Sledeca lista programskih jezika neimenovane anonimne funkcije podrzava u potpunosti, delom, ili ne podrzava.
Ova tabela ukazuje ne neke opste trednove. Jezici koji ne podrzavaju anonimne funkcije(C, Pascal, Object Pascal) su konvencijalni strogo tipizirani jezici. Medjutim, strogo tipizirani jezici mogu podrzavati anonimne funkcije.Na primer, ML jezici su strogo tipizirani i sadrze anonimne funkcije, i Delphi, kao dijalekt objektnog Pascal-a je nadogradjen tako da podrzava anonimne funkcije.Takodje, jezici koji tretiraju funkcije kao 'funkcije prvog reda'(Dylan, Haskell, JavaScript,Lisp,ML, Perl,Python, Ruby,Scheme) sadrze anonimne funkcije tako da mogu biti definisane i prosledjene jednostavno kao i tipovi podataka. Medjutim, novi C 11 standard ih dodaje C -u iako je konvencijalan, strogo tipiziran jezik.
Programski jezik | Podrska | Beleske |
---|---|---|
ActionScript | DA | |
Ada | NE | 'Expression' funkcije su deo jezika Ada2012 |
ALGOL 68 | DA | |
Brainfuck | NE | |
Bash | DA | Biblioteka je napravljena tako da sadrzi anonimne funkcije u jeziku Bash. |
C | NE | Podrska je omogucena u Clang-u zajedno sa LLVM comiler-rt bibliotekom. GCC podrska je data za makro implementaciju koja omogucava mogucnost upotrebe. Detalje videti ispod. |
C# | DA | |
C | DA | Podrska postoji od C 11 standarda |
CFML | DA | Podrska postoji od Railo 4 ColdFusion 10 |
Clojure | DA | |
COBOL | NE | Micro Focus-ov nesandardni Managed COBOL dijalekat podrzava lambde, koje se nazivaju anonimnim metodama |
Curl | DA | |
D | DA | |
Dart | DA | |
Delphi | DA | |
Dylan | DA | |
Eiffel | DA | |
Elixir | DA | |
Erlang | DA | |
F# | DA | |
Factor | DA | "Quotations" podrzava ovo |
Fortran | NE | |
Frink | DA | |
Go | DA | |
Gosu | DA | |
Groovy | DA | |
Haskell | DA | |
Haxe | DA | |
Java | DA | Podrzano u Java 8. videti Java ogranicenja ispod za detalje. |
JavaScript | DA | |
Julia | DA | |
Lisp | DA | |
Logtalk | DA | |
Lua | DA | |
MUMPS | NE | |
Mathematica | DA | |
Maple | DA | |
MATLAB | DA | |
Maxima | DA | |
OCaml | DA | |
Octave | DA | |
Object Pascal | DA | Delfi, dijalekat Objektnog paskala podrzava anonimne funkcije jos od Delphi-ja 2009. Oxygene Object Pascal dijalekat ih takodje podrzava. |
Objective-C | DA | |
Pascal | NE | |
Perl | DA | |
PHP | DA | Od verzije PHP 5.3.0 prave annimne funkcije su podrzane. Pre toga, bile su podrzane samo delom, koji je radio slicno kao C#-ova imprementacija. |
PL/I | NE | |
Python | DA | Python podrzava anonimne funkcije kroz lambda sintaksu, koja podrzava samo izraze, ne naredbe. |
R | DA | |
Racket | DA | |
Rexx | NE | |
RPG | NE | |
Ruby | DA | Ruby-jeve anonimne funkcije su nasledjene od Smalltalk-a, nazivaju se 'blokovi' |
Rust | DA | |
Scala | DA | |
Scheme | DA | |
Smalltalk | DA | Smalltalk-ove anonimne funkcije nazivaju se 'blokovi' |
Standard ML | DA | |
Swift | DA | Swift-ove anonimne funkcije se nazivaju 'Closures' |
TypeScript | DA | |
Tcl | DA | |
Vala | DA | |
Visual Basic
.NET v9 |
DA | |
Visual Prolog v 7.2 | DA | |
Wolfram Language | DA |
- ↑ "Higher order functions". learnyouahaskell.com. Retrieved 3 December 2014.
- ↑ Fernandez, Maribel (2009), Models of Computation: An Introduction to Computability Theory, Undergraduate Topics in Computer Science, Springer Science & Business Media, p. 33, ISBN 9781848824348, "The Lambda calculus ... was introduced by Alonzo Church in the 1930s as a precise notation for a theory of anonymous functions"