Hello,
I am curently translating the logic circuit simulator code from SICP into Common Lisp and have run into a snag that I would like to ask about.
The Scheme code is as follows from section 3.3.4 (page 223 of my hardcover edition):
(define (and-gate a1 a2 output) (define (and-action-procedure) (let ((new-value (locical-and (get-signal a1) (get-signal a2)))) (after-delay and-gat-delay (lambda () (set-signal! output new-value))))) (add-action! a1 and-action-procedure) (add-action! a2 and-action-procedure))
The code basically binds the local function and-action-procedure into a list of functions in a1 and a2 which are then called by another routine later to perform the action when a value is set on the wire.
My translated Common Lisp code is:
(defun make-and-gate (a1 a2 output) (flet ((logical-and (a b) (if (= a 1) b a)) (and-action-proc () (let ((new-value (logical-and (get-signal a1) (get-signal a2)))) (set-signal output new-value)))) (add-action a1 #'and-action-proc) (add-action a2 #'and-action-proc)))
The problem is that the bindings of a1 and a2 in and-action-proc are not being bound to the values of the calling function in the Common Lisp version. This causes the calling of and-action-proc to fail because a1 and a2 are not bound and I am assuming being treated as dynamic (special) variables. I have also tried to define and-action-proc using labels with no difference in results.
Is this a total schemantic difference between CL and Scheme? Is every function in Scheme a closure where free variables of sub-functions bound to the calling functions environment? If so, is there a way to emulate this in Common Lisp?
I would also like to note that I am currently trying out writing this code using LispWorks Personal Edition, rather than my usual SBCL environment, if that would make any difference.
-- Burton Samograd
Burton Samograd burton.samograd@gmail.com writes:
Hello,
I am curently translating the logic circuit simulator code from SICP into Common Lisp and have run into a snag that I would like to ask about.
The Scheme code is as follows from section 3.3.4 (page 223 of my hardcover edition):
(define (and-gate a1 a2 output) (define (and-action-procedure) (let ((new-value (locical-and (get-signal a1) (get-signal a2)))) (after-delay and-gat-delay (lambda () (set-signal! output new-value))))) (add-action! a1 and-action-procedure) (add-action! a2 and-action-procedure))
The code basically binds the local function and-action-procedure into a list of functions in a1 and a2 which are then called by another routine later to perform the action when a value is set on the wire.
My translated Common Lisp code is:
(defun make-and-gate (a1 a2 output) (flet ((logical-and (a b) (if (= a 1) b a)) (and-action-proc () (let ((new-value (logical-and (get-signal a1) (get-signal a2)))) (set-signal output new-value)))) (add-action a1 #'and-action-proc) (add-action a2 #'and-action-proc)))
You should use LABELS instead of FLET, FLET doesn't make its definitions available inside definitions so the call logical-and in and-action-proc can't find logical-and.
And seriously, writing to the _pro_ mailing list to ask trivial questions?
I apologize, my original code was using labels but I copied the one using flet for this question. Please assume that I am using labels; the variable binding question still stands.
I am asking this on the Pro list because it seems that everyone is on the same lists anyways and I get the best answers from the list. I can send it somewhere else if you have a suggestion where I would get the same quality of answer as here.
-- Burton Samograd
On Mon, Mar 5, 2012 at 6:23 AM, Stas Boukarev stassats@gmail.com wrote:
Burton Samograd burton.samograd@gmail.com writes:
Hello,
I am curently translating the logic circuit simulator code from SICP into Common Lisp and have run into a snag that I would like to ask about.
The Scheme code is as follows from section 3.3.4 (page 223 of my hardcover edition):
(define (and-gate a1 a2 output) (define (and-action-procedure) (let ((new-value (locical-and (get-signal a1) (get-signal a2)))) (after-delay and-gat-delay (lambda () (set-signal! output new-value))))) (add-action! a1 and-action-procedure) (add-action! a2 and-action-procedure))
The code basically binds the local function and-action-procedure into a list of functions in a1 and a2 which are then called by another routine later to perform the action when a value is set on the wire.
My translated Common Lisp code is:
(defun make-and-gate (a1 a2 output) (flet ((logical-and (a b) (if (= a 1) b a)) (and-action-proc () (let ((new-value (logical-and (get-signal a1) (get-signal a2)))) (set-signal output new-value)))) (add-action a1 #'and-action-proc) (add-action a2 #'and-action-proc)))
You should use LABELS instead of FLET, FLET doesn't make its definitions available inside definitions so the call logical-and in and-action-proc can't find logical-and.
And seriously, writing to the _pro_ mailing list to ask trivial questions?
-- With best regards, Stas.
Burton Samograd burton.samograd@gmail.com writes:
I apologize, my original code was using labels but I copied the one using flet for this question. Please assume that I am using labels; the variable binding question still stands.
With labels, the code is right, that means either you're not telling something else again, or the problem is in another place in the code.