[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch for better multiple values support

From: Matthias Koeppe
Subject: Patch for better multiple values support
Date: 10 May 2001 11:24:16 +0200
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.6

In this article I propose to change the multiple values support of the
current CVS Guile in order to make it cleaner.  A patch is included at
the end of the article.

Guile uses a special struct type for passing multiple values to
multiple-value continuations.  Ideally, 

1) such an intermediate object should never be exposed to the user, 

2) it should be an error to pass the object to ordinary (single-value)

However, let us look how Guile deals with these objects.  

guile> (version)
guile> (use-modules (ice-9 history))
guile> (define x (values 3 4))        ; should signal error
guile> x
$2 = 3

The `define' should signal an error because it is passed two values
where it expects one.  Instead, Guile binds the intermediate values
object to `x'.  The fancy write representation of intermediate values
objects makes it hard to see what kind of objects are dealt with.  It
is only a kludgy solution for the repl but it already breaks when the
history module is used.

The patch shown below does the following:

A) It replaces the fancy write representation of values with a
   sharp-angle representation like this: #<values (3 4)>.  This is the
   right thing to do because of reason 1) and because the intermediate
   values objects do not have a read representation.

B) It changes the read-eval-print loop in order to explicitly deal
   with multiple values, rather than relying on Guile's "ability" to
   pass multiple values to single-value continuations. 

   boot-9.scm (error-catching-repl): The P ("printer") argument to
   error-catching-repl is now a procedure taking one argument, the
   list of all returned values; error-catching-repl calls the E
   ("eval'er") procedure via call-with-values.
   (scm-style-repl): The `-print' procedure calls `maybe-print' and
   the before/after-print-hook for every element of the list of values
   it receives.

Here is an example how this effects the repl when (ice-9 history) is used.

guile> (values 3 4)
$2 = 3
$3 = 4
guile> $2
$4 = 3

That is, one can properly refer to the multiple return values using
the $NUMBER identifiers.

This patch does NOT make Guile signal an error when multiple values
are passed to ordinary (single-value) continuations.  I don't know how
to do this; probably the evaluator needs to be changed.  Maybe someone
with a deeper understanding of the evaluator can help here.


Index: ice-9/boot-9.scm
RCS file: /cvs/guile/guile-core/ice-9/boot-9.scm,v
retrieving revision 1.240
diff -u -r1.240 boot-9.scm
--- ice-9/boot-9.scm    2001/05/05 13:41:59     1.240
+++ ice-9/boot-9.scm    2001/05/10 08:26:51
@@ -2329,7 +2329,10 @@
 ;;      (display "No backtrace available.\n")))
 (define (error-catching-repl r e p)
-  (error-catching-loop (lambda () (p (e (r))))))
+  (error-catching-loop
+   (lambda ()
+     (call-with-values (lambda () (e (r)))
+       (lambda the-values (p the-values))))))
 (define (gc-run-time)
   (cdr (assq 'gc-time-taken (gc-stats))))
@@ -2434,15 +2437,20 @@
                                              (write result)
-                    (lambda (result)
+                    (lambda (results)
                       (if (not scm-repl-silent)
-                            (run-hook before-print-hook result)
-                            (maybe-print result)
-                            (run-hook after-print-hook result)
-                            (if scm-repl-verbose
-                                (repl-report))
-                            (force-output))))))
+                            (let loop ((results results))
+                              (cond ((null? results)
+                                     (if scm-repl-verbose
+                                         (repl-report))
+                                     (force-output))
+                                    (else
+                                     (let ((result (car results)))
+                                       (run-hook before-print-hook result)
+                                       (maybe-print result)
+                                       (run-hook after-print-hook result))
+                                     (loop (cdr results))))))))))
           (-quit (lambda (args)
                    (if scm-repl-verbose
Index: libguile/values.c
RCS file: /cvs/guile/guile-core/libguile/values.c,v
retrieving revision 1.3
diff -u -r1.3 values.c
--- libguile/values.c   2001/03/26 22:43:23     1.3
+++ libguile/values.c   2001/05/10 08:26:51
@@ -61,13 +61,10 @@
   SCM port = SCM_PORT_WITH_PS_PORT (pwps);
   scm_print_state *ps = SCM_PRINT_STATE (SCM_PORT_WITH_PS_PS (pwps));
-  while (SCM_CONSP (values))
-    {
-      scm_iprin1 (SCM_CAR (values), port, ps);
-      values = SCM_CDR (values);
-      if (SCM_CONSP (values))
-       scm_newline (port);
-    }
+  scm_puts ("#<values ", port);
+  scm_iprin1 (values, port, ps);
+  scm_puts (">", port);

Matthias Köppe --

reply via email to

[Prev in Thread] Current Thread [Next in Thread]