Kent M Pitman <pitman@world.std.com> wrote:
+---------------
| Jon Jacky <jon@bilbo.radonc.washington.edu> 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:http://srfi.schemers.org> 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
-----
Rob Warnock, 31-2-510 rpw3@sgi.com
Network Engineering http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043