Sujet : Re: lisp-sound v0.2.1
De : johan (at) *nospam* freecol.be (zara)
Groupes : comp.lang.lispDate : 14. Feb 2025, 18:30:33
Autres entêtes
Organisation : SunSITE.dk - Supporting Open source
Message-ID : <m2tt8wv3gm.fsf@freecol.be>
References : 1 2 3 4
User-Agent : Gnus/5.13 (Gnus v5.13) Emacs/25.3.50 (darwin)
Hi,
Kaz Kylheku <
643-408-1753@kylheku.com> writes:
On 2025-02-14, zara <johan@freecol.be> wrote:
>
Here's the example of the dictionary actor without CLOS :
>
Your approach has a giant bug, which is fixable.
>
;;
;; -- start of file --
;;
(defun make-dictionary ()
(let ((*dict ()))
>
(defun add (value)
(setq *dict (append *dict (list (length *dict) value))))
>
These defuns are defining and later redefining global function
bindings.
>
I know dynamic binding but using the actor there is little error.
Block scoping using the #'dispatch should almost always call
the defined add, get-with-index methods etc. not something
from environments above the lexical scope.
(I mean if you call a message from dispatch, you better define
your called method locally).
You need
>
(let ((*dict ()))
(labels ((add (value) ...)
(get-with-index (index) ...)
(dispatch (msg)
(case msg
(add #'add)
(get-with-index #'get-with-index))
(t (error "make-dictionary: ...."))))
#'dispathch))
>
(Labels defines lexical functions. So does its sister, flet.
Functions defined in the same labels block can see each other
and call each other. Those defined by flet cannot; they see
only functions outside of the flet.)
>
I didn't know labels. Thanks.
Alternatively, we could use variable bindings, whose values
are closures created by lambda:
>
(let ((*dict ()))
(let* ((add (lambda (value) ...))
(get-with-index (lambda (index) ...))
(dispatch (lambda (msg)
(case msg
(add add)
(get-with-index get-with-index))
(t (error "make-dictionary: ....")))))
dispatch))
>
It's more verbose with the (lambda ...) but we lose the #'.
>
You do not call #'add you call add, unless it is undefined.
Note how I used (error ...) for the unrecognized message
case, which signals a condition, and not (print ...).
>
printing is amateurish. It does nothing to indicate to the
caller that something went wrong, only logs a message and
keeps going. The end user of the application won't even
see the message if it's a GUI unless they know to peek into
some certain console window or whatever. If they see it,
they won't know what to do.
>
I don't use GUIs all the time.
;; tests
;(setf dictionary (make-dictionary))
;(print (funcall (funcall dictionary "add") 255))
>
What result are you expecting from this test case?
The string "add" and symbol add are different objects,
and so (eq "add" 'add) is false; this will not dispatch
the add method.
>
You didn't run it, but it does not just compile in clisp (2019),
it works. SFY.
;;
;; -- end of file --
;;
>
I had to change two parens to make it compile.
The tests ran in clisp in 2019.
>
You forgot to write a test which shows that operations on one dictionary
have no effect on the apparent contents of another.
>
Also, your dictionary is inefficient; Common Lisp already has
hash tables.
I know, but it was just an example. AFAIK I am correct, and you have a
new Actor system for Common Lisp (e.g. bare bones systems).
zara
-- My software & art company : http://ko-fi.com/brandywine9