Skip to content

Instantly share code, notes, and snippets.

@epanji
Last active December 27, 2018 15:50
Show Gist options
  • Save epanji/15c2c0fb8ce46b11f01bb395ca83898b to your computer and use it in GitHub Desktop.
Save epanji/15c2c0fb8ce46b11f01bb395ca83898b to your computer and use it in GitHub Desktop.
Thanks for help.
;;;; experiment-struct.lisp
;;; Replace structure slot accessor with generic function.
;;;
;;; Use it when only one or two slots need generic function otherwise
;;; use class.
(defpackage #:exp-struct
(:use #:cl))
(in-package #:exp-struct)
(defmacro define-struct-generic (name (struct) &body body)
(let ((ns (intern (concatenate 'string "%%" (symbol-name name))))
(fn (symbol-function name))
(sc (find-class struct nil)))
;; Ensure fn is function and struct is structure-class.
(when (and (eql (type-of fn) 'function)
(eql (type-of sc) 'structure-class))
`(progn
(defvar ,ns (copy-symbol ',name t))
(fmakunbound ',name)
(defgeneric ,name (,struct)
(:method ((instance ,struct))
(funcall ,ns instance))
,@body)))))
;;; Test with
;;; C-c C-c => slime-compile-defun
;;; No problem
(defstruct foo bar baz)
;;; No problem
(define-struct-generic foo-bar (foo)
(:method ((instance null)) 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment