Wrong function result


#1

OK, this will be long and messy, I just quickly want to dump it off and may edit my post later, but maybe it will be useful “as is”. So I am have written an AI and I am trying to port it to ulisp.

The original code, in the relevant part, looks like this:

; This is an extremely simplified
; "logical triangulation system" (a general type of symbolic
; AI I invented, and of the "directional" variety: the
; structures AB & BA may BOTH exist and are OPPOSITE).

; How it works: it is based on the idea that it
; (i) RECOGNISES symbolic structures as seen already and
; (ii) tries to CONTINUE the recognised structures
; with other structures according to its observations.
; If structures are unknown, it tries to guess the new
; structures according to delimiters.

; Structures are remembered based on "priority" (most
; recently used or hypothetised ones get high priority)
; and thus a sort of "evolution" ensues which makes
; certain that the system remembers, in the end, only
; the "most useful" or the "most recent" structures.

; "More often seen" structures and structural delimiters
; will thus survive longer and cause future structural
; recognition to be based on them - and thus, they control
; the corresponding action, too. This is how the system,
; over time, "strives to become more intelligent".

; "New" structures are guessed in their delimitations
; according to which symbols already served as
; delimitations in known structures, that is some known
; (A B) proposes (A... and ...B) as delimiters, so
; the system can guess e.g. some (A X) or some (Q B).

; This evolution happens in the "knowledge", the program's
; "long term memory". - A "short term memory" is the
; "history", which serves as a verbatim store of the
; most recently perceived symbols - here, there is no
; evolution and symbols simply enter and are forgotten
; "FIFO-style".

; Usage: after loading the Common Lisp file, simply type
; (run)
; and press Enter. Then, upon receiving the input prompt,
; you can write sentences in form of lists of symbols,
; e.g. (HELLO HOW ARE YOU TODAY).

; Initially, you will receive only an empty reply, i.e.
; the machine has not yet learned how to answer you.
; After a while - and in particular if you keep your
; variety of symbols used as low as you can - you will
; begin to receive materially relevant replies.

; To gain some awareness of "what happens", you will
; see above the received reply also the present state
; of the history and of the evolved stage of the knowledge.

; Receiving a reply may take a very long time - this is
; normal.

; The system also employs projections of history into the
; future prior to "actually" evaluting the user's reply
; and giving an answer: this is a form of "daydreaming"
; or "hypothetising", the way described in prior AI
; research, with the aim of making the system aware of a
; greater count of "possible" - even if not actually
; observed - arrangements of input.

; sample interaction:
; * (run)
; READ----(hello machine how are you)
; 
; (TOP-NEW-KNOWLEDGE
;  (((MACHINE SO) ((YOU DO) OPERATE))
;   ((TRM HELLO) (((MACHINE HOW) ARE) (YOU TRM))))
;  ((MACHINE SO) ((YOU DO) OPERATE))
;  ((TRM HELLO) (((MACHINE HOW) ARE) (YOU TRM))) (((MACHINE HOW) ARE) (YOU TRM))
;  ((MACHINE HOW) ARE) (MACHINE HOW) (MACHINE SO) ((YOU DO) OPERATE) (YOU TRM)
;  (YOU DO) (TRM HELLO)
;  ((((MY DEAR) (MACHINE TRM)) (WELL (MACHINE SO)))
;   ((YOU DO) ((OPERATE TRM) HELLO)))
;  (((MY DEAR) (MACHINE TRM)) (WELL (MACHINE SO)))
;  ((YOU DO) ((OPERATE TRM) HELLO)) ((OPERATE TRM) HELLO)
;  ((MY DEAR) (MACHINE TRM)) (WELL (MACHINE SO)) (MY DEAR) (OPERATE TRM)
;  (MACHINE TRM))
; 
; (NEW-HISTORY HELLO MACHINE HOW ARE YOU TODAY MY DEAR MACHINE TRM WELL MACHINE
;  SO YOU DO OPERATE TRM HELLO MACHINE HOW ARE YOU TRM HELLO MACHINE HOW ARE YOU
;  TODAY MY DEAR MACHINE TRM)
; 
; (REPLY-- HELLO MACHINE HOW AM-ARE ME TODAY YOUR DEAR MACHINE)

; generate lists of a desired symbol and length
(defun proto-gen-sym (n sym lis)
  (loop
    (cond ((zerop n) (return lis)))
    (push sym lis)
    (decf n)))

(defun gen-sym (n sym) (proto-gen-sym n sym '()))

; up to what chunk of symbols can be processed at once
(defvar *seglen* 12)

; how far to advance to the next chunk of symbols;
; should be minimum 1 and not more than *seglen* in
; order to allow overlapping evaluation
(defvar *stepsize* 5)

; the signal that input/output has ended; not
; to be supplied by the user - handled automatically
(defvar *terminator* 'TRM)

; how far a plan can be composed
(defvar *max-plan-range* 20) ; was 10

; how many planning steps would be allowed
(defvar *max-plan-steps* 25) ; normally greater or equal to range ; was 8

; how many symbols shall the short-term memory hold
(defvar *max-history-length* 33)

; how many elements shall knowledge contain -
; remembered are only super-structures, i.e. lists,
; not just singular symbols as these have no structure,
; i.e. do not support structural recognition or usage per se
; (but only as part of a super-structure)
(defvar *max-knowledge-length* 2000)

; generate an initial empty knowledge
(defvar *knowledge* (gen-sym *max-knowledge-length* '()))

; generate an initial empty history
(defvar *history* (gen-sym *max-history-length* '()))

; this is "a hack" - avoid the system telling "nothing"
; if it could give some other answer - avoids a way too
; taciturn system that prefers to give no replies at all
(defvar *allow-terminator* '())

; like Lisp's nthcdr
(defun nth-cdr (n lis)
  (loop
    (cond ((null lis) (return '()))
          ((zerop n) (return lis)))
    (pop lis)
    (decf n)))

; take-first takes the first n elements of a list,
; in a way a complementary effect to nthcdr, only
; with the beginning of a list and not its end
(defun proto-take-first (n lis res)
  (loop
    (cond ((or (zerop n) (null lis)) (return res)))
          (setq res (append res (list (car lis)))) ; slow, but lower memory
          (pop lis)
          (decf n)))

(defun take-first (n lis) (proto-take-first n lis '()))
; (take-first 3 '(A B C D)) --> (A B C)

; take the last n elements of a list
(defun take-last (n lis)
  (loop
    (cond ((null (nth-cdr n lis)) (return lis)))
    (pop lis)))

; this is like Lisp's butlast
(defun proto-but-last (lis res)
  (loop
    (cond ((null (cdr lis)) (return res)))
    ; the below ridiculous mechanism was done
    ; in the hope to decrease memory usage,
    ; though clearly this is painfully slow
    (setq res (append res (list (car lis)))) ; slow... low
    (pop lis)))

(defun but-last (lis) (proto-but-last lis '()))

; an equal-operator that matches lists - nice to have;
; the complex structures to be recognised by the system
; will be lists and these cannot be matched with mere eq
(defun ek (a b)
  (cond ((eq a b) t)
        ((and (listp a) (listp b))
          (cond ((or (null a) (null b)) '())
                ; that was because the above eq would have caught
                ; a mutual nil
                ((not (ek (car a) (car b))) '()) ; deep recursion
                (t (ek (cdr a) (cdr b)))))
        (t '())))
; (ek '((A B) (C D E)) '((A B) (C D E))) --> T

; (defun final (lis)
;   (cond ((null lis) '())
;         (t (car (reverse lis)))))

; this really works like "car", but gives the
; very last element of a list; this is useful for
; "forgetting", if combined with butlast:
; assuming the last element of a list is "least
; relevant" in some chosen model of priority,
; butlast will give you the "valid" part of
; some knowledge list, whereas "final" will
; give you the element to be "forgotten" - and whose
; symbol or "space", then, can be somehow re-used
(defun final (lis)
  (loop
    (cond ((null lis) (return '()))
          ((null (cdr lis)) (return (car lis))))
    (pop lis)))
; ((final '(A B C)) --> C

; this is like member, but with ek, not just eq,
; and is useful for seeking membership of
; complex structures in a list - e.g. main knowledge
(defun memb (el lis)
  (loop
    (cond ((null lis) (return '()))
          ((ek el (car lis)) (return lis)))
    (pop lis)))

; ; (defun forget-element-from-list (el lis)
; ;   (cond ((null lis) '()) ; should never happen
; ;         ((null (cdr lis)) '()) ; FORGET last element
; ;         ((ek (car lis) el) (cdr lis)) ; FORGOT the element - for bubbling purposes!
; ;         (t (cons (car lis) (forget-element-from-list el (cdr lis))))))
; 
; (defun proto-forget-element-from-list (el lis frnt)
;   (loop
;     (cond ((null lis) (return '())) ; should never happen
;           ((null (cdr lis)) (return frnt)) ; FORGET last element
;           ((ek (car lis) el) (return (append frnt (cdr lis))))) ; FORGOT the element - for bubbling purposes!
;     (setq frnt (append frnt (list (car lis)))) ; slow... low mem
;     (pop lis)))
; 
; (defun forget-element-from-list (el lis)
;   (proto-forget-element-from-list el lis '()))
; 
; (defun bubble (el lis) ; no bubbling for elementary atoms and for nils - BUBBLING IS THE ESSENCE OF LEARNING, DO NOT LEARN SUCH TRASH!
;   (cond ((not (listp el)) lis)
;         ((null el) lis)
;         (t (cons el (forget-element-from-list el lis)))))

; ; (defun proto-match-knowledge-pair (history-pair reverse-history-pair knowledge)
; ;   (cond ((null knowledge) '()) ; no match for the pair found
; ;         ((ek history-pair (car knowledge)) history-pair) ; and THEN it's bubbled later
; ;         ((ek reverse-history-pair (car knowledge)) '()) ; Antithesis found: "certainly NOT that pair!"
; ;         (t (proto-match-knowledge-pair history-pair reverse-history-pair (cdr knowledge)))))
; 
; ; This function checks whether a pair - or its antithesis - are found in knowledge
; (defun proto-match-knowledge-pair (history-pair reverse-history-pair knowledge)
;   (loop
;     (cond ((null knowledge) (return '())) ; no match for the pair found
;           ((ek history-pair (car knowledge)) (return history-pair)) ; and THEN it's bubbled later
;           ((ek reverse-history-pair (car knowledge)) (return '()))) ; Antithesis found: "certainly NOT that pair!"
;     (pop knowledge)))
; 
; ; (defun proto2-match-knowledge-pair (reversed-history knowledge) ; the first matching a more recent piece of knowledge
; ;   (cond ((null reversed-history) '()) ; should never happen
; ;         ((null (cdr reversed-history)) '()) ; should not happen, either - should be CAUGHT BEFOREHAND
; ;         (t (let ((p-m (proto-match-knowledge-pair
; ;                          (list (cadr reversed-history) (car reversed-history))
; ;                          (list (car reversed-history) (cadr reversed-history))
; ;                          knowledge)))
; ;           (cond ((null p-m) (proto2-match-knowledge-pair (cdr reversed-history) knowledge))
; ;                 (t p-m))))))
; 
; ; try to match the most recent known pair of the input to the knowledge
; (defun proto2-match-knowledge-pair (reversed-history knowledge) ; the first matching a more recent piece of knowledge
;   (loop
;     (cond ((null reversed-history) (return '())) ; should never happen
;           ((null (cdr reversed-history)) (return '())) ; should not happen, either - should be CAUGHT BEFOREHAND
;           (t (let ((p-m (proto-match-knowledge-pair
;                            (list (cadr reversed-history) (car reversed-history))
;                            (list (car reversed-history) (cadr reversed-history))
;                            knowledge)))
;             (cond ((not (null p-m)) (return p-m))))))
;     (pop reversed-history)))
; 
; ; (defun proto-guess-pair (history but-last-his rev-cdr-his knowledge)
; ;   (cond ((or (null history) (null knowledge)) '())
; ;         ((null (cdr history)) '())
; ;         ((null (car knowledge))
; ;           (proto-guess-pair history but-last-his rev-cdr-his (cdr knowledge)))
; ;         ((memb (caar knowledge) but-last-his)
; ;           (take-first 2 (memb (caar knowledge) history)))
; ;         ((memb (cadar knowledge) rev-cdr-his)
; ;           (reverse (take-first 2 (memb (cadar knowledge) (reverse history)))))
; ;         (t
; ;           (proto-guess-pair history but-last-his rev-cdr-his (cdr knowledge)))))
; 

; if you don't want to bother with lists filled
; aftificially with nil-symbols, this deletes these symbols
(defun eat-nils (lis)
  (loop
    (cond ((null lis) (return '()))
          ((not (null (car lis))) (return lis)))
  (pop lis)))

; (defun pproto-guess-pair (history but-last-his rev-cdr-his knowledge)
;   (loop
;     (cond ((or (null history) (null knowledge)) (return '()))
;           ((null (cdr history)) (return '()))
;           ((memb (caar knowledge) but-last-his)
;             (return (take-first 2 (memb (caar knowledge) history))))
;           ((memb (cadar knowledge) rev-cdr-his)
;             (return (reverse (take-first 2 (memb (cadar knowledge) (reverse history)))))))
;     (pop knowledge)))
; 
; (defun proto-guess-pair (history but-last-his rev-cdr-his knowledge)
;   (pproto-guess-pair history but-last-his rev-cdr-his (eat-nils knowledge)))
; 
; (defun guess-pair (history knowledge)
;   (cond ((null history) '())
;         ((null (cdr history)) '())
;         (t (let ((guess (proto-guess-pair history
;                                            (but-last history)
;                                            (reverse (cdr history))
;                                            knowledge)))
;           (cond ((null guess)
;                   (let ((rev-his (reverse history)))
;                     (list (cadr rev-his) (car rev-his))))
;                 (t guess))))))

; (guess-pair '(A B C D) '((R S) (T U) (B X) (V W))) --> (B C)
; (guess-pair '(A B C D) '((R S) (T U) (Y C) (V W))) --> (B C)

; CHECK NOW IS THE HISTORY EITHER EMPTY OR DOES IT PERHAPS HAVE ONLY ONE ELEMENT;
; and EAT UP the history in so far as it begins with NULLs!

; (defun pr-match-knowledge-pair (history knowledge)
;   (cond ((null history) '())
;         ((null (cdr history)) '())
;         (t (let ((p-match (proto2-match-knowledge-pair (reverse history) knowledge)))
;           (cond ((null p-match) (guess-pair history knowledge)) ; BUBBLE THIS LATER: LEARN IT, POTENTIALLY!
;                 (t p-match)))))) ; BUBBLE THIS LATER

; (defun match-knowledge-pair (history knowledge)
;   (pr-match-knowledge-pair (eat-nils history) knowledge))

; THE HISTORY IS TO BE SEGMENTED INTO SENSIBLE SEGMENTS, AND ONLY _THESE_ ARE TO BE LEARNED: THAT IS A SORT OF "CREEPING"!
; SEGMENTS SHOULD BE *N* ATOMS APART, NOT ONLY 1! ACCELERATE EVALUATION!

; (defun h-hierarchise-pair (history-segment knowledge)
;   (cond ((null history-segment) '()) ; should never happen unless history-segment is reduced by eat-nils
;         ((null (cdr history-segment)) history-segment) ; here, not NIL: allow the ONE listed atom
;                                                                          ; to continue being used for planning, if needed
;         (t (match-knowledge-pair history-segment knowledge))))

; (defun hierarchise-pair (history-segment knowledge)
;   (h-hierarchise-pair (eat-nils history-segment) knowledge))

; assume you want to "recognise a structure", e.g. A and B
; as (A B), then this will turn a list of (X Y Z A B C)
; into (X Y Z (A B) C), i.e. therein (A B) is ONE unit
; and the "structuring" of the given list has advanced:
(defun hier-pair (h-pair history-segment)
  (cond ((null history-segment) '())
        ((null (cdr history-segment)) history-segment)
        ((ek h-pair (list (car history-segment) (cadr history-segment)))
          (cons h-pair (hier-pair h-pair (cddr history-segment))))
        (t
          (cons (car history-segment) (hier-pair h-pair (cdr history-segment))))))

; ALTERNATIVE I:

; (defun hierarchise-all-segment (history-segment knowledge) ; result: LAST ATOM + BUBBLED KNOWLEDGE
;   (cond ((null history-segment) (list '() knowledge)) ; should not happen
;         ((null (car history-segment)) (hierarchise-all-segment (cdr history-segment) knowledge))
;         ((null (cdr history-segment)) (list (car history-segment) (bubble (car history-segment) knowledge)))
;         (t (let ((h-pair (hierarchise-pair history-segment knowledge)))
;           (cond ((null h-pair) (list (final history-segment) (bubble (final history-segment) knowledge)))
;                 (t (hierarchise-all-segment (hier-pair h-pair history-segment) (bubble h-pair knowledge))))))))

; ALTERNATIVE II:

; ; knowledge is NOT YET BUBBLED above; this happens now:
; (defun h-hierarchise-all-segment (history-segment knowledge h-pair) ; result: LAST ATOM + BUBBLED KNOWLEDGE
;   (loop
;     (cond ((null history-segment) (return (list '() knowledge))) ; should not happen
;           ((null (cdr history-segment)) (return (list (car history-segment) (bubble (car history-segment) knowledge)))))
;     (setq h-pair (hierarchise-pair history-segment knowledge))
;     (cond ((null h-pair) (return (list (final history-segment) (bubble (final history-segment) knowledge))))
;           (t (progn
;              (setq history-segment (hier-pair h-pair history-segment))
;              (setq knowledge (bubble h-pair knowledge)))))
; ;   (gc) (room) ; (gc) changes the results really a lot - it all becomes MUCH more "stable"
;   )) ; so (room) above can easily be commented off.
; 
; (defun hierarchise-all-segment (history-segment knowledge)
;   (h-hierarchise-all-segment (eat-nils history-segment) knowledge '()))

; ALTERNATIVE III:

; This is THE largest function of this entire program.
; It is a manually inlined mess of a whole bunch of
; other functions, with hope to save some memory.
; In the end, it should fully "hierarchise" or
; structure the present - into one symbol - and
; update the knowledge accordingly, implanting into
; the knowledge the recognised or hypothetised
; structural elements (so they may serve as future
; models for recognition of structures) and updating
; their "priority" (placing them at the "top" or front
; of knowledge) as well as changing a segment of
; "history" (or input) in such a way that it becomes
; structured. E.g. the input or history segment (A B C A B)
; given to the knowledge ((R S) (T U) (B X) (V W) (W E) (E D)))
; should result in a list of the now structured input as
; well as in an updated knowledge (that has learned the
; newly hypothetised structurings):
; (((A (B C)) (A B)) ; input, and this is knowledge:
; (((A (B C)) (A B)) (A (B C)) (A B) (B C) (R S) (T U)))


(defun h-hierarchise-all-segment (history-segment knowledge h-pair frnt rs nh rh nk)
                                                            ; --> auxiliary variables
  (loop
    (cond ((null history-segment) (return (list '() knowledge))) ; should not happen - history should not be empty
          ((null (cdr history-segment)) ; history has then only one element: FULL STRUCTURE is achieved
            (return
              (progn (setq frnt '()) ; auxiliary catcher for checked knowledge elements
              (list
                (car history-segment) ; the final "top structure" of the present segment
                (cons                 ; and knowledge:
                  (car history-segment) ; ... which is given the "most priority" at the front
                  ; ... but at the same time this "top structure" is forgotten from the body,
                  ; in order to avoid any "copies" of it within the knowledge which would
                  ; only waste knowledge capacity; if the structure does not exist in the
                  ; body, the knowledge is shortened by one element, so the attachment to
                  ; the front does not increase its length and it remains constant
                  (loop
                    (cond ((null knowledge) (return '())) ; should never happen
                          ((null (cdr knowledge)) (return frnt)) ; FORGET last knowledge element
                          ((ek (car knowledge) (car history-segment))
                            (return (append frnt (cdr knowledge))))) ; remove the known top atom from the body
                    (setq frnt (append frnt (list (car knowledge)))) ; slow... low mem: recycle the checked knowledge elements
                    (pop knowledge))))))))
;   (setq h-pair (hierarchise-pair history-segment knowledge)) ; now becomes:
    ; OK, if you did not "return" from the loop before, then it is safe to say, you did NOT
    ; gain yet "final" structuring or hierarchisation of the present - and you should
    ; rather go ahead and proceed doing such structuring:
    (setq h-pair
          (progn
            ; we do not wish to deal with a history-segment full of nils (though it works anyway):
            (setq history-segment (eat-nils history-segment))
            ; ex h-hierarchise-pair (history-segment knowledge)
            (cond ((null history-segment) '())
                  ((null (cdr history-segment)) history-segment) 
                  (t
                    ; ex pr-match-knowledge-pair (history knowledge)
                    (cond ((null history-segment) '())
                          ((null (cdr history-segment)) '()) ; ... maybe unnecessary - check for history of length at least 2,
                                                             ; as two symbols are the required length for a structuring
                          (t (let ((p-match ; (proto2-match-knowledge-pair (reverse history-segment) knowledge)
                                    (progn
                                    ; ex proto2-match-knowledge-pair (reversed-history knowledge)
                                    (setq rs (reverse history-segment))
                                    (loop
                                      (cond ((null rs) (return '())) ; should never happen
                                            ((null (cdr rs)) (return '())) ; should not happen, either - should be CAUGHT BEFOREHAND
                                            (t (let ((p-m 
                                                      ; ex proto-match-knowledge-pair (history-pair reverse-history-pair knowledge)
                                                      (progn 
                                                        (setq nh (list (cadr rs) (car rs)))
                                                        (setq rh (list (car rs) (cadr rs)))
                                                        (setq nk '())
                                                        (loop
                                                          (cond ((null nk) (return '()))
                                                                ((ek nh (car nk)) (progn
                                                                                  (setq knowledge (append (reverse nk) knowledge))
                                                                                  (setq nk '())
                                                                                  (return nh)))
                                                                ((ek rh (car nk)) (progn
                                                                                  (setq knowledge (append (reverse nk) knowledge))
                                                                                  (setq nk '())
                                                                                  (return '()))))
                                                          (push (pop knowledge) nk)))

                                                    ; ; faster, but more memory-hungry alternatively to above progn:
                                                    ; (progn 
                                                    ;   (setq nh (list (cadr rs) (car rs)))
                                                    ;   (setq rh (list (car rs) (cadr rs)))
                                                    ;   (setq nk knowledge) ; THIS COPY SEEMS UNAVOIDABLE
                                                    ;   (loop
                                                    ;     (cond ((null nk) (return '()))
                                                    ;           ((ek nh (car nk)) (progn (setq nk '()) (return nh)))
                                                    ;           ((ek rh (car nk)) (progn (setq nk '()) (return '()))))
                                                    ;     (pop nk)))

                                                    )) ; parentheses of p-m
                                              (cond ((not (null p-m)) (return p-m))))))
                                      (pop rs)))))

                            (cond ((null p-match)
                                    ; ex guess-pair (history knowledge)
                                    (cond ((null history-segment) '())
                                          ((null (cdr history-segment)) '())
                                          (t (let ((guess
                                                   (progn
                                                    (setq nk '())
                                                      ; ex pproto-guess-pair (history but-last-his rev-cdr-his knowledge)
                                                    (let ((but-last-his (but-last history-segment))
                                                          (rev-cdr-his (reverse (cdr history-segment))))
                                                      (loop
                                                        (cond
                                                          ((or (null history-segment) (null knowledge)) (return '()))
                                                          ((null (cdr history-segment)) (return '()))
                                                          ((memb (caar knowledge) but-last-his)
                                                            (return (take-first 2 (memb (caar knowledge) history-segment))))
                                                          ((memb (cadar knowledge) rev-cdr-his)
                                                            (return (reverse (take-first 2 (memb (cadar knowledge) (reverse history-segment)))))))
                                                          (push (pop knowledge) nk))))))
                                            (progn
                                              (setq knowledge (append (reverse nk) knowledge))
                                              (setq nk '())
                                              (cond ((null guess)
                                                      (let ((rev-his (reverse history-segment)))
                                                        (list (cadr rev-his) (car rev-his))))
                                                    (t guess)))))))
                            (t p-match)))))))))
    (cond ((null h-pair)
            (return
              (progn (setq frnt '())
              (list
                (final history-segment)
                (cons
                  (final history-segment)
                  ; ex proto-forget-element-from-list
                  (loop
                    (cond ((null knowledge) (return '())) ; should never happen
                          ((null (cdr knowledge)) (return frnt)) ; FORGET last element
                          ((ek (car knowledge) (final history-segment))
                            (return (append frnt (cdr knowledge))))) ; FORGOT the element - for bubbling purposes!
                    (setq frnt (append frnt (list (car knowledge)))) ; slow... low mem
                    (pop knowledge)))))))
          (t (progn
             (setq history-segment (hier-pair h-pair history-segment))
             (setq frnt '())
             (setq knowledge
                     (cons h-pair
                       (loop
                        (cond ((null knowledge) (return frnt)) ; should never happen
                              ((null (cdr knowledge)) (return frnt)) ; FORGET last element
                             ((ek (car knowledge) h-pair)
                                (return (append frnt (cdr knowledge))))) ; FORGOT the element - for bubbling purposes!
                        (setq frnt (append frnt (list (car knowledge)))) ; slow... low mem
                        (pop knowledge)))))))
;   (gc) (room) ; (gc) changes the results really a lot - it all becomes MUCH more "stable"
  )) ; so (room) above can easily be commented off.

(defun hierarchise-all-segment (history-segment knowledge)
  (h-hierarchise-all-segment (eat-nils history-segment) knowledge '() '() '() '() '() '()))

**; (hierarchise-all-segment '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))**
**; -->**
**; (((A (B C)) (A B)) (((A (B C)) (A B)) (A (B C)) (A B) (B C) (R S) (T U)))**

^^^^^^^^ IT IS THIS LAST FUNCTION CALL THAT DOES NOT WORK OUT AS IN SBCL
It delivers nil instead of the structured lists.


Artificial Intelligence I
#2

The above formatting became weird - dear @johnsondavies , I unfortunately forgot how to do the “code” formatting…

Anyway - I adjusted the code for easier pasting into ulisp as follows - although the names are different, the functionality should be the same (and SBCL works with it fine, too, as does ECL):

(defun pgs (n sym lis)
  (loop
    (cond ((zerop n) (return lis)))
    (push sym lis)
    (decf n)))

(defun g-s (n sym) (pgs n sym '()))

(defvar sl* 12)

(defvar st* 5)

(defvar tr* 'TRM)

(defvar mp* 16)

(defvar ps* 12)

(defvar mh* 33)

(defvar kl* 50)

(defvar k* (g-s kl* '()))

(defvar h* (g-s mh* '()))

(defvar at* '())

(defun ncr (n lis)
  (loop
    (cond ((null lis) (return '()))
          ((zerop n) (return lis)))
    (pop lis)
    (decf n)))

(defun proto-tkf (n lis res)
  (loop
    (cond ((or (zerop n) (null lis)) (return res)))
          (setq res (append res (list (car lis))))
          (pop lis)
          (decf n)))

(defun tkf (n lis) (proto-tkf n lis '()))

(defun tkl (n lis)
  (loop
    (cond ((null (ncr n lis)) (return lis)))
    (pop lis)))

(defun pbl (lis res)
  (loop
    (cond ((null (cdr lis)) (return res)))
    (setq res (append res (list (car lis))))
    (pop lis)))

(defun b-l (lis) (pbl lis '()))

(defun ek (a b)
  (cond ((eq a b) t)
        ((and (listp a) (listp b))
          (cond ((or (null a) (null b)) '())
                ((not (ek (car a) (car b))) '())
                (t (ek (cdr a) (cdr b)))))
        (t '())))

(defun f-l (lis)
  (loop
    (cond ((null lis) (return '()))
          ((null (cdr lis)) (return (car lis))))
    (pop lis)))

(defun mmb (el lis)
  (loop
    (cond ((null lis) (return '()))
          ((ek el (car lis)) (return lis)))
    (pop lis)))

(defun e-n (lis)
  (loop
    (cond ((null lis) (return '()))
          ((not (null (car lis))) (return lis)))
  (pop lis)))

(defun hrp (hpa h-s)
  (cond ((null h-s) '())
        ((null (cdr h-s)) h-s)
        ((ek hpa (list (car h-s) (cadr h-s)))
          (cons hpa (hrp hpa (cddr h-s))))
        (t
          (cons (car h-s) (hrp hpa (cdr h-s))))))

(defun hha (hsg knw hpr frn rs nh rh nk)
  (loop
    (cond ((null hsg) (return (list '() knw)))
          ((null (cdr hsg))
            (return
              (progn (setq frn '())
              (list
                (car hsg)
                (cons
                  (car hsg)
                  (loop
                    (cond ((null knw) (return '()))
                          ((null (cdr knw)) (return frn))
                          ((ek (car knw) (car hsg))
                            (return (append frn (cdr knw)))))
                    (setq frn (append frn (list (car knw))))
                    (pop knw))))))))
    (setq hpr
          (progn
            (setq hsg (e-n hsg))
            (cond ((null hsg) '())
                  ((null (cdr hsg)) hsg) 
                  (t
                    (cond ((null hsg) '())
                          ((null (cdr hsg)) '())
                          (t (let ((p-m
(progn
  (setq rs (reverse hsg))
  (loop
    (cond ((null rs) (return '()))
          ((null (cdr rs)) (return '()))
          (t (let ((p-m 
                    (progn 
                      (setq nh (list (cadr rs) (car rs)))
                      (setq rh (list (car rs) (cadr rs)))
                      (setq nk '())
                      (loop
                        (cond ((null nk) (return '()))
                              ((ek nh (car nk))
                                (progn
                                  (setq knw (append (reverse nk) knw))
                                  (setq nk '())
                                  (return nh)))
                              ((ek rh (car nk))
                                (progn
                                  (setq knw (append (reverse nk) knw))
                                  (setq nk '())
                                  (return '()))))
                        (push (pop knw) nk)))))
               (cond ((not (null p-m)) (return p-m))))))
    (pop rs)))))
(cond ((null p-m)
        (cond ((null hsg) '())
              ((null (cdr hsg)) '())
              (t (let ((guess
                        (progn
                          (setq nk '())
                          (let ((blh (b-l hsg))
                                (rch (reverse (cdr hsg))))
                            (loop
                              (cond
                                ((or (null hsg) (null knw)) (return '()))
                                ((null (cdr hsg)) (return '()))
                                ((mmb (caar knw) blh)
                                  (return
                                    (tkf 2 (mmb (caar knw) hsg))))
                                ((mmb (cadar knw) rch)
                                  (return
                                    (reverse
                                      (tkf 2 (mmb (cadar knw)
                                                  (reverse hsg)))))))
                              (push (pop knw) nk))))))
                 (progn
                   (setq knw (append (reverse nk) knw))
                   (setq nk '())
                   (cond ((null guess)
                           (let ((reh (reverse hsg)))
                             (list (cadr reh) (car reh))))
                         (t guess)))))))
      (t p-m)))))))))
    (cond ((null hpr)
            (return
              (progn (setq frn '())
              (list
                (f-l hsg)
                (cons
                  (f-l hsg)
                  (loop
                    (cond ((null knw) (return '()))
                          ((null (cdr knw)) (return frn))
                          ((ek (car knw) (f-l hsg))
                            (return (append frn (cdr knw)))))
                    (setq frn (append frn (list (car knw))))
                    (pop knw)))))))
          (t (progn
             (setq hsg (hrp hpr hsg))
             (setq frn '())
             (setq knw
                     (cons hpr
                       (loop
                        (cond ((null knw) (return frn))
                              ((null (cdr knw)) (return frn))
                             ((ek (car knw) hpr)
                                (return (append frn (cdr knw)))))
                        (setq frn (append frn (list (car knw))))
                        (pop knw)))))))
    (gc)))

(defun has (h-s knw)
  (hha (e-n h-s) knw '() '() '() '() '() '()))

HERE, (has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D))) DELIVERS NIL INSTEAD OF A LIST STRUCTURE.


#3

And finally - as you will surely guess, I actually “manually inlined” into that main function hha a lot of other functions which previously served as sub-elements. I shall give a version with these, too:

(defun pgs (n sym lis)
  (loop
    (cond ((zerop n) (return lis)))
    (push sym lis)
    (decf n)))

(defun g-s (n sym) (pgs n sym '()))

(defvar sl* 12)

(defvar st* 5)

(defvar tr* 'TRM)

(defvar mp* 16)

(defvar ps* 12)

(defvar mh* 33)

(defvar kl* 50)

(defvar k* (g-s kl* '()))

(defvar h* (g-s mh* '()))

(defvar at* '())

(defun ncr (n lis)
  (loop
    (cond ((null lis) (return '()))
          ((zerop n) (return lis)))
    (pop lis)
    (decf n)))

(defun proto-tkf (n lis res)
  (loop
    (cond ((or (zerop n) (null lis)) (return res)))
          (setq res (append res (list (car lis))))
          (pop lis)
          (decf n)))

(defun tkf (n lis) (proto-tkf n lis '()))

(defun tkl (n lis)
  (loop
    (cond ((null (ncr n lis)) (return lis)))
    (pop lis)))

(defun pbl (lis res)
  (loop
    (cond ((null (cdr lis)) (return res)))
    (setq res (append res (list (car lis))))
    (pop lis)))

(defun b-l (lis) (pbl lis '()))

(defun ek (a b)
  (cond ((eq a b) t)
        ((and (listp a) (listp b))
          (cond ((or (null a) (null b)) '())
                ((not (ek (car a) (car b))) '())
                (t (ek (cdr a) (cdr b)))))
        (t '())))

(defun f-l (lis)
  (loop
    (cond ((null lis) (return '()))
          ((null (cdr lis)) (return (car lis))))
    (pop lis)))

(defun mmb (el lis)
  (loop
    (cond ((null lis) (return '()))
          ((ek el (car lis)) (return lis)))
    (pop lis)))

(defun pfe (el lis frnt)
  (loop
    (cond ((null lis) (return '()))
          ((null (cdr lis)) (return frnt))
          ((ek (car lis) el) (return (append frnt (cdr lis)))))
    (setq frnt (append frnt (list (car lis))))
    (pop lis)))

(defun f-e (el lis)
  (pfe el lis '()))

(defun bub (el lis)
  (cond ((not (listp el)) lis)
        ((null el) lis)
        (t (cons el (f-e el lis)))))

(defun pmp (hp rhp knw)
  (loop
    (cond ((null knw) (return '()))
          ((ek hp (car knw)) (return hp))
          ((ek rhp (car knw)) (return '())))
    (pop knw)))

(defun p2m (rvh knw)
  (loop
    (cond ((null rvh) (return '()))
          ((null (cdr rvh)) (return '()))
          (t (let ((p-m (pmp
                           (list (cadr rvh) (car rvh))
                           (list (car rvh) (cadr rvh))
                           knw)))
            (cond ((not (null p-m)) (return p-m))))))
    (pop rvh)))

(defun e-n (lis)
  (loop
    (cond ((null lis) (return '()))
          ((not (null (car lis))) (return lis)))
  (pop lis)))

(defun p2g (hsy b-l-his rev-cdr-his knw)
  (loop
    (cond ((or (null hsy) (null knw)) (return '()))
          ((null (cdr hsy)) (return '()))
          ((mmb (caar knw) b-l-his)
            (return (tkf 2 (mmb (caar knw) hsy))))
          ((mmb (cadar knw) rev-cdr-his)
            (return (reverse (tkf 2 (mmb (cadar knw)
                                         (reverse hsy)))))))
    (pop knw)))

(defun pgp (hsy b-l-his rev-cdr-his knw)
  (p2g hsy b-l-his rev-cdr-his (e-n knw)))

(defun g-p (hsy knw)
  (cond ((null hsy) '())
        ((null (cdr hsy)) '())
        (t (let ((ges (pgp hsy
                           (b-l hsy)
                           (reverse (cdr hsy))
                            knw)))
          (cond ((null ges)
                  (let ((rev-his (reverse hsy)))
                    (list (cadr rev-his) (car rev-his))))
                (t ges))))))

(defun pmk (hsy knw)
  (cond ((null hsy) '())
        ((null (cdr hsy)) '())
        (t (let ((p-match (p2m (reverse hsy) knw)))
          (cond ((null p-match) (g-p hsy knw))
                (t p-match))))))

(defun mkp (hsy knw)
  (pmk (e-n hsy) knw))

(defun hhp (h-s knw)
  (cond ((null h-s) '())
        ((null (cdr h-s)) h-s)
        (t (mkp h-s knw))))

(defun h-p (h-s knw)
  (hhp (e-n h-s) knw))

(defun hrp (hpa h-s)
  (cond ((null h-s) '())
        ((null (cdr h-s)) h-s)
        ((ek hpa (list (car h-s) (cadr h-s)))
          (cons hpa (hrp hpa (cddr h-s))))
        (t
          (cons (car h-s) (hrp hpa (cdr h-s))))))

(defun hha (h-s knw)
  (loop
    (cond ((null h-s) (return (list '() knw)))
          ((null (cdr h-s))
            (return (list (car h-s) (bub (car h-s) knw))))
          (t (let ((hpa (h-p h-s knw)))
            (cond ((null hpa)
                    (return (list (f-l h-s) (bub (f-l h-s) knw))))
                  (t (progn
                     (setq h-s (hrp hpa h-s))
                     (setq knw (bub hpa knw))))))))))

(defun has (h-s knw)
  (hha (e-n h-s) knw))

HERE, (has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D))) simply hangs.

I would be very grateful for any advice on how to proceed with this. :) Thank you! :)


#5

I’ve added a bit of formatting to make your code clearer.

David


#6

I confirm that I can get the third version of your program to give the same result on Common Lisp, and that it hangs on uLisp. I’ll investigate.


#7

I don’t really understand enough about how your program works to figure out what the problem is, but I can see that Common Lisp and uLisp are giving different results. Perhaps you can narrow the problem down to a simpler example.

If you do:

(trace bub)
(has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))

you’ll see that on uLisp the program gets stuck in a loop. Also, in the first call to bub the arguments are different between uLisp and Common Lisp.

Note that in trying this I discovered a bug with trace, which I’ve fixed in the latest version of ARM uLisp, so please install uLisp 2.8c before doing this.


#8

Dear David,

you are AWESOME as always… :)

“bub” or “bubble” is supposed to do this: you take an element and a list, and if:

the element is not contained in the list, do (cons el (butlast lis)), i.e. “forget” the final list element and add the new element to the list;

the element is contained in the list, place it on the front of the list fron whereever it was in the list.

So:

(bubble '(A) '(W X Y Z)) gives ((A) W X Y)

and

(bubble '(A) '(X Y (A) Z)) gives ((A) X Y Z)

[EDIT: the element MUST be a list]

  • I will now check does it do that.

I will look into this ASAP, and THANK YOU! :) - As to the bug, I am curious does it have something to do with “pop”…


#9

OK, I redefined hha and has as follows (to match the “long” version):


(defun hha (h-s knw hpa)
  (loop

(print 'ALPHA)

    (cond ((null h-s) (return (list '() knw)))
          ((null (cdr h-s))
            (return (list (car h-s) (bub (car h-s) knw)))))

(print 'BETA)

    (setq hpa (h-p h-s knw))

(print 'GAMMA)

    (cond ((null hpa) (progn (print 'DELTA)
            (return (list (f-l h-s) (bub (f-l h-s) knw)))))
          (t (progn

(print 'EPSILON)

             (setq h-s (hrp hpa h-s))
             (setq knw (bub hpa knw)))))))

(defun has (h-s knw)
  (hha (e-n h-s) knw '()))

… and the function call now gives me an infinite stream of

ALPHA
BETA
GAMMA
EPSILON

whereas SBCL, on the re-definition, gives me

ALPHA
BETA
GAMMA
EPSILON
ALPHA
BETA
GAMMA
EPSILON
ALPHA
BETA
GAMMA
EPSILON
ALPHA
BETA
GAMMA
EPSILON
ALPHA
(((A (B C)) (A B)) (((A (B C)) (A B)) (A (B C)) (A B) (B C) (R S) (T U)))


#10

@johnsondavies

Dear David,

in 2.8c, (save-image) and (load-image) don’t work any more on my Adafruit M4 Grand Central

(save-image) seems to do something, but (load-image) fails.

It DID work in 2.8b.


#11

Well, now instead of ALPHA, I let it print the “hierarchised segment”:

(print (cons 'ALPHA (cons 'H-S h-s)))

And SBCL and ulisp give different results:

(ALPHA h-s ((a b) (c (a b)))) ; ulisp, infinitely looping

(ALPHA H-S ((A (B C)) (A B))) ; SBCL, just prior to termination

  • which points to the function “hrp” (or “hier-pair”),
    a normally super-simplistic function with the only task of
    finding some sequence of A B in a list X Y A B F P and
    turning this into X Y (A B) F P or whatever… but:

(HRP '(A B) '(S A R A B T Z))
–> (s a r (a b) t z)

in both ulisp and SBCL, so it does not look like it.

OK, adjusting the print further to:

(print (list 'ALPHA (cons 'H-S h-s) (cons 'KNW knw) (cons 'HPA hpa)))

i.e. to print the list to be hierarchised, the knowledge, and the relevant pair

gives me in SBCL:


(has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))

(ALPHA (H-S A B C A B) (KNW (R S) (T U) (B X) (V W) (W E) (E D)) (HPA))
BETA
GAMMA
EPSILON
(ALPHA (H-S A (B C) A B) (KNW (B C) (R S) (T U) (B X) (V W) (W E)) (HPA B C))
BETA
GAMMA
EPSILON
(ALPHA (H-S A (B C) (A B)) (KNW (A B) (B C) (R S) (T U) (B X) (V W)) (HPA A B))
BETA
GAMMA
EPSILON
(ALPHA (H-S (A (B C)) (A B)) (KNW (A (B C)) (A B) (B C) (R S) (T U) (B X))
 (HPA A (B C)))
BETA
GAMMA
EPSILON
(ALPHA (H-S ((A (B C)) (A B)))
 (KNW ((A (B C)) (A B)) (A (B C)) (A B) (B C) (R S) (T U))
 (HPA (A (B C)) (A B)))
(((A (B C)) (A B)) (((A (B C)) (A B)) (A (B C)) (A B) (B C) (R S) (T U)))

ulisp, on the other hand, does:


(has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))

(ALPHA (h-s a b c a b) (knw (r s) (t u) (b x) (v w) (w e) (e d)) (hpa)) 
BETA 
GAMMA 
EPSILON 
(ALPHA (h-s (a b) c (a b)) (knw (a b) (r s) (t u) (b x) (v w) (w e)) (hpa a b)) 
BETA 
GAMMA 
EPSILON 
(ALPHA (h-s (a b) (c (a b))) (knw (c (a b)) (a b) (r s) (t u) (b x) (v w)) (hpa c (a b))) 
BETA 
GAMMA 
EPSILON 
(ALPHA (h-s ((a b) (c (a b)))) (knw ((a b) (c (a b))) (c (a b)) (a b) (r s) (t u) (b x)) (hpa (a b) (c (a b)))) 
BETA 
GAMMA 
EPSILON 
(ALPHA (h-s ((a b) (c (a b)))) (knw (((a b) (c (a b)))) ((a b) (c (a b))) (c (a b)) (a b) (r s) (t u)) (hpa ((a b) (c (a b))))) 
BETA 
GAMMA 
EPSILON 
(ALPHA (h-s ((a b) (c (a b)))) (knw (((a b) (c (a b)))) ((a b) (c (a b))) (c (a b)) (a b) (r s) (t u)) (hpa ((a b) (c (a b))))) 
BETA 
GAMMA 
EPSILON 

… ad infinitum.


#12

Now, kindly mind the EXITING-marker in the cond: this is where SBCL indeed exits.

We should NEVER witness a printout that reads (BETA), because this condition
should catch it.


(defun hha (h-s knw hpa)
  (loop

(print (list 'ALPHA (cons 'H-S h-s) (cons 'KNW knw) (cons 'HPA hpa)))

    (cond ((null h-s) (return (list '() knw)))
          ((null (cdr h-s)) (progn (print (cons 'EXITING (cdr h-s)))
            (return (list (car h-s) (bub (car h-s) knw))))))

(print (cons 'BETA (cdr h-s)))

    (setq hpa (h-p h-s knw))

(print 'GAMMA)

    (cond ((null hpa) (progn (print 'DELTA)
            (return (list (f-l h-s) (bub (f-l h-s) knw)))))
          (t (progn

(print 'EPSILON)

             (setq h-s (hrp hpa h-s))
             (setq knw (bub hpa knw)))))))

… however, this is EXACTLY what we witness in ulisp, i.e. the
(null …) test FAILS and we see this:

(ALPHA (h-s a b c a b) (knw (r s) (t u) (b x) (v w) (w e) (e d)) (hpa)) 
(BETA b c a b) 
GAMMA 
EPSILON 
(ALPHA (h-s (a b) c (a b)) (knw (a b) (r s) (t u) (b x) (v w) (w e)) (hpa a b)) 
(BETA c (a b)) 
GAMMA 
EPSILON 
(ALPHA (h-s (a b) (c (a b))) (knw (c (a b)) (a b) (r s) (t u) (b x) (v w)) (hpa c (a b))) 
(BETA (c (a b))) 
GAMMA 
EPSILON 
(ALPHA (h-s ((a b) (c (a b)))) (knw ((a b) (c (a b))) (c (a b)) (a b) (r s) (t u) (b x)) (hpa (a b) (c (a b)))) 
(EXITING) 
(BETA) <----------- !
GAMMA 
EPSILON 
(ALPHA (h-s ((a b) (c (a b)))) (knw (((a b) (c (a b)))) ((a b) (c (a b))) (c (a b)) (a b) (r s) (t u)) (hpa ((a b) (c (a b))))) 
(EXITING) 
(BETA) <----------- ! 
GAMMA 
EPSILON 
...

Something is off with the structuring of hpa, too, but this “missing the null-test” seems to be primarily interesting for you.


#13

OK, trying different alternatives to (null (cdr h-s)):

(eq '() (cdr h-s)) --> infinite loop

(progn (print (list 'LEN (length (cdr h-s)))) (zerop (length (cdr h-s)))) --> infinite loop

… and it IS indeed printing (len 0), so I somehow don’t believe the CONDITION is not recognized, but that rather, somehow its CONSEQUENCE is not executed:

I tried appending a final (t nil) to that cond, but it changed nothing, either.

Then I tried turning it into an if-clause, same infinite loop:


(defun hha (h-s knw hpa)
  (loop

(print (list 'ALPHA (cons 'H-S h-s) (cons 'KNW knw) (cons 'HPA hpa)))

    (if (null h-s) (return (list '() knw))
      (if (progn (print (list 'LEN (length (cdr h-s)))) (zerop (length (cdr h-s))))
          (progn (print (cons 'EXITING (cdr h-s)))
            (return (list (car h-s) (bub (car h-s) knw))))))

(print (cons 'BETA (cdr h-s)))

    (setq hpa (h-p h-s knw))

(print 'GAMMA)

    (cond ((null hpa) (progn (print 'DELTA)
            (return (list (f-l h-s) (bub (f-l h-s) knw)))))
          (t (progn

(print 'EPSILON)

             (setq h-s (hrp hpa h-s))
             (setq knw (bub hpa knw)))))))

(has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))

But note something funny: it DOES PRINT “EXITING”, it just doesn’t DO it.

In other words, I think “return” is the actual culprit!


#14

"return" as culprit is confirmed: apparently it does not like the “list”-expression after it, but DOES work if you just setq some result and let then “return” just return that result - this terminates (albeit with wrong results):

(defun hha (h-s knw hpa res)
  (loop

(print (list 'ALPHA (cons 'H-S h-s) (cons 'KNW knw) (cons 'HPA hpa)))

    (if (null h-s) (return (list '() knw))
      (if (progn (print (list 'LEN (length (cdr h-s)))) (zerop (length (cdr h-s))))
          (progn (print (cons 'EXITING (cdr h-s)))
                 (setq res (list (car h-s) (bub (car h-s) knw)))
            (return res))))

(print (cons 'BETA (cdr h-s)))

    (setq hpa (h-p h-s knw))

(print 'GAMMA)

    (cond ((null hpa) (progn (print 'DELTA)
            (return (list (f-l h-s) (bub (f-l h-s) knw)))))
          (t (progn

(print 'EPSILON)

             (setq h-s (hrp hpa h-s))
             (setq knw (bub hpa knw)))))))

(defun has (h-s knw)
  (hha (e-n h-s) knw '() '()))

(has '(A B C A B) '((R S) (T U) (B X) (V W) (W E) (E D)))

EDIT: even more: doing the same change consequently - letting return only return elementary values which I set with progn and setq just before calling it, but no list operations like append etc. - has even repaired the function result.


#15

Thanks for the detective work! I’ll see if I can spot what the problem is.

David


#16

Dear David,

Thank you so much! I know I am doing with uLisp not what it is meant for, but how could I ever not indulge in SUCH a toy? :)

Perhaps it got lost a little above, but I think this is important:

(load-image) fails to load an image. It printed:

64

and hung.


#17

Thank you for reporting the problem with save-image; the problem is fixed in ARM uLisp 2.8d: Download uLisp.


#18

I’ve worked out what’s causing the bug. If the expression in a return statement calls a function that itself uses a return statement, the first return statement never returns. For example:

(defun test (x)
  (loop
   (return (fun x))))

(defun fun (y)
  (loop
   (return (car y))))

then calling:

(test '(a b))

should return a, but instead hangs up.

The workaround, as you have discovered, is to assign the result to a temporary variable, and then return that:

(defun test (x)
  (loop
   (let ((val (fun x)))
     (return val))))

(defun fun (y)
  (loop
   (return (car y))))

So now, as expected:

> (test '(a b))
a

I hope to fix it properly in the near future. Thanks for finding the problem!


#19

This is fixed in Version 2.9.


#20