FOOP colon method invocation from string

Started by refrainrence, August 08, 2013, 03:28:45 PM

Previous topic - Next topic

refrainrence

Hi there,



i play with newLISP from time to time because writing code in 'real world' languages feels like merry go round. So to avoid a lapse of reason i'm playing atm with my imaginary programming task which goes :



Take list of method names stored in list of strings ( or symbols - i'm an ignorant noob) and invoke them on an object.



What i have now:



(define (Circle:area)
    (mul (pow (self 3) 2) (acos 0) 2))

(set 'method1 '(:area))

(set 'mycircle (Circle 1 2 10))

((nth 0 method1)(nth 1 method1) mycircle)



This is my first post, so it's a good time to thank you people, who are behind newLISP for this outstanding piece of software :-)



I'd like to follow with a few more questions considering FOOP in this same thread if you don't mind. The context of newLISP is main reason for using this language to me, so forgive me i started learning from this point and not the basics. I just can't figure out if context from newLISP works for me or not. I'm trying to build my own approach to OOP paradigm. Based on composition, without inheritance. I want to replace PHP with NewLISP as a foundament.



cheers

cormullion

#1
Take a look at ObjectiveNewLISP http://www.taoeffect.com/blog/2009/12/introducing-objective-newlisp/">//http://www.taoeffect.com/blog/2009/12/introducing-objective-newlisp/ as well.

hilti

#2
Welcome to the powerful world of newLISP :-)
--()o Dragonfly web framework for newLISP

http://dragonfly.apptruck.de\">http://dragonfly.apptruck.de

refrainrence

#3
Thanks hilti, thanks cormullion for objective-newlisp link, i think i may need circular links and deep nested access. I will try to write some lines using objective-newlisp later. But before that, i'm going to do some FOOP scripting.



I managed to write a possible solution:




(define (Circle:Circle x y radius)
    (list Circle x y radius))

(define (Circle:area)
    (mul (pow (self 3) 2) (acos 0) 2))


(set 'methods '((:area) (:area)))

(set 'mycircle (Circle 1 2 10))

(dolist (x methods) (println "looping: " (eval (append x '(mycircle)))))



output:



(lambda (x y radius) (list Circle x y radius))
(lambda () (mul (pow (self 3) 2) (acos 0) 2))
((: area) (: area))
(Circle 1 2 10)
looping: 314.1592654
looping: 314.1592654
314.1592654


Does it look alright?

cormullion

#4
Looks good. There are many ways to do it.


(define (Circle:Circle (x 10) (y 10) (radius 3))
    (list Circle x y radius))
   
(define (Circle:area)
    (mul (pow (self 3) 2) (acos 0) 2))
   
(define (Circle:center)
    (list (self 1) (self 2)))

(define (Circle:circumference)
    (mul 2 (self 3) (acos 0)))

(set 'mycircle (Circle 150 130 170))

(set 'functions '(area center circumference))

(dolist (func functions)
   (println (eval (list ': func mycircle))))

giving:


90792.02769
(150 130)
534.0707511


But hopefully other more experienced FOOPers can join in...:)

rickyboy

#5
I'm not a FOOPer, but I'd like to throw out a few comments for discussion, but be warned that what I'm going to cover does NOT improve essentially on what cormullion just wrote -- it just complements it.



Here's the setup, which is slightly different but essentially the same as yours, refrainrence.


(define (Class:Class) (cons (context) (args)))
(define pi (mul 2 (acos 0)))

(new Class 'Circle)
(define (Circle:radius) (self 3))
(define (Circle:circumference) (mul 2 pi (Circle:radius)))
(define (Circle:area) (mul pi (pow (Circle:radius) 2)))

(Notice that I defined a method, radius, which is just an accessor.  It makes some of the other code easier to read.)



If you want to call a bunch of functions (methods, in this case) on an object, but do it in the functional way (warning: FP is a minority cult on the newLISP forum :), you would call a higher-order function, like juxt.  http://www.newlispfanclub.alh.net/forum/viewtopic.php?f=16&t=4202">Here is a discussion on it, but basically it is defined like this:


(define (juxt)
  (letex (_funcs (args))
    (lambda (x)
      (map (lambda (f) (f x)) '_funcs))))

and used like this:


(define (mulby3 x) (mul x 3))
(define (divby3 x) (div x 3))

((juxt mulby3 divby3) 9)
;; => (27 3)

But juxt will fail miserably, when you use it for your Circle example.  For instance, none of these calls work:


((juxt :radius :area :circumference) mycircle)
((juxt radius area circumference) mycircle)
((juxt Circle:radius Circle:area Circle:circumference) mycircle)

They don't work because methods are invoked differently from regular functions.  The colon operator does the dispatching work for you behind the scenes.  So if you want to use something like juxt, you'd only need to write a version of it that handles these methods.  Here is a version I wrote, and I just called it by a different name juxtm.


(define-macro (juxtm)
  (letex (_meths (args))
    (lambda (obj)
      (letex (_calls
              (map (lambda (m) (list ': m obj)) '_meths))
        (map eval '_calls)))))

(Notice the eval in there, just as in cormullion's loop.)



Now, it works as expected.


(setf mycircle (Circle 1 2 10))
(:radius mycircle)
(:area mycircle)
(:circumference mycircle)
((juxtm radius area circumference) mycircle)

yields


> (Circle 1 2 10)
> 10
> 314.1592654
> 62.83185307
> (10 314.1592654 62.83185307)
(λx. x x) (λx. x x)

cormullion

#6
Good work, FOOperman. And thanks for the "compliment"! :)

rickyboy

#7
Heck, you figured it out, cormullion.  Setting up the calls as data and pushing them through eval was the heart of the matter.  Is there a better way?  Idk.



I ain't on FOOPer.  I really am not into OOP at all.  And if I ever did get into FOOP, there are a lot of questions I'd need to answer, the most important of which is what is the inheritance scheme (and I assume the colon operator does the dispatching of methods for you based on the scheme -- but I'm not sure)?



And don't tell anybody that you can make juxtm faster by basing it off of dolist (like you did) as opposed to map.  Shhhhh!  It will just be our secret. :)
(λx. x x) (λx. x x)

rickyboy

#8
Quote from: "cormullion"Good work, FOOperman. And thanks for the "compliment"! :)

Damn you.  I just corrected it.  Thanks. :)
(λx. x x) (λx. x x)