Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

function to object?

 [1/6] from: bry::itnisk::com at: 5-Nov-2003 13:53


Am reading a little rant against object orientation http://www.bluetail.com/~joe/vol1/v1_oo.html When suddenly I wondered, can one convert a function to an object in rebol?

 [2/6] from: SunandaDH:aol at: 5-Nov-2003 8:29


Bryan:
> When suddenly I wondered, can one convert a function to an object in > rebol?
You can easily *add* a function to an object..... a-function: func [a b /local c] [c: a + b print c] a-function 19 21 ;; test it works an-object: make object! [a-function-in-an-object: :a-function] an-object/a-function-in-an-object 19 21 ;; test it works too Sunanda.

 [3/6] from: nitsch-lists:netcologne at: 5-Nov-2003 16:23


Am Mittwoch, 5. November 2003 13:53 schrieb bryan:
> Am reading a little rant against object orientation > http://www.bluetail.com/~joe/vol1/v1_oo.html > > When suddenly I wondered, can one convert a function to an object in > rebol?
means what? f: func[][alert "hi"] o: context[f: none] o/f: :f o/f ;? or functions with state? o: context[ state: 1 set 'f func[][state: state + 1 alert mold state] ] f f f or? (reading article later ;) -Volker

 [4/6] from: joel:neely:fedex at: 5-Nov-2003 16:26


Hi, Bryan, bryan wrote:
> Am reading a little rant against object orientation > http://www.bluetail.com/~joe/vol1/v1_oo.html >
Rant being the operative word. One can tell from the title that this is somebody venting his spleen and not contributing to any objective discussion of programming styles. It goes downhill from the title, as the author proclaims his philosophical/political views as if they were facts of nature. A collegue once described to me his moment of enlightenment when a professor had drawn on the blackboard a table showing relationships between some functions and data structures, something like: |Fn0|Fn1|...|Fnx| ---+---+---+---+---+ DS0| * | * | | * | ---+---+---+ +---+ DS1| | * | | | ---+---+---+ +---+ ...| | ---+---+---+ +---+ DSy| * | | | * | ---+---+---+---+---+ and then remarked offhandedly, "If you slice it vertically, you have functional programming; if you slice it horizontally, you have object- oriented programming."
> When suddenly I wondered, can one convert a function to an object in > rebol? >
Your question highlights the main irony regarding the rant cited above: at a deep level (e.g. the kind of thing well-illustrated in SICP) there isn't much difference. Functional folks are very fond of the idea of closures, which are basically functions that preserve state. For example (a very dinky example, to be sure! ;-) suppose we have this: times: func [a [number!] b [number!]] [ a * b ] and then we discover that we're using the (sub-)expression times 2.54 somelength frequently in our code. We could define in2cm: func [a [number!]] [ times 2.54 a ] quite easily. But then we notice that we also have lots of (sub-) expressions using times 4.546 somegallons and times 0.4535924 somepounds etc... Wouldn't it be nice to make a "function factory" that would "freeze" the first argument to TIMES and give us back a specialized function for a particular class of uses? We could try bogus-product-factory: func [a [number!]] [ func [b] [times a b] ] and then define (and use)
>> in2cm: bogus-product-factory 2.54 >> in2cm 4
== 10.16
>>
So what's wrong? Well, if we subsequently use our bogus factory to define a new function
>> gallons2liters: bogus-product-factory 4.546 >> gallons2liters 10
== 45.46
>> gallons2liters 3
== 13.638 it behaves as expected until we try to use the first one
>> in2cm 4
== 18.184
>>
OOOPS! The gotcha is that both in2cm and gallons2liters are referring to the argument of bogus-product-factory as one of their factors, so a new use of the factory can change the behavior of one of its former products! Time for a factory recall! ;-) We can sidestep that problem (in this trivial case) as follows: compose-product-factory: func [a [number!]] [ func [b] compose [times (a) b] ]
>> in2cm: compose-product-factory 2.54 >> in2cm 4
== 10.16
>> gallons2liters: compose-product-factory 4.546 >> gallons2liters 10
== 45.46
>> gallons2liters 3
== 13.638
>> in2cm 4
== 10.16 but that solution doesn't scale well at all. Instead, we can use an object to maintain the "hidden" factor in our functions like so object-product-factory: func [a [number!]] [ get in make object! [ constant: a f: func [b [number!]] [times constant b] ] 'f ] and we still have nice resulting behavior
>> in2cm: object-product-factory 2.54 >> in2cm 4
== 10.16
>> gallons2liters: compose-product-factory 4.546 >> gallons2liters 10
== 45.46
>> gallons2liters 3
== 13.638
>> in2cm 4
== 10.16
>>
We're simply encapsulating the "state" (the constant factor for each special case) inside an object, because that's what Tiggers do best! But wait! our anti-object screed-monger may cry "You're not mutating the state, so your functions are still -- ermmm --- functional!" So far, so true, but now our management (or our capacity-planning group, who wants to know how many CPU cycles we're burning up on multiplications) asks how many times each of our special-purpose conversion functions is being used. "No problem!" we say "because we're using objects!" object-inventory: [] accounting-product-factory: func [a [number!] /local obj] [ append object-inventory obj: make object! [ constant: a usage: 0 f: func [b [number!]] [ usage: usage + 1 times constant b ] ] get in obj 'f ] and now do our stuff again in2cm: accounting-product-factory 2.54 gallons2liters: accounting-product-factory 4.546 in2cm 4 gallons2liters 10 gallons2liters 3 but now we can also have inventory-usage-report: func [/local count usages] [ count: usages: 0 foreach object object-inventory [ print [ "object with factor" object/constant "was used" object/usage "times" ] count: count + 1 usages: usages + object/usage ] print [count "objects used a total of" usages "times"] ] which gives us
>> inventory-usage-report
object with factor 2.54 was used 1 times object with factor 4.546 was used 2 times 2 objects used a total of 3 times
>>
And (assuming we actually re-used the same name for our factory instead of changing the name every time, as I did above for the purpose of explanation) we accomplished this without changing any of the code that used PRODUCT-FACTORY (the standardized name). Of course, if there's no state that persists between evaluations, using an object seems overkill... or does it? The other nice thing that an object does for us is to provide a private namespace, which allows us to decompose a complicated function into an interface function that uses a collection of (hidden) helper functions and values shared among those functions without cluttering up the global namespace with all of those implementation details. The QAD above left OBJECT-INVENTORY in the global namespace, whereas general-products: make object! [ inventory: [] manufacture: func [a [niumber] /local obj]] [ append inventory obj: make object! [ constant: a usage: 0 f: func [b [number!]] [ usage: usage + 1 times constant b ] ] get in obj 'f ] report: func [/local count usages] [ count: usages: 0 foreach object inventory [ print [ "object with factor" object/constant "was used" object/usage "times" ] count: count + 1 usages: usages + object/usage ] print [count "objects used a total of" usages "times"] ] ] product-factory: get in general-products 'manufacture so now the rest of the world doesn't need to know or worry about the block holding the inventory, and the INVENTORY-USAGE-REPORT doesn't conflict with the warehouse database. ;-) -jn- -- ---------------------------------------------------------------------- Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1

 [5/6] from: jason:cunliffe:verizon at: 5-Nov-2003 18:26


Thanks for that wonderful post -- all of it ! - Jason ----- Original Message ----- From: "Joel Neely" <[joel--neely--fedex--com]> To: <[rebol-list--rebol--com]> Sent: Wednesday, November 05, 2003 5:26 PM Subject: [REBOL] Re: function to object? -- snip--
> A collegue once described to me his moment of enlightenment when a > professor had drawn on the blackboard a table showing relationships
<<quoted lines omitted: 12>>
> functional programming; if you slice it horizontally, you have object- > oriented programming."
--snip--

 [6/6] from: didec:tiscali at: 7-Nov-2003 11:26


Re: Re: function to object? Wonderfull post ! Should be an article for RebolForces, isn't it ? Didec

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted