[REBOL] Re: Functional programming in REBOL
From: larry:ecotope at: 8-Aug-2001 10:13
Hi Ladislav,
Thanks for your excellent comments. I must confess that I was completely
unaware of e-func in your higher-order function library, although I had
looked at some of the other functions. Please accept my apologies.
e-func and cfunc were created from very similar goals. I agree with your
assessment that e-func is more general because it handles refinements and
delayed evaluation args in the spec block.
Two quick comments on e-func, if the line:
:nm-use locals reduce [ ...
was changed to
:use locals copy/deep reduce [ ...
e-func would be self-contained, making it a little more portable.
The other comment is that, for me personally, the e-func code much easier to
read and follow with the internal comments removed.
Out of curiosity, I checked the storage requirements for a curry function
created two ways:
1) using cfunc: 1268 bytes
2) using e-func: 2052 bytes
so e-func is using about 60% more storage. It is also noticeably slower.
I like the method you used to redefine the locals inside the use block, I
think that approach is much preferable to renaming the variables in the body
block as suggested by Gabriele.
I thought about your comments below and decided to add argument
type-checking and allow comment strings in the spec block for cfunc. Here is
the new version:
cfunc: func [spec body /local args][
args: copy []
repeat el spec [if word? :el [append args to-get-word :el]]
func spec compose/deep [
do append reduce [func [(spec)][(body)]][(args)]
]
]
The other restrictions still apply. The spec block for cfunc should not
contain refinements, get-words, lit-words, or set-words. The approach which
I took of reusing the spec block for all the args will not work for dealing
with these items, I think your approach is probably the best one.
On the other hand, I had a limited goal in creating cfunc. I just wanted
something that would handle "ordinary" arguments, so that Scheme code could
be entered more or less the same way as it would be in Scheme and produce
the same results. Scheme does not support user definition of datatypes for
args, or any of the other REBOL features mentioned above.
So, for my purposes, cfunc is acceptable and the version above allows
type-checking and doc strings as well. One of the main ideas from Scheme is
that most of the higher order functions are really simple, and in Scheme
they are simple. When we try to implement them to include all of the nuances
and features of REBOL functions, they tend to get more complex. In this
regard, I note that many of your functions also do not support delayed
evaluation arguments.
> Larry, your CFUNC doesn't have trouble with "active arguments". Some
> differences:
>
> f1: e-func [x [any-type!]] [type? get/any 'x]
> f1 () ; == unset!
>
> while
>
> g1: cfunc [x [any-type!]] [type? get/any 'x]
> ** Script Error: Expected one of: word! - not: block!
> ** Where: to-get-word
> ** Near: to get-word! :value
This is now fixed.
> f2: e-func [:x] [type? get/any 'x]
> f2 // ; == op!
>
> while
>
> g2: cfunc [:x] [type? get/any 'x]
> g2 // ; == get-word!
See above
> f3: e-func [do] [type? get/any 'do]
> f3 "OK" ; == string!
>
> while
>
> g3: cfunc [do] [type? get/any 'do]
> g3 "OK" ; == [func [do][type? get/any 'do] :do]
>
This one bothers me, but I don't see how to fix cfunc. Meanwhile, just don't
use DO as a variable name. Are there any other words that create this
problem?
Thanks again for your comments. And thanks for the effort which you have put
into highfun.r, it is a good resource for all of us.
Meanwhile I am looking forward to your solution of the puzzles ;-)
Cheers
-Larry