diff options
| -rw-r--r-- | es-es/common-lisp-es.html.markdown | 692 | 
1 files changed, 692 insertions, 0 deletions
| diff --git a/es-es/common-lisp-es.html.markdown b/es-es/common-lisp-es.html.markdown new file mode 100644 index 00000000..526ea621 --- /dev/null +++ b/es-es/common-lisp-es.html.markdown @@ -0,0 +1,692 @@ +--- + +language: "Common Lisp" +filename: commonlisp-es.lisp +contributors: +  - ["Paul Nathan", "https://github.com/pnathan"] +  - ["Rommel Martinez", "https://ebzzry.io"] +translators: +  - ["ivanchoff", "https://github.com/ivanchoff"] +  - ["Andre Polykanine", "https://github.com/Menelion"] +lang: es-es +--- + +Common Lisp es un lenguaje de proposito general y multiparadigma adecuado para una amplia variedad +de aplicaciones en la industria. Es frecuentemente referenciado como un lenguaje de programación +programable. + +EL punto de inicio clásico es [Practical Common Lisp](http://www.gigamonkeys.com/book/). Otro libro +popular y reciente es [Land of Lisp](http://landoflisp.com/). Un nuevo libro acerca de las mejores +prácticas, [Common Lisp Recipes](http://weitz.de/cl-recipes/), fue publicado recientemente. + +```lisp + +;;;----------------------------------------------------------------------------- +;;; 0. Sintaxis +;;;----------------------------------------------------------------------------- + +;;; Forma general + +;;; CL tiene dos piezas fundamentales en su sintaxis: ATOM y S-EXPRESSION. +;;; Típicamente, S-expressions agrupadas son llamadas `forms`. + +10            ; un atom; se evalua a sí mismo +:thing        ; otro atom; evaluando el símbolo :thing +t             ; otro atom, denotando true +(+ 1 2 3 4)   ; una s-expression +'(4 :foo t)   ; otra s-expression + + +;;; Comentarios + +;;; comentarios de una sola línea empiezan con punto y coma; usa cuatro para +;;; comentarios a nivel de archivo, tres para descripciones de sesiones, dos +;;; adentro de definiciones, y una para líneas simples. Por ejemplo, + +;;;; life.lisp + +;;; Foo bar baz, porque quu quux. Optimizado para máximo krakaboom y umph. +;;; Requerido por la función LINULUKO. + +(defun sentido (vida) +  "Retorna el sentido de la vida calculado" +  (let ((meh "abc")) +    ;; llama krakaboom +    (loop :for x :across meh +       :collect x)))                    ; guarda valores en x, luego lo retorna + +;;; Comentarios de bloques, por otro lado, permiten comentarios de forma libre. estos son +;;; delimitados con #| y |# + +#| Este es un comentario de bloque el cual +   puede abarcar multiples líneas y +    #| +       estos pueden ser anidados +    |# +|# + + +;;; Entorno + +;;; Existe una variedad de implementaciones; La mayoría son conformes a los estándares. SBCL +;;; es un buen punto de inicio. Bibliotecas de terceros pueden instalarse fácilmente con +;;; Quicklisp + +;;; CL es usualmente desarrollado y un bucle de Lectura-Evaluación-Impresión (REPL), corriendo +;;; al mismo tiempo. El REPL permite la exploración interactiva del programa mientras este esta +;;; corriendo + + +;;;----------------------------------------------------------------------------- +;;; 1. Operadores y tipos de datos primitivos +;;;----------------------------------------------------------------------------- + +;;; Símbolos + +'foo ; => FOO  Note que el símbolo es pasado a mayúsculas automáticamente. + +;;; INTERN manualmente crea un símbolo a partir de una cadena. + +(intern "AAAA")        ; => AAAA +(intern "aaa")         ; => |aaa| + +;;; Números + +9999999999999999999999 ; enteros +#b111                  ; binario=> 7 +#o111                  ; octal => 73 +#x111                  ; hexadecimal => 273 +3.14159s0              ; simple +3.14159d0              ; double +1/2                    ; proporciones +#C(1 2)                ; números complejos + +;;; las funciones son escritas como (f x y z ...) donde f es una función y +;;; x, y, z, ... son los argumentos. + +(+ 1 2)                ; => 3 + +;;; Si deseas crear datos literales use QUOTE para prevenir que estos sean evaluados + +(quote (+ 1 2))        ; => (+ 1 2) +(quote a)              ; => A + +;;; La notación abreviada para QUOTE es ' + +'(+ 1 2)               ; => (+ 1 2) +'a                     ; => A + +;;; Operaciones aritméticas básicas + +(+ 1 1)                ; => 2 +(- 8 1)                ; => 7 +(* 10 2)               ; => 20 +(expt 2 3)             ; => 8 +(mod 5 2)              ; => 1 +(/ 35 5)               ; => 7 +(/ 1 3)                ; => 1/3 +(+ #C(1 2) #C(6 -4))   ; => #C(7 -2) + +;;; Boleanos + +t                      ; true; cualquier valor non-NIL es true +nil                    ; false; también, la lista vacia: () +(not nil)              ; => T +(and 0 t)              ; => T +(or 0 nil)             ; => 0 + +;;; Caracteres + +#\A                    ; => #\A +#\λ                    ; => #\GREEK_SMALL_LETTER_LAMDA +#\u03BB                ; => #\GREEK_SMALL_LETTER_LAMDA + +;;; Cadenas son arreglos de caracteres de longitud fija + +"Hello, world!" +"Benjamin \"Bugsy\" Siegel"   ; la barra invertida es un carácter de escape + +;;; Las cadenas pueden ser concatenadas + +(concatenate 'string "Hello, " "world!") ; => "Hello, world!" + +;;; Una cadena puede ser tratada como una secuencia de caracteres + +(elt "Apple" 0) ; => #\A + +;;; FORMAT es usado para crear salidas formateadas, va desde simple interpolación de cadenas +;;; hasta bucles y condicionales. El primer argumento de FORMAT determina donde irá la cadena +;;; formateada. Si este es NIL, FORMAT simplemente retorna la cadena formateada como un valor; +;;; si es T, FORMAT imprime a la salida estándar, usualmente la pantalla, luego este retorna NIL. + +(format nil "~A, ~A!" "Hello" "world")   ; => "Hello, world!" +(format t "~A, ~A!" "Hello" "world")     ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 2. Variables +;;;----------------------------------------------------------------------------- + +;;; Puedes crear una variable global (ámbito dinámico) usando DEFVAR y DEFPARAMETER +;;; el nombre de la variable puede usar cualquier carácter excepto: ()",'`;#|\ + +;;; La diferencia entre DEFVAR y DEFPARAMETER es que reevaluando una expresión +;;; DEFVAR no cambia el valor de la variable. DEFPARAMETER, por otro lado sí lo hace. + +;;; Por convención, variables de ámbito dinámico tienen "orejeras" en sus nombres. + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;;; Puedes usar también caracteres unicode. +(defparameter *AΛB* nil) + +;;; Accediendo a una variable sin asignar tienen como resultado el error +;;; UNBOUND-VARIABLE, sin embargo este es el comportamiento definido. no lo hagas + +;;; puedes crear enlaces locales con LET. en el siguiente código, `me` es asignado  +;;; con "dance with you" solo dentro de  (let ...). LET siempre retorna  el valor  +;;; del último `form`. + +(let ((me "dance with you")) me) ; => "dance with you" + + +;;;-----------------------------------------------------------------------------; +;;; 3. Estructuras y colecciones +;;;-----------------------------------------------------------------------------; + + +;;; Estructuras + +(defstruct dog name breed age) +(defparameter *rover* +    (make-dog :name "rover" +              :breed "collie" +              :age 5)) +*rover*            ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) +(dog-p *rover*)    ; => T +(dog-name *rover*) ; => "rover" + +;;; DOG-P, MAKE-DOG, y DOG-NAME son creados automáticamente por DEFSTRUCT + + +;;; Pares + +;;; CONS crea pares. CAR y CDR retornan la cabeza y la cola de un CONS-pair + +(cons 'SUBJECT 'VERB)         ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB))   ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB))   ; => VERB + + +;;; Listas + +;;; Listas  son estructuras de datos de listas enlazadas, hechas de pares CONS y terminan con un +;;; NIL (o '()) para marcar el final de la lista + +(cons 1 (cons 2 (cons 3 nil)))     ; => '(1 2 3) + +;;; LIST es una forma conveniente de crear listas + +(list 1 2 3)                       ; => '(1 2 3) + +;;; Cuando el primer argumento de CONS es un atom y el segundo argumento es una lista, +;;; CONS retorna un nuevo par CONS con el primer argumento como el primer elemento y el +;;; segundo argumento como el resto del par CONS + +(cons 4 '(1 2 3))                  ; => '(4 1 2 3) + +;;; Use APPEND para unir listas + +(append '(1 2) '(3 4))             ; => '(1 2 3 4) + +;;; o CONCATENATE + +(concatenate 'list '(1 2) '(3 4))  ; => '(1 2 3 4) + +;;; las listas son un tipo de datos centrales en CL, por lo tanto hay una gran variedad +;;; de funcionalidades para ellas, algunos ejemplos son: + +(mapcar #'1+ '(1 2 3))             ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30))  ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4))         ; => NIL +(some #'oddp '(1 2 3 4))           ; => T +(butlast '(subject verb object))   ; => (SUBJECT VERB) + + +;;; Vectores + +;;; Vectores literales son arreglos de longitud fija + +#(1 2 3) ; => #(1 2 3) + +;;; Use CONCATENATE para juntar vectores + +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + + +;;; Arreglos + +;;; Vectores y cadenas son casos especiales de arreglos. + +;;; Arreglos bidimensionales + +(make-array (list 2 2))         ; => #2A((0 0) (0 0)) +(make-array '(2 2))             ; => #2A((0 0) (0 0)) +(make-array (list 2 2 2))       ; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;;; Precaución: los valores iniciales por defecto de MAKE-ARRAY son implementaciones definidas +;;; para definirlos explícitamente: + +(make-array '(2) :initial-element 'unset)  ; => #(UNSET UNSET) + +;;; Para acceder al elemento en 1, 1, 1: + +(aref (make-array (list 2 2 2)) 1 1 1)     ;  => 0 + +;;; Este valor es definido por implementación: +;;; NIL en ECL, 0 en SBCL and CCL. + +;;; vectores ajustables + +;;; los vectores ajustables tienen la misma representación en la impresión como los vectores literales +;;; de longitud fija. + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) +                                   :adjustable t :fill-pointer t)) +*adjvec* ; => #(1 2 3) + +;;; Agregando nuevos elementos + +(vector-push-extend 4 *adjvec*)   ; => 3 +*adjvec*                          ; => #(1 2 3 4) + + +;;; Conjuntos, ingenuamente son listas: + +(set-difference '(1 2 3 4) '(4 5 6 7))   ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7))     ; => 4 +(union '(1 2 3 4) '(4 5 6 7))            ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4))                    ; => (1 2 3 4) + +;;; Sin embargo, necesitarás una mejor estructura de datos que listas enlazadas +;;; cuando trabajes con conjuntos de datos grandes + +;;; Los Diccionarios son implementados como tablas hash. + +;;; Crear tablas hash + +(defparameter *m* (make-hash-table)) + +;;; definir valor + +(setf (gethash 'a *m*) 1) + +;;; obtener valor + +(gethash 'a *m*) ; => 1, T + +;;; las expresiones en CL tienen la facultad de retornar multiples valores. + +(values 1 2) ; => 1, 2 + +;;; los cuales pueden ser asignados con MULTIPLE-VALUE-BIND + +(multiple-value-bind (x y) +    (values 1 2) +  (list y x)) + +; => '(2 1) + +;;; GETHASH es un ejemplo de una función que retorna multiples valores. El primer +;;; valor es el valor de la llave en la tabla hash: si la llave no existe retorna NIL. + +;;; El segundo valor determina si la llave existe en la tabla hash. si la llave no existe +;;; en la tabla hash retorna NIL. Este comportamiento permite verificar si el valor de una +;;; llave es actualmente NIL. + +;;; Obteniendo un valor no existente retorna NIL + +(gethash 'd *m*) ;=> NIL, NIL + +;;; Puedes declarar un valor por defecto para las llaves inexistentes + +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;;; Vamos a manejar los multiples valores de retornno en el código. + +(multiple-value-bind (a b) +    (gethash 'd *m*) +  (list a b)) +; => (NIL NIL) + +(multiple-value-bind (a b) +    (gethash 'a *m*) +  (list a b)) +; => (1 T) + + +;;;----------------------------------------------------------------------------- +;;; 3. Funciones +;;;----------------------------------------------------------------------------- + +;;; Use LAMBDA para crear funciones anónimas. las funciones siempre retornan el valor  +;;; de la última expresión. la representación imprimible de una función varia entre +;;; implementaciones. + +(lambda () "Hello World") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}> + +;;; Use FUNCALL para llamar funciones anónimas. + +(funcall (lambda () "Hello World"))   ; => "Hello World" +(funcall #'+ 1 2 3)                   ; => 6 + +;;; Un llamado a FUNCALL es también realizado cuando la expresión lambda es el CAR de +;;; una lista. + +((lambda () "Hello World"))           ; => "Hello World" +((lambda (val) val) "Hello World")    ; => "Hello World" + +;;; FUNCALL es usado cuando los argumentos son conocidos de antemano.  +;;; de lo contrario use APPLY + +(apply #'+ '(1 2 3))   ; => 6 +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;;; Para nombrar una funcion use  DEFUN + +(defun hello-world () "Hello World") +(hello-world) ; => "Hello World" + +;;; Los () en la definición anterior son la lista de argumentos + +(defun hello (name) (format nil "Hello, ~A" name)) +(hello "Steve") ; => "Hello, Steve" + +;;; las functiones pueden tener argumentos opcionales; por defecto son NIL + +(defun hello (name &optional from) +  (if from +      (format t "Hello, ~A, from ~A" name from) +      (format t "Hello, ~A" name))) + +(hello "Jim" "Alpacas")       ; => Hello, Jim, from Alpacas + +;;; Los valores por defecto pueden ser especificados + + +(defun hello (name &optional (from "The world")) +   (format nil "Hello, ~A, from ~A" name from)) + +(hello "Steve")               ; => Hello, Steve, from The world +(hello "Steve" "the alpacas") ; => Hello, Steve, from the alpacas + +;;; Las funciones también tienen argumentos llaves para permitir argumentos no positionados + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) +  (format t "Hello, ~A ~A, from ~A" honorific name from)) + +(generalized-greeter "Jim") +; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + + +;;;----------------------------------------------------------------------------- +;;; 4. Igualdad +;;;----------------------------------------------------------------------------- + +;;; CL tiene un sistema sofisticado de igualdad. Una parte es tratada aquí. + +;;; Para números use `=` +(= 3 3.0)               ; => T +(= 2 1)                 ; => NIL + +;;; Para identidad de objetos (aproximadamente) use EQL +(eql 3 3)               ; => T +(eql 3 3.0)             ; => NIL +(eql (list 3) (list 3)) ; => NIL + +;;; para listas, cadenas y bit vectores use EQUAL +(equal (list 'a 'b) (list 'a 'b)) ; => T +(equal (list 'a 'b) (list 'b 'a)) ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 5. Control de flujo +;;;----------------------------------------------------------------------------- + +;;; Condicionales + +(if t                ; testar expresión +    "this is true"   ; then expression +    "this is false") ; else expression +; => "this is true" + +;;; En condicionales, todo valor non-NIL es tratado como true + +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) +    'yep +    'nope) +; => 'YEP + +;;; COND en cadena una serie de pruebas para seleccionar un resultado +(cond ((> 2 2) (error "wrong!")) +      ((< 2 2) (error "wrong again!")) +      (t 'ok)) ; => 'OK + +;;; TYPECASE evalua sobre el tipo del valor +(typecase 1 +  (string :string) +  (integer :int)) +; => :int + + +;;; Bucles + +;;; Recursión + +(defun fact (n) +  (if (< n 2) +      1 +    (* n (fact(- n 1))))) + +(fact 5) ; => 120 + +;;; Iteración + +(defun fact (n) +  (loop :for result = 1 :then (* result i) +     :for i :from 2 :to n +     :finally (return result))) + +(fact 5) ; => 120 + +(loop :for x :across "abcd" :collect x) +; => (#\a #\b #\c #\d) + +(dolist (i '(1 2 3 4)) +  (format t "~A" i)) +; => 1234 + + +;;;----------------------------------------------------------------------------- +;;; 6. Mutación +;;;----------------------------------------------------------------------------- + +;;; use SETF para asignar un valor nuevo a una variable existente. Esto fue demostrado +;;; previamente en el ejemplo de la tabla hash. + +(let ((variable 10)) +    (setf variable 2)) +; => 2 + +;;; Un estilo bueno de lisp es minimizar el uso de funciones destructivas y prevenir +;;; la mutación cuando sea posible. + + +;;;----------------------------------------------------------------------------- +;;; 7. Clases y objetos +;;;----------------------------------------------------------------------------- + +;;; No más clases de animales, tengamos transportes mecánicos impulsados por el humano + +(defclass human-powered-conveyance () +  ((velocity +    :accessor velocity +    :initarg :velocity) +   (average-efficiency +    :accessor average-efficiency +   :initarg :average-efficiency)) +  (:documentation "A human powered conveyance")) + +;;; Los argumentos de  DEFCLASS, en orden son: +;;; 1. nombre de la clase +;;; 2. lista de superclases +;;; 3. slot list +;;; 4. Especificadores opcionales + +;;; cuando no hay lista de superclase, la lista vacia indica clase de  +;;; objeto estándar, esto puede ser cambiado, pero no mientras no sepas +;;; lo que estas haciendo. revisar el arte del protocolo de meta-objetos +;;; para más información. + +(defclass bicycle (human-powered-conveyance) +  ((wheel-size +    :accessor wheel-size +    :initarg :wheel-size +    :documentation "Diameter of the wheel.") +   (height +    :accessor height +    :initarg :height))) + +(defclass recumbent (bicycle) +  ((chain-type +    :accessor chain-type +    :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) +  ((number-of-rowers +    :accessor number-of-rowers +    :initarg :number-of-rowers))) + +;;; Invocando DESCRIBE en la clase  HUMAN-POWERED-CONVEYANCE en REPL obtenemos: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +;  [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #<STANDARD-CLASS +;                                                    HUMAN-POWERED-CONVEYANCE>: +;  Documentation: +;    A human powered conveyance +;  Direct superclasses: STANDARD-OBJECT +;  Direct subclasses: UNICYCLE, BICYCLE, CANOE +;  Not yet finalized. +;  Direct slots: +;    VELOCITY +;      Readers: VELOCITY +;      Writers: (SETF VELOCITY) +;    AVERAGE-EFFICIENCY +;      Readers: AVERAGE-EFFICIENCY +;      Writers: (SETF AVERAGE-EFFICIENCY) + +;;; Tenga en cuenta el comportamiento reflexivo disponible. CL fue diseñado +;;; para ser un systema interactivo + +;;; para definir un método, encontremos la circunferencia de la rueda usando +;;; la ecuación  C = d * pi + +(defmethod circumference ((object bicycle)) +  (* pi (wheel-size object))) + +;;; PI es definido internamente en CL + +;;; Supongamos que descubrimos que el valor de eficiencia del número de remeros +;;; en una canoa es aproximadamente logarítmico. Esto probablemente debería +;;; establecerse en el constructor / inicializador. + +;;; Para inicializar su instancia después de que CL termine de construirla: + +(defmethod initialize-instance :after ((object canoe) &rest args) +  (setf (average-efficiency object)  (log (1+ (number-of-rowers object))))) + +;;; luego para construir una instancia y revisar la eficiencia promedio + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;----------------------------------------------------------------------------- +;;; 8. Macros +;;;----------------------------------------------------------------------------- + +;;; las Macros le permiten extender la sintaxis del lenguaje, CL no viene con +;;; un bucle WHILE, por lo tanto es facil escribirlo, Si obedecemos nuestros +;;; instintos de ensamblador, terminamos con: + +(defmacro while (condition &body body) +    "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" +    (let ((block-name (gensym)) (done (gensym))) +        `(tagbody +           ,block-name +           (unless ,condition +               (go ,done)) +           (progn +           ,@body) +           (go ,block-name) +           ,done))) + +;;; revisemos la versión de alto nivel para esto: + +(defmacro while (condition &body body) +    "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" +  `(loop while ,condition +         do +         (progn +            ,@body))) + +;;; Sin embargo, con un compilador moderno, esto no es necesario; El LOOP se  +;;; compila igualmente bien y es más fácil de leer. + +;;; Tenga en cuenta que se utiliza ```, así como `,` y `@`.  ``` es un operador +;;; de tipo de cita conocido como quasiquote; permite el uso de `,` . `,` permite +;;; variables "entre comillas". @ interpola las listas. + +;;; GENSYM crea un símbolo único que garantiza que no existe en ninguna otra parte +;;; del sistema. Esto se debe a que las macros se expanden en el momento de la compilación +;;; y las variables declaradas en la macro pueden colisionar con las variables utilizadas +;;; en un código regular. + +;;; Consulte Practical Common Lisp y On Lisp para obtener más información sobre macros. +``` + + +## Otras Lecturas + +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Common Lisp: A Gentle Introduction to Symbolic Computation](https://www.cs.cmu.edu/~dst/LispBook/book.pdf) + + +## Información extra + +- [CLiki](http://www.cliki.net/) +- [common-lisp.net](https://common-lisp.net/) +- [Awesome Common Lisp](https://github.com/CodyReichert/awesome-cl) +- [Lisp Lang](http://lisp-lang.org/) + + +## Creditos + +Muchas Gracias a la gente de Scheme por proveer un gran punto de inicio +el cual puede ser movido fácilmente a Common Lisp + +- [Paul Khuong](https://github.com/pkhuong) para un buen repaso. | 
