translation challenge from PythonTranslator...
Evil grin. OK, what about the following Scheme code.
Scheme
;;; Pointers in Scheme
;;; Adding pointer arithmetic is left as an exercise to the reader
(define (make-pointer getter setter)
(cons getter setter))
(define (pointer-ref ptr)
((car ptr)))
(define (pointer-set! ptr value)
((cdr ptr) value))
(define-syntax address
(syntax-rules ()
((address var)
(make-pointer
(lambda () var)
(lambda (value) (set! var value))))))
;;; A few examples
(define x 1)
(define px (address x))
(display (pointer-ref px))(newline)
(pointer-set! px 2)
(display (pointer-ref px))(newline)
Python
# Take a first cut.
class Pointer:
def __init__(self, var):
self.var = var
def set(self, val):
self.var = val
def get(self):
return self.var
x = 1
px = Pointer(x)
print px.get()
px.set(2)
print px.get()
# So far so good. But then this breaks...
y = 10
py = Pointer(y)
py.set(20)
print y
# When we print y, it's still 10. The problem is,
# primitive types pass by value in Python.
# So let's try making an Integer object.
class Integer:
def __init__(self, val):
self.val = val
def set(self, val):
self.val = val
def get(self):
return self.val
# And we can add a level of indirection.
class Ptr:
def __init__(self, var):
self.var = var
def set(self, val):
self.var.set(val)
def get(self):
return self.var.get()
print 'Test #2'
y = Integer(10)
print y.get()
py = Ptr(y)
py.set(20)
print y.get()
# And that seems to work.
-- SteveHowell
So pointer allows you to call get/set on anything that already has a get/set method? So what's the point? :-)
Yep, it's kind of pointless to implement a pointer scheme in a language like Python, which solves problems just fine without them. That's what made this particular challenge so sinister. Insidious, even. -- SteveHowell
Nevertheless, it is an interesting problem. I explore a RubyLanguage version on the SinisterSchemeSampleInRuby page. -- JimWeirich
For the interested, here is some background information on the original Scheme code. The method outlined here to simulate pointers in Scheme was used in an early C-to-Lisp compiler for the MIT Lisp machine. (The C compiler on the later commercial Lisp machine didn't use this trick; it generated machine-code for the Lisp machine directly, just like a conventional C compiler.) One can have more operations that just set and get; in particular, one can implement pointer arithmetic. For this, the limitation in the ANSI C standard that pointer arithmetic only works on pointers that point into the same array is essential.
The piece of memory that contains the value of a variable is called a location in Scheme. In effect, the above Scheme code makes locations available as first-class values. We call this process reification. Thus, the Scheme code implements reifiable locations, or locatives for short. Note that these locatives have unlimited extent, unlike C pointers, which have dynamic extent.
There was a Scheme dialect called T that made heavy use of locatives.
So now you know why C "pointers" should really by called "first-class reified locations with dynamic extent." ;-)
I think I might know how to do arithmetic.
(def *heap* nil)
(define (malloc ()
(def lexvar nil)
(let (a (address lexvar)
(set! *heap* (cons a *heap*))
a)))
Then do heap manipulations. Can someone help with this?
...Oh, wait. I see...
(define (malloc (size)
(if (= size 0)
nil
(cons nil (malloc (- size 1))))))
(define (ptr+ (aConsCell num)
(if (= num 0)
aConsCell
(ptr+ (cdr aConsCell) (- num 1)))))