There is lots of discussion on the mail archive on this topic over the
years.
http://www.mail-archive.com/picolisp@software-lab.de/msg03860.html
There are others. Try searching tail recursion, macros, fexpr.

The mail archive has been an excellent source of information on picolisp.

I haven't found significant advantage to having tail recursion. Either in
picolisp, or other languages I generally work with.
Not recursing saves 'stack' but by the time that is an issue I am looking
for a different algorithm.

I am discovering picolisp has some great general purpose functions for just
that.

Here's an example I worked out recursively last week (set intersection),
then tried to do the same thing without recursion, then with (idx).
(randl, concurret, concurreti, concurretix are defined at the end of this
message)

# Make two lists of random numbers with random range large enough for small
collision set
: (nil (setq M (randl 10000 9999999) N (randl 10000 9999999)))
-> NIL

# Recurse
: (bench (sort (uniq (concurret M N))))
4.103 sec
-> (1144218 1809896 2048032 2258715 2819894 5571078 9413422 9726100 9936515)

# loop
: (bench (sort (uniq (concurreti M N))))
2.566 sec
-> (1144218 1809896 2048032 2258715 2819894 5571078 9413422 9726100 9936515)

# idx
: (bench (sort (uniq (concurretix M N))))
0.018 sec
-> (1144218 1809896 2048032 2258715 2819894 5571078 9413422 9726100 9936515)

Idx 'wins'.


/Lindsay


# ==================================
# Set intersection: recursive solution.
(de membro (X Y)
   (cond
      ((not Y) NIL)
      ((= X (car Y)) T)
      (T (membro X (cdr Y))) ) )

(de concurret (X Y)
   (cond
      ((not X) NIL)
      ((membro (car X) Y)
         (cons (car X) (concurret (cdr X) Y)) )
      (T (concurret (cdr X) Y)) ) )

# Set intersection: no recursion
(de membri (X Y)
   (until (or (not Y) (= X (car Y)))
      (setq Y (cdr Y)) )
   (= X (car Y)) )

(de concurreti (X Y)
   (let (V NIL)
      (until (not X)
         (when (membri (car X) Y)
            (setq V (cons (car X) V)) )
         (setq X (cdr X)) )
      V ) )
# Set intersection: Filter X into (idx); filter Y on that.
(de concurretix (X Y)
   (let (R NIL)
      (filter
         '((V)
            (not (idx 'R (cons (hash V) V) T)) )
         X )
      (uniq
         (filter
            '((V) (idx 'R (cons (hash V) V)))
            Y ) ) ) )

# Generate list of random numbers in given range
(de randl (L R) (make (do L (link (rand 0 R)))))

Reply via email to