|
[oleg@pobox.com: Minor quibbles on the latest draft] scgmille@xxxxxx (30 Jul 2003 22:24 UTC)
|
|
Re: [oleg@pobox.com: Minor quibbles on the latest draft]
scgmille@xxxxxx
(31 Jul 2003 03:20 UTC)
|
|
Re: [oleg@pobox.com: Minor quibbles on the latest draft]
Jens Axel Søgaard
(31 Jul 2003 07:34 UTC)
|
|
Re: [oleg@pobox.com: Minor quibbles on the latest draft]
scgmille@xxxxxx
(31 Jul 2003 13:02 UTC)
|
|
Re: [oleg@pobox.com: Minor quibbles on the latest draft]
Jens Axel Søgaard
(31 Jul 2003 13:55 UTC)
|
|
Re: [oleg@pobox.com: Minor quibbles on the latest draft]
scgmille@xxxxxx
(31 Jul 2003 15:34 UTC)
|
[forwarded on behalf of Oleg]
Hello!
I'm sorry I'm late to the party, which has almost finished. It
looks like a great party.
The following comments apply to the latest draft
http://sgmiller.org/srfi-44.html
"As standard Scheme lacks the ability to automatically dispatch on
different function behaviors based on the types of arguments, it
difficult to devise a portable implementation of this SRFI which
allows arbitrary future collections. It is expected that Scheme system
implementors will take advantage of generic function or
object-oriented features of their systems to implement this SRFI
efficiently."
I wonder why a module system was not mentioned at all? Quite often
people use a particular standard collection as an implementation
vehicle for their advanced data structure. A collection will be
encapsulated into the data structure. For example, a graph data
structure may use a dictionary to store adjacency information for a node
(or to store a cost value for a pair of nodes). In that case, most
of the implementation code is monomorphic with respect to the
collection type and no run-time dispatch is required. Given an
advanced module system, I can import a particular dictionary
implementation (e.g., associative lists) with renaming
make-alist => make-mydict
alist-get => mydict-get
etc. In my own code I would use the names make-mydict, mydict-get,
etc. exclusively. If at a later time I decide to use a different
dictionary implementation, I would only need to change the module
declaration statement.
I have also taken a look at the Edison:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/hfl/hfl/edison/
in particular, Coll/Coll/Collection.hs
The latter gave a few suggestions.
> procedure: % value ... => %
> Constructs a % collection with the zero or more values provided
> as its initial contents.
Should we add that if the collection is a set, it is unspecified which
element is kept in case of duplicates? Or should duplicates be
outlawed? [Edison takes the former approach].
> procedure: *-add bag value => *
> procedure: *-add![!] bag value => *
> Adds a single value to a bag.
> procedure: *-add-all dest-bag source-bag => *
> procedure: *-add-all![!] dest-bag source-bag => *
> Adds all the values in the source bag to the destination bag.
Edison says: insert [our add] keeps the new element in case of
duplicates, but insertSeq [our add-all] keeps an unspecified element.
Edison defines the procedure count, for the occurrence count of an
element in a collection. Sure, count may be expensive for some
collections. For sets, the occurrence count is defined too (but
required to return either 0 or 1). Edison also defines a procedure
> instanceName :: c -> String
> -- the name of the module implementing c
which can be useful, for example, for generating error messages. The
procedure is useful regardless of a particular module or OO system.
For ordered collections, Edison defines procedures to view, insert or
delete the maximum and the minimum elements. I don't know how useful
this may be (many advanced collections do allow efficient
implementations of such operations -- especially for collections that
are used for priority queues or dequeues).
It goes without saying that many operations in Edison -- like union or
intersection of two collections -- are perhaps too high-order or too
laborous or too infrequent to warrant their specification in
SRFI-44. It's better to stick to the bare minimum and provide
extensions only for very frequent operations.
> procedure: *-ref sequence integer => boolean
> Returns the value stored in the sequence at the integer index
> provided. It is an error to reference an index outside the range of
> the sequence.
The return type can't be boolean. Right?
BTW, often a function *-ref-with-default is surprisingly useful. The
function takes an extra argument -- the default value -- and returns
literally (in the sense of eq?) that argument in case the lookup
failed.
Edison's sequences,
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/hfl/hfl/edison/Seq/Sequence.hs
are also interesting, in particular procedures lview, rview, inBounds,
adjust and zippers. However, one may also leave them out for SRFIs to
come.
> (eq? <input collection> (update-procedure <input collection>)) will
> always return a non-false value.
Perhaps this statement is too conservative? R5RS requires that eq? (as
well as eqv? and equal?) return a boolean value. Therefore, the only
non-false return value of eq? is #t. It might be a good idea to say
that explicitly.
> The collection fold procedure then invokes the folding function on a
> value of the collection and the seeds, and receives from the folding
> function a proceed value followed by a like number of seed return
> values. If the termination value is non-false,
Perhaps you meant "the proceed value" rather than a termination
value. Otherwise, "termination value" is not mentioned anywhere else in
the document.
> In order to ensure a consistent ordering in the collection, the
> ordering function must return the same result for like inputs over
> time.
In other words, an ordering function must be a pure function, a
mapping of its arguments. One might add that an implementation of a
collection may assume
(and (equal? x x1) (equal? y y1)) ==>
(equal? (ordering-function x y) (ordering-function x1 y1))
Should the same requirement be applied to a equivalence function as
well?
Cheers,
Oleg