dear list,
is there any objections against this?
(declaim (inline length=1))
(defun length=1 (sequence) (if (listp sequence) (and sequence (null (rest sequence))) (= 1 (length sequence))))
in optimized code, where type information is available, it drops the type check. and otherwise it works for sequences and is fast for lists.
maybe it could be extended into two functions: length= and length=1, where length= optimizes for lists using nthcdr.
On 2/22/08, Attila Lendvai attila.lendvai@gmail.com wrote:
(defun length=1 (sequence)
I think something like this is always useful but would lean towards calling it singlep rather than length=1
sean.
On 2/22/08, Sean Ross rosssd@gmail.com wrote:
On 2/22/08, Attila Lendvai attila.lendvai@gmail.com wrote:
(defun length=1 (sequence)
I think something like this is always useful but would lean towards calling it singlep rather than length=1
How about LENGTH= ?
;; stupid version (defun length= (n seq) (= n (length seq)))
Cheers,
-- Nikodemus
On Feb 22, 2008, at 12:30, Nikodemus Siivola wrote:
How about LENGTH= ?
;; stupid version (defun length= (n seq) (= n (length seq)))
I think the idea is to have something you can use as an argument to functions like find-if. My own solution when I wanted that was functions returning closures:
(defun length= (n) (lambda (seq) (= n (length seq))))
Which lets me do (find-if (length= 1) some-sequence)
Cheers,
On Feb 22, 2008, at 12:30, Nikodemus Siivola wrote:
How about LENGTH= ?
;; stupid version (defun length= (n seq) (= n (length seq)))
I think the idea is to have something you can use as an argument to functions like find-if. My own solution when I wanted that was functions returning closures:
my need comes from cl-rdbms: it can be configured to return resultsets both as vectors and lists, and code dealing with them is full of calls to FIRST, SECOND, LENGTH=1 and friends that should work transparently on both lists and vectors.
for a short moment i wanted to suggest to shadow CL:FIRST and friends in the alexandria package with unexported versions that work on generic sequences and let users :shadowing-import-from as/when they need them. that way i could forget FIRST*. but then i realized that it's kind of like a blasphemy to talk about this, so i only hypothetically mention this idea now, hoping that i won't be thrown with stones... :) so, could this survive without any vetos? there's already FIRST-ELT in sequences.lisp...
but to be specific about length=1:
diff -rN -u old-alexandria/sequences.lisp new-alexandria/sequences.lisp --- old-alexandria/sequences.lisp 2008-02-22 15:53:06.000000000 +0100 +++ new-alexandria/sequences.lisp 2008-02-22 15:53:06.000000000 +0100 @@ -107,9 +107,17 @@ (list (null sequence)) (sequence (zerop (length sequence)))))
+(declaim (inline length=1)) +(defun length=1 (sequence) + (declare (inline sequence-of-length-p) + (optimize speed)) + (sequence-of-length-p sequence 1)) + (defun sequence-of-length-p (sequence length) "Return true if SEQUENCE is a sequence of length LENGTH. Signals an error if SEQUENCE is not a sequence. Returns FALSE for circular lists." + (declare (type array-index length) + (optimize speed)) (etypecase sequence (null (zerop length))
On 2/22/08, Attila Lendvai attila.lendvai@gmail.com wrote:
but to be specific about length=1:
Hah, I had forgotten we already had SEQUENCE-OF-LENGTH-P :)
In that case my only objection to length=1 is the name, which is... not ugly per se, but introduces a new naming convention. No, I don't have any good alternatives to offer straightaway. :/
Cheers,
-- Nikodemus
"Nikodemus Siivola" nikodemus@random-state.net writes:
On 2/22/08, Attila Lendvai attila.lendvai@gmail.com wrote:
but to be specific about length=1:
Hah, I had forgotten we already had SEQUENCE-OF-LENGTH-P :)
In that case my only objection to length=1 is the name, which is... not ugly per se, but introduces a new naming convention. No, I don't have any good alternatives to offer straightaway. :/
Ditch SEQUENCE-OF-LENGTH-P alltogether. It's an absurdily long name for something conceptually simple.
Just compare
(sequence-of-length-p *foo* 1)
vs.
(= (length *foo*) 1)
-T.
"Attila Lendvai" attila.lendvai@gmail.com writes:
Ditch SEQUENCE-OF-LENGTH-P alltogether. It's an absurdily long name for something conceptually simple.
it's optimized for lists
Oh, I think I articulated myself wrongly. I meant, that you should ditch the _name_ SEQUENCE-OF-LENGTH-P in favor of LENGTH=.
-T.
"Attila Lendvai" attila.lendvai@gmail.com writes:
for a short moment i wanted to suggest to shadow CL:FIRST and friends in the alexandria package with unexported versions that work on generic sequences and let users :shadowing-import-from as/when they need them. that way i could forget FIRST*. but then i realized that it's kind of like a blasphemy to talk about this, so i only hypothetically mention this idea now, hoping that i won't be thrown with stones... :) so, could this survive without any vetos? there's already FIRST-ELT in sequences.lisp...
PJB got something like that:
http://darcs.informatimago.com/darcs/public/lisp/common-lisp/generic-cl.lisp
Making that a standalone library on CL.net might be a worthwhile undertaking. But something like that is out of scope of Alexandria, I think.
-T.
"Attila Lendvai" attila.lendvai@gmail.com writes:
dear list,
is there any objections against this?
(declaim (inline length=1))
(defun length=1 (sequence) (if (listp sequence) (and sequence (null (rest sequence))) (= 1 (length sequence))))
in optimized code, where type information is available, it drops the type check. and otherwise it works for sequences and is fast for lists.
maybe it could be extended into two functions: length= and length=1, where length= optimizes for lists using nthcdr.
Yes, I favor such an inclusion. I also vote for including a LENGTH>. I've appended the definitions that I use personally below my email.
There's a compiler macro for LENGTH= for when it's called with either 1 or 2, as these are the numeric arguments I've found myself to use most often.
Exporting LENGTH=1 and LENGTH=2 may be debateable, the only use case is the one Andreas Fuchs mentioned, i.e. as arguments to FIND-IF &c.
-T.
(export '(length= length> length=1 length=2))
(defmacro optimizing-length (inline-p &body body) `(locally (declare (optimize speed) (inline length)) ,@body))
(defun length= (seq n) "Test for whether SEQ contains N number of elements. I.e. it's equivalent to (= (LENGTH SEQ) N), but besides being more concise, it may also be more efficiently implemented." (check-type n integer) (typecase seq (list (do ((i n (1- i)) (list seq (cdr list))) ((or (<= i 0) (null list)) (and (zerop i) (null list))))) (simple-vector (optimizing-length (= n (length seq)))) (vector (optimizing-length (= n (length seq)))) (sequence (optimizing-length (= n (length seq))))))
(define-compiler-macro length= (&whole form sequence n) (cond ((eql n 1) `(length=1 ,sequence)) ((eql n 2) `(length=2 ,sequence)) (t form)))
(defun length> (seq n) "Returns non-nil if (> (length LIST) N)." (check-type n integer) (etypecase seq (list (and (>= n 0) (nthcdr n seq) t)) (simple-vector (optimizing-length (> (length seq) n))) (vector (optimizing-length (> (length seq) n))) (sequence (optimizing-length (> (length seq) n)))))
(defun length=1 (sequence) (declare (optimize speed)) (declare (inline length)) (typecase sequence (list (and sequence (null (rest sequence)))) (simple-vector (= 1 (length sequence))) (vector (= 1 (length sequence))) (sequence (= 1 (length sequence)))))
(defun length=2 (sequence) (declare (optimize speed)) (declare (inline length)) (typecase sequence (list (and sequence (cdr sequence) (null (cddr sequence)))) (simple-vector (= 2 (length sequence))) (vector (= 2 (length sequence))) (sequence (= 2 (length sequence)))))
Exporting LENGTH=1 and LENGTH=2 may be debateable, the only use case is the one Andreas Fuchs mentioned, i.e. as arguments to FIND-IF &c.
i've got this recorded and ready to be pushed. unless soemone has additional comments, i'll push it eventually.
(note: i've not included the debatable length=1/2)
On 3/1/08, Attila Lendvai attila.lendvai@gmail.com wrote:
Exporting LENGTH=1 and LENGTH=2 may be debateable, the only use case is the one Andreas Fuchs mentioned, i.e. as arguments to FIND-IF &c.
i've got this recorded and ready to be pushed. unless soemone has additional comments, i'll push it eventually.
Looks good to me.
Only one comment re the ETYPECASES: I don't think it makes much sense to have a separate dispatch for SIMPLE-VECTOR cases when all we do is call LENGTH. Most implementations are going to emit identical code for (length (the vector x)) and (lenght (the simple-vector) x).
Cheers,
-- Nikodemus
i've got this recorded and ready to be pushed. unless soemone has additional comments, i'll push it eventually.
ok, seems like i wasn't really that happy with it after all. i almost pushed it when i tried to use it in a situation where the sequence argument was a bigger form and the literal length was lost far away in the noise. so i wanted to transpose the two arguments as the = sign in the name suggests, but obviously i couldn't.
then i thought of turning length= into a function that takes &rest arguments and each argument can be either an integer or a sequence. you can find the current implementation at the end of the mail, but i'm not sure vetoers will like it... it's somewhat dwim-ish in that it accepts both integers and sequences at any position, but on the other hand anything else feels crippled from the user point of view.
then i thought of turning length= into a function that takes &rest arguments and each argument can be either an integer or a sequence. you can find the current implementation at the end of the mail, but i'm not sure vetoers will like it... it's somewhat dwim-ish in that it accepts both integers and sequences at any position, but on the other hand anything else feels crippled from the user point of view.
final call for vetos for length=...
then i thought of turning length= into a function that takes &rest arguments and each argument can be either an integer or a sequence. you can find the current implementation at the end of the mail, but i'm not sure vetoers will like it... it's somewhat dwim-ish in that it accepts both integers and sequences at any position, but on the other hand anything else feels crippled from the user point of view.
final call for vetos for length=...
pushed.
and a simple-parse-error to conditions.lisp, too.
alexandria-devel@common-lisp.net