From: David Buchan
Subject: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <MPG.1c3f5484c7d4c3c89896a1@news.ca.inter.net>
In the C version of my program I have:

for (i=0; i<nchar; i=i+1) {
    if (tmp[i]>=0 && tmp[i]<=31) {
      dat[i]=tmp[i]+128;}
    else if (tmp[i]>=32 && tmp[i]<=63) {
      dat[i]=tmp[i];}
    else if (tmp[i]>=64 && tmp[i]<=95) {
      dat[i]=tmp[i]-64;}
    else if (tmp[i]>=128 && tmp[i]<=159) {
      dat[i]=tmp[i]+64;}
    else if (tmp[i]>=160 && tmp[i]<=191) {
      dat[i]=tmp[i]-64;}
    else if (tmp[i]>=192 && tmp[i]<=223) {
      dat[i]=tmp[i]-128;
    }
  }

I'd like to achieve the same thing in Common Lisp (Clisp). But I'm 
confused by the fact that there doesn't seem to be an elseif construct. 
I see there is an if-then-else though.

Part of my problem is likely due to the fact that I'm slavishly 
translating the C form into Lisp, when I should really be thinking in 
different terms. That is, I probably need to do this in an entirely new 
way - one, unfortunately, I cannot see at the moment.

Can anyone give me an idea of how this type of thing should be done in 
Lisp?

Thanks,
Dave

From: jtdubs
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <1104515808.183873.327590@z14g2000cwz.googlegroups.com>
David Buchan wrote:
> In the C version of my program I have:
>
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
>
> I'd like to achieve the same thing in Common Lisp (Clisp). But I'm
> confused by the fact that there doesn't seem to be an elseif
construct.
> I see there is an if-then-else though.

You want cond.  See here:

http://www.lisp.org/HyperSpec/Body/mac_cond.html

Basically, cond takes a list of tests and forms and it evaluates the
tests until it finds one that is true, then it evaluates that test's
forms.

For example:

(cond
((= i 1) (princ "i is 1"))
((= i 2) (princ "i is 2"))
(t  (princ "i is neither 1 nor 2")))

> Part of my problem is likely due to the fact that I'm slavishly
> translating the C form into Lisp, when I should really be thinking in

> different terms. That is, I probably need to do this in an entirely
new
> way - one, unfortunately, I cannot see at the moment.
>
> Can anyone give me an idea of how this type of thing should be done
in
> Lisp?

It's all a matter of style.  You can write lisp in pretty much any
style you want, be it imperitive or functional, OO or procedural.  You
can even fill it with goto's if you want.  You may want to check out:

http://www.gigamonkeys.com/book/
http://www.paulgraham.com/acl.html
http://www.psg.com/~dlamkins/sl/contents.html

Justin Dubs
From: David Buchan
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <MPG.1c3f6e8afa57ba1598968f@news.ca.inter.net>
Thanks everybody!

I really appreciate it.

Dave
From: Cameron MacKinnon
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <n7adnU7rVuK4M0jcRVn-uw@golden.net>
David Buchan wrote:
> In the C version of my program I have:
> 
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
> 
> I'd like to achieve the same thing in Common Lisp (Clisp).

If by "the same thing" you mean a slow program, others here have pointed 
the way.

However, I'd suggest using essentially the same code structure to 
populate an array of values to add to the character. Then, while reading 
characters from the file, use the value of each character as an offset 
into the array, fetch the array element and add it to the character.

You see, on modern x86 processors (especially the Pentium 4), 
mispredicting a branch costs a lot, and your loop is likely to 
mispredict at least once per iteration.
From: Paul Dietz
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <41D5C355.E3A80264@motorola.com>
David Buchan wrote:
> 
> In the C version of my program I have:
> 
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
> 
> I'd like to achieve the same thing in Common Lisp (Clisp). But I'm
> confused by the fact that there doesn't seem to be an elseif construct.
> I see there is an if-then-else though.
[...]
> Can anyone give me an idea of how this type of thing should be done in
> Lisp?

This 'type' of thing? :)

(block done
  (setf (aref dat i)
    (let ((tmpi (aref tmp i)))
       (+ (typecase tmpi
             ((integer 0 31) 128)
             ((integer 32 63) 0)
             ((or (integer 64 95) (integer 160 191)) -64)
             ((integer 128 159) 64)
             ((integer 192 223) -128)
             (t (return-from done nil)))
          tmpi))))

(I assume here that tmp is an array of integers; if not, replace
'integer' with 'real'.  If it was an array of characters, be warned
that Common Lisp doesn't standardly assume ASCII codes for the
characters,
and that you'd have to encode and decode using appropriate functions
such as char-code, char-int, and code-char.)

You could also consider a CASE statement, but there's no
range construct in CASE.  You can fake that with read eval:

;; Put this defun in a separate file
(defun rng (lo hi) (loop for i from lo to hi collect i))

... (case tmpi
      (#.(rng 0 31) ...)
      (#.(rng 32 63) ...)
      ...)


	Paul
From: Peter Seibel
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <m31xd65q4g.fsf@javamonkey.com>
David Buchan <·····@pdbuchan.com> writes:

> In the C version of my program I have:
>
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
>
> I'd like to achieve the same thing in Common Lisp (Clisp). But I'm
> confused by the fact that there doesn't seem to be an elseif
> construct. I see there is an if-then-else though.
>
> Part of my problem is likely due to the fact that I'm slavishly
> translating the C form into Lisp, when I should really be thinking
> in different terms. That is, I probably need to do this in an
> entirely new way - one, unfortunately, I cannot see at the moment.
>
> Can anyone give me an idea of how this type of thing should be done in 
> Lisp?

Try COND.

  (loop for i from 0 below nchar
        for e across tmp do
    (cond 
      ((>= 0 e 31)    (setf (aref dat i) (+ e 128)))
      ((>= 32 e 63)   (setf (aref dat i) e))
      ((>= 64 e 95)   (setf (aref dat i) (- e 64)))
      ((>= 128 e 159) (setf (aref dat i) (+ e 64)))
      ((>= 160 e 191) (setf (aref dat i) (- e 64)))
      ((>= 192 e 223) (setf (aref dat i) (- e 128)))))

Or even:

  (loop for i from 0 below nchar
        for e across tmp do
    (setf (aref dat i)
      (+ e (cond 
            ((>= 0 e 31)    128)
            ((>= 32 e 63)   0)
            ((>= 64 e 95)   -64)
            ((>= 128 e 159) 64)
            ((>= 160 e 191) -64)
            ((>= 192 e 223) -128)

-Peter         

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Kenny Tilton
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <oBgBd.37954$Yh2.15975510@twister.nyc.rr.com>
Peter Seibel wrote:
> David Buchan <·····@pdbuchan.com> writes:
> 
> 
>>In the C version of my program I have:
>>
>>for (i=0; i<nchar; i=i+1) {
>>    if (tmp[i]>=0 && tmp[i]<=31) {
>>      dat[i]=tmp[i]+128;}
>>    else if (tmp[i]>=32 && tmp[i]<=63) {
>>      dat[i]=tmp[i];}
>>    else if (tmp[i]>=64 && tmp[i]<=95) {
>>      dat[i]=tmp[i]-64;}
>>    else if (tmp[i]>=128 && tmp[i]<=159) {
>>      dat[i]=tmp[i]+64;}
>>    else if (tmp[i]>=160 && tmp[i]<=191) {
>>      dat[i]=tmp[i]-64;}
>>    else if (tmp[i]>=192 && tmp[i]<=223) {
>>      dat[i]=tmp[i]-128;
>>    }
>>  }
>>
>>I'd like to achieve the same thing in Common Lisp (Clisp). But I'm
>>confused by the fact that there doesn't seem to be an elseif
>>construct. I see there is an if-then-else though.
>>
>>Part of my problem is likely due to the fact that I'm slavishly
>>translating the C form into Lisp, when I should really be thinking
>>in different terms. That is, I probably need to do this in an
>>entirely new way - one, unfortunately, I cannot see at the moment.
>>
>>Can anyone give me an idea of how this type of thing should be done in 
>>Lisp?
> 
> 
> Try COND.
> 
>   (loop for i from 0 below nchar
>         for e across tmp do
>     (cond 
>       ((>= 0 e 31)    (setf (aref dat i) (+ e 128)))
>       ((>= 32 e 63)   (setf (aref dat i) e))
>       ((>= 64 e 95)   (setf (aref dat i) (- e 64)))
>       ((>= 128 e 159) (setf (aref dat i) (+ e 64)))
>       ((>= 160 e 191) (setf (aref dat i) (- e 64)))
>       ((>= 192 e 223) (setf (aref dat i) (- e 128)))))
> 
> Or even:
> 
>   (loop for i from 0 below nchar
>         for e across tmp do
>     (setf (aref dat i)
>       (+ e (cond 
>             ((>= 0 e 31)    128)
>             ((>= 32 e 63)   0)
>             ((>= 64 e 95)   -64)
>             ((>= 128 e 159) 64)
>             ((>= 160 e 191) -64)
>             ((>= 192 e 223) -128)

Nice. But the cond is not exhaustive and would return nil for e from 96 
to 127 or above 223, so perhaps a final clause is desirable:

If dat should be zero for other slots:

   (cond ...
     (t (- e))

If dat should match tmp for other slots:

   (cond ...
      (t 0))

If dat should really be unchanged:

    (cond ....
      (t (- (aref dat i) e))

Ick. :)

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Icarus Sparry
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <pan.2004.12.31.17.36.36.125458@icarus.freeuk.com>
On Fri, 31 Dec 2004 12:21:01 -0500, David Buchan wrote:

> In the C version of my program I have:
> 
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
> 
> I'd like to achieve the same thing in Common Lisp (Clisp). But I'm 
> confused by the fact that there doesn't seem to be an elseif construct. 
> I see there is an if-then-else though.
> 
> Part of my problem is likely due to the fact that I'm slavishly 
> translating the C form into Lisp, when I should really be thinking in 
> different terms. That is, I probably need to do this in an entirely new 
> way - one, unfortunately, I cannot see at the moment.
> 
> Can anyone give me an idea of how this type of thing should be done in 
> Lisp?

'cond'.

(let ((tval (aref tmp i)))
   (cond ((>= 31 tval 0) (setf (aref dat i) (+ tval 128)))
         ((>= 63 tval 32) (setf (aref dat i) tval))
         ((>= 95 tval 32) (setf (aref dat i) (- tval 64)))
         ((>= 159 tval 128) (setf (aref dat i) (+ tval 64)))
         ((>= 191 tval 160) (setf (aref dat i) (- tval 64)))
         ((>= 223 tval 192) (setf (aref dat i) (- tval 128)))))

Of course given 'if-then-else' you can produce 'elseif', all you do is put
a new 'if-then-else' in the 'else' position. In C the 'elseif' just helps
keep the indentation under control. I am told that many Common Lisp
systems will translate 'cond' into a nested set of 'if-then-else'
statements.
From: Wade Humeniuk
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <0skBd.36148$KO5.2436@clgrps13>
David Buchan wrote:

> Part of my problem is likely due to the fact that I'm slavishly 
> translating the C form into Lisp, when I should really be thinking in 
> different terms. That is, I probably need to do this in an entirely new 
> way - one, unfortunately, I cannot see at the moment.
> 
> Can anyone give me an idea of how this type of thing should be done in 
> Lisp?

In Lisp it is nice to create functions to do things like that.  So, I
would create a function like:

(defun equalize-array (array)
   (map (type-of array)
        (lambda (i)
          (incf i
                (cond
                 ((<= 0 i 31) +128)
                 ((<= 32 i 63) 0)
                 ((<= 64 i 95) -64)
                 ((<= 128 i 159) +64)
                 ((<= 160 i 191) -64)
                 ((<= 192 i 223) -128)
                 (t 0))))
        array))

I called it equalize-array because it looks some kind of equalizer
function (as in sound).  I have the function generate a new array
as opposed to setting an existing array, its more functional.

CL-USER 6 > (equalize-array '#(1 2 161 65 224))
#(129 130 97 1 224)

Wade
From: Wade Humeniuk
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <5PkBd.36152$KO5.6848@clgrps13>
To take this a little further, trying to abstract the solution.

(defun make-equalizer-function (bands)
   (lambda (value)
     (loop for (lower upper adjustment) in bands
           when (<= lower value upper) return (+ value adjustment)
           finally (return value))))

(defvar *default-equalizer-function*
   (make-equalizer-function
    '((0 31 +128)
      (32 63 0)
      (64 95 -64)
      (128 159 +64)
      (160 191 -64)
      (192 223 -128))))

(defun equalize-array (array &optional (equalization-function *default-equalizer-function*))
   (map (type-of array) equalization-function array))

Then,

CL-USER 4 > (equalize-array '#(1 2 161 65 224))
#(129 130 97 1 224)

Wade
From: David Sletten
Subject: Re: Another newbie question: if-elseif-elseif-elseif..etc.
Date: 
Message-ID: <vJlBd.55752$gd.12794@twister.socal.rr.com>
David Buchan wrote:
> In the C version of my program I have:
> 
> for (i=0; i<nchar; i=i+1) {
>     if (tmp[i]>=0 && tmp[i]<=31) {
>       dat[i]=tmp[i]+128;}
>     else if (tmp[i]>=32 && tmp[i]<=63) {
>       dat[i]=tmp[i];}
>     else if (tmp[i]>=64 && tmp[i]<=95) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=128 && tmp[i]<=159) {
>       dat[i]=tmp[i]+64;}
>     else if (tmp[i]>=160 && tmp[i]<=191) {
>       dat[i]=tmp[i]-64;}
>     else if (tmp[i]>=192 && tmp[i]<=223) {
>       dat[i]=tmp[i]-128;
>     }
>   }
> 
> I'd like to achieve the same thing in Common Lisp (Clisp). But I'm 
> confused by the fact that there doesn't seem to be an elseif construct. 
> I see there is an if-then-else though.
> 
> Part of my problem is likely due to the fact that I'm slavishly 
> translating the C form into Lisp, when I should really be thinking in 
> different terms. That is, I probably need to do this in an entirely new 
> way - one, unfortunately, I cannot see at the moment.
> 
> Can anyone give me an idea of how this type of thing should be done in 
> Lisp?
> 
> Thanks,
> Dave

Others have given you valuable responses. Here's a different insight. 
There are at least two limitations to using IF in Lisp:
1. Each of the "then" and "else" expressions must be a single expression.
2. Cascaded if/else if expressions tend to creep off to the right side 
of the page.

Suppose you want to print a message and return a value based on some number:
(defun negative-test (x)
   (if (minsup x)
       (format t "negative~%")
       t
       (format t "non-negative~%")
       nil))
Of course, this won't work as written. A simple solution is to wrap each 
alternative sequence in a PROGN form:
(defun negative-test (x)
   (if (minsup x)
       (progn (format t "negative~%") t)
       (progn (format t "non-negative~%") nil)))

The other problem is illustrated below:
(defun sign-test (x)
   (if (minusp x)
       (progn (format t "negative~%") -1)
       (if (plusp x)
           (progn (format t "positive~%") 1)
           (progn (format t "zero~%") 0))))

COND is often a more concise alternative:
(defun sign-test (x)
   (cond ((minusp x) (format ...) -1)
         ((plusp x) (format ...) 1)
         (t (format ...) 0)))

So a simple rule of thumb is that when your conditional involves complex 
consequent expressions or you have a chain of several possible 
alternatives you probably want COND rather than IF.

Also investigate CASE/TYPECASE and WHEN/UNLESS which are appropriate in 
other circumstances.

David Sletten

P.S. Strictly speaking, C has no "else if" statement either. You simply 
use another 'if' statement in the 'else' part of the surrounding 'if' 
statement:
if (...) {
...
} else {
     if (...) {
     ...
     }
}

This is simply written by convention:
if (...) {
...
} else if (...) {
...
}