Funciones


Las funciones son objetos fundamentales en cualquier lenguaje de programación. En Lisp, ya ni te digo.

apply

; pasa a la función suma los elementos de la lista como argumentos
(apply #'+ '(5 4 2))
11
(apply #'append '((1 2 3) (a b c)))
(1 2 3 A B C)

block

; crea un bloque de sentencias y le asigna un nombre
; devuelviendo el resultado de la última sentencia
(block mibloque
  (+ 1 1)
  (+ 2 2))
4
; return-from fuerza salida de un bloque
(block mibloque
  (+ 1 1)
  (when (> 2 1) (return-from mibloque))
  (+ 2 2))
NIL
; return-from puede devolver un valor
(block mibloque
  (+ 1 1)
  (when (> 2 1) (return-from mibloque 7))
  (+ 2 2))
7
; en bloques anidados return-from indica nivel al que volver
(block mibloque
  (+ 1 1)
  (block mibloqueinterno
    (+ 2 2)
    (return-from mibloqueinterno))
  (+ 3 3))
6
(block mibloque
  (+ 1 1)
  (block mibloqueinterno
    (+ 2 2)
    (return-from mibloque))
  (+ 3 3))
NIL

defun

; define función con un argumento
(defun cubo (a) (* a a a))

(cubo 7)
343
; define función con dos argumentos
(defun frac (num den) (/ num den))

(frac 7 14)
; documentando una función
(defun resta (a b)
  "La función sumalos suma un número arbitrario de números"
  (- a b))

(documentation 'resta 'function)
"La función sumalos suma un número arbitrario de números"
1/2
; define función sin argumentos
(defun di-algo ()
  (concatenate 'string
    "Tengamos "
    "la "
    "fiesta "
    "en "
    "paz."))

(di-algo)
"Tengamos la fiesta en paz."
; define función con número mínimo de tres argumentos,
; pero que admite hasta seis, y no más.
; Los que no se utilicen se sustituyen por NIL
(defun forma-lista (a b &optional c d e f)
  (list a b c d e f))

(forma-lista 2 3 4)
(2 3 4 NIL NIL NIL)
; define función con número mínimo de dos argumentos,
; pero que admite hasta seis, y no más.
; Los que no se utilicen se sustituyen por su valores 
; por defecto
(defun forma-lista-bis (a b &optional (c 45) (d 76) (e 56) f)
  (list a b c d e f))

(forma-lista-bis 2 3 4)
(2 3 4 76 56 NIL)
; define función con un argumento mínimo,
; pero que admite hasta tres, y no más.
; Los que no se utilicen se sustituyen por el valor
; del primer argumento
(defun forma-lista-bis-bis (a &optional (b a) (c a))
  (list a b c))

(forma-lista-bis-bis 200 3)
(200 3 200)
; al establecer el valor por defecto de un argumento opcional
; podemos añadir una variable lógica que valga T si la función
; sido invocada con la variable opcional
(defun forma-lista-bis-bis-bis (a &optional (b a bb) (c a cc))
  (list a b c bb cc))

; aquí se utiliza b, pero no c
(forma-lista-bis-bis-bis 200 3)
(200 3 200 T NIL)
; define función con número arbitrario de argumentos,
; la variable mas almacenará en una lista todos los
; argumentos que se pasen a la función, hasta un máximo de
; 50, aunque hay entornos Lisp que admite muchos más
(defun une-al-reves (&rest mas)
  (apply #'append (reverse mas)))

(une-al-reves '(1 2 3) '(a b c))
(A B C 1 2 3)
; variable global que guarda máximo número de argumentos
; que admite una función
call-arguments-limit
4611686018427387903
; define función con número arbitrario de argumentos,
; pero con uno mínimo
(defun sumalos (a &rest mas)
  "La función sumalos suma un número arbitrario de números"
  (apply #'+ (cons a mas)))

(sumalos 4 3 5)
12
; con el símbolo &key los argumentos se pueden escribir en
; cualquier orden utilizando como clave el nombre de la 
; propia variable. Aquí, b utiliza como clave radio.
(defun forma-vector (&key ((:radio b) 1 bb) (c 2 cc) (d 5 dd))
  (list b c d bb cc dd))

(forma-vector :radio 77 :d 3)
(77 2 3 T NIL T)

eval

; evalúa expresión
(defvar s '(+ 1 2 3 4 5))

(eval s)
15
; la expresión a evaluar se puede crear 'al vuelo'
(eval (cons '+ '(1 2 3 4 5)))
15

funcall

; pasa una varios argumentos a una función
; es simalar a apply
(funcall #'+ 1 2 3 4 5)
15
; pasa una varios argumentos a una función
; es simalar a apply
(funcall #'append '(1 2 3) '(a s d))
(1 2 3 A S D)
; ejemplo de como pasar una función como argumento
; a otra función
(defun fun (f a b)
  (funcall f a b))

(list (fun #'+ 4 5) (fun #'* 4 5))
(9 20)

function, #'

; devuelve la función apply
(function apply)
#<FUNCTION APPLY>
; forma abreviada de esta función
#'append
#<FUNCTION APPLY>

lambda

; crea función anónima o sin nombre sin argumentos
(lambda () 999)
#<FUNCTION (LAMBDA ()) {1003A14B0B}>
; ejecución de una función lambda sin argumentos
((lambda () 999))
999
; uso de función lambda para calcular
; los cuadrados de los números en una lista
(map 'list #'(lambda (z) (* z z)) '(1 2 3 4))
(1 4 9 16)
; función sin nombre para aplicar una única vez
((lambda (z) (* z z)) 10)
100
; función lambda de dos argumentos
((lambda (a b) (* a b)) 10 4)
40
; pasa función lambda como argumento a otra función
(defun fun (f a b)
  (funcall f a b))

(fun #'(lambda (x y) (+ x (* y y))) 4 5)
29

let, let*

; Bloque de instrucciones con variables locales
(let (a b c)
  (setf a 2
        b 4
        c 9)
  (* a b c) )
72
; Bloque de instrucciones con variables locales
; declaradas e inicializadas paralelamente
(let ((a 2)
      (b 4)
      (c 9))
  (* a b c) )
72
; Bloque de instrucciones con variables locales
; declaradas e inicializadas secuencialmente
(let* ((a 2)
       (b (+ a 2))
       (c (* a b)))
  (* a b c) )
64

map, mapcar, mapcan, maplist, mapcon

; Aplica función a todos los elementos de una lista
(map 'list #'car '((1 a) (2 b) (3 c)))
(1 2 3)
; Aplica función lambda a todos los elementos de una lista
(map 'list #'(lambda (z) (+ (car z) 1)) '((1 a) (2 b) (3 c)))
(2 3 4)
; map con más de un argumento
(map 'list #'+ '(1 2 3) '(4 5 6))
(5 7 9)
; mapcar y map son similares, pero no necesita indicar tipo de salidad
(mapcar #'car '((1 a) (2 b) (3 c)))
(1 2 3)
; mapcar con más de un argumento
; los elementos sobrantes se ignoran
(mapcar #'+ '(1 2 3) '(4 5 6 7 8))
(5 7 9)
(mapcar #'(lambda (x) (and (numberp x) (list x)))
          '(a 1 b c 3 4 d 5))
(NIL (1) NIL NIL (3) (4) NIL (5))
; mapcan es como mapcar, pero devuelve
; listas unidas, al estilo de nconc
(mapcan #'(lambda (x) (and (numberp x) (list x)))
          '(a 1 b c 3 4 d 5))
(1 3 4 5)
; aplica función sobre las listas
; y luego sucesivamente a sus cdr
(maplist #'append '(1 2 3 4) '(a b) '(+ - *))
((1 2 3 4 A B + - *) (2 3 4 B - *))
; construye listas con los respectivos cdr
(maplist #'list '(1 2 3 4) '(a b c d))
(((1 2 3 4) (A B C D)) ((2 3 4) (B C D)) ((3 4) (C D)) ((4) (D)))
; como maplist, pero une listas al estilo nconc
(mapcon #'list '(1 2 3 4) '(a b c d))
((1 2 3 4) (A B C D) (2 3 4) (B C D) (3 4) (C D) (4) (D))

prog, prog*, go, return

; prog evalúa una secuencia de sentencias, permitiendo
; el uso de variables locales y la sentencia go. Del  
; resultado se encarga la instrucción return
(prog ()
  1)
NIL
(prog ()
  (return 1))
1
; variables locales, inicializadas o no
(prog (x (y 1))
  (setf x 2)
  (return (+ x y)))
3
; Aunque parezca mentira, Lisp también es capaz de hacer código spaghetti.
; Su uso no es práctica aconsejable, pero es muy útil para traducir
; literalmente a Lisp programas escritos en otros lenguajes,
; como Fortran o Basic.
(prog (x (y 1))
   (setf x 2)
   (go posicion2)
   (return (+ x y))
  posicion2
   (return (* x y)) )
2
; asignación de valores en paralelo
(defvar x 1)
(prog ((x 5)
       (y x)) ; aquí asigna el valor de la variable global x
   (return (+ x y)) )
6
; asignación secuencial de valores
(defvar x 1)
(prog* ((x 5)
        (y x)) ; aquí asigna el valor de la variable local x
   (return (+ x y)) )
10

prog1, prog2, progn

; evalúa una secuencia de sentencias y devuelve
; el resultado de la primera
(defvar a)
(defvar b)
(defvar c)
(prog1
  (setf a 7)
  (setf b 8)
  (setf c 9) )
7
; devuelve resultado de la segunda sentencia
(defvar a)
(defvar b)
(defvar c)
(prog2
  (setf a 7)
  (setf b 8)
  (setf c 9) )
8
; devuelve resultado de la última sentencia
(defvar a)
(defvar b)
(defvar c)
(progn
  (setf a 7)
  (setf b 8)
  (setf c 9) )
9

© 2016, TecnoStats