Helpful List Function

For the Compleat Fan
Locked
Jeremy Dunn
Posts: 95
Joined: Wed Oct 13, 2004 8:02 pm
Location: Bellingham WA

Helpful List Function

Post by Jeremy Dunn »

One thing I always love about LISP is that it always gets you thinking in ever more general terms after you start out with something simple. Here is a good example of it. My starting point was a one-liner that I wrote that is pretty much self-explanatory:

(define (length? lst n)(= (length lst) n))

Can't get much simpler than that. I don't know how many times I wrote (= (length lst) n) before thinking of it. Just like the paper clip. But what about greater abstraction? What do we do with that length once we get it? I find that I either use it in a control structure to branch the program or I use it in a calculation. Let us just consider the control structure aspect of it. Here is the code first:

Code: Select all

(define (iflength lst (n 0) X Y Z , i flg)
  (setq i (length lst) flg (= i n))
  (if Z (if (< i n) X flg Y Z)
      Y (if flg X Y)
      X (if flg X)
      flg
))
So what does iflength do? iflength gobbles up the previous function and acts as a control structure too. Let i be the length of the list, n the number we are comparing to the list, lst the list itself and X,Y,Z are code chunks to be executed depending on how a boolean test is performed. So it goes like this, if we write

(iflength lst n X Y Z) - if i<n then X is executed elseif i=n then Y is executed else Z is executed.
(iflength lst n X Y) - if i=n then X is executed else Y is
(iflength lst n X) - if i=n then X is executed else nothing happens
(iflength lst n) - behaves the same as the length? function

Very simple, very handy.

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Post by rickyboy »

I see what you're trying to do, but you won't get iflength to work the way you want without defining it as a macro. Happy coding! --Ricky
(λx. x x) (λx. x x)

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

It will work if you pass it a quoted list that happens to be an expression. But it should be a macro.
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

I like this function.. a nice alternative for a lenght check..perhpas even
more logical too ;-)
-- (define? (Cornflakes))

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Here's a macro that will do it:

Code: Select all

(define-macro (if-length _list-n _expr-true _expr-nil)
  "Tests length of list (_list-n 0) against integer value (_list-n 1) for
  equality.  If true, evaluates _expr-true; else, evaluates _expr-nil.  Does
  simple type checking on _list-n's elements."
  (let ((lst (eval (_list-n 0))) (n (eval (_list-n 1))))
       ;; Throw error if we get bad data types
       (unless (list? lst) (throw-error "List expected in if-length"))
       (unless (integer? n) (throw-error "Integer expected in if-length"))
       (if (= n (length lst))
           (if _expr-true (eval _expr-true))
           (if _expr-nil (eval _expr-nil)))))

(set 'a '(a b c d))
(if-length (a 4))
(if-length (a 4)
           (println "List is 4 items long."))
(if-length (a 5)
           (println "List is 5 items long.")
           (println "List is not 5 items long."))
It does simple type checking and accepts parameters in the idiomatic way for if-style control structures. I haven't tested it too much, though.
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

Jeremy Dunn
Posts: 95
Joined: Wed Oct 13, 2004 8:02 pm
Location: Bellingham WA

Post by Jeremy Dunn »

You're so right guys, define-macro indeed. This is what happens when you are too enthusiastic and have been working overtime for a couple of weeks. This one works a bit better

Code: Select all

(define-macro (iflength lst n do-X do-Y do-Z)
  (setq L   (if do-Z 5 do-Y 4 do-X 3 n 2 1)
        i   (length (eval lst))
        n   (abs n)
        flg (= i n)
  )
  (if (lessthanorequal 1 L 5)
      (if (= L 5)(eval (if (< i n) do-X flg do-Y do-Z))
          (= L 4)(eval (if flg do-X do-Y))
          (= L 3)(eval (if flg do-X))
          (= L 2) flg
          (= i)
      )
  )
)

Locked