Paul Grahams Accumulator
Chris Double — 2004-06-02 23:13:30
(I searched the archives and couldn't see a discussion related to this.
Apologies if it has been discussed)
Paul Graham poses a problem with example solutions in various programming
languages:
http://www.paulgraham.com/accgen.html
What would a solution in a concatenative language like Joy or Factor look
like? I tried my hand at Factor and got:
: adder ( n -- adder ) <namespace> swap over [ "n" swap put "call" [ "n"
get + dup "n" swap put ] put ] bind ;
: adder-call ( adder -- v ) [ "call" get call ] bind ;
5 adder
2 over adder-call .
=> 7
3 over adder-call .
=> 10
The downside is the needed 'adder-call' rather than a standard call. Any
other approaches to this type of problem or simulating 'closures' in
general?
Chris.
--
Chris Double
chris.double@...
Ivan Tomac — 2004-06-03 04:23:09
Hi Chris,
I'm not 100% sure if my solution in Joy meets all the requirements of
the challanage but here it is:
acc == [uncons [+ dup] dip dup [cons] dip cons] dup [cons] dip cons
to test it type something like:
1 acc 2 swap i 3 swap i 4 swap i pop stack.
Ivan
--- In
concatenative@yahoogroups.com, "Chris Double"
<chris.double@d...> wrote:
> (I searched the archives and couldn't see a discussion related to
this.
> Apologies if it has been discussed)
>
> Paul Graham poses a problem with example solutions in various
programming
> languages:
>
> http://www.paulgraham.com/accgen.html
>
> What would a solution in a concatenative language like Joy or Factor
look
> like? I tried my hand at Factor and got:
>
> : adder ( n -- adder ) <namespace> swap over [ "n" swap put "call"
[ "n"
> get + dup "n" swap put ] put ] bind ;
> : adder-call ( adder -- v ) [ "call" get call ] bind ;
>
> 5 adder
> 2 over adder-call .
> => 7
> 3 over adder-call .
> => 10
>
> The downside is the needed 'adder-call' rather than a standard
call. Any
> other approaches to this type of problem or simulating 'closures' in
> general?
>
> Chris.
> --
> Chris Double
> chris.double@d...
Ivan Tomac — 2004-06-03 04:40:47
After digging a bit through the archives I found the post with Nick
Forde's original solution in Joy:
http://groups.yahoo.com/group/concatenative/message/1407
Ivan
--- In concatenative@yahoogroups.com, "Ivan Tomac" <e1_t@y...> wrote:
> Hi Chris,
>
> I'm not 100% sure if my solution in Joy meets all the requirements of
> the challanage but here it is:
>
> acc == [uncons [+ dup] dip dup [cons] dip cons] dup [cons] dip cons
>
> to test it type something like:
>
> 1 acc 2 swap i 3 swap i 4 swap i pop stack.
>
> Ivan
>
> --- In concatenative@yahoogroups.com, "Chris Double"
> <chris.double@d...> wrote:
> > (I searched the archives and couldn't see a discussion related to
> this.
> > Apologies if it has been discussed)
> >
> > Paul Graham poses a problem with example solutions in various
> programming
> > languages:
> >
> > http://www.paulgraham.com/accgen.html
> >
> > What would a solution in a concatenative language like Joy or Factor
> look
> > like? I tried my hand at Factor and got:
> >
> > : adder ( n -- adder ) <namespace> swap over [ "n" swap put "call"
> [ "n"
> > get + dup "n" swap put ] put ] bind ;
> > : adder-call ( adder -- v ) [ "call" get call ] bind ;
> >
> > 5 adder
> > 2 over adder-call .
> > => 7
> > 3 over adder-call .
> > => 10
> >
> > The downside is the needed 'adder-call' rather than a standard
> call. Any
> > other approaches to this type of problem or simulating 'closures' in
> > general?
> >
> > Chris.
> > --
> > Chris Double
> > chris.double@d...
Slava Pestov — 2004-06-03 20:44:34
Ivan Tomac wrote:
> Hi Chris,
>
> I'm not 100% sure if my solution in Joy meets all the requirements of
> the challanage but here it is:
>
> acc == [uncons [+ dup] dip dup [cons] dip cons] dup [cons] dip cons
This works in Factor too. The only thing you have to change is the word
definition syntax, and adding whitespace around [ and ]:
: acc
[ uncons [ + dup ] dip dup [ cons ] dip cons ] dup
[ cons ] dip cons ;
In practice, I avoid writing functions that return new functions.
Slava
Chris Double — 2004-06-03 22:17:19
On Thu, 03 Jun 2004 04:23:09 -0000, "Ivan Tomac" <
e1_t@...> said:
>
> acc == [uncons [+ dup] dip dup [cons] dip cons] dup [cons] dip cons
>
That does it, thanks! It works in Factor too. I missed the previous
discussion on the list. I tried the search feature on yahoo groups and it
failed to pick it up.
Chris.
--
Chris Double
chris.double@...
Chris Double — 2004-06-03 22:35:22
On Thu, 03 Jun 2004 16:44:34 -0400, "Slava Pestov" <
slava@...>
said:
> In practice, I avoid writing functions that return new functions.
Why is that? Or are functions that 'capture state' an example of the type
of thing that needs to return new functions? I wrote a 'generator'
function in Factor to traverse a tree. Given a tree calling the generator
function will return a function that when called will return the leaves
of the tree in order:
[ 1 2 [ 3 4 ] 5 ] tree->generator
=> a-function
call .
=> 1
call .
=> 2
call .
=> 3
call .
=> 4
call .
=> 5
I did this by having the generated function return the continuation to
call to resume the function and the value of the tree. I couldn't think
of a way to do this without having the function value returned. Any
thoughts on a better interface for the generator function?
BTW, this was working through a Scheme exercise, translating it to
Factor. It's the 'Same Fringe' problem:
http://c2.com/cgi/wiki?SameFringeProblem
My basic example without continuations flattened the trees and compared
for equality. The idea for this one was to use co-routines to go through
the trees one by one and return on the first in-equality, avoiding the
need to cons up and flatten the tree.
Chris.
--
Chris Double
chris.double@...
Slava Pestov — 2004-06-03 23:18:28
I think a better solution to this would be to write a word tree-each (
tree code -- ) that is like 'each' but recursive. Then you could do, for
example:
[ . ] tree-each
Note that tree->generator can be implemented in terms of tree-each and
continuations. Having the more primitive tree-each word available is an
advantage because continuation-using code cannot be compiled.
Chris Double wrote:
> On Thu, 03 Jun 2004 16:44:34 -0400, "Slava Pestov" <slava@...>
> said:
>
>>In practice, I avoid writing functions that return new functions.
>
>
> Why is that? Or are functions that 'capture state' an example of the type
> of thing that needs to return new functions? I wrote a 'generator'
> function in Factor to traverse a tree. Given a tree calling the generator
> function will return a function that when called will return the leaves
> of the tree in order:
>
> [ 1 2 [ 3 4 ] 5 ] tree->generator
> => a-function
>
> call .
> => 1
> call .
> => 2
> call .
> => 3
> call .
> => 4
> call .
> => 5
>
> I did this by having the generated function return the continuation to
> call to resume the function and the value of the tree. I couldn't think
> of a way to do this without having the function value returned. Any
> thoughts on a better interface for the generator function?
>
> BTW, this was working through a Scheme exercise, translating it to
> Factor. It's the 'Same Fringe' problem:
> http://c2.com/cgi/wiki?SameFringeProblem
>
> My basic example without continuations flattened the trees and compared
> for equality. The idea for this one was to use co-routines to go through
> the trees one by one and return on the first in-equality, avoiding the
> need to cons up and flatten the tree.
>
> Chris.
Chris Double — 2004-06-04 01:40:48
On Thu, 03 Jun 2004 19:18:28 -0400, "Slava Pestov" <
slava@...>
said:
> I think a better solution to this would be to write a word tree-each (
> tree code -- ) that is like 'each' but recursive.
Here's my attempt at tree-each in Factor:
: tree-each ( [ tree ] [ quotation ] -- )
over [
over cons? [
>r uncons r> tuck [ tree-each ] 2dip tree-each
] [
call
] ifte
] [
2drop
] ifte ;
[ 1 2 [ 3 4 ] 5 ] [ . ] tree-each
Regarding formatting code, is the nesting approach above the generally
preferred way to present it?
I can't the above to compile in 0.58 though. I do:
"tree-each" compile
"tree-each" worddef compiled? .
=> f
Is there something I'm doing that's preventing the compilation? Or am I
using an incorrect check to see if it is compiled?
Chris.
--
Chris Double
chris.double@...
Slava Pestov — 2004-06-04 01:53:19
Hi,
Nicely done!
The reason it doesn't compile is because it is a higher-order word. Only
specific *instances* of higher order words compile. For example, the
following word compiles:
: tree-each-test [ drop ] tree-each ;
To find out why a word doesn't compile, enable verbose compilation:
t "verbose-compile" set
Although the error messages are quite cryptic right now.
Do you want me to include this word in the library?
Slava
Chris Double — 2004-06-04 04:04:23
On Thu, 03 Jun 2004 21:53:19 -0400, "Slava Pestov" <
slava@...>
said:
>
> Nicely done!
Thanks!
> Do you want me to include this word in the library?
Sure, that'd be great.
Chris.
--
Chris Double
chris.double@...