2

After quite a while of studying CL and practising as a hobby in different small projects, I still have some blank areas on my personal CL map. Recently, I had a number of functions using all the same let construct and I thought of writing a macro which makes the code more concise:

(defmacro with-context (&body body)
   `(let ((context (make-array 4 :element-type 'fixnum
                                 :initial-contents '(0 1 2 3))))
     ,@body))

So that I can later define functions like (just as a minimal example):

(defun test-a ()
  (with-context
    (setf (aref context 3)
          (+ (aref context 0) (aref context 1)))
    context))

Now I was wondering if I could shorten the (aref context n) expressions with a macro/function like (context n).

(defun context (n)
  (aref context n))

But the variable context is unknown at compile time, of course. I just don't know if I have a case of basic misunderstanding here or how I could tell lisp what I actually want. So, my question is basically if it is possible and if it is a good idea.

2 Answers 2

4

What's wrong with a local function?

(defmacro with-context (&body body)
  `(let ((context (make-array 4 :initial-contents '(0 1 2 3))))
     (flet ((context (n)
              (aref context n)))
       ,@body)))

Setting, too:

(defmacro with-context (&body body)
  `(let ((context (make-array 4 :initial-contents '(0 1 2 3))))
     (flet ((context (n)
              (aref context n))
            ((setf context) (new n)
              (setf (aref context n) new)))
       ,@body)))
Sign up to request clarification or add additional context in comments.

4 Comments

This wouldn't be a place you could setf, no?
@Svante: added now
Thanks for clarification. Just for my understanding: If if have a main function using with-contextand other function defined outside of main which want to use context I end up in a situation similar to the one discussed in another question, recently and should consider another strategy, I guess.
@RainerJoswig I will try ;-)
3

You could put a macrolet into your macro expansion:

(defmacro with-context (&body body)
  (with-gensyms (i)
    `(let ((context (make-array 4 …)))
       (macrolet ((context (,i)
                    `(aref context ,,i)))
         ,@body))))

Some personal notes:

I dislike anaphoric macros, so I'd generally let the user define the name for the context. That would feel strange with the context macrolet though. I'd then maybe come to the conclusion that all I want is a make-standard-context function and keep using let. I think this is in line with the general guideline “be conventional”.

1 Comment

I understand your point and will consider another solution. Nevertheless, I think there is a , missing before `(aref context ,i)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.