Hi. Need help with creating the ‘for’ macro. It must take a parameter, an initial value, an end value, and a loop step. Macro must return amount of iteration. Various operations should take place inside it. It should be designed without leaks.The preliminary version looks like this:

(defmacro for ((param-name start-value end-value &optional (step1 1)) &body body)
  (let* ((func-name (gensym))
(start (gensym))
(param-name (gensym))
(comparison (if (< step1 0) '< '>))
(end (gensym))
(step (gensym))
(k (gensym)))
'(labels ((,func-name (,param-name ,start ,end ,step ,k)
(let ((new-exprs (progn ,@body))
(newK (+ 1 ,k)))
(if (,comparison ,end ,param-name)
(,func-name (+ ,param-name ,step) ,start ,end ,step newK)
newK))))
(,func-name ,param-name ,start-value ,end-value ,step1 0))))

I understand that it looks terrible. I don’t understand how you can access the parameter without violating the rule about leaks.

  • jacobb11@alien.topB
    link
    fedilink
    English
    arrow-up
    1
    ·
    10 months ago

    Any particular reason for the macro to use recursion instead of “do”?

    I don’t understand why the function “,func-name” has both a “,param-name” and “,start” parameter. I think (maybe misuderstanding intent) that you should drop “,param-name” from the last line and drop “,start” from function “,func-name”.

    Hm. “,end” never changes, so it would probably be simpler to declare it outside “,func-name” rather than pass it around. Same for “,step”. And maybe “,k”, but I’m not clear why “,k” is needed as well as “,param-name” and “start”.

    Also you need to change + to either + or - depending on “(< step1 0)”.

    • Revolutionary_Utena@alien.topOPB
      link
      fedilink
      English
      arrow-up
      1
      ·
      10 months ago

      The teacher said to do it this way. As I understand it, when using a macro, you need to refer to a parameter, for example (let ((s 0))

      (for (i 2 N)

      ((inch s (sin i)))

      s) Here it is necessary to refer to the modified sh. Therefore, it is passed to the recursive param-name call.

      • jacobb11@alien.topB
        link
        fedilink
        English
        arrow-up
        1
        ·
        10 months ago

        Here it is necessary to refer to the modified sh. Therefore, it is passed to the recursive param-name call.

        You can bind a variable outside the function and still refer to it inside the function. Here is an example that does so with “,end”:

        (defmacro for ((param-name start-value end-value &amp;optional (step1 1)) &amp;body body)
          (let* ((func-name (gensym))
                 (start (gensym))
                 (param-name (gensym))
                 (comparison (if (&lt; step1 0) '&lt; '>))
                 (end (gensym))
                 (step (gensym))
                 (k (gensym)))
            `(let ((,end ,end-value))
              (labels ((,func-name (,param-name ,start ,step ,k)
                           (let ((new-exprs (progn ,@body))
                                 (newK (+ 1 ,k)))
                             (if (,comparison ,end ,param-name)
                                 (,func-name (+ ,param-name ,step) ,start ,step newK)
                                 newK))))
                 (,func-name ,param-name ,start-value ,step1 0)))))
        
        • Revolutionary_Utena@alien.topOPB
          link
          fedilink
          English
          arrow-up
          1
          ·
          10 months ago
          (defmacro for ((param start-value end-value &amp;optional (step1 1)) &amp;body body)
            (let* ((func-name (gensym))
                   (start (gensym))
                   (param-name (gensym))
                   (comparison (if (&lt; step1 0) '&lt; '>))
                   (end (gensym))
                   (step (gensym))
                   (k (gensym)))
              `(let ((,end ,end-value)
                     (,step ,step1)
                     (,start ,start-value))
                (labels ((,func-name (,param-name ,k)
                             (let ((new-exprs (progn ,@body))
                                   (newK (+ 1 ,k)))
                               (if (,comparison ,end ,param-name)
                                   (,func-name (+ ,param-name ,step) newK)
                                   newK))))
                   (,func-name ,param 0)))))
          
          (let ((s 0))
          (for (i 2 5)
          (incf s (sin i)))
          s)
          

          I made some changes but when I try to call macros with parameter (i 2 5) compiler give me error about unbound variable i.