• Re: lisp-sound v0.2.1

    From zara@johan@freecol.be to comp.lang.lisp on Mon Feb 17 09:55:15 2025
    From Newsgroup: comp.lang.lisp

    Hi,

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2025-02-14, zara <johan@freecol.be> wrote:
    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 can't make heads or tails of this paragraph, but it sounds as if you
    might be trying to convince me that your little coding tidbit isn't incorrect. Are /you/ even convinced?

    Make a test case which makes two dictionaries:

    (let ((dict1 (make-dictionary))
    (dict2 (make-dictionary)))
    ...)

    In the ... part, write some tests which show that an operation on
    dict1 has no effect on a lookup in dict1.


    Every time you do make-dictionary it updates its local *dict. You do not
    call anything dynamic binded, the meaning is to have a method you call
    in an actor class instance, which is block scoped (OOP class and actor).
    If you do not field the message the actor has it not but it is a feature of
    the Lisp language not of my OOP Lisp.

    (I mean if you call a message from dispatch, you better define
    your called method locally).

    That's the thing; you've not defined anything locally other
    than the dict* variable.

    defun is not a form which has a local effect.


    That's it, literally.

    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).

    In AFAIK, what exactly do you mean by K, know?


    It used to work on 2019 clisp with a string not just the symbol,
    which is now correct.

    You are not correct, therefore if you "know" you are correct, there is something wrong with how you determine when you know something
    and when you don't.

    See the clisp output.

    zara
    --
    My software & art company : http://ko-fi.com/brandywine9
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.lisp on Mon Feb 17 16:46:53 2025
    From Newsgroup: comp.lang.lisp

    On 2025-02-17, zara <johan@freecol.be> wrote:
    Every time you do make-dictionary it updates its local *dict. You do not

    Every trime you call make-dictionary it redefines a bunch of defuns
    that are contained in the function. Their bodies are lambdas, which
    capture the current lexical dict* variable, but the functions are global.
    Every make-dictionary call you have ever made now uses those new
    functions, which refer to the latest dict* variable and not their
    original one!

    Effectively, your code:

    - wipes the dictionary every time the make-dictionary constructor is called.

    - has all lambdas returned by make-dictionary working with the same
    dictionary object.

    This is the last post in which I'm going to explain it, or reply to
    this topic.

    You are not correct, therefore if you "know" you are correct, there is
    something wrong with how you determine when you know something
    and when you don't.

    See the clisp output.

    What CLISP output? Your only two "test cases" are commented out
    by a semicolon?

    Here is a real CLISP interaction with your code:

    (defun make-dictionary ()
    (let ((*dict ()))

    (defun add (value)
    (setq *dict (append *dict (list (length *dict) value))))

    (defun get-with-index (index)
    (let ((*index 0))
    (loop for el in *dict
    do (if (= (car el) index)
    (return (cadr el))
    (setq *index (+ 1 *index)))
    (return ()))))

    (defun dispatch (msg)
    (cond ((eq msg 'add) #'add)
    ((eq msg 'get-with-index) #'get-with-index)
    (T (print "make-dictionary : Message not understood"))))

    #'dispatch))
    MAKE-DICTIONARY
    (defvar d0 (make-dictionary))
    D0
    (funcall (funcall d0 'add) 'apple)
    (0 APPLE)
    (funcall (funcall d0 'add) 'banana)
    (0 APPLE 2 BANANA)
    (funcall (funcall d0 'add) 'orange)
    (0 APPLE 2 BANANA 4 ORANGE)
    (defvar d1 (make-dictionary)) ;; make new dict, continue with d0
    D1
    (funcall (funcall d0 'add) 'peach)
    (0 PEACH)

    Oops!

    Do you see how dictionary d0 has suddenly developed amnesia?

    What happened to apple, banana and orange?

    Do you think that a dictionary abstration should lose its data
    when someone creates another instance? And if that's the design, why
    use all these function objects. Why allocate several new lambdas
    in each make-dictionary call, when there is only one dictionary?
    Just define a global variable:

    (defvar *dict* ()) ;; the one and only dict

    (defun dict-add (index) ...) ;; add to dictionary

    Maybe read some books/tutorials. (Try not to close them when you think
    you know something different).
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21d-Linux NewsLink 1.2