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