[comp.lang.scheme] Re : set in Scheme

pierce@CS.UCLA.EDU (05/07/88)

In reply to David Chin about "set in Scheme".  I'd have to agree with
Pavel that it's better to recode without passing around different symbols.  
However, there's a lot of code out there, UCILISP for natural language
processing for example, which uses "set" all over the place.  If you just
want to get some simple examples from a text or article running, you
may not consider it worth your time to recode everything; fortunately the
problems described by Pavel may not be that critical either for this type of
code.  If so, why not just forget about elegance for a little while and save
yourself some trouble. Just hack out a horrible little ugly macro like the
following:

(macro set
   (lambda (e) `(eval ,`(set! ,(eval (cadr e)) ,(caddr e)))))

But I don't think I'd be "sticking my neck out" by saying that THIS doesn't
adhere to the "Scheme philosophy", so I would use it only in emergencies.

-- Brad Pierce

<pierce@cs.ucla.edu>

pierce@CS.UCLA.EDU (05/08/88)

Sorry about the last message, I wrote the set macro down a little too
fast and it clearly won't work as intended.  I meant to say something
like this:

(macro set
   (lambda (e)
      (list 'eval
            (list 'list
                  ''set!
                  (list 'eval (list 'quote (cadr e)))
                  (list 'quote (caddr e))))))

Then if you

(define a 's)
(define s 'any)
(define b 'r)

the effect of (set a b) should be to assign the value r to s. 

So far so good.  But what about this function?

(define foo
   (lambda (x y)
      (set x y)))

If we (define s 'any) then the effect of (foo a b) is the same as above.

Judging by my last posting, this may not be perfect either, but at least it's 
a lot closer.  I'd be interested in seeing a shorter or better solution.  

Thanks for your patience.

-- Brad Pierce

<pierce@cs.ucla.edu>

crabb@phoenix.Princeton.EDU (David W Crabb) (05/10/88)

Dybvig's extend-syntax is a natural for your problem:

     (extend-syntax (set)
        ( (set  x y)
          (set! x y) ))

   -- David

manis@faculty.cs.ubc.ca (Vincent Manis) (05/10/88)

Well, putting my radical hat on, not only is set evil, but also set!. Only 
non-destructive programming practices are safe, and everything else inevitably
leads to disaster.

But back here in the real world, one occasionally wants global variables.
Those you can have via set! and define. I guess the frequency with which 
I use set in Lisp can be best judged by the fact that I hadn't realised 
it was absent in Scheme until reading the original posting on this subject.

There are good reasons for omitting it. First of all, set makes programs
opaque in that one has no idea which variable is getting modified. More to
the point, Scheme dispenses with value cells, so implementing set would be
non-trivial in most Schemes (though Chez Scheme's "boxes" might make it 
easier).

My eyes glaze over when I see two levels of backquote in a macro definition, 
so I don't know how effective the posted  solution is. However, my choice is
the humble property list. Still not terribly structured, but efficiently 
implemented and a bit more modular (different bits of code can use plists
without interfering, so long as they use different pnames). 

Of course, the *right* way to do this is probably a hash table or tree...



Vincent Manis                    | manis@cs.ubc.ca
The Invisible City of Kitezh     | manis@cs.ubc.cdn
Department of Computer Science   | manis@ubc.csnet
University of British Columbia   | {ihnp4!alberta,uw-beaver,uunet}!
<<NOTE NEW ADDRESS>>             |      ubc-cs!manis

dorai@titan.rice.edu (Dorai Sitaram) (05/10/88)

Here's my invaluable ;-) comment about _set_ in Scheme. As it is fairly easy
to build up a case for loss of program readability with the addition of _set_
(as opposed to _set!_), we should perhaps be pleased that it is probably 
impossible (with macros, extend-syntax, what-not) to define _set_ in Scheme.

The most "correct" version of _set_ in terms of _set!_ given on the net,
(herein transliterated to extend-syntax) is probably

(extend-syntax (set)
  [(set x y) (eval (list 'set! x (quote y)))]).

However, Scheme does not offer 'eval' to the user. The most it does is offer
a *global* eval, which ain't the same thing. So,

(define x 0)
==> x
(define y 'x)
==> y
(let ([x 1])
  (let ([y 'x])
    (set y 2)
    x))
==> 1 {instead of 2}
x
==> 2 {instead of 0}

Continuing { with global x = 2, y = x }

(define z 3)
==> z
(let ([z 4])
  (set y z)
  x)
==> 3 {instead of 4}

The second problem can be appeased by evaluating the settend (to coin a 
word) beforehand as in,

(extend-syntax (set)
  [(set x y) (begin (set! |weird-identifier| y)
		    (eval (list 'set! x (quote |weird-identifier|))))])

{|weird-identifier| HAS to be a global variable, because of the globalness
of eval.}

But the first problem remains. A modified version of the second problem can
occur if there are _set_'s inside the settee (to coin a not-so-new word), as 
in

(set (set <blah> <foo>) <hukares>)

Any amount of tweaking the extend-syntax for set, seems destined to lead
nowhere. That, as they (and Magnum) say, is "the hell of it".

--dorai