common-lisp                
            Funktioner som första klassvärden
        
        
            
    Sök…
Syntax
- (funktionsnamn); hämtar funktionsobjektet för det namnet
- #'namn ; syntaktiskt socker för (funktionsnamn)
- (symbol-funktionssymbol); returnerar funktionen bunden till symbol
- (funcall-funktion args ...); samtalsfunktion med args
- (tillämpa funktion arglist); samtalsfunktion med argument som anges i en lista
- (tillämp funktionen arg1 arg2 ... argn arglist); samtalsfunktion med argument som ges av arg1, arg2, ..., argn och resten i listan arglist
parametrar
| Parameter | detaljer | 
|---|---|
| namn | någon (ej utvärderad) symbol som namnger en funktion | 
| symbol | en symbol | 
| fungera | en funktion som ska kallas | 
| args ... | noll eller fler argument ( inte en lista med argument) | 
| arglist | en lista som innehåller argument som ska skickas till en funktion | 
| arg1, arg2, ..., argn | var och en är ett enda argument som ska överföras till en funktion | 
Anmärkningar
När man talar om Lisp-liknande språk skiljer man sig mellan vad som kallas Lisp-1 och Lisp-2. I en Lisp-1 har symboler bara ett värde och om en symbol hänvisar till en funktion kommer värdet på den symbolen att vara den funktionen. I en Lisp-2 kan symboler ha separata tillhörande värden och funktioner och därför krävs en speciell form för att hänvisa till funktionen lagrad i en symbol istället för värdet.
Common Lisp är i grunden en Lisp-2 men det finns faktiskt mer än 2 namnutrymmen (saker som symboler kan hänvisa till) - symboler kan till exempel hänvisa till värden, funktioner, typer och taggar.
Definiera anonyma funktioner
 Funktioner i Common Lisp är förstklassiga värden . En anonym funktion kan skapas med lambda . Här är till exempel en funktion av funcall argument som vi sedan kallar med funcall 
CL-USER> (lambda (a b c) (+ a (* b c)))
#<FUNCTION (LAMBDA (A B C)) {10034F484B}>
CL-USER> (defvar *foo* (lambda (a b c) (+ a (* b c))))
*FOO*
CL-USER> (funcall *foo* 1 2 3)
7
Anonyma funktioner kan också användas direkt. Common Lisp ger en syntax för det.
((lambda (a b c) (+ a (* b c)))    ; the lambda expression as the first
                                   ; element in a form
  1 2 3)                           ; followed by the arguments
Anonyma funktioner kan också lagras som globala funktioner:
(let ((a-function (lambda (a b c) (+ a (* b c)))))      ; our anonymous function
  (setf (symbol-function 'some-function) a-function))   ; storing it
(some-function 1 2 3)                                   ; calling it with the name
Citerade lambda-uttryck är inte funktioner
Observera att citerade lambda-uttryck inte är funktioner i Common Lisp. Detta fungerar inte :
(funcall '(lambda (x) x)
         42)
 För att konvertera ett citerat lambda-uttryck till en funktion använder du coerce , eval eller funcall : 
CL-USER > (coerce '(lambda (x) x) 'function)
#<anonymous interpreted function 4060000A7C>
CL-USER > (eval '(lambda (x) x))
#<anonymous interpreted function 4060000B9C>
CL-USER > (compile nil '(lambda (x) x))
#<Function 17 4060000CCC>
Med hänvisning till befintliga funktioner
Alla symboler i Common Lisp har en plats för en variabel som ska bindas och en separat lucka för en funktion som ska bindas.
 Observera att namnet i det här exemplet endast är för att illustrera. Globala variabler bör inte benämnas foo , utan *foo* . Den senare notationen är en konvention för att göra det klart att variabeln är en speciell variabel med dynamisk bindning . 
CL-USER> (boundp 'foo) ;is FOO defined as a variable?
NIL
CL-USER> (defvar foo 7)
FOO
CL-USER> (boundp 'foo)
T
CL-USER> foo
7
CL-USER> (symbol-value 'foo)
7
CL-USER> (fboundp 'foo) ;is FOO defined as a function?
NIL
CL-USER> (defun foo (x y) (+ (* x x) (* y y)))
FOO
CL-USER> (fboundp 'foo)
T
CL-USER> foo
7
CL-USER> (symbol-function 'foo)
#<FUNCTION FOO>
CL-USER> (function foo)
#<FUNCTION FOO>
CL-USER> (equalp (quote #'foo) (quote (function foo)))
T
CL-USER> (eq (symbol-function 'foo) #'foo)
T
CL-USER> (foo 4 3)
25
CL-USER> (funcall foo 4 3)
;get an error: 7 is not a function
CL-USER> (funcall #'foo 4 3)
25
CL-USER> (defvar bar #'foo)
BAR
CL-USER> bar
#<FUNCTION FOO>
CL-USER> (funcall bar 4 3)
25
CL-USER> #'+
#<FUNCTION +>
CL-USER> (funcall #'+ 2 3)
5
Högre ordningsfunktioner
 Common Lisp innehåller många högre ordningsfunktioner som skickas funktioner för argument och kallar dem. Kanske de mest grundläggande är funcall och apply : 
CL-USER> (list 1 2 3)
(1 2 3)
CL-USER> (funcall #'list 1 2 3)
(1 2 3)
CL-USER> (funcall #'list 1 2 3 4 5)
(1 2 3 4 5)
CL-USER> (apply #'list '(1 2 3))
(1 2 3)
CL-USER> (apply #'list 1 2 '(4 5))
(1 2 3 4 5)
CL-USER> (apply #'+ 1 (list 2 3))
6
CL-USER> (defun my-funcall (function &rest args)
           (apply function args))
MY-FUNCALL
CL-USER> (my-funcall #'list 1 2 3)
(1 2 3)
Det finns många andra högre ordningsfunktioner som till exempel tillämpar en funktion många gånger på element i en lista.
CL-USER> (map 'list #'/ '(1 2 3 4))
(1 1/2 1/3 1/4)
CL-USER> (map 'vector #'+ '(1 2 3 4 5) #(5 4 3 2 10))
#(6 6 6 6 15)
CL-USER> (reduce #'+ '(1 2 3 4 5))
15
CL-USER> (remove-if #'evenp '(1 2 3 4 5))
(1 3 5)
Sammanföra en lista
Funktionen reducera kan användas för att summera elementen i en lista.
(reduce '+ '(1 2 3 4))
;;=> 10
Som standard, minska utför en vänster-associativ reduktion, vilket innebär att summan 10 beräknas som
(+ (+ (+ 1 2) 3) 4)
De första två elementen summeras först, och sedan läggs resultatet (3) till nästa element (3) för att producera 6, som i sin tur läggs till 4, för att producera det slutliga resultatet.
Detta är säkrare än att använda applicera (t.ex. i (applicera '+' (1 2 3 4)) eftersom längden på argumentlistan som kan passeras för att tillämpas är begränsad (se call-argument-limit ), och reducera kommer att fungera med funktioner som bara tar två argument.
Genom att ange nyckelordargumentet från slutet kommer reducering att bearbeta listan i den andra riktningen, vilket innebär att summan beräknas i omvänd ordning. Det är
(reduce '+ (1 2 3 4) :from-end t)
;;=> 10
är beräkning
(+ 1 (+ 2 (+ 3 4)))
Implementera omvänd och återlänga
Common Lisp har redan en omvänd funktion, men om den inte gjorde det, kan det implementeras enkelt med reducera . Får en lista som
(1 2 3) === (cons 1 (cons 2 (cons 3 '())))
den omvända listan är
(cons 3 (cons 2 (cons 1 '()))) === (3 2 1)
Det kanske inte är en uppenbar användning av reducera , men om vi har en "omvänd nackdel" -funktion, säg xcons , så att
(xcons 1 2) === (2 . 1)
Sedan
(xcons (xcons (xcons () 1) 2) 3)
vilket är en minskning.
(reduce (lambda (x y)
          (cons y x))
        '(1 2 3 4)
        :initial-value '())
;=> (4 3 2 1)
Common Lisp har en annan användbar funktion, revappend , som är en kombination av omvänd och bifoga . Konceptuellt vänder den en lista och lägger den till någon svans:
(revappend '(3 2 1) '(4 5 6))
;;=> (1 2 3 4 5 6)
Detta kan också implementeras med reducera . Det är faktiskt detsamma som implementeringen av omvänd ovan, förutom att initialvärdet skulle behöva (4 5 6) istället för den tomma listan.
(reduce (lambda (x y)
          (cons y x))
        '(3 2 1)
        :initial-value '(4 5 6))
;=> (1 2 3 4 5 6)
nedläggningar
Funktioner kommer ihåg det lexikala omfattning de definierades i. På grund av detta kan vi omsluta en lambda i ett låt för att definiera stängningar.
(defvar *counter* (let ((count 0))
                    (lambda () (incf count))))
(funcall *counter*) ;; => 1
(funcall *counter*) ;; = 2
I exemplet ovan är räknarvariabeln endast tillgänglig för den anonyma funktionen. Detta framgår tydligare i följande exempel
(defvar *counter-1* (make-counter))
(defvar *counter-2* (make-counter))
(funcall *counter-1*) ;; => 1
(funcall *counter-1*) ;; => 2
(funcall *counter-2*) ;; => 1
(funcall *counter-1*) ;; => 3
Definiera funktioner som tar funktioner och returnerar funktioner
Ett enkelt exempel:
CL-USER> (defun make-apply-twice (fun)
           "return a new function that applies twice the function`fun' to its argument"
           (lambda (x)
             (funcall fun (funcall fun x))))
MAKE-APPLY-TWICE
CL-USER> (funcall (make-apply-twice #'1+) 3)
5
CL-USER> (let ((pow4 (make-apply-twice (lambda (x) (* x x)))))
           (funcall pow4 3))
81
Det klassiska exemplet på funktionskomposition : ( f ∘ g ∘ h ) ( x ) = f ( g ( h ( x )):
CL-USER> (defun compose (&rest funs)
           "return a new function obtained by the functional compositions of the parameters"
           (if (null funs) 
               #'identity
               (let ((rest-funs (apply #'compose (rest funs))))
                 (lambda (x) (funcall (first funs) (funcall rest-funs x))))))
COMPOSE
CL-USER> (defun square (x) (* x x))
SQUARE
CL-USER> (funcall (compose #'square #'1+ #'square) 3)
100  ;; => equivalent to (square (1+ (square 3)))