Search code examples
schemeracketcurly-braces

Improperly placed closed parenthesis in scheme function


I have the following scheme function:

(define get-ivars
  (λ (ivars num)
    (cond ((null? ivars) '())
          (else
           (append (list (car ivars) `(nth args ,num)) (list (get-ivars (cdr ivars) (+ num 1))))))))

That returns the following in a specific instance:

(x (nth args 1) (y (nth args 2) ()))

The problem is, I need it to return:

((x (nth args1)) (y (nth args 2)) ())

-the two closing parenthesis at the end should be after the (nth statements.

How would I go about getting this to work properly?

get-ivars caller:

(define gen-classes
  (λ (classes)
    (cond ((null? classes) '())
          (else
           (let* ((class (car classes)))
             (eval
              `(define ,(cadr class)
                 (λ (args)
                   (let (
                          ,(get-ivars (cdr (cadddr class)) 1)
                          )
                     (eval
                      (let* ,(cdar (cddddr class))
                        (λ (method . args)
                          ,(get-methods (cdadr (cddddr class)))
     ))))))))))))

Solution

  • That second (list ...) in your else clause is what's screwing you up. It's nesting each successive call deeper and deeper. The recursion will naturally create the list; you don't need to wrap it again.

    Try:

    (define get-ivars
      (λ (ivars num)
        (if (null? ivars) '()
          (cons (list (car ivars) `(nth args ,num)) 
                (get-ivars (cdr ivars) (+ num 1))))))
    

    Regarding the get-ivars caller code, the parentheses surrounding the unquoted call to get-ivars are what's giving you the trouble you mention in the comments. With them, this code:

    `(define ClassName
       (lambda (args)
         (let (,(get-ivars '(iVar1 iVar2 iVar3) 1))
           ;; your method-getting code
           )))
    

    Gives you this:

    (define ClassName
      (lambda (args)
        (let (((iVar1 (nth args 1))
               (iVar2 (nth args 2))
               (iVar3 (nth args 3))))
          ;; method-getting code
         )))
    

    Which, as you can see, gives you an extra set of parentheses around the assignments in the let.

    So you want to do this:

    `(define ClassName
       (lambda (args)
         (let ,(get-ivars '(iVar1 iVar2 iVar3) 1)
            ;; your method-getting code
          )))
    

    get-ivars is returning a list of lists, which is exactly what you want for the assignments in the let, so you don't need to wrap or (as I had it earlier) splice it. Just use the unquote on its own, and the result is:

    (define ClassName
      (lambda (args)
        (let ((iVar1 (nth args 1))
              (iVar2 (nth args 2))
              (iVar3 (nth args 3)))
          ;; method-getting code
         )))
    

    Which should do the trick.

    Incidentally, I found it helpful to leave off the eval when I was playing around with this; one can then visually inspect the result to make sure its syntax is okay.