From: Bldahdad
Subject: LISP QUESTION1
Date: 
Message-ID: <Xns91AE15E5977F8blahblahdscom@68.1.17.6>
How do you write a function (case? s) that returns the 'upper if the 
characters in the string s are all upper case, 'lower if the characters are 
all lower case, and 'mixed if there are some lower case and some upper case 
letters?  

From: Kaz Kylheku
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <Har88.34489$2x2.2168912@news3.calgary.shaw.ca>
In article <·····························@68.1.17.6>, Bldahdad wrote:
>How do you write a function (case? s) that returns the 'upper if the 
>characters in the string s are all upper case, 'lower if the characters are 
>all lower case, and 'mixed if there are some lower case and some upper case 
>letters?  

This is a good opportunity to expore the nice library of Common Lisp,
rather than drop down to character-by-character processing.

(defun case? (string)
  (cond
    ((every #'lower-case-p string) 'lower)
    ((notevery #'upper-case-p string) 'mixed)
    (t 'upper)))

Bad name for the function, though, IMHO. The question mark suffix is 
a convention from Scheme, and other languages, for denoting predicates.
In Lisp, the convention for predicates is to use a P or -P suffix,
but it's still a bad idea to use a ? suffix for non-predicates.
A function that classifies input into three or more buckets is not
a predicate; a predicate is boolean-valued.  I would call it case-classify
or something.

Any more homework you want people to do for you?
From: Takehiko Abe
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <keke-0702022234170001@solg4.keke.org>
In article <·······················@news3.calgary.shaw.ca>, ···@ashi.footprints.net wrote:

> In article <·····························@68.1.17.6>, Bldahdad wrote:
> >How do you write a function (case? s) that returns the 'upper if the 
> >characters in the string s are all upper case, 'lower if the characters are 
> >all lower case, and 'mixed if there are some lower case and some upper case 
> >letters?  
> 
> This is a good opportunity to expore the nice library of Common Lisp,
> rather than drop down to character-by-character processing.
> 
> (defun case? (string)
>   (cond
>     ((every #'lower-case-p string) 'lower)
>     ((notevery #'upper-case-p string) 'mixed)
>     (t 'upper)))

I think you got it wrong.

? (case? "LISP QUESTION1")
MIXED

(defun case? (string)
  (cond
   ((every #'upper-case-p string) 'upper)
   ((every #'lower-case-p string) 'lower)
   ((and (some #'upper-case-p string)
         (some #'lower-case-p string))
    'mixed)
   (t (error "You lose."))))

abe

-- 
<keke at mac com>
From: Kent M Pitman
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <sfw6659xpq7.fsf@shell01.TheWorld.com>
····@ma.ccom (Takehiko Abe) writes:

Is this homework? I don't recall being told.  Homework should not be 
presented to this newsgroup without identifying it as such.

> In article <·······················@news3.calgary.shaw.ca>, ···@ashi.footprints.net wrote:
> 
> > In article <·····························@68.1.17.6>, Bldahdad wrote:
> > >How do you write a function (case? s) that returns the 'upper if the 
> > >characters in the string s are all upper case, 'lower if the characters are 
> > >all lower case, and 'mixed if there are some lower case and some upper case 
> > >letters?  
> > 
> > This is a good opportunity to expore the nice library of Common Lisp,
> > rather than drop down to character-by-character processing.

And maybe have half a hope that the person hasn't been given the direct
answer to a homework problem.

> > (defun case? (string)
> >   (cond
> >     ((every #'lower-case-p string) 'lower)
> >     ((notevery #'upper-case-p string) 'mixed)
> >     (t 'upper)))
> 
> I think you got it wrong.
> 
> ? (case? "LISP QUESTION1")
> MIXED
> 
> (defun case? (string)
>   (cond

If you're going to insist on pure-letters, then you maybe want to start with:

 ((notevery #'both-case-p string) 'garbage)

Wow. I never saw a use of NOTEVERY.  I almost missed my chance and wrote
the probably less efficient:

  ((some (complement #'both-case-p) string) 'garbage)

If you don't do a "guard test" like this, then you'll need some of the
other changes I suggest below...

>    ((every #'upper-case-p string) 'upper)

I might prefer (complement #'lower-case-p) here, so that both F and $
count as upper for this situation.  Though this would have the problem
that '$$$ counts as all upper.  Certainly it is not all lower, nor is
it mixed.

>    ((every #'lower-case-p string) 'lower)

and (complement #'upper-case-p) here, so that both f and $ count as 
lowercase.

>    ((and (some #'upper-case-p string)
>          (some #'lower-case-p string))

If you make my suggested changes above, then T is a fine test here.
If you don't, then you're insisting on all letters as input and it
probably makes sense to require the same here.  In this case,
 (every #'both-case-p string)
would be more rational test here.

>     'mixed)
>    (t (error "You lose."))))

I might just return 'garbage here rather than signal an error, since
that leaves it to clients of this function to determine whether in fact
that was an error...

And it's a subtle point, but if you are going to signal an error,
I'd make the error message more informative. Something like: 

  (error "~S was given input that it was not specified to handle.~
        ~%Please report this as a bug."
         'case?)

Though if foo1 counts as mixed, that's kind of weird, since it's not a mix
of the other two possible return values.  All in all, had I written it, I
might have written:

(defun case? (string)
  (cond ((some #'upper-case-p string)
	 (if (some #'lower-case-p string)
	     'mixed    ;but maybe also non-alpha
             'upper))  ;but maybe also non-alpha
	((some #'lower-case-p string)
         'lower)       ;but maybe also non-alpha
	(t ;"" or all non-alpha
         'garbage)))

or

(defun case? (string)
  (cond ((notevery #'both-case-p string) 'garbage)
        ((some #'upper-case-p string)
	 (if (some #'lower-case-p string)
	     'mixed
             'upper))
	((some #'lower-case-p string)
         'lower)
	(t ;""
         'none)))

If you wanted to be manic about efficiency, either the following, or better
still the equivalents with position-if and position-if-not open-coded
into loop in case the compiler isn't smart enough to do even that.
(Then again, this will be pessimal in clisp, which is byte-compiled and
prefers you to use standard operators rather than rolling your own.
Even in other implementations the savings may only be in the range of  
25-50% ...) Certainly the loss of readability is substantial and you'd
have to test it a lot more thoroughly to be sure it was right...

(defun case? (string)
  (if (= (length string) 0) 'none
      (let ((ch0 (char string 0)))
	(macrolet ((check-consistency (test fliptest result)
		     `(let ((pos (position-if-not #',test string :start 1)))
			(if (not pos) ',result
			    (if (,fliptest (char string pos))
				(if (position-if-not #'both-case-p string
						     :start 2)
				    'garbage
				  'mixed)
			      'garbage)))))
	  (cond ((upper-case-p ch0)
		 (check-consistency upper-case-p lower-case-p upper))
		((lower-case-p ch0)
		 (check-consistency lower-case-p upper-case-p lower))
		(t 'garbage))))))
From: Takehiko Abe
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <keke-0802020124110001@solg4.keke.org>
In article <···············@shell01.TheWorld.com>, Kent M Pitman <······@world.std.com> wrote:

> > > (defun case? (string)
> > >   (cond
> > >     ((every #'lower-case-p string) 'lower)
> > >     ((notevery #'upper-case-p string) 'mixed)
> > >     (t 'upper)))
> > 
> > I think you got it wrong.
> > 
> > ? (case? "LISP QUESTION1")
> > MIXED
> > 
> > (defun case? (string)
> >   (cond
> 
> If you're going to insist on pure-letters, then you maybe want to start with:

I don't insist on pure letters. The instruction says:

  'upper if all the chars are upper case letters.
  'lower if all lower.
  'mixed if some are upper case and some are lower case.

>  ((notevery #'both-case-p string) 'garbage)

So, I believe, for instance, "Lisp Question 1" should return 'mixed
instead of 'garbage.

> [...]

I'll study the rest tomorrow. Good night.

abe

-- 
<keke at mac com>
From: Kaz Kylheku
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <aVA88.35917$Jq.1935110@news2.calgary.shaw.ca>
In article <·····················@solg4.keke.org>, Takehiko Abe wrote:
>In article <·······················@news3.calgary.shaw.ca>, ···@ashi.footprints.net wrote:
>
>> In article <·····························@68.1.17.6>, Bldahdad wrote:
>> >How do you write a function (case? s) that returns the 'upper if the 
>> >characters in the string s are all upper case, 'lower if the characters are 
>> >all lower case, and 'mixed if there are some lower case and some upper case 
>> >letters?  
>> 
>> This is a good opportunity to expore the nice library of Common Lisp,
>> rather than drop down to character-by-character processing.
>> 
>> (defun case? (string)
>>   (cond
>>     ((every #'lower-case-p string) 'lower)
>>     ((notevery #'upper-case-p string) 'mixed)
>>     (t 'upper)))
>
>I think you got it wrong.
>
>? (case? "LISP QUESTION1")
>MIXED
>
>(defun case? (string)
>  (cond
>   ((every #'upper-case-p string) 'upper)
>   ((every #'lower-case-p string) 'lower)
>   ((and (some #'upper-case-p string)
>         (some #'lower-case-p string))
>    'mixed)
>   (t (error "You lose."))))

What, there are other characters beside letters? Damn! ;)
From: David Sletten
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <3C634E6E.5070203@home.com>
Takehiko Abe wrote:

> In article <·······················@news3.calgary.shaw.ca>, ···@ashi.footprints.net wrote:
> 
> 
>>In article <·····························@68.1.17.6>, Bldahdad wrote:
>>
>>>How do you write a function (case? s) that returns the 'upper if the 
>>>characters in the string s are all upper case, 'lower if the characters are 
>>>all lower case, and 'mixed if there are some lower case and some upper case 
>>>letters?  
>>>
>>This is a good opportunity to expore the nice library of Common Lisp,
>>rather than drop down to character-by-character processing.
>>
>>(defun case? (string)
>>  (cond
>>    ((every #'lower-case-p string) 'lower)
>>    ((notevery #'upper-case-p string) 'mixed)
>>    (t 'upper)))
>>
> 
> I think you got it wrong.
> 
> ? (case? "LISP QUESTION1")
> MIXED
> 
> (defun case? (string)
>   (cond
>    ((every #'upper-case-p string) 'upper)
>    ((every #'lower-case-p string) 'lower)
>    ((and (some #'upper-case-p string)
>          (some #'lower-case-p string))
>     'mixed)
>    (t (error "You lose."))))
> 
> abe
> 
> 

The original statement of the problem says specifically ". . .'mixed if 
there are some lower case and some upper case letters?". There are 
clearly upper case letters in your example string "LISP QUESTION1", 
however, which lower case letters does it contain? Your example should 
trigger the error clause. The problem is that the specification is 
ambiguous. It doesn't explain what behavior to expect for characters 
without a case.  There seems to be something wrong with your Lisp 
implementation. Mine says that (both-case-p #\1) and (both-case-p 
#\Space) return NIL.

David Sletten
From: Takehiko Abe
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <keke-0802021517030001@solg4.keke.org>
In article <················@home.com>, 
David Sletten wrote:

> Your example should trigger the error clause.

It signals an error -- "You lose." I admit that it's not
informative nor helpful.

> There seems to be something wrong with your Lisp implementation.

You seem to misunderstand something. My Lisp implementation is
fine.

How about this:

(defun case? (string)
  (cond
   ((every #'upper-case-p string) 'upper)
   ((every #'lower-case-p string) 'lower)
   ((and (some #'upper-case-p string)
         (some #'lower-case-p string))
    'mixed)
   (t (restart-case (error "You got ~S. Ask your instructor what to do."
                           string)
        (specify-return-value (value)
                              :report "Specify a return value."
                              :interactive
                              (lambda ()
                                (format t "~&Value: ")
                                (list (read)))
                              value)))))

abe

-- 
<keke at mac com>
From: David Sletten
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <3C637771.8000803@home.com>
Takehiko Abe wrote:


> 
> You seem to misunderstand something. My Lisp implementation is
> fine.
> 

Yes, I did misunderstand something. In your initial response you wrote:

 >
 > I think you got it wrong.
 >
 > ? (case? "LISP QUESTION1")
 > MIXED
 >
 > (defun case? (string)
 >   (cond
 >    ((every #'upper-case-p string) 'upper)
 >    ((every #'lower-case-p string) 'lower)
 >    ((and (some #'upper-case-p string)
 >          (some #'lower-case-p string))
 >     'mixed)
 >    (t (error "You lose."))))

It was not evident that you were invoking the previous poster's function 
and then defining your own. I thought you were displaying the output of 
your version and then showing how you had defined it. However, 
interpreting your post in the normal context of a Lisp session (where 
your function could not be invoked before it was defined) makes sense 
now. You were demonstrating that his version produced MIXED given "LISP 
QUESTION1", and you did not demonstrate your own version, which of 
course is correct under a certain interpretation of the problem. Gomen 
nasai.

My point still stands though that the specification is ambiguous. It 
does not say what to do when not all characters are upper case yet none 
are lower case and vice versa.

David Sletten
From: Bruce Hoult
Subject: Re: LISP QUESTION1
Date: 
Message-ID: <bruce-59EE39.21522507022002@news.paradise.net.nz>
In article <·····························@68.1.17.6>, Bldahdad 
<····@blasdh.com> wrote:

> How do you write a function (case? s) that returns the 'upper if the 
> characters in the string s are all upper case, 'lower if the characters 
> are 
> all lower case, and 'mixed if there are some lower case and some upper 
> case 
> letters?  

That function is incompletely specified, and looks like a homework 
question.  So here's a solution in a closely related language (my choice 
of which won't be any surprise to regular reasders :-)):

  define function case?(s)
    select
      every?(uppercase?, s) => #upper;
      every?(lowercase?, s) => #lower;
      otherwise => #mixed;
    end
  end

-- Bruce