- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]

From: Harvey J. Stein <abel_at_netvision.net.il>

Date: Thu, 7 Nov 1996 12:46:38 +0200

David Fox writes:

* > Using snow 3.1 on my Linux box the following function produces
*

* > different results each time I run it on (split1 (string->list
*

* > "ab/cd"))
*

* >
*

* > (define (split1 lst)
*

* > (cond ((null? lst) '(()))
*

* > ((eq? (car lst) #\/) (cons () (split1 (cdr lst))))
*

* > (else
*

* > (let ((sf (split1 (cdr lst))))
*

* > (set-car! sf (cons (car lst) (car sf)))
*

* > sf))))
*

* >
*

* > If I replace "'(())" with "(list (list))" it works correctly.
*

It's not a bug, really.

The problem is that you've written some self-modifying code. The

culprit is the set-car! When (split1 ()) returns, it returns '(())).

Then the caller, which would be (split1 '(#\d)) lets sf be this

result, and then does (set-car! sf (cons (car '(#\d))) (car sf)),

since sf is '(()), this modifies '(()). Since '(()) is just sitting in

memory, the next time you run split1, the (split1 '()) call returns a

different result.

Using (list (list)) fixes it, because it creates a new copy of '(())

each time it runs.

Technically, '(()) should be in read-only memory, and the above

set-car! should throw an error, but all scheme implementations I've

tested don't do this.

Here's a simple example of similar self modifying code to illustrate

the point.

(define (save-add)

(let ((x '(a . 1)))

(set-cdr! x (1+ (cdr x)))

x))

STk> (save-add)

(a . 2)

STk> (save-add)

(a . 3)

You'd think that each time save-add is called, it sets x to

'(a . 1), increments (cdr x), and returns x, so it should always

return '(a . 2). However, since '(a . 1) isn't recreated each time

save-add is executed, the 2nd time around, '(a . 1) has become '(a

. 2), so the function returns '(a . 3).

Not to belabor the point, but since I find my own above description

unclear, maybe it'd be helpful to describe it differently:

The above let gets converted to a lambda expression, so that the above

definition is equivalent to:

(define (save-add)

((lambda (x) (set-cdr! x (1+ (cdr x))) x)

'(a . 1)))

Now since '(a . 1) is a quoted list, it's just created when save-add

is defined, and each time save-add is executed, we're modifying the

cdr of '(a . 1). Thus, the 2nd call to save-add returns '(a . 3)

instead of '(a . 2).

Of course, if one wrote (cons 'a 1) instead, then you'd be applying

the above lambda to a new cons cell each time save-add is executed,

in which case (save-add) would always return '(a . 2).

Date: Thu, 7 Nov 1996 12:46:38 +0200

David Fox writes:

It's not a bug, really.

The problem is that you've written some self-modifying code. The

culprit is the set-car! When (split1 ()) returns, it returns '(())).

Then the caller, which would be (split1 '(#\d)) lets sf be this

result, and then does (set-car! sf (cons (car '(#\d))) (car sf)),

since sf is '(()), this modifies '(()). Since '(()) is just sitting in

memory, the next time you run split1, the (split1 '()) call returns a

different result.

Using (list (list)) fixes it, because it creates a new copy of '(())

each time it runs.

Technically, '(()) should be in read-only memory, and the above

set-car! should throw an error, but all scheme implementations I've

tested don't do this.

Here's a simple example of similar self modifying code to illustrate

the point.

(define (save-add)

(let ((x '(a . 1)))

(set-cdr! x (1+ (cdr x)))

x))

STk> (save-add)

(a . 2)

STk> (save-add)

(a . 3)

You'd think that each time save-add is called, it sets x to

'(a . 1), increments (cdr x), and returns x, so it should always

return '(a . 2). However, since '(a . 1) isn't recreated each time

save-add is executed, the 2nd time around, '(a . 1) has become '(a

. 2), so the function returns '(a . 3).

Not to belabor the point, but since I find my own above description

unclear, maybe it'd be helpful to describe it differently:

The above let gets converted to a lambda expression, so that the above

definition is equivalent to:

(define (save-add)

((lambda (x) (set-cdr! x (1+ (cdr x))) x)

'(a . 1)))

Now since '(a . 1) is a quoted list, it's just created when save-add

is defined, and each time save-add is executed, we're modifying the

cdr of '(a . 1). Thus, the 2nd call to save-add returns '(a . 3)

instead of '(a . 2).

Of course, if one wrote (cons 'a 1) instead, then you'd be applying

the above lambda to a new cons cell each time save-add is executed,

in which case (save-add) would always return '(a . 2).

-- Dr. Harvey J. Stein Berger Financial Research abel_at_netvision.net.ilReceived on Thu Nov 07 1996 - 11:48:50 CET

*
This archive was generated by hypermail 2.3.0
: Mon Jul 21 2014 - 19:38:59 CEST
*