Skip to search.

Breaking News Visit Yahoo! News for the latest.

×Close this window

concatenative · Discuss the concatenative variety of computer languages: Joy, Forth, Postscript

The Yahoo! Groups Product Blog

Check it out!

Group Information

? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Hear how Yahoo! Groups has changed the lives of others. Take me there.

Messages

Advanced
Messages Help
Messages 1847 - 1876 of 4941   Oldest  |  < Older  |  Newer >  |  Newest
Messages: Show Message Summaries Sort by Date ^  
#1847 From: "Chris Double" <chris.double@...>
Date: Wed Jun 2, 2004 11:13 pm
Subject: Paul Grahams Accumulator
chris.double@...
Send Email Send Email
 
(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@...

#1848 From: "Ivan Tomac" <e1_t@...>
Date: Thu Jun 3, 2004 4:23 am
Subject: Re: Paul Grahams Accumulator
e1_t
Send Email Send Email
 
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...

#1849 From: "Ivan Tomac" <e1_t@...>
Date: Thu Jun 3, 2004 4:40 am
Subject: Re: Paul Grahams Accumulator
e1_t
Send Email Send Email
 
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...

#1850 From: Slava Pestov <slava@...>
Date: Thu Jun 3, 2004 8:44 pm
Subject: Re: [stack] Re: Paul Grahams Accumulator
slava@...
Send Email Send Email
 
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

#1851 From: "Chris Double" <chris.double@...>
Date: Thu Jun 3, 2004 10:17 pm
Subject: Re: [stack] Re: Paul Grahams Accumulator
chris.double@...
Send Email Send Email
 
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@...

#1852 From: "Chris Double" <chris.double@...>
Date: Thu Jun 3, 2004 10:35 pm
Subject: Re: [stack] Re: Paul Grahams Accumulator
chris.double@...
Send Email Send Email
 
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@...

#1853 From: Slava Pestov <slava@...>
Date: Thu Jun 3, 2004 11:18 pm
Subject: Re: [stack] Re: Paul Grahams Accumulator
slava@...
Send Email Send Email
 
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.

#1854 From: "Chris Double" <chris.double@...>
Date: Fri Jun 4, 2004 1:40 am
Subject: Re: [stack] tree-each (was Re: Paul Grahams Accumulator)
chris.double@...
Send Email Send Email
 
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@...

#1855 From: Slava Pestov <slava@...>
Date: Fri Jun 4, 2004 1:53 am
Subject: Re: [stack] tree-each (was Re: Paul Grahams Accumulator)
slava@...
Send Email Send Email
 
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

#1856 From: "Chris Double" <chris.double@...>
Date: Fri Jun 4, 2004 4:04 am
Subject: Re: [stack] tree-each (was Re: Paul Grahams Accumulator)
chris.double@...
Send Email Send Email
 
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@...

#1857 From: John Cowan <cowan@...>
Date: Fri Jun 4, 2004 4:17 am
Subject: OT: John Cowan announces the "Unix Power Classic"
johnwcowan
Send Email Send Email
 
My apologies for this cross-post, but I just can't tell which of you
will be interested in my latest effort: the Unix Power Classic,
an evolving hacker-oriented version of the Tao Te Ching.
See http://www.ccil.org/~cowan/upc .

Please don't reply on-list, but directly to cowan@....  Thanks.

--
Schlingt dreifach einen Kreis vom dies!    John Cowan <jcowan@...>
Schliesst euer Aug vor heiliger Schau,     http://www.reutershealth.com
Denn er genoss vom Honig-Tau,              http://www.ccil.org/~cowan
Und trank die Milch vom Paradies.            -- Coleridge (tr. Politzer)

#1858 From: "stevan apter" <sa@...>
Date: Sat Jun 5, 2004 1:24 am
Subject: Re: [stack] same fringe [was: tree-each (was Re: Paul Grahams Accumulator)]
sa@...
Send Email Send Email
 
thanks to both of you for triggering some thoughts on this problem
(that is, the "same fringe" problem.)

i've posted those (and some code) at

     http://www.nsl.com/papers/samefringe.htm

to sum up my findings:

the challenge was to implement a 'samefringe' function which (a) used
no (or very little) additional storage over and above what is needed
for the input trees, (b) discovered fringe-difference as early as possible,
(c) and didn't use either coroutines or continuations.  (c) was easy,
since my language of choice, k, doesn't have these critters.  (b) followed
without additional work from (a), which took a bit of thinking, but my
solution is now easily generalized to apply to structures other than
trees, so that's pretty satisfying.

thanks again.

----- Original Message -----
From: "Slava Pestov" <slava@...>
To: <concatenative@yahoogroups.com>
Sent: Thursday, June 03, 2004 9:53 PM
Subject: Re: [stack] tree-each (was Re: Paul Grahams Accumulator)


> 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
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>

#1859 From: "Chris Double" <chris.double@...>
Date: Mon Jun 7, 2004 6:58 am
Subject: Factor and continuations
chris.double@...
Send Email Send Email
 
I'm experimenting with writing generators and coroutines and thought I'd
post the findings here in case others have questions.

For a coroutine code I wanted to create a continuation that when called
returns back to the current caller, not the original caller when the
continuation was captured.

Here's some code:

: test
	 [ "test1 escaping continuation is " print
	   dup print
	   test2
         ] callcc1
	 "end-of-test" print ;

: test2 ( escape -- )
	 "test2 will call escape continuation" print
	 dup print
	 [
		 "test2 continuation to re-enter is " print
		 dup print
		 swap call
	 ] callcc1
	 nip
	 "Stack after calling of test2s re-enter continuation is" print
	 .s
	 call ;

: test3 ( cont -- )
	 "calling test2s re-enter continuation" print
	 dup print
	 [
		 "test3 escaping continuation which test should call is" print dup print
		 swap call
	 ] callcc0
	 drop
	 "test3-end" print ;

The intent is to provide a continuation in 'test2' that can be called to
re-enter test2 but exit to the caller of the continuation, not to the
original caller of 'test2'. So calling 'test' will return to
"end-of-test" and calling test3 on the continuation returned by 'test'
will return to 'test3-end'.

So I'll call 'test', which will place the continuation on the stack. Then
call 'test3' which calls that continuation and passes it the continuation
to call to exit back. I'm printing out the values of the continuations so
I can keep track of what is happening.

     343] clear
     344] .s
     345] test
test1 escaping continuation is
[ #<factor.FactorArrayStack@120dbf3> #<factor.FactorCallStack@4845aa>
#<factor.FactorArrayStack@d5c0f9> [ unit ] continue ]
test2 will call escape continuation
[ #<factor.FactorArrayStack@120dbf3> #<factor.FactorCallStack@4845aa>
#<factor.FactorArrayStack@d5c0f9> [ unit ] continue ]
test2 continuation to re-enter is
[ #<factor.FactorArrayStack@1701bdc> #<factor.FactorCallStack@1353249>
#<factor.FactorArrayStack@1786286> [ unit ] continue ]
end-of-test

346] .s
[ #<factor.FactorArrayStack@1701bdc> #<factor.FactorCallStack@1353249>
#<factor.FactorArrayStack@1786286> [ unit ] continue ]

And this is the continuation that I will want to call when running
'test3'. Note that it is the one from the 'test2 continuation to re-enter
is' line which is correct.

     346] dup
     347] test3
calling test2s re-enter continuation
[ #<factor.FactorArrayStack@1701bdc> #<factor.FactorCallStack@1353249>
#<factor.FactorArrayStack@1786286> [ unit ] continue ]
test3 escaping continuatoin which test should call is
[ #<factor.FactorArrayStack@8c5ea2> #<factor.FactorCallStack@198defc>
#<factor.FactorArrayStack@1579a30> [ unit ] continue ]
Stack after calling of test2s re-enter continuation is
[ #<factor.FactorArrayStack@120dbf3> #<factor.FactorCallStack@4845aa>
#<factor.FactorArrayStack@d5c0f9> [ unit ] continue ]
[ #<factor.FactorArrayStack@8c5ea2> #<factor.FactorCallStack@198defc>
#<factor.FactorArrayStack@1579a30> [ unit ] continue ]
test3-end

This works fine. Because of the 'dup' I can recall it by running 'test3'
and it works again, and again. Nice!

A couple of points that tripped me up when first experimenting:

1) I can't just 'call' the continuation captured by 'test2'. If I do this
I'll end up returning back to 'test' with its stack restored rather than
where I want to be in the current call stack. This is why 'test3' is used
to capture a new escaping continuation and pass it to the continuation
I'm calling.
2) I got confused by what state the stack should be after calling a
continuation. I had to remember to drop items off the stack that I no
longer needed after the 'callcc0' or 'callcc1' call as the stack is
restored to the point after callcc0 or callcc1 has popped the code to be
executed off the stack. So:

     : x ( a b c -- ) [ >r drop drop drop r> call ] callcc0 .s ;

     1 2 3 x ( 1 2 3 -- )

     : y ( a b c -- ) [ drop drop drop drop ] callcc1 .s ;

     1 2 3 y ( -- )

This is why there is the 'nip' in 'test2' and the 'drop' in test3 after
the callcc.

Am I understanding how continuations work in Factor correctly?

Chris.
--
   Chris Double
   chris.double@...

#1860 From: "Chris Double" <chris.double@...>
Date: Mon Jun 7, 2004 7:50 am
Subject: Generators in Factor
chris.double@...
Send Email Send Email
 
Here's some code to create a tree generator and generic code to iterate
over generators:

! Given a tree and an escaping continuation, call that continuation with
! a generator. The generator can be called with 'call-generator' and
! it will return successive items from the tree in-order from left to
right.
: make-tree-generator ( tree escape -- cont )
	 swap [
		 rot
		 call
	 ] callcc1
	 [ nip ] dip
	 swap
 	 [
		 [
		    cons
                    swap call
                 ] callcc1
		 [ 2drop ] dip
	 ] tree-each
         f swap call ;

! Given a tree, return a generator for that tree. The generator can be
! called with 'call-generator' and will return successive items from
! the tree in-order from left to right on each call.
: tree>generator ( tree -- generator ) [ make-tree-generator ] callcc1
nip ;

! Call a generator. It will return the next item
! in the tree at the top of the stack followed by the generator to call
to get the
! next value in the tree. If there are no values left in the three a
single f
! value is returned.
: call-generator ( generator --  generator v )
	 [ swap call ] callcc1 nip dup [ uncons swap ] [ ] ifte ;

! Given a generator call the given code on each generated item
: generator-each ( generator code -- )
	 swap
	 [
		 call-generator dup
	 ] [
		 swap
                 [ over [ swap call ] dip ] dip
	 ] while
	 2drop ;

[ 1 2 [ 3 4 ] 5 ] tree>generator
call-generator .
=> 1
call-generator .
=> 2
call-generator .
=> 3
call-generator .
=> 4
call-generator .
=> 5
call-generator .
=> f

[ 1 2 [ 3 4 ] 5 ] tree->generator [ . ] generator-each
=> 1
    2
    3
    4
    5

Note that generator-each will work on any 'generator' where the generator
is a function that has the signature ( escape-continuation -- [ v
generator ] or f ).

Chris.

--
   Chris Double
   chris.double@...

#1861 From: "Chris Double" <chris.double@...>
Date: Mon Jun 7, 2004 8:41 am
Subject: Re: [stack] Generators in Factor
chris.double@...
Send Email Send Email
 
The tree iteration example can be generalized further using the
equivalent of Pythons yield:

[ [ 1 2 [ 3 4 ] 5 ] [ yield ] tree-each ] make-generator
call-generator
  => 1
call-generator
  => 2
[ . ] generator-each
  => 3
     4
     5

Here's the implementation:

! Python's yield statement. From inside a block passed to make-generator,
! calling yield will return the value on the top of the stack to the
! caller (access to the caller provided by the escape continuation). When
! the generator is called again, execution is returned from the point
! after the yield call will the new escape continuation on the stack.
: yield ( escape value -- escape ) [ cons swap call ] callcc1 ;

! Given a code block create and return a generator that when called will
! pass the escape continuation to the code block. This block can then
! 'yield' using that continuation to return a value back to the caller
and
! suspend the generator.
: make-generator ( code -- generator )
	 [
		 [
			 swap
			 call
		 ] callcc1
		 nip
		 swap call
		 nip
		 f swap
		 call
	 ] callcc1
	 nip ;

! Simple yield example
[ 5 yield 10 yield 30 yield ] make-generator [ . ] generator-each
  => 5
     10
     30

[ 5 yield 10 yield 30 yield ] make-generator [ dup ] generator-each
  => 5
     5
     10
     10
     30
     30

! The previously given tree example can be done with these generic tools
[ [ 1 2 [ 3 4 ] 5 ] [ yield ] tree-each ] make-generator
call-generator
  => 1
call-generator
  => 2
[ . ] generator-each
  => 3
     4
     5
--
   Chris Double
   chris.double@...

#1862 From: "stevan apter" <sa@...>
Date: Mon Jun 7, 2004 9:22 pm
Subject: Re: [stack] Generators in Factor
sa@...
Send Email Send Email
 
this is interesting, but hard to follow.  it would be great
if one of you could write up a tutorial on continuations and
generators in factor (for dummies).  i.e. assume no knowledge
of factor beyond the simple stack processing model.  explain
each word as you introduce it.  &c.

again, i recommend close study of manfred's exemplary papers.
note that each one starts pretty much from the same place,
namely, ignorance of joy, and then introduces just those
words/concepts which are required by the topic.



----- Original Message -----
From: "Chris Double" <chris.double@...>
To: "concatenative mailing list" <concatenative@yahoogroups.com>
Sent: Monday, June 07, 2004 4:41 AM
Subject: Re: [stack] Generators in Factor


> The tree iteration example can be generalized further using the
> equivalent of Pythons yield:
>
> [ [ 1 2 [ 3 4 ] 5 ] [ yield ] tree-each ] make-generator
> call-generator
>  => 1
> call-generator
>  => 2
> [ . ] generator-each
>  => 3
>     4
>     5
>
> Here's the implementation:
>
> ! Python's yield statement. From inside a block passed to make-generator,
> ! calling yield will return the value on the top of the stack to the
> ! caller (access to the caller provided by the escape continuation). When
> ! the generator is called again, execution is returned from the point
> ! after the yield call will the new escape continuation on the stack.
> : yield ( escape value -- escape ) [ cons swap call ] callcc1 ;
>
> ! Given a code block create and return a generator that when called will
> ! pass the escape continuation to the code block. This block can then
> ! 'yield' using that continuation to return a value back to the caller
> and
> ! suspend the generator.
> : make-generator ( code -- generator )
> [
> [
> swap
> call
> ] callcc1
> nip
> swap call
> nip
> f swap
> call
> ] callcc1
> nip ;
>
> ! Simple yield example
> [ 5 yield 10 yield 30 yield ] make-generator [ . ] generator-each
>  => 5
>     10
>     30
>
> [ 5 yield 10 yield 30 yield ] make-generator [ dup ] generator-each
>  => 5
>     5
>     10
>     10
>     30
>     30
>
> ! The previously given tree example can be done with these generic tools
> [ [ 1 2 [ 3 4 ] 5 ] [ yield ] tree-each ] make-generator
> call-generator
>  => 1
> call-generator
>  => 2
> [ . ] generator-each
>  => 3
>     4
>     5
> --
>   Chris Double
>   chris.double@...
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>

#1863 From: "Chris Double" <chris.double@...>
Date: Mon Jun 7, 2004 11:34 pm
Subject: Re: [stack] Generators in Factor
chris.double@...
Send Email Send Email
 
On Mon, 7 Jun 2004 17:22:16 -0400, "stevan apter" <sa@...> said:
> this is interesting, but hard to follow.  it would be great
> if one of you could write up a tutorial on continuations and
> generators in factor (for dummies).

Sure, I'll see what I can do. I'm completely new to Factor myself so
don't know what makes good coding style or idiomatic usage though. Much
of what can be done with generators is done in languages like Joy by just
passing a code block to a combinator. The only thing the generator gets
you is the ability to 'early escape' (ie. it's effectively a lazy list).

The difficulty with the implementation I did was having to pass the
escape continuation around which I'm not sure is the best approach.

> again, i recommend close study of manfred's exemplary papers.

Yes, I agree they are great and very approachable.

Chris.
--
   Chris Double
   chris.double@...

#1864 From: Slava Pestov <slava@...>
Date: Tue Jun 8, 2004 6:13 am
Subject: New Factor release
slava@...
Send Email Send Email
 
Hi all,

I uploaded a new Factor release, 0.59 at www.jedit.org/factor/.

Several years ago I wrote a simple symbolic algebra program with complex
numbers and complex-valued elementary functions. I adopted the complex
number code to Factor with minimal effort.

There is a new document describing this, www.jedit.org/factor/math.txt.

Apart from complex number support, this release has the usual bug fixes
and cleanups.

Here is pretty much the entire set of words for working with complex
numbers. Yes, I'm showing them here because I think they're pretty neat
:-) (The definitions of the real-valued fsin, fcos, etc are not shown
here, and can be found in Factor.jar, factor/math/real-math.factor).

Since one of the goals of Factor is to be useful as a desktop
calculator, lease let me know if you find the math features useful, and
what I could do to improve them.

: conjugate ( z -- z* )
      >rect neg rect> ;

: arg ( z -- arg )
      #! Compute the complex argument.
      >rect swap fatan2 ; inline

: abs ( z -- abs )
      #! Compute the complex absolute value.
      >rect mag2 ; inline

: >polar ( z -- abs arg )
      dup abs swap arg ; inline

: cis ( theta -- cis )
      dup fcos swap fsin rect> ;

: polar> ( abs arg -- z )
      cis * ; inline

: exp >rect swap fexp swap polar> ;
: log >polar swap flog swap rect> ;

: sqrt ( z -- sqrt )
      >polar dup pi = [
          drop fsqrt 0 swap rect>
      ] [
          swap fsqrt swap 2 / polar>
      ] ifte ;

: ^mag ( w abs arg -- magnitude )
      [ [ >rect swap ] dip swap fpow ] dip rot * fexp / ;

: ^theta ( w abs arg -- theta )
      [ [ >rect ] dip flog * swap ] dip * + ;

: ^ ( z w -- z^w )
      swap >polar 3dup ^theta [ ^mag ] dip polar> ;

: cos ( z -- cos )
      >rect 2dup
      fcosh swap fcos * -rot
      fsinh swap fsin neg * rect> ;

: sec cos recip ;

: cosh ( z -- cosh )
      >rect 2dup
      fcos swap fcosh * -rot
      fsin swap fsinh * rect> ;

: sech cosh recip ;

: sin ( z -- sin )
      >rect 2dup
      fcosh swap fsin * -rot
      fsinh swap fcos * rect> ;

: cosec sin recip ;

: sinh ( z -- sinh )
      >rect 2dup
      fcos swap fsinh * -rot
      fsin swap fcosh * rect> ;

: cosech sinh recip ;

: tan dup sin swap cos / ;
: tanh dup sinh swap cosh / ;
: cot dup cos swap sin / ;
: coth dup cosh swap sinh / ;

: acosh dup sq pred sqrt + log ;
: asech recip acosh ;
: asinh dup sq succ sqrt + log ;
: acosech recip asinh ;
: atanh dup succ swap pred neg / log 2 / ;
: acoth recip atanh ;
: <=1 ( x -- ? ) dup complex? [ drop f ] [ abs 1 <= ] ifte ;
: asin dup <=1 [ fasin ] [ i * asinh -i * ] ifte ;
: acos dup <=1 [ facos ] [ asin pi/2 swap - ] ifte ;
: atan dup <=1 [ fatan ] [ i * atanh i * ] ifte ;
: asec recip acos ;
: acosec recip asin ;
: acot recip atan ;

#1865 From: Slava Pestov <slava@...>
Date: Tue Jun 8, 2004 6:21 am
Subject: Continuations and generators
slava@...
Send Email Send Email
 
Chris,

I think your generator library should be included with Factor; what do
you think? Your code is nicely written. You're certainly making more use
of continuations than I do :)

Two minor style notes; your definitions are maybe a tad too long. Also,
can you please use the documentation comment syntax:

: some-word ( ... )
      #! docs...
      #! more docs...
      ... ;

That way, the comments will be visible when the word definition is
inspected in the interpreter using "see".

Perhaps we could use a name other than 'yield'. My game library already
contains a word 'yield', with a different meaning. While vocabularies
will prevent the two names from clashing, it could still get confusing :)

Slava

PS: I forgot to incorporate tree-each in 0.59. It will be in the next
release.

#1866 From: Slava Pestov <slava@...>
Date: Tue Jun 8, 2004 6:31 am
Subject: The Factor workspace
slava@...
Send Email Send Email
 
Hi all,

I'm currently working on a 'workspace' feature for improved startup
speed and transparent persistence.

In 0.59, it is now stable enough to try out briefly. However, it has
problems with the compiler. This will be fixed in 0.60. In the meantime
use the -no-compile switch.

Try running the interpreter like so (all on one line):

java -cp factor.FactorInterpreter
      -db:factor.db.BTreeStore:factor.db:64
      -no-compile

The first time, this will create a b-tree database 'factor.db',
bootstrap the interpreter and save all objects from the user environment
to the database. Subsequent times, no source files are read -- the
database is simply opened and the interpreter begins executing words,
loading them as necessary.

Try defining words in a non-default vocabulary, they will persist;

IN: user
: hello-world "Hello world" print ;

... restart interpreter

hello-world
==> "Hello world"

The default vocabulary, 'scratchpad', does not persist.

Variable values are saved as well.

In particular, the following types of objects are persited:

- Tables. A table is a persistent namespace, created with <table>
(workspace vocabulary). Apart from being persistent, it does not differ
from a namespace created with <namespace> in any way. The global
namespace is a table. Vocabularies are also tables under the hood.

- Words and word definitions (except in the scratchpad vocabulary).

- Any object with a readable representation, such as strings, numbers,
lists, and so on.

- Compiled word definitions -- in theory anyway. Don't count on it
working in this release just yet.

It is possible that a persitent object might become unreachable -- at
present, no on-disk garbage collection is performed so it will continue
taking up space. Also, the b-tree still has bugs and sometimes the
database is corrupted.

Slava

#1867 From: phimvt@...
Date: Wed Jun 9, 2004 5:44 am
Subject: Re: [stack] Re: the false programming language
phimvt
Send Email Send Email
 
On Mon, 24 May 2004, Paul-V Khuong wrote:

> >    Date: Mon, 24 May 2004 17:24:02 +1100
> >    From: phimvt@...
> > Subject: Re: the false programming language
> >
> >
> > On Mon, 17 May 2004, stevan apter wrote:
[...]
> > I see, yes indeed, you are using a stack. The Joy
> > interpreter
> > of course does something which has the same net
> > effect, but
> > without pushing onto the program stack. This is
> > possible
> > because the evaluator uses recursion to keep track
> > of all
> > oustanding program fragments that are to be
> > executed. So the
> > fragments are never combined into a single
> > structure. The
> > recursion takes place whenever a combinator executes
> > something.
> > The advantage of never combining fragments into a
> > single structure
> > becomes very apparent when the fragment is very
> > long, and not
> > as short as the [2+] in your example. I am assuming
> > that in your
> > trace which I have marked, there are actually two
> > separate pushes
> > from "start" to "finish".
> >
> I'm not quite sure of what i am advancing, but if one
> implements stacks as linked lists (à la lisp), doesn't
> this disadvantage disappear? Pushing a link on a stack
> should be a simple matter of alterating a few CDRs and
> updating the stack pointer.

That depends. There are several ways of implementing all the
requisite "push-onto-the-program-stack". Let Q = [x y1 y2 ...yN z]
be the program fragment to be pushed from the stack back onto
the program P

1. Proper concatenation:
Concatenate Q with the remaining program P. This involves recursion:
recurse down into Q to find z, link to first node of P, and on
the way back make newnodes yN .. y2 y1 x. This takes time and
requires new nodes.
2. Destructive concatenation:
Find z, change its nil (cdr, end-of-list) field to point to the beginning
of P. Finding z is fast, changing the cdr is trivial). BUT: this
destroys the original structure of Q. If there are other links
pointing to Q (as there would be if it had been "dup"ed, or something
similar), this would be disastrous for a language like Joy.
3. Lazy concatenation:
Allow "pairing nodes" for the program stack. Replace P by
a single node "pair(Q,P)" - meaning: these are to be concatenated
to form a single list (stack). Fast, only needs one new node,
irrespective of how long Q is. But it is a new concept, and
the runtime system will need to know how to handle such new nodes.
4. Recursion in the runtime system:
Instead if shifting anything from the stack to the program, the
runtime system recursively calls itself to execute Q (which has been
popped) and when that is done it returns to executing P. (This
is the method which the Joy interpreter uses - function "exeterm")

Hope this helps.

>                               Note that i am currently
> working on such a system, where i try to stick as much
> as possible to the linearity of stack languages, so i
> might have some blinders on.

Keep in mind that once nesting to arbitrary depth is allowed,
even in linear languages, recursion is often an excellent way
to deal with it.

[...]

> PS. Pseudo-closures can be created with lambda-lifting
> and tacking arguments in front of the function.
> However, lambda-lifting mkes it impossible for
> different functions to share [mutable] variables. Does
> anyone see a way to allow such shared variables?

could you elaborate on this, please ?

   - Manfred

#1868 From: Slava Pestov <slava@...>
Date: Thu Jun 10, 2004 10:05 pm
Subject: New compiler docs
slava@...
Send Email Send Email
 
Hi everybody,

I finally sat down and properly documented the Factor compiler.

http://www.jedit.org/factor/compiler-use.txt
http://www.jedit.org/factor/compiler-impl.txt

Comments about the design are welcome. I hope I made the main ideas
clear, if not, there is always the source :-)

Slava

#1869 From: Don Groves <dgroves@...>
Date: Fri Jun 11, 2004 10:03 pm
Subject: Stack Terminology
pollyfonic
Send Email Send Email
 
Hi all,

The classic definition of a stack has only two operations,
push and pop.  Under this definition, only the top item is
available for use - the prototypical example being a stack
of dinner plates at a buffet, only the topmost plate is
visible to the diners.

The stack that Concatenators use also has permutation
operations defined, swap, rot, etc., which require that
more than just the topmost item be "visible", in a sense.

Maybe we should invent a new term for this kind of "stack"
to avoid any possible confusion.  I propose calling a
concatenative stack a "pack" - short for permutation stack
as used in the Henry Baker article, "Linear Logic and
Permutation Stacks -- The Forth Shall be First".

A pack then is a data structure with push, pop, and the usual
permutation operators defined on it.  Like a pack of cards
which is normally dealt from the top (by honest folks) but
can be shuffled as well.

Any agreement, booing and hissing, or other suggestions?
--
Don Groves

#1870 From: Slava Pestov <slava@...>
Date: Fri Jun 11, 2004 10:15 pm
Subject: Re: [stack] Stack Terminology
slava@...
Send Email Send Email
 
Hi,

Permutations can be defined in terms of pop/push; for example, dup is just

temp = pop();
push(temp);
push(temp);

swap is

a = pop();
b = pop();
push(a);
push(b);

... and so on.

Don Groves wrote:
> Hi all,
>
> The classic definition of a stack has only two operations,
> push and pop.  Under this definition, only the top item is
> available for use - the prototypical example being a stack
> of dinner plates at a buffet, only the topmost plate is
> visible to the diners.
>
> The stack that Concatenators use also has permutation
> operations defined, swap, rot, etc., which require that
> more than just the topmost item be "visible", in a sense.
>
> Maybe we should invent a new term for this kind of "stack"
> to avoid any possible confusion.  I propose calling a
> concatenative stack a "pack" - short for permutation stack
> as used in the Henry Baker article, "Linear Logic and
> Permutation Stacks -- The Forth Shall be First".
>
> A pack then is a data structure with push, pop, and the usual
> permutation operators defined on it.  Like a pack of cards
> which is normally dealt from the top (by honest folks) but
> can be shuffled as well.
>
> Any agreement, booing and hissing, or other suggestions?
> --
> Don Groves
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>

#1871 From: Martin Young <martin@...>
Date: Fri Jun 11, 2004 10:25 pm
Subject: Re: [stack] Stack Terminology
venusian_1999
Send Email Send Email
 
On Fri, 2004-06-11 at 23:03, Don Groves wrote:
> The classic definition of a stack has only two operations,
> push and pop [...] The stack that Concatenators use also has
> permutation operations defined, swap, rot, etc.

In my experience stacks are generally understood to include all the
operators you mention.  The classic stack orientated language, forth,
has them all and more.

I don't think a new term will do anything other than make concatenative
programming a teensy bit less accessible.

So I guess that's a boo and a hiss.

--
Martin Young, at home.

#1872 From: Don Groves <dgroves@...>
Date: Fri Jun 11, 2004 10:31 pm
Subject: Re: [stack] Stack Terminology
pollyfonic
Send Email Send Email
 
This is true, but it is not the way we implement or
visualize the situation.  In the same way, multiplication
can be defined in terms of addition but having a multiplication
operator greatly simplies the syntax of arithmetic.  Carrying
this to the extreme, all we need are the S and K combinators
to compute anything we want, why do we have all this other stuff?
--
Don


On Fri, 11 Jun 2004 18:15:18 -0400, Slava Pestov <slava@...> wrote:

> Hi,
>
> Permutations can be defined in terms of pop/push; for example, dup is just
>
> temp = pop();
> push(temp);
> push(temp);
>
> swap is
>
> a = pop();
> b = pop();
> push(a);
> push(b);
>
> ... and so on.
>
> Don Groves wrote:
>> Hi all,
>>
>> The classic definition of a stack has only two operations,
>> push and pop.  Under this definition, only the top item is
>> available for use - the prototypical example being a stack
>> of dinner plates at a buffet, only the topmost plate is
>> visible to the diners.
>>
>> The stack that Concatenators use also has permutation
>> operations defined, swap, rot, etc., which require that
>> more than just the topmost item be "visible", in a sense.
>>
>> Maybe we should invent a new term for this kind of "stack"
>> to avoid any possible confusion.  I propose calling a
>> concatenative stack a "pack" - short for permutation stack
>> as used in the Henry Baker article, "Linear Logic and
>> Permutation Stacks -- The Forth Shall be First".
>>
>> A pack then is a data structure with push, pop, and the usual
>> permutation operators defined on it.  Like a pack of cards
>> which is normally dealt from the top (by honest folks) but
>> can be shuffled as well.
>>
>> Any agreement, booing and hissing, or other suggestions?
>> --
>> Don Groves
>>
>>
>>
>>
>>
>> Yahoo! Groups Links
>>
>>
>>
>>
>>
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>
>

#1873 From: Don Groves <dgroves@...>
Date: Fri Jun 11, 2004 10:39 pm
Subject: Re: [stack] Stack Terminology
pollyfonic
Send Email Send Email
 
Forth is not a "classic stack" oriented language. The classic
stack as defined in any University class or book on data
structures has only the two original operators defined.
The Forth stack was the first to use the permutation operators,
Forth was not the first language to use stacks.

What I'm proposing is to make concatenative programming a
teensy bit more rigorous.
--
Don


On 11 Jun 2004 23:25:47 +0100, Martin Young <martin@...> wrote:

> On Fri, 2004-06-11 at 23:03, Don Groves wrote:
>> The classic definition of a stack has only two operations,
>> push and pop [...] The stack that Concatenators use also has
>> permutation operations defined, swap, rot, etc.
>
> In my experience stacks are generally understood to include all the
> operators you mention.  The classic stack orientated language, forth,
> has them all and more.
>
> I don't think a new term will do anything other than make concatenative
> programming a teensy bit less accessible.
>
> So I guess that's a boo and a hiss.
>

#1874 From: "asimjalis" <asimjalis@...>
Date: Fri Jun 11, 2004 10:45 pm
Subject: Re: [stack] Stack Terminology
asimjalis
Send Email Send Email
 
On Fri, Jun 11, 2004 at 03:31:03PM -0700, Don Groves wrote:
> This is true, but it is not the way we implement or visualize
> the situation.  In the same way, multiplication can be defined
> in terms of addition but having a multiplication operator
> greatly simplies the syntax of arithmetic.  Carrying this to
> the extreme, all we need are the S and K combinators to compute
> anything we want, why do we have all this other stuff?

1. Whether you define number theory with multiplication or not,
in both cases you would call the underlying model the set of
numbers. Adding new operations defined in terms of previous ones
should not change the name of the underlying model.

2. Multiplication is not implemented in terms of addition in most
architectures. Yet, we persist in calling the underlying data
structure integers.

Asim
----
http://asimjalis.blogspot.com

#1875 From: Don Groves <dgroves@...>
Date: Fri Jun 11, 2004 11:00 pm
Subject: Re: [stack] Stack Terminology
pollyfonic
Send Email Send Email
 
Sorry, but I don't understand your comments in the context
of the operations defined on a stack.
--
Don


On Fri, 11 Jun 2004 22:45:39 -0000, asimjalis <asimjalis@...> wrote:

> On Fri, Jun 11, 2004 at 03:31:03PM -0700, Don Groves wrote:
>> This is true, but it is not the way we implement or visualize
>> the situation.  In the same way, multiplication can be defined
>> in terms of addition but having a multiplication operator
>> greatly simplies the syntax of arithmetic.  Carrying this to
>> the extreme, all we need are the S and K combinators to compute
>> anything we want, why do we have all this other stuff?
>
> 1. Whether you define number theory with multiplication or not,
> in both cases you would call the underlying model the set of
> numbers. Adding new operations defined in terms of previous ones
> should not change the name of the underlying model.
>
> 2. Multiplication is not implemented in terms of addition in most
> architectures. Yet, we persist in calling the underlying data
> structure integers.
>
> Asim

#1876 From: "Chris Double" <chris.double@...>
Date: Sun Jun 13, 2004 2:34 am
Subject: Re: [stack] Continuations and generators
chris.double@...
Send Email Send Email
 
On Tue, 08 Jun 2004 02:21:02 -0400, "Slava Pestov" <slava@...>
said:
> I think your generator library should be included with Factor; what do
> you think? Your code is nicely written. You're certainly making more use
> of continuations than I do :)

Sure, if you want to include it that's fine with me. Continuations
combined with a Forth/Joy like language is an interesting combination and
is the area I'm playing with the most at the moment. Also my main job is
maintaining a continuation based web application server in Scheme so it
interests me to compare the approaches of the two languages. I suspect
that because continuations can't be compiled that some of the things I'm
doing won't be very efficient or the best way of doing things though.

> Two minor style notes; your definitions are maybe a tad too long. Also,
> can you please use the documentation comment syntax:

Sure, I'll change the code. The funny thing is, although I have long
definitions, I write them piece by piece and test each bit then combine
them into the one definition! I need to come up with names and keep the
smaller pieces around. I marvel at the nicely factored code in the Factor
source code and in the Joy examples on the Joy website.

> Perhaps we could use a name other than 'yield'. My game library already
> contains a word 'yield', with a different meaning. While vocabularies
> will prevent the two names from clashing, it could still get confusing :)

"suspend" is a common name for this. Or maybe gen-yield?

Chris.
--
   Chris Double
   chris.double@...

Messages 1847 - 1876 of 4941   Oldest  |  < Older  |  Newer >  |  Newest
Add to My Yahoo!      XML What's This?

Copyright © 2010 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines NEW - Help