So i tried to fix this by making a macro, i named program-to-class that (with macro hooks)recognized defvars, defparameters, and made them
into slots of a class. Recognizing defun, defmethod, defgeneric, and adding the argument that is the class (and
type declare for defun) at the start. It also recognizes defclass and defstruct. defmacro is still todo. (Except i am not going to do it anymore)
But then i noticed how defvar and defparameter work a little perculiarly; LET takes them over even when they're used in a function.
Code: Select all
(defparameter *meh* -1)
(defun mah ()
(print (setf- + *mah* 1)))
(let ((*mah* -5))
(mah))
Code: Select all
(defpackage #:class-var
(:use #:common-lisp #:iterate)
(:documentation "Puts all variables in a class, makes all functions have\
this class as first argument.")
(:export class-using-vars class-being-vars))
(in-package #:class-var)
(defmacro if-with (var cond true else)
`(let ((,var ,cond))
(if ,cond ,true ,else)))
(defmacro if-use (&rest conds)
(let ((var (gensym)))
`(if-with ,var ,(car conds)
,var ,(if (null (cdr conds))
(car conds)
`(if-use ,@(cdr conds))))))
;;The simple way.
(defmacro class-using-var (class-name vars &key types options)
"Makes a class with given variables."
`(defclass ,class-name ()
(,@(iter
(for v in vars)
(for tp in (if-use types types (iter (repeat (length vars))
(collect nil))))
(collect
`(,v :initform ,v :initarg ,(intern (symbol-name v) :keyword)
,@(when tp `(:type ,tp)))))
,@options)))
(defmacro class-being-vars ((instance &rest vars) &rest body)
"Lets a class take over the variables. (from defvar/defparameter)
Note that all the vars must be available as slots."
(let ((inst (gensym)))
`(let ((,inst ,instance))
(let (,@(iter (for v in vars) ;Override variables.
(collect `(,v (slot-value ,inst ',v)))))
,@body ;Do the body.
,@(iter (for v in vars) ;Write back.
(collect `(setf (slot-value ,inst ',v) ,v)))))))
Code: Select all
(use-package :class-var)
(defparameter *meh* -1)
(defparameter *mah* 1)
(class-using-var moeh (*mah* *meh*))
(defvar *inst* (make-instance 'moeh))
(defvar *inst2* (make-instance 'moeh))
(defun meh () (print (setf *meh* (+ *meh* 1))))
(defun mah () (print (setf *mah* (+ *mah* 1))))
(class-being-vars (*inst2* *mah* *meh*)
(meh) (mah))
I couldn't find any library that does this. Btw cliki should have an application domain called 'macros' or something, where stuff like this, iterate, series, alexandria etc. goes. Edit: a start