Here's the comments.

* Overall:

It may be easier to understand (and justify) the rich set of
APIs by regarding ideque not just as a variation of a queue,
but also a variation of a bidirectional immutable list.
Mentioning so in the intro will help the reader to see what
the srfi is aiming at.  We can add something like "It can
also be used as a bidirectional list (sequence) and many
APIs reflect list operations." in the first paragraph of
Rationale, for example.


* Nitpicks:

ideque-take, etc. : Maybe add "It is an error if N is
greater than the length of i", for the consistency with
srfi-1.

ideque-map: Maybe explicitly mention that the dynamic order
PROC is applied isn't specified, just as map.

ideque-every: The current draft can read that ideque-every
returns #t if all elements satisfy PRED.  Srfi-1's every
returns the last value returned by PRED in that case, and
it's better to be consistent.

ideque-zip, ideque-map, ideque-for-each, ideque-fold,
ideque-fold-right, ideque-append-map: The current draft can
read as if it is allowed to pass zero ideques.  We can
define so, but for the consistency we may want to say at
least one ideque is required.

ideque-fold, ideque-fold-right: "passing the result of the
previous invocation as a second argument" is confusing when
more than one ideque are passed.  Maybe "passing the
result ... as the last argument"?

ideque-any, ideque-every, ideque-count: Srfi-1's
corresponding procedures can take more than one lists.  How
about making them take more than one ideques?  (I know the
policy isn't consistently kept across other sequence types,
though.)

* Missing:

(ideque-tabulate n init-proc): Not difficult to define with
ideque-unfold, but for the consistency.

(ideque= elt= ideque1 ideque2 ideque ...): Returns #t iff
all ideques are the same length and every corresponing
elements satisfies elt=.

(ideque-ref ideque n): It's weird to have this if we see
ideque as a queue, but if we see ideque as a bidirectional
sequence, why not?

(ideque-concatenate list-of-ideques): Same reason as we have
concatenate.

(ideque-map-in-order proc ideque1 ideque2 ...): This may be
less important, but we have map-in-order in srfi-1

(ideque-for-each-right proc ideque1 ideque2 ...): If we see
ideque as bidirectional list, it's cleaner to have
operations on both directions whenever it makes sense.

(ideque-filter-map proc ideque1 ideque2 ...): ideque version
of filter-map.

(ideque-any-right proc ideque1 ideque2 ...),
(ideque-every-right proc ideque1 ideque2 ...): Apply PROC in
reverse order.  The names are debatable.

(reverse-list->ideque list), (ideque->reverse-list ideque):
Because of bidirectional nature of ideque.  Less important,
however, for ideque-reverse is O(1).


* Some more controversial issues:

ideque-find, ideque-find-right: I don't like the signature
inconsistency with 'find'.  I can think of two options:
 (1) Make failure thunk optional, defaulted to (lambda () #f).
     This is under prospect that we'll extend list's 'find'
     operation to allow such optional thunk as well.
 (2) Use different name, e.g.  ideque-search.

ideque-unfold, ideque-unfold-right: srfi-1's unfold and
unfold-right takes optoinal TAIL-GEN and TAIL argument,
which sometimes comes handy.  Unfortunately this convension
isn't very consistent--- srfi-13's string-unfold instead
takes optional "base" (raw strings) and "make-tail".  Also,
because of bidirectional nature of ideque, we could argue
that ideque-unfold should take HEAD argument and
ideque-unfold-right should take HEAD-GEN argument as well.
We could also argue that, since appending tail to ideque is
cheap, it's less important to have these.  I don't strongly feel
about this, but slightly prefer having the same optional arg
as srfi-1, for the consistency.
     
Variation of ideque-any, ideque-every: If the caller uses
these only as predicates, that is, if she doesn't care the
order PRED is applied, then there's a room for optimization.
Is it too confusing to have such variation?


On Sun, Jan 24, 2016 at 4:03 PM, Shiro Kawai <xxxxxx@gmail.com> wrote:
I incorporated the current ideque API into Gauche.  Will send comments later.
Meanwhile, I wrote a blackbox test suite; if you haven't, feel free to grab it.
(I tried to follow Chibi test forms, but I'm running it with my ad-hoc compatibility
layer in Gauche, so I can't guarantee it runs on Chibi as is.)


On Fri, Jan 22, 2016 at 10:34 AM, John Cowan <xxxxxx@mercury.ccil.org> wrote:
Shiro Kawai scripsit:

> (My current implementation is based on Chris Okasaki's book:
> https://github.com/shirok/Gauche/blob/master/lib/data/immutable-deque.scm
> If you need another reference implementation, I'd be happy to make it
> portable
> and adapt to this srfi's api.)

I may, though I currently expect an implementation based on 2,3-finger
trees to land soon.  If it's *very* soon, I'll skip writing the two-list
implementation, even though it's trivial to do.  At any rate I need to
write the black-box tests as soon as the API stabilizes.

> I feel it's a bit overwhelming to have the whole set of sequence-like APIs.
> The fundamental operations of deque are basically emtpy?,
> front, back, add-front, add-back, remove-front and remove-back.
> I just expect them, plus some constructors and converters, for
> immutable deque.
>
> I can understand the motivation of the rich API; although they can
> be implemented trivially with ideque->list and list operation,
> having them directly in ideque can save construction of intermediate
> data structures.

The logic is that I don't want people to say "Lists have the richest set
of library routines, so I'll just use lists because they are the easiest
to use", at the expense of contorting their data structures.  By making
all libraries equally rich, the choice of data structure can follow other
criteria.

> OTOH, if we keep on having this set across sequence-like data types,
> I'd like to see them consistent.  Each data type exposing slightly
> different set of APIs will be very confusing.

I try.  There are two forces pushing me toward incompatibility: One is
that sometimes the old definitions are just bad:  not having a failure
thunk for SRFI 1 find and returning #f was a mistake.  There's a
workaround for this mistake, so it's not fatal, but it's discouraging.

> Missing: Obviously the "linear update" version doesn't make sense
> in immutable data types, but there are other APIs that are in
> srfi-1 but not in ideque.  Each of which I can imagine the reason;
> e.g. make-ideque makes little sense in practice.

Just so.  That is the second reason for incompatibilities: some operations
(especially constructors) just aren't reasonable for particular data
types.  I don't know anything to do about this.  Even in languages with
interfaces or type classes, typically constructors are not covered by them.

If you see particular operations that seem to be missing, please let me know.

> I don't see ideque-take is so much useful that it is worth to
> be in.   (I'd imagine the use case where I want to get first
> or last N items of ideque, but then I want it in list of N items
> rather than another ideque.)

The idea is that it allows you to partition an ideque by size of elements.

--
John Cowan          http://www.ccil.org/~cowan        xxxxxx@ccil.org
I am he that buries his friends alive and drowns them and draws them
alive again from the water. I came from the end of a bag, but no bag
went over me.  I am the friend of bears and the guest of eagles. I am
Ringwinner and Luckwearer; and I am Barrel-rider.  --Bilbo to Smaug