google / lisp-koans

Common Lisp Koans is a language learning exercise in the same vein as the ruby koans, python koans and others. It is a port of the prior koans with some modifications to highlight lisp-specific features. Structured as ordered groups of broken unit tests, the project guides the learner progressively through many Common Lisp language features.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

I think test code might be ran more than once and that causes errors with values.

still-learning opened this issue · comments

macros.lsp: test-log-form-and-value

The following macro fails the first test (which checks if the log is empty to start with).

(defvar *log-with-value* nil)

;; you must write this macro
(defmacro log-form-with-value (form)
  "records the body form, and the form's return value
    to the list *log-with-value* and then evalues the body normally"
`(let ((logform nil)
            (retval ,form))
    (push '(:form ,form  :value ,(eval form)) *log-with-value*)
    retval))
    (define-test test-log-form-and-value
    "log should start out empty"
        (assert-equal nil *log-with-value*)  => FAIL
      .....) => (FAIL PASS FAIL PASS PASS FAIL PASS PASS)

When I throw in a print statement within the test, it says that log-with-value is set to:
((:FORM (- 2013 1978) :VALUE 35))

Which would be the last value logged (hinting that the value is being carried over from the last time the test was ran).

By throwing a setf at the begginning of the test, ALL of the tests pass:

 (define-test test-log-form-and-value
        (setf *log-with-value* nil)
    "log should start out empty" 
        (assert-equal nil *log-with-value*)  => PASS
      .....) => (PASS PASS PASS...)

I had a similar issue with other koans (though I don't remember which specifically). In those instances removing the print statements made the tests pass. However, this is not the case for this particular test. So I'm not sure if it's my macro or the test that is incorrect.

Just experienced the very same problem. I think our macros are identical, though, so can't rule out that we're both making some mistake:

(defmacro log-form-with-value (form)
  "records the body form, and the form's return value
   to the list *log-with-value* and then evalues the body normally"
  `(let ((logform nil)
         (retval ,form))
     (push '(:form ,form :value ,(eval form)) *log-with-value*)
     retval))

I am not sure exactly what's going on (I'm still learning CL too!).

That said, you are provided two local variables (logform and retval) and you both only use retval in your solution. That is a clue that there is another solution that will work.

as astronaut-wannabe hinted at there are two local variables. I use both but also get the same result..
(defvar log-with-value nil)
(defmacro log-form-with-value (form)
`(let ((logform '(:form ,form :value ,(eval form)))
(retval ,form))
(push logform log-with-value)
retval))