Subject: Re: distinction?
From: (Rob Warnock)
Date: 2000/12/05
Newsgroups: comp.lang.lisp
Message-ID: <90i9te$6uger$>
Kent M Pitman  <> wrote:
| Jon Jacky <> writes:
| > This can be expressed functionally in Scheme using map...
| > It's not necessary to use iteration.
| But MAP is not good for expressing "For every number from 0 to 9, make sure
| it appears on the phone dial" because Scheme does not provide an object
| over which one can "map" numeric ranges, as CL's LOOP does.

I tend to use the functions "iota" and "every" for that kind of thing:

    (unless (every (map (lambda (x) (is-on-dial? phone x) (iota 10))))
      ... )

And in Scheme, one tends to use closures a lot more, so "is-on-dial?"
would probably already be closed over the "phone" object:

    (let (is-on-dial? (lambda (x) (phone x)))
      (unless (every (map is-on-dial? (iota 10)))
        ... ))

| Neither does Scheme provide the ability to map over objects like
| hash tables.

Since hash tables aren't in the Scheme spec, "Scheme" doesn't provide
mapping over them either. But those implementations which *do* provide
a hash table extension also always (AFAIK) provide an enumeration method,
e.g., MzScheme provides "hash-table-map" & "hash-table-for-each":

	> (let* ((h (make-hash-table))
	         (put! (lambda (x) (hash-table-put! h (car x) (cadr x)))))
	    (for-each put! '((foo 13) (bar 7) (baz 23) (gorp 42)))
	    (hash-table-remove! h 'baz)
	    (hash-table-for-each h (lambda (k v)(print k " ==> " v) )))
	foo ==> 13
	bar ==> 7
	gorp ==> 42

But I'll grant Scheme implementations don't tend to provide mapping or
iteration over other sequence types such as vector or string (although
there's a SRFI for that).

| Indeed, the Scheme community has outright shunned the creation of standard
| terminology in the language, preferring that it be added elsewhere.  In so
| doing, and in not creating itself a useful library that is part of the
| standard, it must stand the criticism that comes from not including this
| stuff...

True enough, though the SRFI process <URL:> seeks
to partially remedy that by providing an extra-standard concensus on many
of those issues.

| I think one of the greatest strengths of CL is not that it makes in any way
| the best decision of how to standardize certain facilities, since there can
| be no uniquely determined best (and this is why Scheme is forever at an 
| impassible barrier, waiting for consensus on the "right" way to do things,
| when no right way can ever exist)

Again, the SRFI process is heading away from "the one true way", more
towards a quasi-experimental process of "here's a useful way, can we
all agree it's useful to some large-enough subset of us?"

| the strength of CL is that it has the guts to recognize the need for
| arbitrary choices as a way of forging forward.

I'll stop with SRFI mantra after one more mention here, but I do think
that maybe the SRFIs *are* to a large extent an attempt to do exactly
that -- forge forward with a few fairly-carefully thought-out but
essentially still arbitrary choices, recruit some implementations,
let people *use* then, and see what happens.

|   (mymap f lst cddr)
| might be a way to specify how to step over every other element of lst when
| mapping f over it, but it's not perspicuous.  For all the possible elements
| of a mapping operation (the step, the accumulation, etc.) that I could
| want to affect, I need functional entry points for each one and the language
| helps me not at all with this--there aren't even optional args, much less
| keyword args.

"In the language", meaning IEEE or R5RS Scheme, no. You're right there.
But many of use routinely allow ourselves the *usefulness* of optionals
and keywords, by using helper routines to parse the "rest" argument
(improper lambda list) that Scheme-the-language does provide. E.g.,
my personal "iota" allows "end", "start/end", or "start/step/end":

	> (iota)
	procedure iota: expects at least 1 argument, given 0
	> (iota 5)
	(0 1 2 3 4)
	> (iota 5 10)
	(5 6 7 8 9)
	> (iota 5 3 19)
	(5 8 11 14 17)
	> (iota 1 2 3 4)
	procedure iota: expects 1-3 arguments, given 4

| So it's maybe "concise" but it's far from "expressive" in the sense
| that I mean it, which is specifically "focusing on terminology that
| expresses rather than implements an idea".  That doesn't mean 
| syntactically minimal.  For example, if you could say 
|    (mymap  f lst step: cddr)
| that would be an improvement in the domain of language expressivity.

Well, of course Scheme doesn't have CL-style keywords, but using a common
helper routine (such as mentioned above), the Elk implementation used
normal symbols as "keywords" in its X Windows binding, so you wrote code
that tended to look like this ["parse-geometry" was my own routine to crack
an X command line "-geom 40x30+123+456"]:

  (let-values (((width height x y) (parse-geometry geom-arg)))
    (let* ((dpy (open-display))
           (black (black-pixel dpy))
           (white (white-pixel dpy))
           (win (create-window 'parent (display-root-window dpy)
                               'width width 'height height 'x x 'y y
                               'background-pixel white
                               'border 0
                               'event-mask '(exposure)))
           (gc (create-gcontext 'window win 'function 'xor
                                'background black 'foreground white))
      (set-wm-normal-hints! 'window win
			    'width width 'height height 'x x 'y y)
      ... )

Those "keyword/value" pairs really were order-independent, so one could
equally well have written:

         (create-gcontext 'foreground white 'function 'xor
                          'background black 'window win)

Is that the kind of thing you're talking about?


Rob Warnock, 31-2-510
Network Engineering
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043