Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Weird ML program...

1 view
Skip to first unread message

Nick Harvey

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

I have a question related to the question I asked in class about a
"self-rewriting fib()". Consider the following program:

val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );

This should define a function, curry, which takes an integer parameter x, and
returns x+2. However, as a side effect, it also redefines itself.

> val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );
std_in:2.29-2.33 Error: unbound variable or constructor: curry

It doesn't quite work though -- curry has not yet been defined, so it
can't be used in its own definition... We kludge around that problem by
first defining curry to be an simple function.

> val curry = ref ( fn x => x+1 );
val curry = fn : int -> int
> val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );
val curry = fn : int -> int

Okay, so now everything is happy. So, we test it out:

> !curry 100;
val it = 102: int

Great! Just what we expected... But now the devious curry has redefined
itself to be the function (fn y=>y+3). What happens if we try evaluating
curry again?

> !curry 200;
val it = 202: int


So, the question is, why wasn't curry able to redefine itself?


Does anyone know?

Thanks,
- Nick

--
--
Nick Harvey
PGP signed and encrypted email preferred
finger njah...@undergrad.math.uwaterloo.ca for PGP key

Gordon V. Cormack

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

In article <EntMr...@undergrad.math.uwaterloo.ca>,

Nick Harvey <njah...@undergrad.math.uwaterloo.ca> wrote:
>I have a question related to the question I asked in class about a
>"self-rewriting fib()". Consider the following program:
>
>val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );
>
>This should define a function, curry, which takes an integer parameter x, and
>returns x+2. However, as a side effect, it also redefines itself.
>
>> val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );
>std_in:2.29-2.33 Error: unbound variable or constructor: curry

val doesn't allow recursive definitions. you should be able to use
"val rec" but i just tried and ML allows "val rec" only for fn definitions..


>
>> val curry = ref ( fn x => x+1 );
>val curry = fn : int -> int
>> val curry = ref ( fn x => ( curry := (fn y=>y+3); x+2) );
>val curry = fn : int -> int
>
>Okay, so now everything is happy. So, we test it out:
>
>> !curry 100;
>val it = 102: int
>
>Great! Just what we expected... But now the devious curry has redefined
>itself to be the function (fn y=>y+3). What happens if we try evaluating
>curry again?
>
>> !curry 200;
>val it = 202: int
>
>
>So, the question is, why wasn't curry able to redefine itself?

The second definition of "curry" creates a new binding for the same
name; the old value still exists, but is simply hidden. The expression
on the RHS of the definition references the old curry.

You can achieve the effect you want by:

- val curry = ref ( fn x => x+1 );
val curry = ref fn : (int -> int) ref
- curry := ( fn x => ( curry := (fn y=>y+3); x+2) );
val it = () : unit
- !curry 100;


val it = 102 : int

- !curry 200;
val it = 203 : int


--
Gordon V. Cormack CS Dept, University of Waterloo, Canada N2L 3G1
gvco...@uwaterloo.ca http://cormack.uwaterloo.ca/cormack

0 new messages