Dans toutes les présentations, tous les tutoriels, les cours, les livres que vous verrez sur LISP, les macros sont citées comme l'aspect le plus puissant et le plus singulier du langage. Elles n'ont en effet pas d'équivalent ailleurs et permettent aussi bien d'améliorer le confort du programmeur par de nouvelles syntaxes plus légères et plus lisibles que de créer des mini-langages adaptés au domaine particulier de programmation.

Je propose dans cette discussion de recueillir les meilleures macros de chacun, expérimenté ou novice.

Pour les novices comme moi, le but serait de faire corriger/améliorer ce que nous avons réussi à faire; pour les "lispiens" expérimentés, ils auraient la satisfaction de partager leur savoir et de faire grandir la communauté

----------------------------

Je me lance tout de suite avec une macro de memoization (la memoization consiste à conserver en cache les résultats d'une fonction afin d'éviter de refaire le calcul lorsqu'elle est appelée avec les mêmes arguments une nouvelle fois).

En python, une syntaxe spéciale a été introduite dans le langage, assez compliquée et variable selon le nombre d'arguments, pour décorer les fonctions déclarées. Je voulais voir, avec Lisp, si le système de macro permettait de faire cela de façon native. La réponse est oui! et j'ai été vraiment surpris d'y parvenir rapidement, étant débutant. Voici la macro:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
;; mémoize la déclaration de fonction en argument
;; ex:
;; (memoize
;;   (defun inc (x) (1+ x)))
;; =>
;; (LET ((#1=#:G42 (MAKE-HASH-TABLE)) (#2=#:G43 (LAMBDA (X) (1+ X))))
;;  (DEFUN INC (X)
;;    (IF (NOT (NTH-VALUE 1 (GETHASH (LIST-TO-SYMBOL '(X)) #1#)))
;;        (PROGN (PRINT "added key")
;;               (SETF (GETHASH (LIST-TO-SYMBOL '(X)) #1#) (FUNCALL #2# X))))
;;    (GETHASH (LIST-TO-SYMBOL '(X)) #1#)))
 
(defmacro memoize ((dfn funcname (args) &body  body))
  (let ((hashed-results (gensym)) ;; pour éviter des conflits de nom
	(lambda-func (gensym)))
    `(let ((,hashed-results (make-hash-table))
	   (,lambda-func (lambda (,args) ,@body)))
       (defun ,funcname (,args)
	 (if (not (nth-value 1 (gethash (list-to-symbol '(,args)) ,hashed-results)))
	     (progn 
	       (print "added key") 
	       (setf (gethash (list-to-symbol '(,args)) ,hashed-results) (funcall ,lambda-func ,args))))
	 (gethash (list-to-symbol '(,args)) ,hashed-results)))))

Merci d'avance pour vos macros, conseils et suggestions!