From: Andrew Cooke
Subject: Sequence types
Date: 
Message-ID: <88u6uo$vv0$1@nnrp1.deja.com>
Hi,

I was writing a small function that manipulated a sequence.  At first it
returned a list, but then it struck me that it would be more useful if
it returned a sequence of the same type as the input data.

It turns out this isn't trivial - is this why similar functions in
common lisp take a sequence type (concatenate, for example)?

The problem is that somewhere in the function there is the line

(let ((result-type (type-of input-sequence)))

and then later, in assembling the result

(concatenate result-type ....)

But if the input is a list then (at least for CLISP), result-type is
CONS, which is not a sequence type, so concatenate dies.  (Obviously I
can catch this, but what else will break the code at a later date?).  I
get the impression from the docs that there isn't a "stronger" or
sequence-specific type-of (which, afaik, is allowed to return CONS
rather than LIST).

Comments appreciated,
Thanks,
Andrew
http://www.andrewcooke.free-online.co.uk/index.html


Sent via Deja.com http://www.deja.com/
Before you buy.

From: Lieven Marchand
Subject: Re: Sequence types
Date: 
Message-ID: <88uvfo$9j5$1@newnews1.news.nl.uu.net>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> It turns out this isn't trivial - is this why similar functions in
> common lisp take a sequence type (concatenate, for example)?
> 

Not really. CONCATENATE can take a sequence of sequences of different
type. From the Hyperspec:

(concatenate 'list "ABC" '(d e f) #(1 2 3) #*1011)
=>  (#\A #\B #\C D E F 1 2 3 1 0 1 1)

Choosing the type of the resulting sequence to be the first would be
rather arbitrary. Likewise only allowing the resulting type to be
unspecified if all the sequences of the sequence have the same type.

  
> I get the impression from the docs that there isn't a "stronger" or
> sequence-specific type-of (which, afaik, is allowed to return CONS
> rather than LIST).

It is. It could even return something like (CONS FIXNUM *) for a list
'(1 2 3) which would also give problems. If you want to do this, you
could do something like this.

(defmethod sequence-type-of ((x cons))
   'list)

(defmethod sequence-type-of ((x string))
   'string)

...

-- 
Lieven Marchand <···@bewoner.dma.be>
If there are aliens, they play Go. -- Lasker
From: Chris Double
Subject: Re: Sequence types
Date: 
Message-ID: <wkvh3gjl3x.fsf@double.co.nz>
Lieven Marchand <···@bewoner.dma.be> writes:

> If you want to do this, you could do something like this.
> 
> (defmethod sequence-type-of ((x cons))
>    'list)
> 
> (defmethod sequence-type-of ((x string))
>    'string)
> 

Dylan has a similar generic function but calls it 'type-for-copy'
which is described as:

  "Returns an appropriate type for creating mutable copies of its
  argument."

Chris.
From: Barry Margolin
Subject: Re: Sequence types
Date: 
Message-ID: <F7zs4.12$VM6.576@burlma1-snr2>
In article <············@nnrp1.deja.com>,
Andrew Cooke  <······@andrewcooke.free-online.co.uk> wrote:
>Hi,
>
>I was writing a small function that manipulated a sequence.  At first it
>returned a list, but then it struck me that it would be more useful if
>it returned a sequence of the same type as the input data.
>
>It turns out this isn't trivial - is this why similar functions in
>common lisp take a sequence type (concatenate, for example)?
>
>The problem is that somewhere in the function there is the line
>
>(let ((result-type (type-of input-sequence)))
>
>and then later, in assembling the result
>
>(concatenate result-type ....)
>
>But if the input is a list then (at least for CLISP), result-type is
>CONS, which is not a sequence type, so concatenate dies.  (Obviously I
>can catch this, but what else will break the code at a later date?).  I
>get the impression from the docs that there isn't a "stronger" or
>sequence-specific type-of (which, afaik, is allowed to return CONS
>rather than LIST).

I expect that most such functions contain something like:

(let ((result-type
        (etypecase input-sequence
          (list 'list)
          (vector (type-of input-sequence)))))

to get around this.  They might also have code in the VECTOR branch to
ensure that a type that's appropriate to CONCATENATE is returned there as
well.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Pekka P. Pirinen
Subject: Re: Sequence types
Date: 
Message-ID: <ixd7ppqftg.fsf@harlequin.co.uk>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:
> I was writing a small function that manipulated a sequence.  At first it
> returned a list, but then it struck me that it would be more useful if
> it returned a sequence of the same type as the input data.
>
> It turns out this isn't trivial - is this why similar functions in
> common lisp take a sequence type (concatenate, for example)?

It's that, and that similar functions often take multiple sequences of
different types, and it's that "the same type" is fuzzy (see below).

> (let ((result-type (type-of input-sequence)))
> [...]
> (concatenate result-type ....)
> 
> But if the input is a list then (at least for CLISP), result-type is
> CONS, which is not a sequence type, so concatenate dies.  (Obviously I
> can catch this, but what else will break the code at a later date?).

Actually, CONS is a sequence type; CLISP just has a bug in
CONCATENATE.  (CONS is a recognizable subtype of LIST.)

Nevertheless, you're right: TYPE-OF isn't quite suitable for this
purpose.  It could return something that CONCATENATE doesn't
understand (a vector type whose element type it can't determine -- the
spec of CONCATENATE should really say more about which vector types it
recognizes), or something that doesn't specify the type ou wanted.

The result of `(EQL ,INPUT-SEQUENCE) denotes "the same type", so does
T, and everything in between.  Which one did you mean?  TYPE-OF is
somewhat constrained, so it won't return T or an EQL-type, but it
couldn't be right for all uses, so you have to write your own.

If the rules of COPY-SEQ happen to be what you had in mind, then you
might hack something using that.
-- 
Pekka P. Pirinen
Adaptive Memory Management Group, Harlequin/Xanalys
Mail should be private, whether on paper or on disk.  Public gatherings
should be a right, whether virtual or in person.