*Abdulaziz Ghuloum <xxxxxx@cs.indiana.edu> |I assume you mean "other Scheme values", not expressions. Doesn't the |following code bind the evaluated result of VALUES to a single variable? | |(call-with-values (lambda () (values 1 2 3)) | (lambda VALS | VALS)) The VALS is not the evaluated result of (values 1 2 3) but a list which the evaluated result is converted into. |QUOTE: Moreover, the pair of VALUES and CALL-WITH-VALUES is clumsy to use |Is this a fact or an opinion? A SRFI would be more appealing to implementors |if its rationale is based on facts. If it is an inconvenient way that "decomposition of multiple values is done by simple application", it will be not a fact. |QUOTE: and somewhat slow under some circumstances. |How slow is "somewhat slow"? How do you quantify it? And what are the |circumstances that make VALUES and CALL-WITH-VALUES somewhat slow? Or |do you really mean under some *implementations*? Was the topic of |Efficient Implementation of Multiple Return Values in Scheme ever |discussed in the literature? Even in Chez Petite Scheme and Scheme48 that have VALUES/CALL-WITH-VLUES implemented with "An Efficient Implementation of Multiple Return Values in Scheme (http://citeseer.ist.psu.edu/27481.html)", VALUES/CALL-WITH-VALUES is somewhat slow under some circumstances. The following are the results of simple tests "on REPL".(Intel 586, Debian or Windows) (define-syntax mu (syntax-rules () ((mu argument ...) (lambda (f) (f argument ...))))) (define m (mu 1 2 3)) (define v (lambda () (values 1 2 3))) (define mm (lambda (x) (if (< x 0) (mu 1 2 3) (if (= x 0) (mu 4 5 6) (mu 7 8 9))))) (define vv (lambda (x) (if (< x 0) (values 1 2 3) (if (= x 0) (values 4 5 6) (values 7 8 9))))) (time (for-each (lambda (x) (m list)) (make-list 100000 1))) (time (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1))) (time (for-each (lambda (x) ((mm x) list)) (make-list 100000 1))) (time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1))) 1. Mzscheme Welcome to MzScheme version 301, Copyright (c) 2004-2005 PLT Scheme Inc. > (time (for-each (lambda (x) (m list)) (make-list 100000 1))) cpu time: 230 real time: 230 gc time: 70 > (time (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1))) cpu time: 270 real time: 281 gc time: 70 > (time (for-each (lambda (x) ((mm x) list)) (make-list 100000 1))) cpu time: 280 real time: 280 gc time: 70 > (time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1))) cpu time: 310 real time: 311 gc time: 80 2. Chicken Version 1, Build 66 - linux-unix-gnu-x86 (c)2000-2004 Felix L. Winkelmann Using hygienic macros ; loading /usr/local/share/chicken/chicken-highlevel-macros.scm ... #;14> (time (for-each (lambda (x) (m list)) (make-list 100000 1))) 0.23 seconds elapsed 0.03 seconds in (major) GC 0 mutations 974 minor GCs 1 major GCs #;15> (time (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1))) 0.31 seconds elapsed 0.03 seconds in (major) GC 0 mutations 1340 minor GCs 1 major GCs #;25> (time (for-each (lambda (x) ((mm x) list)) (make-list 100000 1))) 0.44 seconds elapsed 0.02 seconds in (major) GC 0 mutations 2295 minor GCs 1 major GCs #;26> (time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1))) 0.55 seconds elapsed 0.02 seconds in (major) GC 0 mutations 2661 minor GCs 1 major GCs 3. MIT Scheme Scheme Microcode Version 14.8 MIT Scheme running under GNU/Linux Type `^C' (control-C) followed by `H' to obtain information about interrupts. Scheme saved on Friday March 15, 2002 at 12:00:53 AM Release 7.7.0 Microcode 14.8 Runtime 15.0 SF 4.40 Liar (Intel i386) 4.115 Edwin 3.112 1 ]=> (with-timings (lambda () (for-each (lambda (x) (m list)) (make-list 100000 1))) (lambda (run-time gc-time real-time) (write (internal-time/ticks->seconds run-time)) (write-char #\space) (write (internal-time/ticks->seconds gc-time)) (write-char #\space) (write (internal-time/ticks->seconds real-time)) (newline))) .27 .2 .47 ;Unspecified return value 1 ]=> (with-timings (lambda () (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1))) (lambda (run-time gc-time real-time) (write (internal-time/ticks->seconds run-time)) (write-char #\space) (write (internal-time/ticks->seconds gc-time)) (write-char #\space) (write (internal-time/ticks->seconds real-time)) (newline))) .56 .3 .873 ;Unspecified return value 1 ]=> (with-timings (lambda () (for-each (lambda (x) ((mm x) list)) (make-list 100000 1))) (lambda (run-time gc-time real-time) (write (internal-time/ticks->seconds run-time)) (write-char #\space) (write (internal-time/ticks->seconds gc-time)) (write-char #\space) (write (internal-time/ticks->seconds real-time)) (newline))) .66 .3 .971 ;Unspecified return value 1 ]=> (with-timings (lambda () (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1))) (lambda (run-time gc-time real-time) (write (internal-time/ticks->seconds run-time)) (write-char #\space) (write (internal-time/ticks->seconds gc-time)) (write-char #\space) (write (internal-time/ticks->seconds real-time)) (newline))) .98 .3 1.294 ;Unspecified return value 4. Scheme48 Welcome to Scheme 48 1.3 (made by soo on Mon Jul 11 09:51:36 2005) Copyright (c) 1993-2005 by Richard Kelsey and Jonathan Rees. Please report bugs to scheme-48xxxxxx@s48.org. Get more information at http://www.s48.org/. Type ,? (comma question-mark) for help. > ,time (for-each (lambda (x) (m list)) (make-list 100000 1)) Run time: 0.46 seconds; Elapsed time: 0.47 seconds #{Unspecific} > ,time (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1)) Run time: 0.56 seconds; Elapsed time: 0.56 seconds #{Unspecific} > ,time (for-each (lambda (x) ((mm x) list)) (make-list 100000 1)) Run time: 0.62 seconds; Elapsed time: 0.65 seconds #{Unspecific} > ,time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1)) Run time: 0.73 seconds; Elapsed time: 0.76 seconds #{Unspecific} 5. Petite Chez Scheme Petite Chez Scheme Version 7.0 Copyright (c) 1985-2005 Cadence Research Systems Linked with Pthreads-Win32 under GNU LGPL http://sources.redhat.com/pthreads-win32/ Copyright (c) 1998 John E. Bossom Copyright (c) 1999,2002 Pthreads-win32 contributors > (time (for-each (lambda (x) (m list)) (make-list 100000 1))) (time (for-each (lambda (...) ...) ...)) 3 collections 90 ms elapsed cpu time, including 20 ms collecting 90 ms elapsed real time, including 20 ms collecting 3200680 bytes allocated, including 5678856 bytes reclaimed > (time (for-each (lambda (x) (call-with-values v list)) (make-list 100000 1))) (time (for-each (lambda (...) ...) ...)) 3 collections 100 ms elapsed cpu time, including 20 ms collecting 100 ms elapsed real time, including 20 ms collecting 3200680 bytes allocated, including 3271304 bytes reclaimed > (time (for-each (lambda (x) ((mm x) list)) (make-list 100000 1))) (time (for-each (lambda (...) ...) ...)) 4 collections 190 ms elapsed cpu time, including 40 ms collecting 190 ms elapsed real time, including 40 ms collecting 4000904 bytes allocated, including 3537112 bytes reclaimed > (time (for-each (lambda (x) (call-with-values (lambda () (vv x)) list)) (make-list 100000 1))) (time (for-each (lambda (...) ...) ...)) 4 collections 201 ms elapsed cpu time, including 50 ms collecting 210 ms elapsed real time, including 70 ms collecting 4800904 bytes allocated, including 5963232 bytes reclaimed |QUOTE: A solution would be to enclose the arguments of VALUES expression |QUOTE: in a procedure of one argument, a consumer procedure of QUOTE: |CALL-WITH-VALUS. How does this SRFI address the efficiency problem? Looking |at the implementation section, I see many calls to |call-with-current-continuation. Is that not somewhat slow under some |circumstances? Looking further down, there are many recursive procedures and |many assignments that are performed at runtime. Maybe your intension is to |have a reference implementation outlining the concept and implementors are |encouraged to provide their own implementations. If that's the case, it may |be a good idea to state it in the implementation section. How many calls to call-with-current-continuation are there? CALL-WITH-CURRENT-CONTINUATION is used only once in implementation of ALET[*] for escaspe function, so if you don't use the function, there will be no problem. Recursive procedures are the same. They are used only for recursive function like named-let[*]. There is only one additional assignment, in single value binding of ALET implementation. It is for sequential binding from left to right. Thanks for comments. -- Joo ChurlSoo