• strange behaviour of (delete .. in Allegro

    From slowman01@21:1/5 to All on Sat Dec 17 08:38:52 2022
    Hello!

    I try to remove random elements from a list until the list is empty. My environment is Allegro Lisp , free edition.

    (setq set1 '(Nr1 Nr2 Nr3))
    (delete (nth (random (length set1)) set1) set1)

    after some repetitions , the output of sequential calls to delete (and the content of set1) start to look like this

    (NR1 NR2 NR3)
    (NR2 NR3)
    (NR1 NR2)
    (NR1)
    NIL
    that is, sometimes items are not deleted, sometimes deleted items reappear. If I use remove there is no such problem.

    Is this a bug or do I miss something about delete ?

    thank you
    Thomas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lieven Marchand@21:1/5 to tomue.pallas@gmail.com on Sat Dec 17 18:04:30 2022
    slowman01 <tomue.pallas@gmail.com> writes:

    Hello!

    I try to remove random elements from a list until the list is
    empty. My environment is Allegro Lisp , free edition.

    after some repetitions , the output of sequential calls to delete (and
    the content of set1) start to look like this

    that is, sometimes items are not deleted, sometimes deleted items
    reappear. If I use remove there is no such problem.

    Is this a bug or do I miss something about delete ?

    REMOVE is non destructive and will if needed create fresh lists. DELETE
    is potentially destructive and will modify the existing list. So you
    need to reassign the result of DELETE.

    (setf list (delete item list)) will fix your problem.

    --
    Laat hulle almal sterf. Ek is tevrede om die wêreld te sien brand en die vallende
    konings te spot. Ek en my aasdier sal loop op die as van die verwoeste aarde.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to tomue.pallas@gmail.com on Sat Dec 17 19:03:02 2022
    On Sat, 17 Dec 2022 08:38:52 -0800 (PST)
    slowman01 <tomue.pallas@gmail.com> wrote:
    Hello!

    I try to remove random elements from a list until the list is empty.
    My environment is Allegro Lisp , free edition.

    (setq set1 '(Nr1 Nr2 Nr3))
    (delete (nth (random (length set1)) set1) set1)

    after some repetitions , the output of sequential calls to delete (and
    the content of set1) start to look like this

    (NR1 NR2 NR3)
    (NR2 NR3)
    (NR1 NR2)
    (NR1)
    NIL
    that is, sometimes items are not deleted, sometimes deleted items reappear. If I use remove there is no such problem.

    Use REMOVE how ?

    Is this a bug or do I miss something about delete ?

    You are missing 2 things : first , modifying a quoted object is undefined behaviour. So if you want to use DELETE you have to do
    (setq set1 (list 'Nr1 'Nr2 'Nr3))

    Second , the new list created by DELETE won't necessarily be what set1
    points to. So you must do [as <87a63m2c81.fsf@wyrd.be> has said]
    (setq set1 (delete ...))

    Don't you do it like this when you use REMOVE ?

    --
    man telnet
    BUGS
    The source code is not comprehensible.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to tomue.pallas@gmail.com on Sun Dec 18 22:26:54 2022
    On 2022-12-17, slowman01 <tomue.pallas@gmail.com> wrote:
    Hello!

    I try to remove random elements from a list until the list is empty. My environment is Allegro Lisp , free edition.

    (setq set1 '(Nr1 Nr2 Nr3))
    (delete (nth (random (length set1)) set1) set1)

    1. You must capture the result of remove or delete!
    Even though delete is destructive, what that means is that
    there is a new list which is destructively made out of the pieces of
    the old list. //That new list appears as the return value of
    delete.///

    The original input object stored in setl is possibly just one of the
    fragments of the original list. Think about it: what if the first
    item is deleted? Setl still points to the cons cell which held that
    item; delete cannot update the setl variable.

    2. Because delete is destructive, you must generally take special
    care about correctness. Get the code working with remove, and then
    carefully change remove calls to delete, if you're able to justify
    that the program doesn't break.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From smh@21:1/5 to All on Sun Dec 18 21:07:42 2022
    The two previous answers so far are (almost) correct, but will not make the real issue clear to a beginner.

    But first, the reason these two answers are not quite correct is that they miss that the desired behavior is incompatible with Common Lisp! Specifically, the original question created the list as a quoted literal, i.e. '(Nr1 Nr2 Nr3), and Common Lisp
    prohibits modifying any literal datum (ANS 3.7.1). This allows an implementation to place some or all constants in pure space where an attempt to modify the constant would result in an exception. Now, most actual implementations don't exploit this so
    modifying a constant will generally work (despite being considered poor practice in most languages) so constant modification is not the issue here.

    The following interaction might better illustrate what delete does and does not do, and what OP probably experienced

    cl-user(8): (defparameter *foo* (list 'a 'b 'c 'd)) ; A conforming way to create a mutable list.
    *FOO*
    cl-user(9): (delete 'd *foo*)
    (A B C)
    cl-user(10): *foo*
    (A B C)
    cl-user(11): (delete 'a *foo*)
    (B C) ; The original list is not modified
    cl-user(12): *foo*
    (A B C) ; The value of *foo* is also not modified.

    Now, the delete in (9) steps down the list and when it finds a cons whose car is d, it sets the cdr of the _previous_ cons to the cdr of the cons cell holding d (which in this example is nil because that cons is the last element of the list). Thus, the
    list has been destructively modified deletining d, and the value of *foo* is still the first cons of the original list, the one containing a.
    The delete in (11) encounters the a in the very first cons cell of the list. There is no previous cons whose cdr can be changed, so delete simply returns the cdr of the "deleted" cons, which is the correct result. The symbol (better called the variable)
    *foo* is not passed to delete, only its value (the list) so delete can not and should not destructively modify it. So *foo* still points to the first cons of the original list, and the cdr of that cons still points to the second element of the original
    list. delkete does not and can not modify the value stored in *foo*.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From slowman01@21:1/5 to Spiros Bousbouras on Mon Dec 19 09:50:17 2022
    Spiros Bousbouras schrieb am Samstag, 17. Dezember 2022 um 20:03:07 UTC+1:
    Don't you do it like this when you use REMOVE ?
    Yes, I did so when using remove but not with delete, because I misunderstood the nature of variable set1. It is clear to me now.
    Thank you!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From slowman01@21:1/5 to smh on Mon Dec 19 09:35:35 2022
    smh schrieb am Montag, 19. Dezember 2022 um 06:07:45 UTC+1:
    The two previous answers so far are (almost) correct, but will not make the real issue clear to a beginner.
    ..
    Thank you, this is exactly what I didn't understand . I treated *foo* as if it is a structure holding a list which can be updated. I missed the point that it is just the car of the original list. I also didn't know the difference between '(a b c) and (
    list 'a 'b 'c).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)