¿Es posible utilizar/implementar tacit programming (también conocido como programación sin puntos) en Lisp? Y en caso de que la respuesta sea sí, ¿se ha hecho?Programación tácita en Lisp
Respuesta
Este estilo de programación es posible en CL en principio, pero, al ser un Lisp-2, hay que agregar varios #'
sy funcall
s. Además, a diferencia de Haskell, por ejemplo, las funciones no se curry en CL, y no hay una aplicación parcial implícita. En general, creo que ese estilo no sería muy idiomático CL.
Por ejemplo, se podría definir una aplicación parcial y la composición de esta manera:
(defun partial (function &rest args)
(lambda (&rest args2) (apply function (append args args2))))
(defun comp (&rest functions)
(flet ((step (f g) (lambda (x) (funcall f (funcall g x)))))
(reduce #'step functions :initial-value #'identity)))
(Estos son sólo ejemplos rápidos que nos prepararon rápidamente - en realidad no están probados o bien pensada para diferentes casos de uso.)
Con ellos, algo así como map ((*2) . (+1)) xs
en Haskell se convierte en:
CL-USER> (mapcar (comp (partial #'* 2) #'1+) '(1 2 3))
(4 6 8)
El ejemplo sum
:
CL-USER> (defparameter *sum* (partial #'reduce #'+))
*SUM*
CL-USER> (funcall *sum* '(1 2 3))
6
(En este ejemplo, se puede también ajustar la función celular de un símbolo en lugar de almacenar la función en la celda de valor, con el fin de conseguir alrededor de la funcall.)
En Emacs Lisp, por el camino, la aplicación parcial está incorporada como apply-partially
.
En Qi/Shen, funciones están al curry, y la aplicación parcial implícita (cuando las funciones son llamadas con un argumento) se apoya:
(41-) (define comp F G -> (/. X (F (G X))))
comp
(42-) ((comp (* 2) (+ 1)) 1)
4
(43-) (map (comp (* 2) (+ 1)) [1 2 3])
[4 6 8]
También hay azúcar roscado sintáctica en Clojure que da una sensación similar de "pipelining":
user=> (-> 0 inc (* 2))
2
Sí, esto es posible en general con las funciones correctas. Por ejemplo, aquí hay un ejemplo de la aplicación de la raqueta sum
de la página de Wikipedia:
#lang racket
(define sum (curry foldr + 0))
Dado que los procedimientos no están al curry por defecto, que ayuda a utilizar curry
o escribir sus funciones en un estilo de forma explícita al curry. Podría abstraer esto con una nueva macro define
que usa currying.
SÍ, es posible y @danlei ya lo explicó muy bien. Voy a agregar algunos ejemplos del libro ANSI Common Lisp por Paul Graham, capítulo 6.6 de los constructores de función:
puede definir un constructor función como esta:
(defun compose (&rest fns)
(destructuring-bind (fn1 . rest) (reverse fns)
#'(lambda (&rest args)
(reduce #'(lambda (v f) (funcall f v))
rest
:initial-value (apply fn1 args)))))
(defun curry (fn &rest args)
#'(lambda (&rest args2)
(apply fn (append args args2))))
y utilizar de esta manera
(mapcar (compose #'list #'round #'sqrt)
'(4 9 16 25))
vuelve
((2) (3) (4) (5))
La llamada compose
función:
(compose #'a #'b #'c)
se equlvalent a
#'(lambda (&rest args) (a (b (apply #'c args))))
Esto significa componer puede tomar cualquier número de argumentos, sí.
hacer una función que se suman a 3 argumento:
(curry #'+ 3)
Ver más en el libro.
pero no tiene mucho sentido. Esto lleva a un código malo Más difícil de leer y depurar. Además, casi todos los compiladores CL generarán código lento para eso (listas de argumentos consp, etc.). –
@RainerJoswig Tienes razón. Esto podría mostrar cuán flexible es CL y qué cierre nos puede ayudar ... o_O – juanitofatas
Su ejemplo 'compose' también funciona con mi versión. Acabo de tener un pequeño error de copiar y pegar o un error tipográfico en 'comp' (el orden incorrecto de las llamadas de función en' step', versión de trabajo en el REPL) que está arreglado ahora. Además, creo que Rainer tiene razón: aunque está claro que es bueno poder hacer esto en CL, no es muy idiomático. Haskell se presta mucho más a este estilo de programación.(El estilo de Graham, por cierto, es considerado bastante idiosincrásico por muchos programadores de CL). – danlei
Se podría utilizar algo como (esto es hace un poco más de ->
en Clojure):
(defmacro -> (obj &rest forms)
"Similar to the -> macro from clojure, but with a tweak: if there is
a $ symbol somewhere in the form, the object is not added as the
first argument to the form, but instead replaces the $ symbol."
(if forms
(if (consp (car forms))
(let* ((first-form (first forms))
(other-forms (rest forms))
(pos (position '$ first-form)))
(if pos
`(-> ,(append (subseq first-form 0 pos)
(list obj)
(subseq first-form (1+ pos)))
,@other-forms)
`(-> ,(list* (first first-form) obj (rest first-form))
,@other-forms)))
`(-> ,(list (car forms) obj)
,@(cdr forms)))
obj))
(hay que tener cuidado para exportar también el símbolo $
del paquete en que se colocan ->
- vamos a llamar a ese paquete tacit
- y poner tacit
en el use
cláusula de cualquier paquete donde va a utilizar ->
, por lo ->
y $
se heredan)
Ejemplos de uso:
(-> "TEST"
string-downcase
reverse)
(-> "TEST"
reverse
(elt $ 1))
Esto es más como F # 's |>
(y el tubo de la cáscara) que Haskell de .
, pero son más o menos lo mismo (yo prefiero |>
, pero esto es una cuestión de gusto personal).
para ver lo que está haciendo ->
, simplemente macroexpand el último ejemplo tres veces (en el limo, esto se logra al poner el cursor en la primera (
en el ejemplo y escribir C-c RET
tres veces).
- 1. Programación de Common Lisp Parallel
- 2. programación de robots con lisp?
- 3. ¿influencia de Lisp en el lenguaje de programación de factores?
- 4. referencias variables en Lisp
- 5. Common Lisp a Lisp-n?
- 6. A J2ME lisp?
- 7. Game Oriented Assembler Lisp
- 8. Lisp "algo" en Python?
- 9. Infinito negativo en Lisp
- 10. PINTURA en Emacs Lisp?
- 11. Asociación en Common Lisp
- 12. Lisp en plataformas integradas
- 13. Webdevelopment en Common Lisp
- 14. (define (promedio ...)) en Lisp
- 15. Usando Lisp en C#
- 16. Comparando listas en Lisp
- 17. ¿Qué significa # en LISP
- 18. problemas variable en Lisp
- 19. Anidado si en lisp
- 20. nula en Lisp
- 21. Secuencias en Common Lisp?
- 22. Análisis en Emacs Lisp
- 23. CONS LISP en python
- 24. Gramática Lisp en yacc
- 25. str_replace en Lisp?
- 26. Punteros en Lisp?
- 27. cómo se implementó lisp en lenguaje ensamblador?
- 28. ¿Qué dialecto de LISP está escrito en 'Paradigmas de programación de inteligencia artificial'?
- 29. Cómo implementar Multi-Threads en Common Lisp
- 30. CMS en el lenguaje de programación funcional
La pregunta es sobre Common Lisp, esta respuesta es correcta para Scheme, pero no para CL –
Bueno, en realidad la pregunta era sobre Lisp en general. Agregué CL como una etiqueta ya que es el dialecto Lisp con el que estoy más familiarizado, pero esta respuesta que usa Scheme también es útil. – paldepind