Re: [stack] What does "concatenative" actually mean?

William Tanksley <[email protected]>
Newsgroups gmane.comp.lang.concatenative
Message-ID <1236284778.32020.4900.camel@tanksley>
John Nowak wrote:
> John Cowan wrote:
> > John Nowak scripsit:
> >> In a concatenative language, one thing you can do as add the 'world'
> >> to the top of the stack and have all operations work below it except
> >> those that perform IO. This does let you sort of hand-wave and claim
> >> the language is purely functional. The problem is that *everything*
> >> now has a forced evaluation order, not just those things that perform
> >> IO. In other words, even though your language is purely functional,
> >> you're still essentially stuck with having to use eager evaluation.

I don't see why this approach forces a totally fixed evaluation order.
It seems to me that it forces a fixed order only for words which don't
"work below the world" (I'm not certain precisely what you mean by
that).

In general, you don't have to add the world to the top of the stack; you
can add the I/O to the "state of the system", which includes the stack.
A dumb optimizer has to assume that every operation changes the entire
state; a smarter one knows to look at stack effects; a really smart one
knows to look for I/O effects.

> >> This is why I claim this approach is mostly hand-waving; it doesn't
> >> let you do anything different than you otherwise would.
> > Nobody ever claimed that Joy was lazy; "pure functional" does not mean
> > "pure, functional, and lazy".  Lazy languages have their virtues, but
> > so do eager ones.

> I never claimed anyone ever claimed Joy was lazy. My claim was  
> essentially that, if Joy were purely functional in the same sense  
> Haskell was, you *could* evaluate it lazily if you wanted to. Given  

IMO a stronger description would be "out of order execution". You want
an optimizer to be able to decide that one particular word can be
executed prior to a word that appears in the source before it. The
phrase "lazy execution" would seem to imply -- in the context of a
concatenative language -- that a function could leave a "promise" on the
stack. In an applicative language, 'lazy' means that actual parameters
can be bound to such promises.

And you _can_ execute Joy out of order. You just have to watch your
dataflow. Doing so does not depend on whether the code is functional; it
depends on dataflow.

> that you cannot do so, I don't think it is correct to call it "purely  
> functional". The reason for this is that it does not have the property  
> that you can replace an expression with the result of evaluating it as  
> Haskell does (i.e. referential transparency). Such a property is what  
> enables sensible lazy evaluation.

No, I wouldn't claim that; I just claim that concatenative languages
_can_ be purely (or partially, or not at all) functional, and still
retain full concatenativity. Of course, they lose OTHER advantages.

> I'm aware eager languages have their virtues. I did after all say I'd  
> prefer Disciple Haskell (which is eager and uses an effect system to  
> control effects instead of monads).

Your effects inference work is very interesting.

> > Similarly, it has a type system, just not a static type system.

> I'll clarify then: You need a static type system to enforce that the  
> world value is used properly.
> The only possible alternative I can think of is to reference count  
> everything and error if attempting to use the world value when it has  
> more than one reference to it. Unfortunately, this approach is  
> unsatisfactory in a number of ways that I could elaborate on if anyone  
> is interested.

One can also simply make it impossible to duplicate the world by not
putting it on the stack.

> - John

-Wm
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.