<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body bgcolor="#ffffff" text="#000000">
<div class="moz-text-html" lang="x-western">
I'm a student using scheme for a class (at Northern Arizona
University), and I've run into a roadblock with an assignment. The idea
is to create a form of objects with simple functions, by creating a
local environment with "let" with all the instance variables and
declaring the object (a lambda function) within that environment. The
main trick is that, of course, I have to be able to read in arbitrary
class definitions, as definedI thought I had a very elegant and simple
solution, which declared the functions within a let at construction and
then called whichever function was passed. So, if you call (point1
'setx 3), all point1 just calls (setx 3) in its local environment
(well, it's slightly more complicated to allow for overloading with
different numbers of arguments) - a simple eval call on the list of
arguments.
<br>
<br>
This is where I ran into my problem - eval evaluates in the global
environment. I can't declare the functions in the global environment,
because I need to be able to create new instances of each "object"
dynamically, and the functions can't refer to global variables.
<br>
<br>
Is there any way to achieve the same effect (passed a symbol, look up
the symbol and return the function it is attached to) but referring to
the environment created by a let function?
<br>
<br>
As an example, this is what is constructed by the "new" function I
originally created, if I use the definition for a "point" object
provided by the professor:
<br>
<br>
(let ((x '2) (y '3))
<br>
&nbsp;(let ((xval x) (yval y))
<br>
&nbsp;&nbsp; (let ((getx-0 (lambda () xval))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (gety-0 (lambda () yval))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (display-0
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (lambda () (begin (display "Coords: x=") (display xval)
(display ", y=") (display yval) (newline))))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setx-1 (lambda (newx) (set! xval newx)))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (polar-0
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (lambda ()
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (let ((radius (sqrt (+ (* xval xval) (* yval yval))))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (angle (/ (truncate (* (atan (/ yval xval)) (/ 36000
(* 2 3.1415)))) 100)))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (list radius angle))))
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (dist-1
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (lambda (p2)
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (let ((x2 (p2 'getx)) (y2 (p2 'gety))) (sqrt (+ (expt (-
x2 xval) 2) (expt (- y2 yval) 2)))))))
<br>
&nbsp;&nbsp;&nbsp;&nbsp; (lambda msg (eval (cons (methods-append (car msg) (cdr msg) 0)
(cdr msg)))))))
<br>
<br>
Methods-append takes the method name and list of arguments, and appends
the number of arguments to the method name. Of course, the above
returns a function and if I were to bind that to point1 and call
(point1 'getx), all I get is an undefined identifier error for getx,
since it is not defined globally.
<br>
<br>
<br>
I've also constructed an alternative solution, which was much more
convoluted, which uses a long cond statement, with a check for each
(appended) method name. However, after remaking the new function, I
haven't gotten it working yet, but I realized I have no idea how to
implement self-referential methods - that is, methods in the object
being able to call (<b class="moz-txt-star"><span class="moz-txt-tag">*</span>this<span
 class="moz-txt-tag">*</span></b> methodname args). This would work
naturally in my first solution, since the methods are defined, but with
the second, the cond statement, the "object" would have to call itself.
Normally, when I have a function call itself, it's because I'm
assigning it a label then referring to that label. Since I have to have
"new" only return a function, per the professor's specification, I
can't know the label.
<br>
If there's no solution to my eval problem, is there a way to have a
function call itself without any label?
<br>
<br>
Sorry for the long explanation for what boils down to a simple
question, and thanks in advance for any help.
<br>
<br>
- David Johnson<br>
</div>
</body>
</html>