summaryrefslogtreecommitdiff
path: root/Examples/guile/multivalue
diff options
context:
space:
mode:
Diffstat (limited to 'Examples/guile/multivalue')
-rw-r--r--Examples/guile/multivalue/Makefile18
-rw-r--r--Examples/guile/multivalue/example.c18
-rw-r--r--Examples/guile/multivalue/example.i32
-rw-r--r--Examples/guile/multivalue/runme.scm66
4 files changed, 134 insertions, 0 deletions
diff --git a/Examples/guile/multivalue/Makefile b/Examples/guile/multivalue/Makefile
new file mode 100644
index 0000000..dc9c66d
--- /dev/null
+++ b/Examples/guile/multivalue/Makefile
@@ -0,0 +1,18 @@
+TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+SRCS = example.c
+TARGET = example
+INTERFACE = example.i
+
+all::
+ $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
+ TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' guile
+
+static::
+ $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
+ TARGET='my-guile' INTERFACE='$(INTERFACE)' guile_static
+
+clean::
+ $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' guile_clean
+
+check: all
diff --git a/Examples/guile/multivalue/example.c b/Examples/guile/multivalue/example.c
new file mode 100644
index 0000000..c9ebad1
--- /dev/null
+++ b/Examples/guile/multivalue/example.c
@@ -0,0 +1,18 @@
+void divide_l(int a, int b, int *quotient_p, int *remainder_p)
+{
+ *quotient_p = a/b;
+ *remainder_p = a%b;
+}
+
+void divide_v(int a, int b, int *quotient_p, int *remainder_p)
+{
+ *quotient_p = a/b;
+ *remainder_p = a%b;
+}
+
+void divide_mv(int a, int b, int *quotient_p, int *remainder_p)
+{
+ *quotient_p = a/b;
+ *remainder_p = a%b;
+}
+
diff --git a/Examples/guile/multivalue/example.i b/Examples/guile/multivalue/example.i
new file mode 100644
index 0000000..1353894
--- /dev/null
+++ b/Examples/guile/multivalue/example.i
@@ -0,0 +1,32 @@
+/* -*- c -*- */
+
+%module example;
+
+%{
+void divide_l(int a, int b, int *quotient_p, int *remainder_p);
+void divide_v(int a, int b, int *quotient_p, int *remainder_p);
+void divide_mv(int a, int b, int *quotient_p, int *remainder_p);
+%}
+
+/* Multiple values as lists. By default, if more than one value is to
+be returned, a list of the values is created and returned; to switch
+back to this behavior, use: */
+%values_as_list;
+
+void divide_l(int a, int b, int *OUTPUT, int *OUTPUT);
+
+/* Multiple values as vectors. By issueing: */
+%values_as_vector;
+/* vectors instead of lists will be used. */
+
+void divide_v(int a, int b, int *OUTPUT, int *OUTPUT);
+
+/* Multiple values for multiple-value continuations.
+ (This is the most elegant way.) By issueing: */
+%multiple_values;
+/* multiple values are passed to the multiple-value
+ continuation, as created by `call-with-values' or the
+ convenience macro `receive'. (See the Scheme file.) */
+
+void divide_mv(int a, int b, int *OUTPUT, int *OUTPUT);
+
diff --git a/Examples/guile/multivalue/runme.scm b/Examples/guile/multivalue/runme.scm
new file mode 100644
index 0000000..73eb5af
--- /dev/null
+++ b/Examples/guile/multivalue/runme.scm
@@ -0,0 +1,66 @@
+;;;; Show the three different ways to deal with multiple return values
+
+(use-modules (example))
+
+;;; Multiple values as lists. By default, if more than one value is to
+;;; be returned, a list of the values is created and returned. The
+;;; procedure divide-l does so:
+
+(let* ((quotient/remainder (divide-l 37 5))
+ ;; divide-l returns a list of the two values, so get them:
+ (quotient (car quotient/remainder))
+ (remainder (cadr quotient/remainder)))
+ (display "37 divided by 5 is ")
+ (display quotient)
+ (display ", remainder ")
+ (display remainder)
+ (newline))
+
+;;; Multiple values as vectors. You can get vectors instead of lists
+;;; if you want:
+
+(let* ((quotient-remainder-vector (divide-v 40 7))
+ ;; divide-v returns a vector of two values, so get them:
+ (quotient (vector-ref quotient-remainder-vector 0))
+ (remainder (vector-ref quotient-remainder-vector 1)))
+ (display "40 divided by 7 is ")
+ (display quotient)
+ (display ", remainder ")
+ (display remainder)
+ (newline))
+
+;;; Multiple values for multiple-value continuations. (The most
+;;; elegant way.) You can get multiple values passed to the
+;;; multiple-value continuation, as created by `call-with-values'.
+
+(call-with-values (lambda ()
+ ;; the "producer" procedure
+ (divide-mv 91 13))
+ (lambda (quotient remainder)
+ ;; the "consumer" procedure
+ (display "91 divided by 13 is ")
+ (display quotient)
+ (display ", remainder ")
+ (display remainder)
+ (newline)))
+
+;;; SRFI-8 has a very convenient macro for this construction:
+
+(use-modules (srfi srfi-8))
+
+;;; If your Guile is too old, you can define the receive macro yourself:
+;;;
+;;; (define-macro (receive vars vals . body)
+;;; `(call-with-values (lambda () ,vals)
+;;; (lambda ,vars ,@body)))
+
+(receive (quotient remainder)
+ (divide-mv 111 19) ; the "producer" form
+ ;; In the body, `quotient' and `remainder' are bound to the two
+ ;; values.
+ (display "111 divided by 19 is ")
+ (display quotient)
+ (display ", remainder ")
+ (display remainder)
+ (newline))
+