Mutable objects in FOOP in development v.10.1.8

Notices and updates
Locked
Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

Mutable objects in FOOP in development v.10.1.8

Mutable objects in FOOP (Functional Object Oriented Programming) has been the most asked feature for FOOP, and now its here:

Code: Select all

(new Class 'Circle)

(define (Circle:move dx dy)
    (inc (self 1) dx)
    (inc (self 2) dy))

(set 'aCircle (Circle 1 2 3))

(:move aCircle 10 20)

aCircle => (Circle 11 22 3)
Now FOOP methods drop the object parameter and the target objects is accessed via the new function 'self'.

For files and complete changes notes see:

http://www.newlisp.org/downloads/development/

See changed FOOP documentation here:

http://www.newlisp.org/downloads/develo ... .html#foop
http://www.newlisp.org/downloads/develo ... html#colon
http://www.newlisp.org/downloads/develo ... .html#self

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by itistoday »

This is fascinating, and I can't help but think that we both should have communicated regarding what we were doing.

Since our email exchange I've created an object-oriented system for newLISP that I'll announce today, it has several advantages over FOOP, even this redesigned version. In short it allows you to do real object-oriented programming with reference passing, and is backwards compatible with many old versions of newLISP. :-)

I.e., it solves this problem with FOOP (which exists even with this updated version):

Code: Select all

(setf my-obj (MyFOOPClass 1 2 3))

(define (func-1 obj)
	(func-2 obj)
)

(define (func-2 obj)
	(:modify obj 54)
	obj
)

(func-1 obj)

obj ; obj remains unchanged here
But this is still a very welcome change to FOOP, as I'm assuming the use of the 'self' function makes it more efficient too!
Get your Objective newLISP groove on.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

When you wrap a destructive function (:move ...) with a non-destructive one (func-1 and func-2), then of course the result is non-destructive. But 'obj' will be modified after excecution of (:modify …). One must stay in the paradigm of either FOOP or normal .

Yes, the new 'self' makes FOOP also faster, less overhead internally and less newLISP code to write. Before when modifying objects, you always had to return the modified object and then do a re-assignment on the higher level, which now is not necessary anymore.

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by itistoday »

Lutz wrote:When you wrap a destructive function (:move ...) with a non-destructive one (func-1 and func-2), then of course the result is non-destructive. But 'obj' will be modified after excecution of (:modify …). One must stay in the paradigm of either FOOP or normal.
Sure, I'm just saying that this still doesn't allow full-on object-oriented programming (which is something that I need for that database wrapper, but thankfully I found an excellent solution).

Note to Dragonfly users: don't upgrade to this yet, as Dragonfly makes use of the old-style FOOP.

Edit: Nevermind. Dragonfly's use of FOOP does not cause any problems, it's OK to upgrade! :-)
Get your Objective newLISP groove on.

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by itistoday »

When used in this way, Functional-OOP becomes a misnomer. ;-p
Get your Objective newLISP groove on.

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by m i c h a e l »

I've wondered about this ever since I first toyed around with mutability in my experiments (BTW, bravo on self, Lutz! Perfectly simple and fits newLISP to a tee.). Surely, if the 'F' in FOOP means anything, it must be immutable objects, right? I don't know. I've tried to approach FOOP without preconceptions or prejudices. Still, I've tried hard to find a good way to add mutability to FOOP. Unchangeable objects would appear to be an oxymoron. When I think of objects, I think of little self-manipulating packages of data.

If FOOP is to lose its 'F', perhaps it should be called newOOP instead ;-)

m i c h a e l

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by TedWalther »

Cool. It looks like "self" is doing what I was hoping for with "this". I'll go refresh myself on FOOP again. Things are calming down at work again; perhaps over Christmas break I can power through and fix up configure-alt enough to be a suitable replacement for configure, and get a first release of the OpenBSD port/package done. Are there any outstanding issues with configure-alt, Lutz? Also, the OpenBSD test environment is now upgraded to version 4.6.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

The fact that each object in FOOP is the functional expression which generates itself - its own constructor expression - still justifies the 'F' in FOOP.

Code: Select all

(new 'Class 'Obj)
(Obj 1 2 3) ;=> (Obj 1 2 3)
(eval (Obj 1 2 3)) ;=> (Obj 1 2 3)
(apply (first (Obj 1 2 3)) (rest (Obj 1 2 3))) ;=> (Obj 1 2 3)
The same is true for nested objects, they are nested constructor functions:

Code: Select all

(new Class 'Foo)
(new Class 'Bar)
(set 'x 1 'y 2 'z 3)
(Foo (Bar x y z) (Bar x y z)) ;=> (Foo (Bar 1 2 3) (Bar 1 2 3))
(Foo (Bar 1 2 3) (Bar 1 2 3)) ;=> (Foo (Bar 1 2 3) (Bar 1 2 3))
So the object-oriented programming in FOOP may not be full functional, but the object is. Not functional object-oriented programming but functional-object oriented programming.


ps -> Ted: I don't think there are any outstanding issues in configure-alt at the moment.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by TedWalther »

How is (new) different from (copy)? Is object an internal datatype the way contexts and red-black dictionaries are?
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by cormullion »

This looks cool, but ... Can you explain why in your code

Code: Select all

(define (Circle:move dx dy)
    (inc (self 1) dx)
    (inc (self 2) dy))

(set 'aCircle (Circle 1 2 3))

(:move aCircle 10 20)

aCircle => (Circle 11 22 3)
you pass three numbers with Circle, yet only the first two are modified, and yet they're referred to as (self 1) and (self 2), so these aren't indexes? But:
Old FOOP methods have to be rewritten to drop the obj parameter:

old : (define (Foo:method obj p1 p2) ...)
new : (define (Foo:method p1 p2) ...)
looks like I'd want to modify 0 and 1, not 1 and 2.

As I said, confused a bit here... :)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

It is less confusing if we describe the code in original object oriented terminology (all in italic font). The following function call is called a message call in OO:

Code: Select all

(:move aCircle 10 20)
:move is the message sent to the object aCircle and 10 and 20 are the message parameters, only two of them in this example. In OO Java or JavaScript you would write aCircle.move(10, 20).

The object aCircle encapsulates the object data and the methods how to process the data. So when we receive the call, we really are inside the object aCircle and can refer to it with (self). There are only two parameters in the :move message, in this case 10 and 20 for the dx and dy method parameters.

The function (self) returns the object with the Class Id at index 0 and values for x-position, y-position and radius at index 1,2 and 3. In out example (self) is aCircle, the receiver of the message

Code: Select all

(define (Circle:move dx dy)
    (inc (self 1) dx)
    (inc (self 2) dy))
Because all the shapes of Class Circle use the same methods, we don't have to carry them around in each object instance of that Class, but can just point to with a Class Id, which is the first thing in the aCircle object (Circle 1 2 3).

Note that :move is not the same thing as Circle:move. :move is the message sent, and Circle:move is the method processing the message received by the object aCircle which is an instantiation of Class Circle. The message :move is polymorph and depending on the object Class it may point to different methods, there could also be a Rectangle:move method or Triangle:move method.

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by m i c h a e l »

I started this response before Lutz answered you, cormullion, but I'll post it anyway :-)

I think Circle's third attribute is its radius, which, of course, would not be affected by moving the circle.

The indexes used in self represent the positions of the attributes within an object. The first element of an object is the class (at index 0). In the case of Circle, x is 1, y is 2, and the radius is 3.

Most object-oriented languages don't specifically declare an argument for the object passed to a method (Python being one exception). They use some form of pseudo-variable, usually self or this, that can only be used within a method (you'll notice calling newLISP's self outside of a method will always return nil).

Just remember that self refers to the object that received the message, not the arguments of the method.

m i c h a e l

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by TedWalther »

Thanks, I've been wanting to use context-objects more extensively, with millions of items of the same class type, but wasn't sure how to do it without duplicating the methods for every single object instance. It looks like there is a way after all, even if I don't fully grokk it yet. Hurray! I won't get out of memory errors after all.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

There was a newlisp-10.1.8-foop.tgz in the development directory, whoever downloaded this, throw it away, it is an older version. The correct version containing the FOOP changes talked about in this thread is: newlisp-10.1.8.tgz.

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by cormullion »

Ah. Great - I wasn't thinking straight... Thanks both.

Mostly I use FOOP mainly in timeutilities.lsp at the moment. I've converted it over to the new style and it seems to work fine.

One thing you could advise on: I have a method called :shift which adds time to a time object. In the old style FOOP I was happy enough with the clarity and restriction of immutability - it made sense for 'fixed' times (if not for appointments):

Code: Select all

>; older style FOOP
(set 'xmas (Time 2009 12 25))
(Time 1261699200 0)
> (set 'boxing-day (:shift xmas 1 'days))
(Time 1261785600 0)
> (:represent xmas)
"Friday December 25 2009 00:00:00"
> (:represent boxing-day)
"Saturday December 26 2009 00:00:00"
With the new style, doing this also shifts xmas day - objects being no longer immutable. So I tried putting in a flag at the end of the :shift method call such that you could say either 'please modify the object' or not. So, with f as the increment, the shift method ends like this:

Code: Select all

(if modify-flag 
      (begin 
         (setf (self 1) (add f (self 1)))
         (self)) ; return the modified original object
      (begin
         (set 'new-time (self))
         (setf (new-time 1) (add f (new-time 1)))
         new-time ; return the modified copy
))))
Is this the best way to do this? It appears to work, but...

m35
Posts: 171
Joined: Wed Feb 14, 2007 12:54 pm
Location: Carifornia

Re: Mutable objects in FOOP in development v.10.1.8

Post by m35 »

Wow Lutz--you've been a big proponent of the functional/immutable approach for so long, I'm surprised and impressed you added mutable objects. I hope you don't feel like you're compromising on all us poor, industry brainwashed, OOP developers ;)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Mutable objects in FOOP in development v.10.1.8

Post by Lutz »

… actually, I think OO programming is a good paradigm. I just didn't want to put something into the language which didn't fit well. Now, built only with the colon operator :, the 'self' function and namespaces, FOOP has a good feel to it, is small and naturally fits into newLISP.

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by m i c h a e l »

cormullion wrote:Is this the best way to do this? It appears to work, but...
How about turning the problem around by leaving the method as is and simply copying the original?

Code: Select all

> (setq xmas (Time 2009 12 25))
(Time 1261699200 0)
> (setq boxing-day (:shift (copy xmas) 1 'days))
(Time 1261785600 0)
> (:represent xmas)
"Friday December 25 2009 00:00:00"
> (:represent boxing-day)
"Saturday December 26 2009 00:00:00"
> _
copy creates a new object from its argument, and it's this new object that will be referenced by self within the method. As long as your method returns the modified object (as you were already doing), you can use it either way.

m i c h a e l

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

Re: Mutable objects in FOOP in development v.10.1.8

Post by cormullion »

Thanks - that's probably the best solution...

Locked