[gambit-list] Reading binary files

Bob McIsaac bobmc at fcibroadband.com
Thu Dec 20 22:11:16 EST 2007


Christian Jaeger wrote:
> Bob McIsaac wrote:
>> The puzzling comment to my humble form said : "This code assumes that
>> arguments to functions are evaluated left-to-right."  But what of it?
>> There is a stream of text to be evaluated.  Choices are 1. left-right
>> evaluation in one pass; 2. parsing the stream into tokens and sorting
>> the tokens into a tree according to the rules of the grammar ... not
>> Lispy.  Choice 1 means typing parentheses so that the evaluator can be
>> simple and recursive.  ( I assume that evaluation results in a linked
>> list)
>
> Hm, we're not talking about nested expressions here. We're talking
> about multiple expressions given to one function. And at that point,
> regardless of whether your internal representation is lists or
> something else, the evaluator could be programmed to evaluate function
> arguments in different orders.
>
> The problematic code is:
>
> >  (bitwise-ior
> >    (bitwise-and (arithmetic-shift (read-u8 INP) 24) #xff000000)
> >    (bitwise-and (arithmetic-shift (read-u8 INP) 16) #xff0000)
> >    (bitwise-and (arithmetic-shift (read-u8 INP) 8) #xff00)
> >    (bitwise-and (read-u8 INP) #xff)))
>
> It contains four (read-u8 INP) forms; the order in which they are
> evaluated matters (because reading from a port advances the position
> in the underlying stream as a side effect).
>
> The problem is that those forms are indirectly positioned as arguments
> to bitwise-ior. bitwise-ior is a function. Scheme dictates that the
> arguments to functions are evaluated before the function is called
> (meaning before the body of the function definition is evaluated). So
> you're guaranteed that all four (read-u8 INP) forms have been
> evaluated before the bitwise-ior call. *But* Scheme does not specify
> in which order the four arguments of bitwise-ior are evaluated. So
> it's very well possible that some Scheme implementation first
> evaluates (bitwise-and (read-u8 INP) #xff)), then (bitwise-and
> (arithmetic-shift (read-u8 INP) 8) #xff00), then (bitwise-and
> (arithmetic-shift (read-u8 INP) 16) #xff0000), and at last
> (bitwise-and (arithmetic-shift (read-u8 INP) 24) #xff000000). Or the
> other way round. Or even in some other order or even in parallel. So
> the bytes coming from INP will end up at unspecified and possibly
> random places.
>
> OTOH, special forms like let and let* do specify the order of
> evaluation (they are not functions). So writing
>
>   (let* ((a (bitwise-and (arithmetic-shift (read-u8 INP) 24) #xff000000))
>      (b (bitwise-and (arithmetic-shift (read-u8 INP) 16) #xff0000))
>      (c (bitwise-and (arithmetic-shift (read-u8 INP) 8) #xff00))
>      (d (bitwise-and (read-u8 INP) #xff)))
>     (bitwise-ior a b c d))
>
> makes the order of evaluation explicit (first a, then b, then c, then
> d) and thus portable (and deterministic).
>
> Christian.
>
>
>
Thank you for taking time to explain.

-Bob-





More information about the Gambit-list mailing list