unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: ludo@gnu.org (Ludovic Courtès)
To: guile-devel@gnu.org
Subject: SRFI-1 in Scheme
Date: Tue, 13 Jul 2010 00:57:07 +0200	[thread overview]
Message-ID: <8739vocnr0.fsf@gnu.org> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 1320 bytes --]

Hello!

The attached patch is a first stab at re-implementing SRFI-1 in Scheme.

Here’s a quick benchmark of ‘fold’, for large and small lists:

  - in C

    ("srfi-1.bm: fold: fold" 30 user 5.55 benchmark 5.54999599456787 bench/interp 5.54999599456787 gc 0.0)
    ("srfi-1.bm: fold: fold" 2000000 user 4.41 benchmark 4.14297119140625 bench/interp 4.14297119140625 gc 0.0)

  - in Scheme (debug engine)

    ("srfi-1.bm: fold: fold" 30 user 6.04 benchmark 6.03999599456787 bench/interp 6.03999599456787 gc 0.0)
    ("srfi-1.bm: fold: fold" 2000000 user 5.14 benchmark 4.87297119140625 bench/interp 4.87297119140625 gc 0.0)

  - in Scheme (regular engine)

    ("srfi-1.bm: fold: fold" 30 user 5.46 benchmark 5.45999656677246 bench/interp 5.45999656677246 gc 0.0)
    ("srfi-1.bm: fold: fold" 2000000 user 4.64 benchmark 4.4111181640625 bench/interp 4.4111181640625 gc 0.0)

IOW, with the debug engine (currently the default) and for large lists
‘fold’ in Scheme is ~9% slower than in C; for small lists it’s ~17%
slower.

With the regular engine, Scheme is ~2% faster for large lists and still
~5% slower for small lists.

I’m tempted to put this in and then make the regular engine the default
unless ‘--debug’ is specified.

What do you think?

Thanks,
Ludo’.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: the patch --]
[-- Type: text/x-patch, Size: 21065 bytes --]

From 927b96b48d4870c768da093741af6e6bcd438cad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org>
Date: Tue, 13 Jul 2010 00:07:12 +0200
Subject: [PATCH] Start rewriting SRFI-1 in Scheme.

This partially reverts commit e556f8c3c6b74ee6596e8dcbe829109d7745da2c
(Fri May 6 2005).

* module/srfi/srfi-1.scm (xcons, list-tabulate, not-pair?, car+cdr,
  last, fold, list-index): New procedures.

* srfi/srfi-1.c (srfi1_module): New variable.
  (CACHE_VAR): New macro.
  (scm_srfi1_car_plus_cdr, scm_srfi1_fold, scm_srfi1_last,
  scm_srfi1_list_index, scm_srfi1_list_tabulate, scm_srfi1_not_pair_p,
  scm_srfi1_xcons): Rewrite as proxies of the corresponding Scheme
  procedure.

* test-suite/tests/srfi-1.test ("list-tabulate")["-1"]: Change exception
  type to `exception:wrong-type-arg'.

* benchmark-suite/benchmarks/srfi-1.bm: New file.

* benchmark-suite/Makefile.am (SCM_BENCHMARKS): Add
  `benchmarks/srfi-1.bm'.
---
 benchmark-suite/Makefile.am          |    1 +
 benchmark-suite/benchmarks/srfi-1.bm |   38 ++++
 module/srfi/srfi-1.scm               |   64 +++++++-
 srfi/srfi-1.c                        |  318 ++++++----------------------------
 test-suite/tests/srfi-1.test         |    4 +-
 5 files changed, 154 insertions(+), 271 deletions(-)
 create mode 100644 benchmark-suite/benchmarks/srfi-1.bm

diff --git a/benchmark-suite/Makefile.am b/benchmark-suite/Makefile.am
index d99e457..b58219a 100644
--- a/benchmark-suite/Makefile.am
+++ b/benchmark-suite/Makefile.am
@@ -5,6 +5,7 @@ SCM_BENCHMARKS = benchmarks/0-reference.bm		\
                  benchmarks/if.bm			\
                  benchmarks/logand.bm			\
 		 benchmarks/read.bm			\
+		 benchmarks/srfi-1.bm			\
 		 benchmarks/srfi-13.bm			\
 		 benchmarks/structs.bm			\
 		 benchmarks/subr.bm			\
diff --git a/benchmark-suite/benchmarks/srfi-1.bm b/benchmark-suite/benchmarks/srfi-1.bm
new file mode 100644
index 0000000..2888934
--- /dev/null
+++ b/benchmark-suite/benchmarks/srfi-1.bm
@@ -0,0 +1,38 @@
+;;; -*- mode: scheme; coding: utf-8; -*-
+;;; SRFI-1.
+;;;
+;;; Copyright 2010 Free Software Foundation, Inc.
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU Lesser General Public License
+;;; as published by the Free Software Foundation; either version 3, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU Lesser General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU Lesser General Public
+;;; License along with this software; see the file COPYING.LESSER.  If
+;;; not, write to the Free Software Foundation, Inc., 51 Franklin
+;;; Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+(define-module (benchmarks srfi-1)
+  #:use-module (srfi srfi-1)
+  #:use-module (benchmark-suite lib))
+
+(define %big-list
+  (iota 1000000))
+
+(define %small-list
+  (iota 10))
+
+\f
+(with-benchmark-prefix "fold"
+
+  (benchmark "fold" 30
+    (fold (lambda (x y) y) #f %big-list))
+
+  (benchmark "fold" 2000000
+    (fold (lambda (x y) y) #f %small-list)))
diff --git a/module/srfi/srfi-1.scm b/module/srfi/srfi-1.scm
index c32eb1c..27aa39e 100644
--- a/module/srfi/srfi-1.scm
+++ b/module/srfi/srfi-1.scm
@@ -1,6 +1,6 @@
 ;;; srfi-1.scm --- List Library
 
-;; 	Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
+;; 	Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc.
 ;;
 ;; This library is free software; you can redistribute it and/or
 ;; modify it under the terms of the GNU Lesser General Public
@@ -225,6 +225,11 @@
 
 ;;; Constructors
 
+(define (xcons d a)
+  "Like `cons', but with interchanged arguments.  Useful mostly when passed to
+higher-order procedures."
+  (cons a d))
+
 ;; internal helper, similar to (scsh utilities) check-arg.
 (define (check-arg-type pred arg caller)
   (if (pred arg)
@@ -235,7 +240,15 @@
 ;; the srfi spec doesn't seem to forbid inexact integers.
 (define (non-negative-integer? x) (and (integer? x) (>= x 0)))
 
-
+(define (list-tabulate n init-proc)
+  "Return an N-element list, where each list element is produced by applying the
+procedure INIT-PROC to the corresponding list index.  The order in which
+INIT-PROC is applied to the indices is not specified."
+  (check-arg-type non-negative-integer? n "list-tabulate")
+  (let lp ((n n) (acc '()))
+    (if (<= n 0)
+        acc
+        (lp (- n 1) (cons (init-proc (- n 1)) acc)))))
 
 (define (circular-list elt1 . elts)
   (set! elts (cons elt1 elts))
@@ -294,6 +307,13 @@
     (else
      (error "not a proper list in null-list?"))))
 
+(define (not-pair? x)
+  "Return #t if X is not a pair, #f otherwise.
+
+This is shorthand notation `(not (pair? X))' and is supposed to be used for
+end-of-list checking in contexts where dotted lists are allowed."
+  (not (pair? x)))
+
 (define (list= elt= . rest)
   (define (lists-equal a b)
     (let lp ((a a) (b b))
@@ -317,9 +337,17 @@
 (define third caddr)
 (define fourth cadddr)
 
+(define (car+cdr x)
+  "Return two values, the `car' and the `cdr' of PAIR."
+  (values (car x) (cdr x)))
+
 (define take list-head)
 (define drop list-tail)
 
+(define (last pair)
+  "Return the last element of the non-empty, finite list PAIR."
+  (car (last-pair pair)))
+
 ;;; Miscelleneous: length, append, concatenate, reverse, zip & count
 
 (define (zip clist1 . rest)
@@ -343,6 +371,21 @@
 
 ;;; Fold, unfold & map
 
+(define (fold kons knil list1 . rest)
+  "Apply PROC to the elements of LIST1 ... LISTN to build a result, and return
+that result.  See the manual for details."
+  (if (null? rest)
+      (let f ((knil knil) (list1 list1))
+	(if (null? list1)
+	    knil
+	    (f (kons (car list1) knil) (cdr list1))))
+      (let f ((knil knil) (lists (cons list1 rest)))
+	(if (any null? lists)
+	    knil
+	    (let ((cars (map1 car lists))
+		  (cdrs (map1 cdr lists)))
+	      (f (apply kons (append! cars (list knil))) cdrs))))))
+
 (define (fold-right kons knil clist1 . rest)
   (if (null? rest)
     (let f ((list1 clist1))
@@ -463,6 +506,23 @@
 	  (else
 	   (and (pred (car ls)) (lp (cdr ls)))))))
 
+(define (list-index pred clist1 . rest)
+  "Return the index of the first set of elements, one from each of
+CLIST1 ... CLISTN, that satisfies PRED."
+  (if (null? rest)
+    (let lp ((l clist1) (i 0))
+      (if (null? l)
+	#f
+	(if (pred (car l))
+	  i
+	  (lp (cdr l) (+ i 1)))))
+    (let lp ((lists (cons clist1 rest)) (i 0))
+      (cond ((any1 null? lists)
+	     #f)
+	    ((apply pred (map1 car lists)) i)
+	    (else
+	     (lp (map1 cdr lists) (+ i 1)))))))
+
 ;;; Association lists
 
 (define alist-cons acons)
diff --git a/srfi/srfi-1.c b/srfi/srfi-1.c
index 537c2b3..71cfcf9 100644
--- a/srfi/srfi-1.c
+++ b/srfi/srfi-1.c
@@ -27,13 +27,32 @@
 
 #include "srfi-1.h"
 
-/* The intent of this file is to gradually replace those Scheme
- * procedures in srfi-1.scm which extends core primitive procedures,
+/* The intent of this file was to gradually replace those Scheme
+ * procedures in srfi-1.scm that extend core primitive procedures,
  * so that using srfi-1 won't have performance penalties.
  *
- * Please feel free to contribute any new replacements!
+ * However, we now prefer to write these procedures in Scheme, let the compiler
+ * optimize them, and have the VM execute them efficiently.
  */
 
+
+/* The `(srfi srfi-1)' module.  */
+static SCM srfi1_module = SCM_BOOL_F;
+
+/* Cache variable NAME in C variable VAR.  */
+#define CACHE_VAR(var, name)						\
+  static SCM var = SCM_BOOL_F;						\
+  if (scm_is_false (var))						\
+    {									\
+      if (SCM_UNLIKELY (scm_is_false (srfi1_module)))			\
+	srfi1_module = scm_c_resolve_module ("srfi srfi-1");		\
+									\
+      var = scm_module_variable (srfi1_module,				\
+                                 scm_from_locale_symbol (name));	\
+      if (scm_is_false (var))						\
+        abort ();							\
+    }
+
 static long
 srfi1_ilength (SCM sx)
 {
@@ -253,16 +272,12 @@ SCM_DEFINE (scm_srfi1_break_x, "break!", 2, 0, 0,
 #undef FUNC_NAME
 
 
-SCM_DEFINE (scm_srfi1_car_plus_cdr, "car+cdr", 1, 0, 0,
-            (SCM pair),
-	    "Return two values, the @sc{car} and the @sc{cdr} of @var{pair}.")
-#define FUNC_NAME s_scm_srfi1_car_plus_cdr
+SCM
+scm_srfi1_car_plus_cdr (SCM pair)
 {
-  SCM_VALIDATE_CONS (SCM_ARG1, pair);
-  return scm_values (scm_list_2 (SCM_CAR (pair), SCM_CDR (pair)));
+  CACHE_VAR (car_plus_cdr, "car+cdr");
+  return scm_call_1 (car_plus_cdr, pair);
 }
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_srfi1_concatenate, "concatenate", 1, 0, 0,
             (SCM lstlst),
@@ -935,131 +950,19 @@ SCM_DEFINE (scm_srfi1_find_tail, "find-tail", 2, 0, 0,
 }
 #undef FUNC_NAME
 
-
-SCM_DEFINE (scm_srfi1_fold, "fold", 3, 0, 1,
-            (SCM proc, SCM init, SCM list1, SCM rest),
-	    "Apply @var{proc} to the elements of @var{lst1} @dots{}\n"
-	    "@var{lstN} to build a result, and return that result.\n"
-	    "\n"
-	    "Each @var{proc} call is @code{(@var{proc} @var{elem1} @dots{}\n"
-	    "@var{elemN} @var{previous})}, where @var{elem1} is from\n"
-	    "@var{lst1}, through @var{elemN} from @var{lstN}.\n"
-	    "@var{previous} is the return from the previous call to\n"
-	    "@var{proc}, or the given @var{init} for the first call.  If any\n"
-	    "list is empty, just @var{init} is returned.\n"
-	    "\n"
-	    "@code{fold} works through the list elements from first to last.\n"
-	    "The following shows a list reversal and the calls it makes,\n"
-	    "\n"
-	    "@example\n"
-	    "(fold cons '() '(1 2 3))\n"
-	    "\n"
-	    "(cons 1 '())\n"
-	    "(cons 2 '(1))\n"
-	    "(cons 3 '(2 1)\n"
-	    "@result{} (3 2 1)\n"
-	    "@end example\n"
-	    "\n"
-	    "If @var{lst1} through @var{lstN} have different lengths,\n"
-	    "@code{fold} stops when the end of the shortest is reached.\n"
-	    "Ie.@: elements past the length of the shortest are ignored in\n"
-	    "the other @var{lst}s.  At least one @var{lst} must be\n"
-	    "non-circular.\n"
-	    "\n"
-	    "The way @code{fold} builds a result from iterating is quite\n"
-	    "general, it can do more than other iterations like say\n"
-	    "@code{map} or @code{filter}.  The following for example removes\n"
-	    "adjacent duplicate elements from a list,\n"
-	    "\n"
-	    "@example\n"
-	    "(define (delete-adjacent-duplicates lst)\n"
-	    "  (fold-right (lambda (elem ret)\n"
-	    "                (if (equal? elem (first ret))\n"
-	    "                    ret\n"
-	    "                    (cons elem ret)))\n"
-	    "              (list (last lst))\n"
-	    "              lst))\n"
-	    "(delete-adjacent-duplicates '(1 2 3 3 4 4 4 5))\n"
-	    "@result{} (1 2 3 4 5)\n"
-	    "@end example\n"
-	    "\n"
-	    "Clearly the same sort of thing can be done with a\n"
-	    "@code{for-each} and a variable in which to build the result,\n"
-	    "but a self-contained @var{proc} can be re-used in multiple\n"
-	    "contexts, where a @code{for-each} would have to be written out\n"
-	    "each time.")
-#define FUNC_NAME s_scm_srfi1_fold
+SCM
+scm_srfi1_fold (SCM proc, SCM init, SCM list1, SCM rest)
 {
-  SCM lst;
-  int argnum;
-  SCM_VALIDATE_REST_ARGUMENT (rest);
-
-  if (scm_is_null (rest))
-    {
-      /* one list */
-      SCM_VALIDATE_PROC (SCM_ARG1, proc);
-
-      for ( ; scm_is_pair (list1); list1 = SCM_CDR (list1))
-        init = scm_call_2 (proc, SCM_CAR (list1), init);
-
-      /* check below that list1 is a proper list, and done */
-      lst = list1;
-      argnum = 2;
-    }
-  else
-    {
-      /* two or more lists */
-      SCM  vec, args, a;
-      size_t  len, i;
-
-      /* vec is the list arguments */
-      vec = scm_vector (scm_cons (list1, rest));
-      len = SCM_SIMPLE_VECTOR_LENGTH (vec);
-
-      /* args is the argument list to pass to proc, same length as vec,
-         re-used for each call */
-      args = scm_make_list (SCM_I_MAKINUM (len+1), SCM_UNDEFINED);
-
-      for (;;)
-        {
-          /* first elem of each list in vec into args, and step those
-             vec entries onto their next element */
-          for (i = 0, a = args, argnum = 2;
-               i < len;
-               i++, a = SCM_CDR (a), argnum++)
-            {
-              lst = SCM_SIMPLE_VECTOR_REF (vec, i);  /* list argument */
-              if (! scm_is_pair (lst))
-                goto check_lst_and_done;
-              SCM_SETCAR (a, SCM_CAR (lst));  /* arg for proc */
-              SCM_SIMPLE_VECTOR_SET (vec, i, SCM_CDR (lst));  /* rest of lst */
-            }
-          SCM_SETCAR (a, init);
-
-          init = scm_apply (proc, args, SCM_EOL);
-        }
-    }
-
- check_lst_and_done:
-  SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, argnum, FUNC_NAME, "list");
-  return init;
+  CACHE_VAR (fold, "fold");
+  return scm_apply_3 (fold, proc, init, list1, rest);
 }
-#undef FUNC_NAME
-
 
-SCM_DEFINE (scm_srfi1_last, "last", 1, 0, 0,
-            (SCM lst),
-	    "Like @code{cons}, but with interchanged arguments.  Useful\n"
-	    "mostly when passed to higher-order procedures.")
-#define FUNC_NAME s_scm_srfi1_last
+SCM
+scm_srfi1_last (SCM lst)
 {
-  SCM pair = scm_last_pair (lst);
-  /* scm_last_pair returns SCM_EOL for an empty list */
-  SCM_VALIDATE_CONS (SCM_ARG1, pair);
-  return SCM_CAR (pair);
+  CACHE_VAR (last, "last");
+  return scm_call_1 (last, lst);
 }
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_srfi1_length_plus, "length+", 1, 0, 0,
             (SCM lst),
@@ -1073,106 +976,12 @@ SCM_DEFINE (scm_srfi1_length_plus, "length+", 1, 0, 0,
 #undef FUNC_NAME
 
 
-SCM_DEFINE (scm_srfi1_list_index, "list-index", 2, 0, 1,
-            (SCM pred, SCM list1, SCM rest),
-	    "Return the index of the first set of elements, one from each of\n"
-	    "@var{lst1}@dots{}@var{lstN}, which satisfies @var{pred}.\n"
-	    "\n"
-	    "@var{pred} is called as @code{(@var{pred} elem1 @dots{}\n"
-	    "elemN)}.  Searching stops when the end of the shortest\n"
-	    "@var{lst} is reached.  The return index starts from 0 for the\n"
-	    "first set of elements.  If no set of elements pass then the\n"
-	    "return is @code{#f}.\n"
-	    "\n"
-	    "@example\n"
-	    "(list-index odd? '(2 4 6 9))      @result{} 3\n"
-	    "(list-index = '(1 2 3) '(3 1 2))  @result{} #f\n"
-	    "@end example")
-#define FUNC_NAME s_scm_srfi1_list_index
+SCM
+scm_srfi1_list_index (SCM pred, SCM list1, SCM rest)
 {
-  long  n = 0;
-  SCM   lst;
-  int   argnum;
-  SCM_VALIDATE_REST_ARGUMENT (rest);
-
-  if (scm_is_null (rest))
-    {
-      /* one list */
-      SCM_VALIDATE_PROC (SCM_ARG1, pred);
-
-      for ( ; scm_is_pair (list1); n++, list1 = SCM_CDR (list1))
-        if (scm_is_true (scm_call_1 (pred, SCM_CAR (list1))))
-          return SCM_I_MAKINUM (n);
-
-      /* not found, check below that list1 is a proper list */
-    end_list1:
-      lst = list1;
-      argnum = 2;
-    }
-  else if (scm_is_pair (rest) && scm_is_null (SCM_CDR (rest)))
-    {
-      /* two lists */
-      SCM list2 = SCM_CAR (rest);
-      SCM_VALIDATE_PROC (SCM_ARG1, pred);
-
-      for ( ; ; n++)
-        {
-          if (! scm_is_pair (list1))
-            goto end_list1;
-          if (! scm_is_pair (list2))
-            {
-              lst = list2;
-              argnum = 3;
-              break;
-            }
-          if (scm_is_true (scm_call_2 (pred,
-                                       SCM_CAR (list1), SCM_CAR (list2))))
-            return SCM_I_MAKINUM (n);
-
-          list1 = SCM_CDR (list1);
-          list2 = SCM_CDR (list2);
-        }
-    }
-  else
-    {
-      /* three or more lists */
-      SCM     vec, args, a;
-      size_t  len, i;
-
-      /* vec is the list arguments */
-      vec = scm_vector (scm_cons (list1, rest));
-      len = SCM_SIMPLE_VECTOR_LENGTH (vec);
-
-      /* args is the argument list to pass to pred, same length as vec,
-         re-used for each call */
-      args = scm_make_list (SCM_I_MAKINUM (len), SCM_UNDEFINED);
-
-      for ( ; ; n++)
-        {
-          /* first elem of each list in vec into args, and step those
-             vec entries onto their next element */
-          for (i = 0, a = args, argnum = 2;
-               i < len;
-               i++, a = SCM_CDR (a), argnum++)
-            {
-              lst = SCM_SIMPLE_VECTOR_REF (vec, i);  /* list argument */
-              if (! scm_is_pair (lst))
-                goto not_found_check_lst;
-              SCM_SETCAR (a, SCM_CAR (lst));  /* arg for pred */
-              SCM_SIMPLE_VECTOR_SET (vec, i, SCM_CDR (lst));  /* rest of lst */
-            }
-
-          if (scm_is_true (scm_apply (pred, args, SCM_EOL)))
-            return SCM_I_MAKINUM (n);
-        }
-    }
-
- not_found_check_lst:
-  SCM_ASSERT_TYPE (SCM_NULL_OR_NIL_P (lst), lst, argnum, FUNC_NAME, "list");
-  return SCM_BOOL_F;
+  CACHE_VAR (list_index, "list-index");
+  return scm_apply_2 (list_index, pred, list1, rest);
 }
-#undef FUNC_NAME
-
 
 /* This routine differs from the core list-copy in allowing improper lists.
    Maybe the core could allow them similarly.  */
@@ -1206,25 +1015,12 @@ SCM_DEFINE (scm_srfi1_list_copy, "list-copy", 1, 0, 0,
 }
 #undef FUNC_NAME
 
-
-SCM_DEFINE (scm_srfi1_list_tabulate, "list-tabulate", 2, 0, 0,
-            (SCM n, SCM proc),
-	    "Return an @var{n}-element list, where each list element is\n"
-	    "produced by applying the procedure @var{init-proc} to the\n"
-	    "corresponding list index.  The order in which @var{init-proc}\n"
-	    "is applied to the indices is not specified.")
-#define FUNC_NAME s_scm_srfi1_list_tabulate
+SCM
+scm_srfi1_list_tabulate (SCM n, SCM proc)
 {
-  long i, nn;
-  SCM ret = SCM_EOL;
-  nn = scm_to_signed_integer (n, 0, LONG_MAX);
-  SCM_VALIDATE_PROC (SCM_ARG2, proc);
-  for (i = nn-1; i >= 0; i--)
-    ret = scm_cons (scm_call_1 (proc, scm_from_long (i)), ret);
-  return ret;
+  CACHE_VAR (list_tabulate, "list-tabulate");
+  return scm_call_2 (list_tabulate, n, proc);
 }
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_srfi1_lset_adjoin, "lset-adjoin", 2, 0, 1,
             (SCM equal, SCM lst, SCM rest),
@@ -1609,21 +1405,12 @@ SCM_DEFINE (scm_srfi1_ninth, "ninth", 1, 0, 0,
 }
 #undef FUNC_NAME
 
-
-SCM_DEFINE (scm_srfi1_not_pair_p, "not-pair?", 1, 0, 0,
-            (SCM obj),
-	    "Return @code{#t} is @var{obj} is not a pair, @code{#f}\n"
-	    "otherwise.\n"
-	    "\n"
-	    "This is shorthand notation @code{(not (pair?  @var{obj}))} and\n"
-	    "is supposed to be used for end-of-list checking in contexts\n"
-	    "where dotted lists are allowed.")
-#define FUNC_NAME s_scm_srfi1_not_pair_p
+SCM
+scm_srfi1_not_pair_p (SCM obj)
 {
-  return scm_from_bool (! scm_is_pair (obj));
+  CACHE_VAR (not_pair_p, "not-pair?");
+  return scm_call_1 (not_pair_p, obj);
 }
-#undef FUNC_NAME
-
 
 SCM_DEFINE (scm_srfi1_partition, "partition", 2, 0, 0,
 	    (SCM pred, SCM list),
@@ -2153,17 +1940,14 @@ SCM_DEFINE (scm_srfi1_tenth, "tenth", 1, 0, 0,
 #undef FUNC_NAME
 
 
-SCM_DEFINE (scm_srfi1_xcons, "xcons", 2, 0, 0,
-            (SCM d, SCM a),
-	    "Like @code{cons}, but with interchanged arguments.  Useful\n"
-	    "mostly when passed to higher-order procedures.")
-#define FUNC_NAME s_scm_srfi1_xcons
+SCM
+scm_srfi1_xcons (SCM d, SCM a)
 {
-  return scm_cons (a, d);
+  CACHE_VAR (xcons, "xcons");
+  return scm_call_2 (xcons, d, a);
 }
-#undef FUNC_NAME
-
 
+\f
 void
 scm_init_srfi_1 (void)
 {
diff --git a/test-suite/tests/srfi-1.test b/test-suite/tests/srfi-1.test
index ecff82f..909f58c 100644
--- a/test-suite/tests/srfi-1.test
+++ b/test-suite/tests/srfi-1.test
@@ -1,6 +1,6 @@
 ;;;; srfi-1.test --- Test suite for Guile's SRFI-1 functions. -*- scheme -*-
 ;;;;
-;;;; Copyright 2003, 2004, 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+;;;; Copyright 2003, 2004, 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -1563,7 +1563,7 @@
 
 (with-test-prefix "list-tabulate"
 
-  (pass-if-exception "-1" exception:out-of-range
+  (pass-if-exception "-1" exception:wrong-type-arg
     (list-tabulate -1 identity))
   (pass-if "0"
     (equal? '() (list-tabulate 0 identity)))
-- 
1.7.0


[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

             reply	other threads:[~2010-07-12 22:57 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-12 22:57 Ludovic Courtès [this message]
2010-07-13 21:25 ` SRFI-1 in Scheme Andy Wingo
2010-07-13 22:09   ` Ludovic Courtès
2010-07-13 22:27     ` Andy Wingo
2010-07-13 22:44       ` Ludovic Courtès
2010-07-14  7:41         ` Andy Wingo
2010-07-15 21:40           ` Ludovic Courtès
2010-07-19 20:30             ` Andy Wingo
2010-07-20 16:35               ` Ludovic Courtès
2010-07-20 20:11                 ` Andy Wingo
2010-07-21 23:10                   ` Ludovic Courtès
2010-07-20 20:15                 ` Andy Wingo
2010-09-01 16:04               ` Allowing the choice of a VM engine? Ludovic Courtès
2010-09-03  5:23                 ` Andy Wingo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8739vocnr0.fsf@gnu.org \
    --to=ludo@gnu.org \
    --cc=guile-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).