This page is part of the web mail archives of SRFI 86 from before July 7th, 2015. The new archives for SRFI 86 contain all messages, not just those from before July 7th, 2015.
*Abdulaziz Ghuloum <aghuloum@xxxxxxxxxxxxxx> |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-48-bugs@xxxxxxxx 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