[racket] This is too clumsy. Is there a better way?

From: Stephen Bloch (bloch at adelphi.edu)
Date: Fri Jul 13 09:30:28 EDT 2012

On Jul 13, 2012, at 9:02 AM, Rouben Rostamian wrote:

> The function `all-lower-case?' defined below takes a string and
> returns #f if the string has at least one uppercase alphabetic
> character, else returns #t.

> Examples:
>  (all-lower-case? "asdf12#@") => #t
>  (all-lower-case? "asDf12#@") => #f

Then a better name would be no-upper-case? .  I would expect (all-lower-case? "asdf12#@") to return false.

> Here is how I have written it:
> (define (all-lower-case? str)
>  (not (memq #t
>             (map (lambda (i)
>                    (if (and (char-alphabetic? i) (char-upper-case? i))
>                      #t #f))
>                  (string->list str)))))

For starters, I would replace
	(if (and (char-alphabetic? i) (char-upper-case? i))
             #t #f)
with the logically equivalent
	(and (char-alphabetic? i) (char-upper-case? i))
(As a general rule of thumb, Boolean-valued functions are usually shorter and simpler if you write them WITHOUT conditionals.)

Second, since char-upper-case? is a subset of char-alphabetic?, you can simplify this further to
	(char-upper-case? i)
which is just a single function, so you can now drop the "lambda" and just say
	(map char-upper-case? ...)

You can also replace
	(memq #t (map F L))
	(ormap F L)

So the new definition is
(define (no-upper-case? str)
   (not (ormap char-upper-case? (string->list str))))

> This looks rather clumsy to me.  I am converting the string into
> a list of characters, then I check the case of each character
> and issue the requisite verdict.

We're still doing the exact same thing, but in a whole lot less code -- indeed, the code is very nearly a rewording of the purpose statement.  As a bonus, it's also more efficient, since "ormap" does short-circuit evaluation: as soon as it finds an upper-case letter, it stops without looking at the rest of the string.

Another, weirder and less efficient but even shorter, definition is
(define (no-upper-case? str)
   (string=? str (string-downcase str)))

Stephen Bloch
sbloch at adelphi.edu

Posted on the users mailing list.