This page is part of the web mail archives of SRFI 10 from before July 7th, 2015. The new archives for SRFI 10 contain all messages, not just those from before July 7th, 2015.
> Using `#,' in a program has two effects: it causes side effects to > occur at read time and it ensures that a form is evaluated only once. > The first has questionable utility and semantics. The second is > already available in R5RS as `delay' and `force'. I have come across a counter-example to the last statement. do ((i 0 (+ 1 i))) ((>= i 5)) (let ((b (list (force (delay (begin (display "in form\n") 1 )))))) (display b) (newline))) ===> in form (1) in form (1) in form (1) in form (1) in form (1) (include "myenv.scm") (include "read-apply.scm") (define-reader-ctor 'form (lambda () (display "in form\n") 1)) (do ((i 0 (+ 1 i))) ((>= i 5)) (let ((b (list #,(form)))) (display b) (newline))) ===> in form (1) (1) (1) (1) (1) This shows that #,(ctor) has quite a different semantics than (force (delay (ctor)). The latter can be evaluated several times if occurs within a special form. The #,(ctor) expression is _really_ evaluated only once - when it is read. This counter-example appears to invalidate the counter-proposal and its discussion. It is instructive however to look into differences between #,(ctor) and (force (delay (ctor)) further. The former evaluates at read-time. By the time compiler/interpreter comes across #,(ctor), the latter will be substituted by a _constant_ expression. A special form will never see #,(ctor) as it is -- it will see a constant. In contrast, (force (delay (form)) within a special form will appear as an expression, which cannot be tested at macro-expansion time, is not eligible for const-folding, etc. Sergei Egorov was right that "It's a pity that this [counter-proposal] form won't work inside quoted constants, though." I should add that the counter-proposal "will not work" within any syntax form (quote being one of them). > I could get the same effect in vanilla R5RS, with much more power > and flexibility, by using EVAL and an extensible reader: > (define my-reader (make-reader ...)) > (eval (my-reader filename) some-environment) I would like to dispute this statement as well. The first problem is which 'some-environment' do you pass to eval? If it is an (scheme-report-environment 5), a form read from the 'filename' may not refer to procedures other than those in R5RS. Even if the parent program defines a custom constructor for uniform vectors (per SRFI-4), the 'filename' may not refer to it as it is not a part of R5RS. If the 'some-environment' stands for an interaction-environment the parent then program tacitly permits the 'filename' to apply any function defined in the parent program -- even such dangerous functions as OS:system or OS:unlink if the current interaction-environment happens to define them. You really don't want to do that. In any case this is an "all-or-nothing" proposition. SRFI-10 devotes a special paragraph to these issues (see a "Comparisons" subsection). Note R5RS does not define any function to manipulate 'eval-environment's. Another problem with the eval-solution above is that it contains "eval". SRFI-10 does not require a Scheme reader to perform an evaluation of arbitrary expressions. SRFI-10 merely specifies that the reader should be able to locate a constructor-procedure and apply it to arguments. BTW, nowhere does SRFI-10 tell that the constructor is a Scheme function; it can be written in any language as long as the reader is able to invoke it passing appropriate parameters. For example, one can write a Scheme->foo _compiler_ in ML and implement reader-constructors as ML functions. The biggest problem with the above eval-solution is that it assumes that the form read from a file is an expression to be evaluated. Suppose the file contains a string "(1 2 #,(f32 1.0 2.0))" How can you pass the result of reading of this string to eval? All the counter-example discussion tacitly assumes that the form being read is a code form. But one can use a 'read' procedure to read arbitrary data. For example, one can use read to load "persistent" data; or to read information sent over communication channels. It has to be stressed that not every Scheme object has a readable representation (structures and records spring to mind). Furthermore, not every R5RS object can be written (and then reloaded): for example, cyclical lists and other data structures with circular dependencies, data structures with large caches or memoization tables, etc. SRFI-10 proposes a way to define a custom loader -- the only extension to the Scheme reader that will be necessary to solve an immense number of problems.