Mutable FOOP

Pondering the philosophy behind the language
Locked
m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Mutable FOOP

Post by m i c h a e l »

Dear Club,

My continuing adventures in FOOP have led me to a new discovery: mutable FOOP objects.

By adding a self-reference to its second element, a mutable object can preserve its state without manually resetting the reference each time the object is updated. (Actually, manual resetting still occurs, but it's hidden within the object's methods.)

Preliminary disclaimer: Please remember this code is still experimental and unproven. Proceed with care. You can view (and the brave can download) the code here.

First, let me introduce a class method and three object methods that can be included in your "init.lsp" file in case you do a lot of FOOP programming (or you could put it in a file called "foop.lsp" that you load before doing serious FOOP):

Code: Select all

;; [class method] generic class predicate
(define (Class:? it) (= (and it (list? it) (it 0)) (context)))

;; making objects displayable
(define (Class:string  it) (MAIN:string it))
(define (Class:print   it) (MAIN:print (:string it)))
(define (Class:println it) (:print it) (MAIN:print "\n"))
The class method :? is not essential for this demonstration, but it is included for completeness.

I've had these methods defined in my "init.lsp" for a long time now without any problems, but everyone's setup is different, so beware!

Next is the code for doing mutable objects:

Code: Select all

(new Class 'Mutable)

;; note: mutable objects require accessors to update their state
;; an inherited helper method called :access simplifies accessor writing

;; the constructor creates the object's reference
(define (Mutable:Mutable id) 
	(set id (cons (context) (cons id (args))))
)

;; an accessor for the object's id (currently read-only)
(define (Mutable:id it) (it 1))

;; a helper method for writing accessors
(define (Mutable:access it idx value allow-nil?)
	(setq this (eval (:id it)))
	(if (or value allow-nil?)
		(begin
			(setf (this idx) value)
			(set (:id it) this)
		)
		(this idx)
	)
)
Next, an example Mutable class:

Code: Select all

(new Mutable 'Point)

;; keeping a reference to the inherited constructor so we can overwrite it
(setq Point:^Point Point:Point)

;; overwriting the constructor
(define (Point:Point id (x 0) (y 0))
	(Point:^Point id x y)
)

;; Point's x and y accessors using inherited :access method
(define (Point:x it value) (:access it 2 value))
(define (Point:y it value) (:access it 3 value))

;; Point's string representation
(define (Point:string it) (replace "MAIN:" (string it) ""))

;; moving a Point to a specific place (x y)
(define (Point:move it x y) (:x it x) (:y it y))

;; sliding a Point by some amount (x y)
(define (Point:slide it x y)
	(:move it (MAIN:+ (:x it) x) (MAIN:+ (:y it) y))
)

;; adding two Points together
(define (Point:+ it other)
	(:slide it (:x other) (:y other))
)
Finally, the code to produce a sample run:

Code: Select all

;; a helper function that displays an expression and its result
;; as if it had been entered on the command-line
 (define (run e)
	(print "> " (string e) "\n")
	(:println (eval e))
)

(println "Sample Run using Mutable Points")
(run '(Point 'p1 10 20))
(run 'p1)
(run '(:slide p1 5 8))
(run 'p1)
(run '(Point 'p2 88 99))
(run '(:+ p1 p2))
(run 'p1)
(run 'p2)
(println "> _")
Which produces the following output:

Code: Select all

Sample Run using Mutable Points
> (Point 'p1 10 20)
(Point p1 10 20)
> p1
(Point p1 10 20)
> (: slide p1 5 8)
(Point p1 15 28)
> p1
(Point p1 15 28)
> (Point 'p2 88 99)
(Point p2 88 99)
> (: + p1 p2)
(Point p1 103 127)
> p1
(Point p1 103 127)
> p2
(Point p2 88 99)
> _
Before settling on symbols in the MAIN context for the references, I used a Tree named obj with string references. While this solution was adequate, it lacked the natural feel the symbols provide.

That's it! Mutable objects. Looking forward to hearing how they work for you!

m i c h a e l
Last edited by m i c h a e l on Wed Jun 10, 2009 6:56 pm, edited 2 times in total.

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

you know micheal, first of all I always write your name wrong dont know why that is.. and secondly every time you post these wonderful solutions I always
need to read it 2 or 3 times befor i get it.. Also this one.. I need to realy think
befor I get it .. thats actualy a compliment on how you bind your code !

Give me 3 more readings ill be back with a reply ;-)
-- (define? (Cornflakes))

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

newdep wrote:you know micheal, first of all I always write your name wrong dont know why that is.
Norman, that's meta! But maybe I'm only saying that because I've got metaness on the brain ;-)
newdep wrote:and secondly every time you post these wonderful solutions I always need to read it 2 or 3 times befor i get it.
Elegant solutions always come from a chaos of construction.
newdep wrote:Also this one.. I need to realy think befor I get it ..
The circularity of it is probably confusing. The reference part, I mean. We have a symbol in an object that is referencing that object, and all of the methods use that symbol to update that object.
newdep wrote:thats actualy a compliment on how you bind your code !
Thank you, Norman :-)
newdep wrote:Give me 3 more readings ill be back with a reply ;-)
Sounds good!

m i c h a e l

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Ah, this looks interesting. I seem to remember my brain didn't immediately take to the immutability aspect of foop, so this may persuade some more of my brain cells to go foop.

And you seem to have gone all Gödel Escher Bach on us, Michael... ?

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

cormullion,

Weren't you working on something to do with GS that needed mutable objects? Maybe this solution can help you achieve that. It really just moves the resetting of the variable into the accessors, but if there ever was a good reason for accessors, this is it.

I'm glad my Gödel/Escher/Bach correspondence courses are starting to pay off ;-)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

At the time I was wondering how to integrate FOOP with newLISP-GUI... Ie, an object to represent state and behaviour, then instances of it created and displayed on a canvas or layout. For example, an object that describes how an analog meter works, then placed as instances so that they could show different levels. I was having trouble getting started. (I then got sidetracked into using Phun (http://www.phunland.com/wiki/Home) which was a bit easier... :)
I'm glad my Gödel/Escher/Bach correspondence courses are starting to pay off ;-)
Ah, you got yours!? Unfortunately, the postman didn't deliver any of the course materials to my house, since I had enrolled under the name "Return T. O. Sender"...

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

cormullion wrote:At the time I was wondering how to integrate FOOP with newLISP-GUI... Ie, an object to represent state and behaviour, then instances of it created and displayed on a canvas or layout. For example, an object that describes how an analog meter works, then placed as instances so that they could show different levels. I was having trouble getting started.
Ah yes, I see. I, too, was hoping custom widgets and widget groupings would be possible with FOOP, but the mutability issue did hamper it. I've got myself spread a bit thin at the moment, so I wonder if I'll ever get around to it. Plus, FOOP is still young yet, which is why I always refer to it as an experiment.
cormullion wrote:since I had enrolled under the name "Return T. O. Sender"...
So, the jig is up! cormullion is actually Return of Return T.O. Sender fame! Wow, I've been talking with the Return all this time. I'm gonna go tell all my friends. Bye!

m i c h a e l

P.S. Thanks for the link to Phun. Looks like fun.

Locked