From: basi
Subject: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <1104298927.824574.107140@z14g2000cwz.googlegroups.com>
Hello,
Is there a place where one can ask very specific *newbie* questions
about Lisp?  Or is this the place to do it?

How do I exit from a loop when a condition is met?

Something like:

(defun hasIllegalCharacter (aString)
(loop for char across aString
(if (isIllegalChar char) (return 't)
)
)
)

where isIllegalChar is defined as not in a set of characters.

Might there be a kind of a place, a free service, like tutors.lisp.org
where it is acceptable to ask *dumb* questions. 

Thanks.
basi

From: basi
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <1104326188.016807.129510@f14g2000cwb.googlegroups.com>
Thank you all for the helpful replies. Now my code works. I try hard to
do my homework before asking a question. For me asking a "how do I"
question is like asking for the nearest gas station -- it's an act of
desperation because I've been going around the neighborhood many times
looking for one and the empty red light has been on since half an hour
ago. I'm an experienced *average* programmer, and after many years of
hesitation, I'm finally writing my first program in Lisp. CL is
massive; I feel like I'm under the Niagara Falls and it's coming down
on me. While I value elegance in code, I'd settle for anything that
works right now. 

Cheers!
Basi
From: GP lisper
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <1104328095.1fd428eaa175f81e631195e1506b5d25@teranews>
On 29 Dec 2004 05:16:28 -0800, <··········@yahoo.com> wrote:
> 
> CL is massive; I feel like I'm under the Niagara Falls and it's coming
> down on me. While I value elegance in code, I'd settle for anything 
> that works right now. 

You are not the first to have that feeling...nor shall you be the last.



-- 
Everyman has three hearts;
one to show the world, one to show friends, and one only he knows.
From: ···············@yahoo.com
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <1104421757.021340.92130@z14g2000cwz.googlegroups.com>
> I try hard to do my homework before asking a question.

I have the sense that you did.  :-)

> I'm an experienced *average* programmer, and after many years of
> hesitation, I'm finally writing my first program in Lisp.

Welcome!  The part of this thread that really shows the power
of Lisp may be the transition to (some ...).  That's the
cool stuff.
From: Frode Vatvedt Fjeld
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <2h7jn1o4s1.fsf@vserver.cs.uit.no>
"basi" <··········@yahoo.com> writes:

> Something like:
>
> (defun hasIllegalCharacter (aString)
> (loop for char across aString
> (if (isIllegalChar char) (return 't)
> )
> )
> )

  (defun has-illegal-character (string)
    (loop for char across string
       do (when (illegal-char-p char)
            (return t))))

This variant is also legal, although personally I prefer the above:

  (defun has-illegal-character (string)
    (loop for char across string
       when (illegal-char-p char)
       return t))

You'd also be well advised to learn this style of parens, indentation,
and symbol naming.

However, you can express pretty much the same thing like this:

  (some #'illegal-char-p string)

or one of the variations

  (find-if #'illegal-char-p string)

  (position-if #'illegal-char-p string)

You can look up the meaning of each of these operators in the
HyperSpec, at http://www.lispworks.com/reference/HyperSpec/

> Might there be a kind of a place, a free service, like
> tutors.lisp.org where it is acceptable to ask *dumb* questions.

Dumb questions are those where the author makes no effort to
understand the issue before asking the question, or any effort to
understand and learn from the answers provided to him. I doubt you'll
find any forum where anyone will helpfully answer truly dumb questions
for free.

-- 
Frode Vatvedt Fjeld
From: Kenny Tilton
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <zhvAd.34269$kq2.5987@twister.nyc.rr.com>
basi wrote:
> Hello,
> Is there a place where one can ask very specific *newbie* questions
> about Lisp?  Or is this the place to do it?
> 
> How do I exit from a loop when a condition is met?
> 
> Something like:
> 
> (defun hasIllegalCharacter (aString)
> (loop for char across aString
> (if (isIllegalChar char) (return 't)

[snip]

You have gotten lots of good tips, but just in case this "(return 't)" 
reflects a certain misunderstanding: hasIllegalCharacter can offer 
useful information at the same time as acting as a predicate, because 
Lisp considers anything other than NIL to be true. So you can return the 
illegal character or its position or both and still be able to write:

     (if (hasIllegalCharacter "hi mom")....

For example:

  (defun hasIllegalCharacter (aString)
    (loop for char across aString
         for pos from 0
         when (isIllegalChar char)
         return (values char pos)))

Then you could use the "predicate" this way (untested):

   (multiple-value-bind (bad-c bad-pos)
        (hasIllegalCharacter "hi mom")
      (when bad-c
        (format t "Character ~a at position ~a stinks." bad-c bad-pos)))

...or still code "(if (hasIllegalCharacter...)..." and ignore any 
returned values.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Edi Weitz
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <ullbh31n1.fsf@agharta.de>
On 28 Dec 2004 21:42:07 -0800, "basi" <··········@yahoo.com> wrote:

> Is there a place where one can ask very specific *newbie* questions
> about Lisp?  Or is this the place to do it?

I think it's fine to ask here.  There is (or used to be) also a "Lisp
Newbie" mailing list at

  <http://lists.unlambda.com/mailman/listinfo/lisp-newbies>.

> How do I exit from a loop when a condition is met?
>
> Something like:
>
> (defun hasIllegalCharacter (aString)
> (loop for char across aString
> (if (isIllegalChar char) (return 't)
> )
> )
> )
>
> where isIllegalChar is defined as not in a set of characters.

I hope that the lack of proper indentation is due to your posting
through Google Groups.  Also note that the symbol T need not be
quoted.

  (defun has-illegal-character (string)
    (loop for char across string
          when (is-illegal-character char)
            do (return t))) 

or

  (defun has-illegal-character (string)
    (loop for char across string
          thereis (is-illegal-character char)))

The second form might not return T but, depending on your
IS-ILLEGAL-CHARACTER predicate, a "generalized boolean" (see CLHS)
instead.  If you insist on your function returning T use it like this:

  (defun has-illegal-character (string)
    (loop for char across string
          thereis (and (is-illegal-character char) t)))

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Kalle Olavi Niemitalo
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <87k6r1jyix.fsf@Astalo.kon.iki.fi>
"basi" <··········@yahoo.com> writes:

> How do I exit from a loop when a condition is met?

Use the termination-test loop keywords (while, until, always,
never, thereis; repeat doesn't take a condition), LOOP-FINISH,
RETURN, RETURN-FROM, or GO.

> (defun hasIllegalCharacter (aString)
> (loop for char across aString
> (if (isIllegalChar char) (return 't)
> )
> )
> )

That will work if you add a DO in front of the (if ...).
However, please consider these style issues:
- In Common Lisp, words are normally not written together
  as in isIllegalChar.  is-illegal-char would be more typical,
  and even that might be written as illegal-char-p.
- If your IF form has no else-form in it, use WHEN instead.
- You can name the parameter just string rather than aString.
- (return 't) looks like it is important to return a symbol.
  If you only care of the Boolean value, use (return t).
- Please indent the code, and get an editor that matches
  closing parentheses for you so that you needn't put them
  on separate lines.
- "Illegal" normally means a law is violated.

Because strings are vectors, which are sequences, the function
can also be written like this:

  (defun hasIllegalCharacter (aString)
    (some #'isIllegalChar aString))

However, this shorter version may be slower than yours, because
now the compiler won't know that the parameter is a vector (even
though its name suggests that), and will have to use code that
works with lists too.  Also, if isIllegalChar returns a value
that is neither T nor NIL, then this hasIllegalCharacter will
return the same value, whereas yours would return T.
From: Svein Ove Aas
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <cqubot$3nf$1@services.kq.no>
start quoting Kalle Olavi Niemitalo :

> Because strings are vectors, which are sequences, the function
> can also be written like this:
> 
>   (defun hasIllegalCharacter (aString)
>     (some #'isIllegalChar aString))
> 
> However, this shorter version may be slower than yours, because
> now the compiler won't know that the parameter is a vector (even
> though its name suggests that), and will have to use code that
> works with lists too.  Also, if isIllegalChar returns a value
> that is neither T nor NIL, then this hasIllegalCharacter will
> return the same value, whereas yours would return T.

This is true; however, it can be fixed like this:
(defun has-illegal-char (string)
    (check-type string string)
    (some #'illegal-char-p string))

Since the invocation of some can only happen if string is actually of type
string, the compiler will get to optimize it down to a specialized
function. It probably will, too.
From: ···············@yahoo.com
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <1104419829.052909.60290@c13g2000cwb.googlegroups.com>
Svein Ove Aas wrote:
> start quoting Kalle Olavi Niemitalo :
>
> > Because strings are vectors, which are sequences, the function
> > can also be written like this:
> >
> >   (defun hasIllegalCharacter (aString)
> >     (some #'isIllegalChar aString))
> >
> > However, this shorter version may be slower than yours, because
> > now the compiler won't know that the parameter is a vector (even
> > though its name suggests that), and will have to use code that
> > works with lists too.
[snip]
>
> This is true; however, it can be fixed like this:
> (defun has-illegal-char (string)
>     (check-type string string)
>     (some #'illegal-char-p string))
>
> Since the invocation of some can only happen if string is actually of
type
> string, the compiler will get to optimize it down to a specialized
> function. It probably will, too.

I don't think check-type tells the compiler to optimize for strings.  I
think it just signals an error if the type is wrong.  I'd use

(defun has-illegal-char (str)
(declare (string str))
  (some #'illegal-char-p str))
From: Brian Downing
Subject: Re: Newbie: How do I exit from a loop when a condition is met?
Date: 
Message-ID: <0rVAd.727000$mD.215952@attbi_s02>
In article <·······················@c13g2000cwb.googlegroups.com>,
 <···············@yahoo.com> wrote:
> Svein Ove Aas wrote:
> > This is true; however, it can be fixed like this:
> > (defun has-illegal-char (string)
> >     (check-type string string)
> >     (some #'illegal-char-p string))
> >
> > Since the invocation of some can only happen if string is actually
> > of type string, the compiler will get to optimize it down to a
> > specialized function. It probably will, too.
> 
> I don't think check-type tells the compiler to optimize for strings.
> I think it just signals an error if the type is wrong.  I'd use
> 
> (defun has-illegal-char (str)
>   (declare (string str))
>   (some #'illegal-char-p str))

Theoretically the compiler could could type-infer that any use of
the lexical variable "string" after the CHECK-TYPE will in fact be of
type string, because execution cannot progress beyond the CHECK-TYPE
otherwise.

That being said, SBCL 0.8.16 doesn't do this.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net>