You are on page 1of 83

Lambda the Ultimate

Home » forums » LtU Forum

Concatenative Language Kont
An interesting project. Kont came out of an attempt to design a programming language in which every program was expressed in continuation-passing style. A concatenative language is a language in which programs are formed by the concatenation of smaller primitives, ala Forth. By Chris at 2005-08-08 16:17 | LtU Forum | previous forum topic | next forum topic | other blogs | 13661 reads

Comment viewing options
Select your preferred way to display the comments and click "Save settings" to activate your changes.

A comment about concatenative languages in general
I don't get why anyone considers concatenative languages to be suitable for high-level programming. How are you supposed to be able to remember or keep track of what is on the stack at any given point? How can you build reusable encapsulated abstractions? I can't imagine writing any nontrivial program in a concatenative language; it seems like a tour de force comparable to writing a Turing machine program, or directly in the lambda calculus using de Bruijn indices. As low-level languages to be used as a compilation targets, I can kind of see the point. But enthusiasts for Forth, etc. seem to be saying that they write nontrivial application programs in these languages. How? By dhopwood at Tue, 2005-08-09 20:25 | login or register to post comments

With small, well-behaved words
(Note, I don't use any concatenative language, although I do use an HP-41 and have programmed it) The trick is simply to use small, functional words (i.e., local stack effects). That way, you only have to treat words as black boxes that take input and give output, aka functions. When you start having to track the stack, it's probably a good hint you need to break the word down in a couple more intuitive words (or that your interface for that word is extremely messy).

By pkhuong at Tue, 2005-08-09 23:21 | login or register to post comments

Lots of factoring
The trick is small, easily testable words. Any time you do lots of stack manipulations is a sign that you need to refactor. 'Thinking Forth' has lots of good advice in this area: http://thinking-forth.sourceforge.net Manfred von Thun's Joy pages also covers this in some of the articles. His one on the quadratic formula for example: http://www.latrobe.edu.au/philosophy/phimvt/joy/jp-quadratic.html By doublec at Tue, 2005-08-09 23:28 | login or register to post comments

The quadratic example in that last URL is a good example...
... but I think it just supports my point.
-b +/- sqrt(b^2 - 4 * a * c) ----------------------------2 * a (define quadratic-formula (lambda (a b c) (let ([minusb (- 0 b)] [radical (sqrt (- (* b b) (* 4 ( * a c))))] [divisor (* 2 a)] ) let ([root1 (/ (+ minusb radical) divisor)] [root2 (/ (- minusb radical) divisor)]) (cons root1 root2)))))

The structure of the Scheme code directly reflects the structure of the formula. Indeed, there are only trivial notational differences between the formula and the code, as we can see by writing the formula with the same auxiliary variables and in prefix notation:
quadratic-formula(a, b, c) def= (root1, root2) where minusb = - 0 b radical = sqrt (- (* b b) (* 4 (* a c)))) divisor = * 2 a root1 = / (+ minusb radical) divisor root2 = / (- minusb radical) divisor

Compare that with the 2nd version in Joy (the one suggested to be "the best of the three in this note"):
quadratic-2 == ] [ [ [ pop pop 2 * ] [ pop 0 swap - ] [ swap dup * rollup * 4 * - sqrt ] ] [i] map ] ternary i [ [ [ + swap / ] [ - swap / ] ] [i] map ] ternary. # a b c => [root1 root2 # divisor # minusb # radical # root1 # root2

** Huh? ** I don't think it's just my lack of familiarity with Joy that is at issue here: the code structure is simply quite different from the formula. It's impossible to understand

what this code is doing without thinking about how it uses a stack that is not present in the original problem (and that could map to the problem in many different ways). The difference that stands out most is that none of the variables are explicitly named -the names on the right are only comments. These comments are not equivalent to using names in the code -- what if they were wrong? The variables have to be referred to by keeping track of their position on the stack (which is what I was getting at in the reference to de Bruijn indices above). OK, it is possible to mitigate this problem by minimizing the size of the stack at any given time, but the risk of making an error is going to be larger for any given number of variables than it is in an equivalent program that uses names. Some proportion of those errors won't be found by testing. For a large program, that is likely to add up to an unacceptable risk. [Edit: corrected "0 - b" to "- 0 b"] By dhopwood at Wed, 2005-08-10 03:51 | login or register to post comments

Re: Quadratic formula
In Factor, the quadratic formula is a non-problem. Just embed a domain-specific language for infix arithmetic and be done with it. It is very easy to write such a language that compiles down to concatenative code which then runs through Factor's native compiler. It already exists; see contrib/algebra/ in the distribution. About the rate of errors being higher; my experience is not conclusive either way. I have found that the time going from noting a bug, to resolving it, to fixing it is very short in Factor. Unit tests flow easily, and debugging is pure joy with tools like our GUI inspector, single-stepper, various tracing tools, and of course, the grand-daddy of them all, the REPL. Many stack errors can be caught statically, using the stack effect inferencer. I will admit, I have had a few several-day-long debugging marathons, however these had nothing to do with the stack, but issues such as buggy relocation in the compiler's code generator leading to clobbered code, or incorrect rewriting rules in the optimizer, and so on. On the other hand, the other large piece of software I maintain, jEdit is written in Java. Like all Java software, it is a pain to maintain, and I always find new, mysterious bugs that are almost impossible to resolve, due to Java's non-interactive, static nature, and laborous edit/compile/run cycle. By slava at Wed, 2005-08-10 06:39 | login or register to post comments

Not the point
Just embed a domain-specific language for infix arithmetic and be done with it. And then you're not writing the arithmetic in a concatenative language. The example just happened to use arithmetic, though; the criticisms (e.g. about the potential error-

proneness of the stack implicitly introducing variables without names) are not specific to that case. It is very easy to write such a language that compiles down to concatenative code which then runs through Factor's native compiler. Right -- I didn't say that concatenative languages aren't suitable as intermediate languages (although I wonder why you would use them in preference to a register-based IL, if you're targetting a register-based machine). I have found that the time going from noting a bug, to resolving it, to fixing it is very short in Factor. And in applicative languages as well, usually, if you notice the bug. ... jEdit is written in Java. Like all Java software, it is a pain to maintain, ... Did I inadvertently defend Java? By dhopwood at Wed, 2005-08-10 14:07 | login or register to post comments

"Higher-Order" intermediate language?
Maybe it could function this way, as something easier to reason about than a registerbased machine? It seems there are a few orthogonal ways languages like Forth differ from e.g. Scheme: * postfix vs. prefix * stack-manipulation vs. named-variables * eschewing of parentheses (though they might make for greater readability) Scheme & other languages (C) can of course use a stack; they just address it differently. [Anyone use a postfix language that uses named variables?] By dbfaken at Wed, 2005-08-10 15:31 | login or register to post comments

Monads
Just embed a domain-specific language for infix arithmetic and be done with it. And then you're not writing the arithmetic in a concatenative language. Let's try rewriting that a little bit differently... Just use monads (like an embeded domain-specific language) for sequencing sideeffects and be done with it. And then you're not writing functions in a pure language.

That's a classic sign of a low-level language (think of assembler). By Anton van Straaten at Wed. Factor has a stack effect inferencer that could be used to check that foo does in fact return the right values. 2005-08-10 18:02 | login or register to post comments I agree I agree. multiple-value-bind and setf in Common Lisp programs? They also have nothing to do with the problem domain.By Greg Buchholz at Wed. like pop. In the concatenative context.could return a value other than 33. The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain. this sort of behavior is called "unsafe": that an abstraction is not protected from unauthorized outside interference. dup. This kind of non-local side effect for bugs is reminiscent of something like a pointer error. and it violates its contract by mutating the object into an incorrect state. "like assembler"? This kind of non-local side effect for bugs is reminiscent of something like a pointer error. In other contexts. you're making an assumption about what's on the stack. Suppose you write a function that takes a mutable object as input. swap. Is CL low level. and rollup What about names like let. swap. as though an expression such as: (let ((x 33)) (foo) x) . how is this any different from a function with an invalid stack effect? Are you going to argue in favor of purelyfunctional languages. labels. like pop. dup. the programmer depends heavily on abstractions which the language doesn't enforce or even know about: every time you use pop. but that assumption could be violated by unrelated code. you can play language lawyer and claim that since the language doesn't have the notion of a local binding. and rollup... this sort of behavior is called "unsafe": that an abstraction is not protected from unauthorized outside interference. 2005-08-10 15:48 | login or register to post comments Incorrect The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain. In other contexts. which are solely the domain of academics? . Also. that would only be a good argument if programmers didn't need to rely heavily on faking local bindings in concatenative languages. in concatenative languages. nothing is being violated. if foo had a bug. However.

Second. they're still more meaningful to the problem being solved than stack operators are. are enthusiastic about them. That's not a good argument from the language user's perspective. I'm referring partly to frequency of occurrence. Is CL low level. Are you going to argue in favor of purely-functional languages. and it's a purely functional language. to transparently guarantee the safety of unrelated "bindings" (or whatever you want to call them in a concatenative language). Having all programs depend implicitly on a stack which can be directly side-effected by any function is a step backwards in this respect. what stands out? If you see very few names that relate to the problem domain. What logic is used to justify the idea that you can only have global names? It boils down to something like "because it's easy to implement a language that way. Simple refutation: Erlang is used to run telecom switches. It might explain why you. it's demonstrably false that they are "solely the domain of academics". how is this any different from a function with an invalid stack effect? It's different in that the caller knows that he's passed a mutable object to that function — it's not a case where an essentially unrelated function can destroy an abstraction which it has no connection to. that's a problem for the comprehensibility of the code. since they all support global names. 2005-08-10 16:11 | login or register to post comments Incorrect pop Correct push What about names like let. which are solely the domain of academics? First. However. labels. Suppose you write a function that takes a mutable object as input. There are plenty more examples where that came from. Could be used? That implies that this is not something which happens automatically. and it violates its contract by mutating the object into an incorrect state. though. which would otherwise not need to be worried about. as an implementor of such a language. and many names that relate to some abstraction in the programming language. which is why the most powerful languages provide ways to control side effects. . Even concatenative languages acknowledge that names are important. multiple-value-bind and setf in Common Lisp programs? They also have nothing to do with the problem domain. many of the names you mentioned are used to introduce names that are relevant to the problem domain. "like assembler"? First. When you look at a piece of code. Factor has a stack effect inferencer that could be used to check that foo does in fact return the right values. it's true that side effects are a major cause of problems. As such. If that's the case. then this creates an area that the user has to worry about. It's hard to see how that would be a benefit.By slava at Wed. and possible to get away with it and work around it".

because I don't follow it. then notice that this toy interpreter is hard to work with. 2005-08-10 17:02 | login or register to post comments More incorrect claims What logic is used to justify the idea that you can only have global names? I'm not sure what logic is used.Second. to transparently guarantee the safety of unrelated "bindings" (or whatever you want to call them in a concatenative language). while I wouldn't use purely functional languages in every context. but you're not going to convince many people by blustering about it and making over-the-top criticisms of other. and written a toy Joy interpreter. but I don't think that those languages can support the kind of claims you seem to want to make. which would otherwise not need to be worried about. and I do write code which avoids side effects for the most part. 2005-08-10 17:09 | login or register to post comments Is not/is so titles are boring . like Scheme. Lest I be taken as entirely negative about concatenative languages. So your only experience with concatenative languages is having written a toy Joy interpreter? If I write a toy interpreter for a simple applicative language. experimented with Joy. If that's the case. proven languages. I'd point you here. Did you even bother to look at it? Could be used? That implies that this is not something which happens automatically. By slava at Wed. and can be fun and useful in certain kinds of applications. I should mention that I've written systems in Forth. This has numerous provable benefits — if you want to start arguing against them. I should mention that I've written systems in Forth. proven languages. Show where I have been "blustering" and making over-the-top criticisms. but you're not going to convince many people by blustering about it and making over-thetop criticisms of other. It's hard to see how that would be a benefit. By Anton van Straaten at Wed. experimented with Joy. then this creates an area that the user has to worry about. I do use languages that encourage and support the controlling of side effects. If Factor can support such claims. Lest I be taken as entirely negative about concatenative languages. should I conclude that applicative languages on the whole are useless? If Factor can support such claims. I think they're very interesting languages. that would be interesting. I could easily add some tools to do this automatically for every new word definition. and written a toy Joy interpreter. Factor has variables and nested namespaces and scope. that would be interesting.

Does Factor provide such a feature? I could easily add some tools to do this automatically for every new word definition. some months ago. or Factor in particular. then I'd suggest we abandon the poorly-defined term "concatenative" and switch to something like "direct stack manipulation languages". but some of the quotes in question are as follows: . i. because I don't follow it. I claim that the combination of my experiences with Forth and Joy.e. temporary name/value bindings that can be relied on for the life of a procedure.I'm not sure what logic is used. combined with knowledge of programming language semantics and experiences with a variety of other languages. and written a toy Joy interpreter. I've looked briefly at Factor. I've already responded to specific cases. and not even capable of implementing their own optimizing native compilers. The discussion started out more generally. So your only experience with concatenative languages is having written a toy Joy interpreter? Is it your intent to get into a definitional argument now. Are you going to argue in favor of purely-functional languages. Factor has variables and nested namespaces and scope. Show where I have been "blustering" and making over-the-top criticisms. we need to be clear about whether we're discussing actual concatenative languages in general. Did you even bother to look at it? Well. What I was referring to is that these languages demonstrate that they recognize that supporting safe bindings between names and values is important. One question is that as you add such features. might you reach a point where it becomes apparent that simply addressing the issue at the language level is a good idea? Lest I be taken as entirely negative about concatenative languages. which are solely the domain of academics? By Anton van Straaten at Wed. 2005-08-10 19:55 | login or register to post comments You're just trolling I've already responded to specific cases. but within individual procedures. experimented with Joy. I didn't state that clearly. and say that Forth is not concatenative? If so. I should mention that I've written systems in Forth. but I didn't find that it sufficiently addressed the sort of concerns I've mentioned. makes it possible for me to make comparisons and draw conclusions related to certain properties of these languages. Since it's still under development. That sounds as though it would be useful. they don't provide such a feature. which is more meaningful in any case. but some of the quotes in question are as follows: This is a richer level of functionality than offered by most languages discussed on this web site one could even conclude that applicative languages are totally non-productive. it'll be interesting to see how it turns out over time. Regarding my point about global names.

I've responded to every one of your substantive points. assuming that what you have to say has more basis in rational argument than your comments on those languages so far. So why do you do the equivalent thing here? By slava at Wed. Instead of discussing the Kont language. since you haven't addressed my points. I'm having difficulty discerning the rules you think I should be following here. Your assumption is incorrect. and I've defended that in exchanges with others. You don't even bother refuting my points Which points are those? Afaict. You're free to dispute my points. I responded to another post which made a point which I agreed with. but lashing out at academia. and instead draw blanket conclusions and generalizations based on your limited experience with Joy and Forth. claiming that static typing is overly restrictive. So why do you do the equivalent thing here? . applicative languages. Instead of discussing the Kont language. and research languages doesn't qualify. you decided to talk about Factor. "most languages discussed on this web site". you decided to troll instead. It's particularly ironic given that your own language would. by some definitions. with rational arguments. the very first post to this thread was your disparaging claim that concatenative languages are unsuitable for developing applications. However. but I assume from your general reaction that you disagree. I know you wouldn't be very happy if I went and jumped into threads where discussion of ML and Haskell is taking place. qualify as a research language. You don't even bother refuting my points. please You see. Heh. the very first post to this thread was your disparaging claim that concatenative languages are unsuitable for developing applications. I said concatenative languages show a particular sign of being a low-level language. I'm not even sure if you disagree. I suggest you reread the thread more carefully. I'm not trolling.You see. I know you wouldn't be very happy if I went and jumped into threads where discussion of ML and Haskell is taking place. claiming that static typing is overly restrictive. 2005-08-10 22:29 | login or register to post comments Substance. I noticed that instead of discussing the Kont language yourself. you decided to troll instead. and instead draw blanket conclusions and generalizations based on your limited experience with Joy and Forth. I believe that's true.

but for whatever reason. and among other things. no matter how low-level you prove them to be.a. it was an attempt to characterize one of the semantic issues that distinguishes concatenative languages from languages with namebased procedure-local abstractions (a. If a C compiler uses an intermediate form that is single assignment only. I'm interested in the semantics of programming languages. the point is to understand more about programming language features and their consequences. I'd just like to remind you that you won't convince Slava or me to stop using concatenative languages because we're perfectly comfortable with them. local variables). I said concatenative languages show a particular sign of being a low-level language. it was an attempt to characterize one of the semantic issues that distinguishes concatenative languages from languages with name-based procedure-local abstractions (a. I believe that this issue is one of the factors which underlies a common negative user reaction to these languages. in a way that other languages happen to use as an intermediate form. By Anton van Straaten at Thu.) But I really have no interest in changing your choice of programming language. They just handle things differently. I'd just like to remind you that you won't convince Slava or me to stop using concatenative languages because we're perfectly comfortable with them. As someone interested in concatenative languages. how those semantics relate to the user experience of programming. though. Other people have.This is a forum for discussion of programming languages. if you don't understand Slava (even though he's being perfectly clear). you haven't chosen to offer those yet. You sound almost as though you're nervous I might succeed! . This does not mean at all that it is worse.k. Rather. Rather. just different. local variables). I believe that this issue is one of the factors which underlies a common negative user reaction to these languages. My original post in this thread wasn't intended as a critique of Kont specifically (and besides. Of . I would think you might have some interesting thoughts on the matter.a. does that mean that C higher-level than any kind of single assignment form? Of course not. which is the reason I'm here. 2005-08-11 17:33 | login or register to post comments reference sense pop First.k. 2005-08-11 00:20 | login or register to post comments Let me reiterate those substa Let me reiterate those substatiative points. no matter how low-level you prove them to be. How are local variables abstractions? Could you explain that? How are they more abstract and flexible than stack shuffling operators? By Daniel Ehrenberg at Thu. First. No. Brian Mastenbrook has already heard my opinion on this issue). I don't think concatenative languages are more low-level.

to deal with the constraints of single assignment — the fact that those extra operations aren't necessary in the C source indicates that they are irrelevant to the expression of the original problem.. When you push a value on a stack and later apply some operation to that value. You've suggested elsewhere that the same is true of lexical names. It can also help in assessing the appropriateness of a language in a given situation. The irrelevant thing in this case is direct stack manipulation. . Direct stack manipulation alone doesn't scale very well. that's not what I'm doing. this can lead to changing preferences. which you've acknowledged: "there are only a few cases where the stack really matters". we were reminded that "any time you do lots of stack manipulations is a sign that you need to refactor. This has been covered in a few posts.any kind of single assignment form". This does not mean at all that it is worse. However. The name refers to some other thing. programming style. that's also a kind of abstraction. How are local variables abstractions? Could you explain that? How are they more abstract and flexible than stack shuffling operators? A local variable is an abstraction in the same way that any name is an abstraction. The way you can tell that is to look at the extra operations that are being performed in the single-assignment code. Early on in the thread. and connected to Alan Perlis' observation that low-level implies that "programs require attention to the irrelevant". a good understanding of PL features and how they affect programs and programming can make you a better programmer in any language. which (implemented properly) are more scalable. If a C compiler uses an intermediate form that is single assignment only. as every concatenative programmer already knows. That particular issue is different in a way that's more low-level. safer abstractions than storing values on a stack. drawing conclusions about ". keeping track of values via stack manipulation gets more complex. That's abstraction. and help with cutting through hype about particular programming languages. not all abstractions are equal. in a way that other languages happen to use as an intermediate form. just different. and indicates that the single-assignment form is lower level. They just handle things differently. in most cases.course. and concluding that this is a lower-level way of dealing with abstraction over values than using names. I'm looking at specific languages that regularly embed direct stack manipulation operators in their code.e. As procedures get bigger. etc — mine have certainly changed a great deal over the years. C code is certainly usually higher-level than any internal single-assignment form it's likely to be compiled to. If your concern is with generalization. i. and we can use the name and manipulate whatever it refers to without knowing which specific thing it refers to.. But more importantly." And what do you do when you refactor? You create names. does that mean that C higher-level than any kind of single assignment form? Of course not. but I've addressed this in my response to your last point below. I don't think concatenative languages are more low-level.

e. In general. non-local names used in conjunction with the stack locally works out very well most of the time. both expressions could have the exact same computational effect. Keep in mind I've programmed in these languages. But omitting names is one thing. One of the critical features of names is that they can actually serve two purposes: 1. you have a double loss of the program's ability to express its algorithm to the human reader. and wherever this replaces the use of names which might be informative. within a procedure? And of course. and I'm familiar with the arguments. 2. My main interest is in characterizing the differences in a more specific way than just saying something along . However. it's not necessary to name the intermediate values. a name is a "reference". A name can provide information to programmers about the value. If a language commonly forces you to omit names. languages which force you to name e. if names are so useful and important when code scales up past a single procedure. Using a stack to abstract values hardly ever serves the second purpose above. and why the expression you gave elsewhere in this thread was compiling dataflow optimize linearize simplify generate. or its role in the computation. Defined appropriately. instead of a b c d e f. A name acts as a way to refer to a value. either. but one is much more meaningful to us than the other. many languages demonstrate that they are. and that's something that should be done thoughtfully. a name can also have a "sense" or "connotation". Using stack shuffling operators is a low-level detail no matter how you look at it. mightn't they be useful locally. or can be said to "denote" some value. that's something worth taking a close look at. i. naming every value isn't necessary or appropriate. In the expression quoted above. etc. The most convincing arguments. we're omitting one of the only things which connects the code to the problem it's solving. I'm sure there's plenty in what I've written above for a concatenative fan to object to. I could make them myself: you don't need local names because factoring keeps procedures small enough to be tractable. When we omit names from our code.e.g. This why we try to pick informative names.So one question is. replacing them with operators that manipulate an abstraction (the stack) that's not otherwise directly relevant to the computation is something else entirely. which can have various benefits. it's difficult to argue that expressing most problems in terms of an essentially LIFO stack is an approach that makes sense in and of itself. etc. i. function return values just to be able to rearrange them to pass to another function are similarly obscuring the solution to the problem. the job of the language implementation is simplified. and most languages support this sort of omission of names in one form or another. have to do with the benefits of that approach to language implementation: by pushing some of the work of arranging the abstraction mechanism onto the user. I think.

2005-08-12 03:55 | login or register to post comments 2Variable In #comment-8723. What do you think of tacit programming in J? . the memory manager. no. I ran into it while skimming through Forth Sorts Fruit Down Under by Paul Frenger in ACM SIGPLAN Notices. Believe it or not. How do you define power? The APL dialects and derivatives. but if we can't describe their effect clearly other than just listing the technical features. or "I think this is a fun way to program". those names are unnecessary. Anton wrote: So one question is. There are obviously differences. are enthusiastic about them. are all much more expressive than any purely functional language. By Anton van Straaten at Fri. What logic is used to justify the idea that you can only have global names? It boils down to something like "because it's easy to implement a language that way. that implies a gap in our understanding. for example. the variables are simply assigned useless placeholder names. mightn't they be useful locally. In a great deal of applicative code. the reason they're frowned upon is because in most cases they are an impediment to proper factoring. I/O handling (mostly for accessing files). many languages demonstrate that they are. It might explain why you. vol. 8. aug 2005 (not yet online): The CF [ColdForth] manual has other interesting chapters to describe its features: numbers/parameters (CF supports local variables via stack frames). TCP/IP capability and the multi-tasker. though. strings. as an implementor of such a language. not everyone considers Haskell and friends to be the pinnacle of language design or expressive power. 2005-09-14 12:11 | login or register to post comments 2drop Even concatenative languages acknowledge that names are important. it's true that side effects are a major cause of problems.the lines of "I don't like this". and possible to get away with it and work around it". within a procedure? And of course. if names are so useful and important when code scales up past a single procedure. which is why the most powerful languages provide ways to control side effects. object-oriented extensions. since they all support global names. It's worrying to me that this claim of "most powerful" is accepted here essentially on faith. I'm not sure if the following quote supports your contention. 40. for example. Aside from the fact that several concatenative languages do actually support local variables. This should indicate something to you: most of the time. By el-vadimo at Wed. That's not a good argument from the language user's perspective. However.

How do you define power? Hopefully my response above gives a better idea of what I was getting at. the list goes on). such as declaring that a method cannot side-effect the object it's associated with." Perhaps you should reconsider whose claims are 'over the top'. Ada — languages which provide qualifiers like "const" that allow the programmer to guard in a meaningful way against unwanted side effects. What do you think of tacit programming in J? . not just at the language level but in the design of systems. Functional languages just implement this at the language level on a more comprehensive basis. are they safe from being changed by unrelated stack operations? the reason they're frowned upon is because in most cases they are an impediment to proper factoring. but you're not going to convince many people by blustering about it and making over-the-top criticisms of other. like "expressiveness".e. proven languages. I said that "it's true that side effects are a major cause of problems.g. 2005-08-10 23:38 | login or register to post comments Stacks of responses Aside from the fact that several concatenative languages do actually support local variables Do those local variables protect against the issue I've raised. Is that an issue specific to the concatenative languages? Otherwise. those names are unnecessary. in languages with traditional local variables. in most cases. I didn't say that. not just on individual variables but also over larger scopes. that would be interesting.Simple refutation: Erlang is used to run telecom switches. not everyone considers Haskell and friends to be the pinnacle of language design or expressive power. The APL dialects and derivatives. Controlling of side effects is a major theme in very demanding systems. the variables are simply assigned useless placeholder names. This should indicate something to you: most of the time. which is difficult to formalize satisfactorily. and it's a purely functional language. for example. There are cases where a stack is certainly the right abstraction to use. which is why the most powerful languages provide ways to control side effects. I don't see how using "push" and "pop" to abstract values helps address that. "power" is one of those things. Can you give an example? In a great deal of applicative code. dets. If Factor can support such claims. i. Erlang is not purely functional (ets. including e. C++. Believe it or not. Java. I find it hard to see how names are an impediment. or directly in the lambda calculus using de Bruijn indices." I would include many imperative languages in that list. of course. preferably demonstrated in practice. Obviously. but it could perhaps be characterized as the ability to handle very demanding tasks. process dictionary. By Mackenzie Straight at Wed. It's worrying to me that this claim of "most powerful" is accepted here essentially on faith. The original poster likened concatenative programming to "writing a Turing machine program. mnesia. are all much more expressive than any purely functional language.

even with the I/O monad and the things it can talk to? My real point was that a strong emphasis on avoidance of side effects is not something that's solely the domain of academics. In functionalapplicative languages. loop indices. I can see his point. 2005-08-11 01:26 | login or register to post comments A temporary by any other name.. the list goes on). for the reasons stated elsewhere in this thread. process dictionary.g. dets. although if you focus purely on how local value abstraction works. This should indicate something to you: most of the time. Define it however you like — very functional? Do you consider Haskell purely functional. just on a scale greater than the local procedure. Ideally. I think. and I don't think it's over the top to say that. anything that interacts with a traditional database is ultimately impure. the variables are simply assigned useless placeholder names. when considered as a whole system. those names are unnecessary. The need for temporaries with useless names. it's almost always possible to avoid this. 2005-08-11 01:18 | login or register to post comments What's in a name? Aside from the fact that several concatenative languages do actually support local variables. However. Also. or directly in the lambda calculus using de Bruijn indices. In a great deal of applicative code. The cons tend to have to do with being more difficult to reason about. the original poster did also make some other real points.I consider tacit programming — which has strong similarities to point-free style — to be higher-level than direct stack manipulation. The original poster likened concatenative programming to "writing a Turing machine program. I don't see direct stack manipulation as one that's likely to be the best choice in most situations. How does this reconcile with the idea that using local names is an impediment to refactoring? Erlang is not purely functional (ets. On the subject of scaling up expressions. . differ considerably in how many named intermediate variables they use (personally I find the number of intermediates in the above Scheme code a bit excessive). a language should be able to support a variety of styles. and typical programming styles in various languages. mnesia. that means you're relying on names for abstraction again. But it's generally agreed..g. That's a fair point. the reason they're frowned upon is because in most cases they are an impediment to proper factoring. the traditional concatenative answer to that is that you should factor larger expressions into multiple words. e. Of all of these. I consider the definition of "purely" here to be a quibble — e. Having the option to use de Bruijn indices might be an improvement over having no alternative to direct stack manipulation. in imperative-applicative languages (some more than others) is indeed a valid criticism of them." Perhaps you should reconsider whose claims are 'over the top'. By dhopwood at Thu. that introducing variables with useless names is bad style. By Anton van Straaten at Thu. Programmers. so that the appropriate one can be picked in a given situation. all of these things have pros and cons. especially as expressions scale up. However.

you're making an assumption about what's on the stack. 2005-08-12 17:36 | login or register to post comments Types? I agree. Do you consider not being able to not name part of the state a weakness? The only way to avoid it in many imperative languages would require programming in a dramatically different style than the the language supports. . but that assumption could be violated by unrelated code Is it really that much different from the applicative language example? If your function takes three integers. but that assumption could be violated by unrelated code That sounds like a plea for static typing. how do you know you're calling it with the arguments in the correct order? Especially in the presence of macros? (apply quadratic-formula '(1 0 -4)) (apply quadratic-formula (reverse '(1 0 -4)) By Greg Buchholz at Wed. Are the stack manipulation functions that you mention (pop.. but part of the essence of reasoning within an imperative paradigm is knowing the current state. 2005-08-10 17:08 | login or register to post comments . I disagree that temporaries have "useless names". dup.) a sign of a low-level language or a linear language (like Linear Lisp)? Or are all linear langauges low-level by definition? Also.> By David B.. Not being able to name part of that state is what I would consider to be a weakness. like pop. Loop indices may not be referenced other than as a control structure. The only useless names I can think of is for function arguments that aren't used. . Held at Thu. 2005-08-11 03:52 | login or register to post comments Functional languages can "nam Functional languages can "name part of the state". in concatenative languages. you're making an assumption about what's on the stack. The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain.The need for temporaries with useless names. the programmer depends heavily on abstractions which the language doesn't enforce or even know about: every time you use pop. dup. e. And in better languages. you don't actually have to name those. swap. and rollup.g. swap.every time you use pop. By Derek Elkins at Fri. loop indices. etc. in imperativeapplicative languages (some more than others) is indeed a valid criticism of them. That's a classic sign of a low-level language (think of assembler).

I'll admit I can't give a formal definition of "low-level" off the top of my head. Yes. yes. The question is what the costs of introducing it are. swap. I find the costs high enough that I can easily justify using it in some cases.More Linear For better reference to linear lanugages (which also mentions the quadradic formula!) see Linear Logic and Permutation Stacks--The Forth Shall Be First By Greg Buchholz at Wed. and avoiding it in others. dup. but I'd be interested to hear (reasoned) arguments about how something like Linear Lisp or the concatenative languages are not lower-level. The costs of introducing static typing are positive. That sounds like a plea for static typing. and doesn't compromise unrelated abstractions elsewhere in the program. and that a language with named bindings which can make some guarantees about those bindings is both safer and higher-level than a language that doesn't have those features. I'm just saying that there's a spectrum of safety and levels of abstraction. I'll admit I can't give a formal definition of "low-level" off the top of my head. it is. how do you know you're calling it with the arguments in the correct order? It's different at least in the sense that that's a local effect: the error is confined to the interface between the caller and the callee. etc. Is it really that much different from the applicative language example? If your function takes three integers. The costs of introducing a safe name abstraction are negative. In the case of relying primarily on direct interaction with a stack to store values. 2005-08-10 18:10 | login or register to post comments low vs. . but I'd be interested to hear (reasoned) arguments about how something like Linear Lisp or the concatenative languages are not lower-level. By Anton van Straaten at Wed. In the static typing case. yes.) a sign of a low-level language or a linear language (like Linear Lisp)? Or are all linear langauges low-level by definition? I would say that Linear Lisp is certainly lower-level than ordinary Lisp. 2005-08-10 17:44 | login or register to post comments Differences Are the stack manipulation functions that you mention (pop. I'm not saying that any language with named bindings solves all such problems. lower I would say that Linear Lisp is certainly lower-level than ordinary Lisp. and arguably not insignificant. I can easily justify avoiding that in most cases.

I'd point to higher order functions and a clean algebra of programs as indicators of higher-levelness. 2005-08-10 18:37 | login or register to post comments The Joy of obfuscated abstractions Well I don't know if I can define "low-level" either. by that definition. monads result in low-level code. Likewise. by my definition and Alan Perlis'. Anyway. Although I don't think it's really completely correct to label languages high or low level. because you're forced to think about category theory just to print "hello" :-) . 2005-08-11 21:43 | login or register to post comments "Low level" I'll admit I can't give a formal definition of "low-level" off the top of my head There's always Alan Perlis's definition: A programming language is low level when its programs require attention to the irrelevant. concatenative code is low-level because it forces you to write your solution in terms of a stack. By Anton van Straaten at Wed. At most you can say that writing in a given language generally results in high or low level code. but of the cuff. HOFs are ubiquitous in Joy. By Daniel Ehrenberg at Thu. but really. there's tons of this stuff. I'd point to higher order functions and a clean algebra of programs as indicators of higher-levelness.Well I don't know if I can define "low-level" either. concatenative languages do provide both of those things in your definition of high level languages. renamed combinators. They are used more frequently than HOFs in any applicative language I've seen. 2005-08-10 20:04 | login or register to post comments Not low level Though I don't particularly like that Joy code. despite the fact that there's no stack in your problem specification. Maybe the assembly language remark was aimed more at Forth and less at something like Joy? I agree that HOFs and algebraic compability are high-level indicators. As for theory. Factor and Kont. but of the cuff. but it doesn't necessarily make up for all of its problems. there's tons of concatenative theory. The Joy code sample near the beginning of this thread provides an example of low-level code. That moves a language like Joy up the spectrum I mentioned. Check out the Joy and Factor websites for more details. Maybe the assembly language remark was aimed more at Forth and less at something like Joy? By Greg Buchholz at Wed.

. specifically... 2005-08-10 17:31 | login or register to post comments The semantics of Joy Indeed. which is Manfred's fundamental insight. 2005-08-10 19:30 | login or register to post comments I agree with everything you w I agree with everything you wrote. Likewise.. it can return ⊥ if foo does not terminate. (let ((x 33)) (foo) x) can return something other than 33. so doesn't affect a relative comparison of features between languages. 2005-08-10 20:05 | login or register to post comments Analogy. because it can be detected and flagged when it happens. that would only be a good argument if programmers didn't need to rely heavily on faking local bindings in concatenative languages. Global words can be defined at read time. but irrelevant. (let ((x 33)) (foo) x) can return something other than 33. The cases that are problematic are when the stack is not . specifically. :) By Anton van Straaten at Wed. executing pop on an empty stack likewise produces ⊥ Empty stack is a special case that's not as problematic. Sounds a lot like type errors in dynamically checked languages. However. But now I guess I'm the one trolling. True. write. Likewise. nothing is being violated. 2005-08-10 20:40 | login or register to post comments The Joy of the next 700 titles Indeed. By johnwcowan at Wed. it can return ⊥ if foo does not terminate. executing pop on an empty stack likewise produces ⊥.. etc. do not pop the file object off the stack constitutes the concatenative analogue of the I/O monad).. but cannot be changed at run time. In the concatenative context. . thus they are analogous to function definitions rather than global variables. since this problem applies to all useful general-purpose languages. This interpretation depends on the view that the words of concatenative languages are functions from sequences to other sequences.) By Matt Hellige at Wed. you can play language lawyer and claim that since the language doesn't have the notion of a local binding.By Dan Winship at Wed. Joy is different from other concatenative languages because it is functional: it is impossible to make any changes of state except through the file functions (the fact that read.

I'm not saying that this issue alone makes concatenative languages unfit for human consumption. I think the negative reaction to the tractability of these languages that's been expressed by some posters in this thread is not an uncommon one. then I'll agree it has the potential to become a mess. Am I missing something? By Greg Buchholz at Wed. 2005-08-10 21:05 | login or register to post comments Static analysis The Factor language apparently includes a stack effect inference tool which performs such analysis. By Anton van Straaten at Wed. 2005-08-10 22:35 | login or register to post comments empty stacks Likewise. 2005-08-10 20:50 | login or register to post comments Static vs. The cases that are problematic are when the stack is not empty. executing pop on an empty stack likewise produces ⊥ Empty stack is a special case that's not as problematic. but is out of sync with the program's expectations. and I've attempted to identify a couple of the semantic issues which underly this reaction. Dynamic The cases that are problematic are when the stack is not empty. There are no problems at all about empty stacks. However. By Anton van Straaten at Wed. But it seems like you should be able to prevent getting "out-of-sync" with static analysis. That's when the programmer's implicit abstractions are violated. This seems like a lot of trouble to go to to achieve a kind of safety that other languages get for free. The documentation mentions combining unit testing with stack effect inferencing to check the stack effect of procedures (words). In this particular case. that the approach these languages take to local value abstraction is less safe and requires more care than languages with name-based local abstraction. I'm saying that even if you get past the lack of procedure-local name/value bindings. That's when the programmer's implicit abstractions are violated. but is out of sync with the program's expectations. because it can be detected and flagged when it happens. or by dynamicism? If your language allows you to push 1 or 2 things on the stack. but is out of sync with the program's expectations. Like requiring both branches of an "if" statement have the same stack effect. depending on a conditional. Is that a problem caused by concatenativityness (!). Factor solves the stack underflow problem by mprotecting (or something like that) the memory directly underneath the .empty.

). because of effects . it's caught automatically and printed out. dup.. By dhopwood at Thu.g. because of effects . If foo has an exception. nontermination. I meant that assuming normal completion of foo. . By Greg Buchholz at Thu. and it the toplevel of the repl. dup. nontermination. i. 2005-08-11 00:48 | login or register to post comments The original thread As long as we're alread discussing it. ternary) in such a simple example. and presumably happens for a reason. All this stuff about ⊥ is useless outside of research. swap. but complex The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain.. And some might be interested in Pointless Haskell. also like any other exception. Actually I think the more important point is why you should have to use six of these (pop. we might as well mention the original thread that spawned the quadratic formula article. such a PL is less safe than reasonable? No. 2005-08-11 17:03 | login or register to post comments No special machinery required I guess you meant that though it's absolutely possible to have a PL in which the value of (let ((x 33)) (foo) x) is not 33 (e. one can rely on a value of 33 being returned from that expression. By Daniel Ehrenberg at Thu. 2005-08-11 01:45 | login or register to post comments Effects&type system for Scheme? :-) I guess you meant that though it's absolutely possible to have a PL in which the value of (let ((x 33)) (foo) x) is not 33 (e. An infinite loop has a very different outcome than stack underflow. swap. That's a classic sign of a low-level language (think of assembler). the segfault can be caught like any other exception. like pop. such a PL is less safe than reasonable? Here is another example of non-local bugs: a badly-formed HTML post in a naive weblog system can break the whole page. Should this happen.e.). and rollup. By Andris Birkmanis at Thu. triggering a segfault if there's underflow. 2005-08-11 17:50 | login or register to post comments Not just low-level and unsafe. continuations.exceptions. etc. rollup. map. that's fine. The case I'm pointing to as undesirable is if the expression ends up returning 42 or the string "gotcha" instead.exceptions.g. Also note a previous discussion on point-free programming on LtU. the program produces an incorrect result. continuations.stack. etc.

2005-08-10 16:50 | login or register to post comments you can't.i can't remember the exact details of otuto v1. apart from the RPN. scopes are not concatenative Once you add names then the code is no longer concatenative. Concatenative languages (and Lisp. in otuto you'd have something like { quadratic | a b c } => { roots ~ b sqrt .x y z } which seems clear enough. in each case using the correct lexical context. they could hold a pointer to their lexical context. followed by the second one.] By James McCartney at Wed. a language implementer) from labelling items on the stack.) By Anton van Straaten at Thu. and v2 is stalled until i gain enough patience to return to the uml tool (i'm trying to implement it in c++ for various (vaguely financial) reasons). where lambdas are firstclass too) are not all about cons cells and lists. You can no longer compose functions by concatenating lists of words because the two quotations may come from different lexical environments. No-one in their right mind would defend such a system. rather than lists of words. then each quotation would need a pointer to its lexical scope. by the way. iterates over the first one.* 4 * a c * b b * 2 a } where { roots | x y z } => { / + x y z / . [edit: otuto is very interesting. For example if you were to add names for items on the stack as an extension of the Joy language.Here is another example of non-local bugs: a badly-formed HTML post in a naive weblog system can break the whole page. 2005-08-10 20:01 | login or register to post comments concrete example . I hadn't realized what language your example was from. and when evaluated. . disclaimer . 2005-08-11 17:17 | login or register to post comments there's nothing to stop you ( there's nothing to stop you (or rather. By slava at Wed. By andrew cooke at Wed. Yes. 2005-08-10 19:08 | login or register to post comments Scopes are concatenative If quotations were first-class types in Joy. that simply holds references to both quotations. Appending two quotations could be implemented with a 'cord' data structure.

a quoted symbol. if a language is concatenative then functions are sequences of operators where you can take any function and split it at any point and you have two valid functions. 2 [x] [x 1 +] let so that the above returns 3. that syntax is a very simple "template" for rewriting the stack (actually. By andrew cooke at Fri. since they are rules with 4 separate sections. but i'm pretty sure that those variable names are just sugar. By James McCartney at Sat.OK perhaps you can have hidden lexical scope pointers and use a cord.i've never bothered to prove it. 2005-08-13 16:32 | login or register to post comments well. 2005-08-11 19:13 | login or register to post comments there is no lexical scope dur there is no lexical scope during evaluation. but i would be amazed if it were not true). you could implement them by cross-compiling to an intermediate representation without variable names (using swap. all that the otuto definitions describe is how you rearrange the stack(s). i'm not 100% convinced i understand what concatenative is. not simple sequences of operations. so you'd define dup as: { dup | x } => { | x x } there's some syntactic sugar involving implicit quoting that means you can write that as { dup | x } => { x x } but that's beside the point. stacks). when i mentioned this on the joy email list. and another quotation which is evaluated in an environment where that symbol is bound to the value. I'm not sure what it would mean to split or join functions in otuto. now: 1 [x] [[x]] let [x x +] 2 [x] [[x +]] let concat this returns the concatenated function: however each x is bound to a different value. so i can't say otuto is concatenative. But this seems to create a pretty confusing language. or you can join two functions and have a valid function. roll etc etc) (i believe . [x x +] i returns 3 By James McCartney at Thu. For a simple example suppose we have a Joy-like language plus an operator 'let' that takes a value. the rules are restricte . a long time back. someone added something similar to another language there. 2005-08-12 22:01 | login or register to post comments otuto As I understand it.

which uses names to similar effect (that is. so is XY. that there is a simple mapping from otuto to concatenative languages.they always match a single value on the left hand stack.well. regarding your proposal for cross-compilation. compile { [a b c] a b * a c * + } to abc--abac * [*] dip + [edited to show an example of compilation from pattern-notation to shuffle-notation] By sa at Sat. For example. A language in which the concatenation of programs denote the composition of functions has been called a concatenative language. 2005-08-13 23:37 | login or register to post comments . as i argued above. Billy Tanksley has suggested a notation (supported in XY) in which an initial "shufflepattern" is followed by name-free code. in which names are used to map items from the stack to multiple locations. i think. so the top value on that stack can be interpreted as the current instruction. then that implies. a definition like: { foo | a } => { bar baz | a a } is equivalent to defining foo as bar baz dup in a concatenative language. if you then take the right hand stack as "values" then you can think of a rule as saying how to apply the intruction (top of the left stack) to the values. now if you accept. I first heard this terminology from Billy Tanksley. to map items from the stack to multiple locations in the body of the code): . -. By andrew cooke at Sun. Here's one version of quadratic in that language. ok. the rules are restricted . 2005-08-14 01:43 | login or register to post comments concatenative is .5 ^ [1 -1] * + a 2 * % } . . (this breaks down with meta-programming. i think it would be sufficient to compile programs like quadratic.Manfred von Thun otuto is concatenative. that the variables are just syntactic sugar. followed by code which is name-free. now if you continue with that.. to programs which consist of an initial reordering of items on the stack. though. quadratic { [a b c] b -: a c * 4 * b 2 ^ -. since you can change the assumptions made above).

and factorial.. in their common recursive definitions have a defined evaluation order. fold compose id [1 4 dup * +] Replace 'compose' with 'bind' for your favorite monad. 2005-08-15 22:57 | login or register to post comments Looks applicative to me I don't know whether otutu as a whole is applicative or a hybrid. Subroutines (quotations) in Joy are lists of functions and you interpret them by folding in a 'compose' and applying to a stack. then how are monadic expressions not concatenative? Say. issue. and much less significant. I might understand "composition of functions" a bit wrongly. There is still a stack. ignoring associativity information. in imperative PLs one can concatenate statements (usually using '. The code is not applicative. By Greg Buchholz at Mon. and I think you might be on your way to removing much of the mystery behing monads (or at least you've given them an opportunity to see monads that aren't tied up in Haskell syntax and type-classes). Well. even I think some Simon Peyton-Jones stuff really mention both of those facts. and quite often "imperative" means working in some compound monad. 2005-08-11 01:48 | login or register to post comments The code is not applicative...) By dhopwood at Thu.. In fact. (RPN vs prefix vs infix is a separate.'). By Marcin Tustin at Mon. . it's just reverse RPN (just polish notation) and it uses named variables.Monads as concatenative PLs? If we squint our eyes enough to see bind as concatenation. which are familiar functions that. By Andris Birkmanis at Mon. then illustrate with reference to examples like lists with mapping. but the above code is definitely applicative. None of the tutorials on the web I have read. 2005-08-15 14:25 | login or register to post comments They recently made much more They recently made much more sense to me when I combined the two pieces of information that monads are (1) an algebraic structure that (2) forces a particular evaluation order. 2005-08-15 06:03 | login or register to post comments Squinting I don't think squinting is necessary at all. lately I've been thinking that there might be a benefit for newbies by writing a monad tutorial using a language like Joy.

applicative semantics for otherwise comparable languages. so ironically. it is used to implement a single-stepper. There is no "boilerplate" code. Your emphasis on the word "seem" suggests that you don't believe that concatenative languages are used to develop non-trivial applications. and the simplicity of concatenative languages allows one to develop such tools more easily than with other languages. Factor with Java. the simplicity of concatenative languages allows one to develop such tools more easily than with other languages. I'm interested in the effects of concatenative vs. While it's true that there are few complex concatenative languages. in fact I am the lead developer of the Factor programming language.. there are plenty of equally simple applicative ones. the burden of bridging the gap between the programmer and the language lies squarely on the development tools at one's disposal. A meta-circular interpreter is a page of code in Factor. I'm not sure what you mean by "How can you build reusable encapsulated abstractions?". As always. There is a static stack effect inferencer tool. various development tools. The compiler takes maximal advantage of the simple semantics to implement the concatenative equivalent of "lambda lifting". and various other optimizations such as partial evaluation.. a GUI toolkit-inprogress. you will see a very high degree of abstraction and code reuse. also used by the compiler. notwithstanding the clear fact that there is enough commercial demand to keep several Forth vendors in business. and not even capable of implementing their own optimizing native compilers. say. one could even conclude that applicative languages are totally non-productive. If you look at Factor's library. and it is not an academic exercise. and more. Re: "writing a Turing machine program". Factor has an HTTP server with a continuation-based web framework. . This is a richer level of functionality than offered by most languages discussed on this web site. By slava at Wed. after working with Factor's libraries for sequences and mathematics.By Daniel Ehrenberg at Thu. I'd like to see a single-stepper in another language that is equally clear. 2005-08-10 06:30 | login or register to post comments Re: A comment about concatenative languages in general . 2005-08-11 16:14 | login or register to post comments Re: A comment about concatenative languages in general I consider concatenative languages suitable for high-level programming. Well. I'm not particularly interested in comparing. going back to a language like Java with annoyingly handcoded boilerplate loops seems more like a Turing machine.

2005-08-10 16:13 | login or register to post comments Research is a Good Thing "Research language" is a euphemism for "useless language".. but it will not change the fact that for me... weakly final coalgebras and other academic concerns until you are blue in the face. static type systems. and not even capable of implementing their own optimizing native compilers. And also beside the point. still I think that assertion is very likely false. And where do you think the ideas for features in 'mainstream' languages come from? . I write code. various development tools. By slava at Wed. but the broader consequences of everyone holding that opinion are not pretty.. I could truthfully say "for me...[. and I find that concatenative languages let me do this just as easily as applicative ones. weakly final coalgebras and other academic concerns until you are blue in the face. thinking in terms of a stack is not a problem. You can discuss semantics. static type systems. This is just trolling. but it will not change the fact that for me. with the additional advatange that writing tools is easier. thinking in terms of a stack is not a problem. dealing with unrestricted pointers in C is not a problem". I'm really only interested in practical concerns. . one could even conclude that applicative languages are totally non-productive. Perhaps. a GUI toolkit-inprogress. since the maturity of language implementations is not the topic of discussion. the next person who has to deal with your code may indeed have a problem. You can discuss semantics. By Anton van Straaten at Wed.] is a richer level of functionality than offered by most languages discussed on this web site Even though this web site disproportionately discusses research languages and prototype language implementations. 2005-08-10 16:08 | login or register to post comments For me. since the maturity of language implementations is not the topic of discussion...] an HTTP server with a continuation-based web framework. And also beside the point. 2005-08-10 14:31 | login or register to post comments Irrelevant Even though this web site disproportionately discusses research languages and prototype language implementations. and I like to write stable code quickly. However. By dhopwood at Wed. and more [. "Research language" is a euphemism for "useless language". still I think that assertion is very likely false.

By dhopwood at Thu, 2005-08-11 02:07 | login or register to post comments

things Factor can do
While it's true that there are few complex concatenative languages, there are plenty of equally simple applicative ones. I'm not particularly interested in comparing, say, Factor with Java; I'm interested in the effects of concatenative vs. applicative semantics for otherwise comparable languages. The point is, you can't do a lot of the stuff Factor does in an applicative language. I can't imagine Factor being applicative. The closest parallel I can find is Common Lisp, but there are many things about Factor that make it much better. One example that comes to mind is the word watch. The implementation isn't more than 3 or 4 lines, and what it does is it prints out the name of the word and the contents of the datastack when the word is called. It's been really useful for me and I've been able to get rid of all the debugging prints in my code. One time, I needed to see what was on the stack when leaving the word, so I made a new watch-after thing. It also only took 4 lines and not much thought. In Common Lisp, this would probably take the form of a new macro for when defining a function or macro, but that technique is less flexible. In Haskell or ML, making a debugging tool like this is even harder, involving complicated templating libraries.

Even though this web site disproportionately discusses research languages and prototype language implementations, still I think that assertion is very likely false. And also beside the point, since the maturity of language implementations is not the topic of discussion. I, unlike Slava, am OK with research languages. They're good for research. As lothed as Slava is to admit it, Factor isn't really suitable for most applications yet. Of course, it is intended for use, but Factor's libraries aren't mature enough, especially crucial ones like the GUI library. Factor has a pretty good FFI, but that's not because it's concatenative. We really shouldn't discuss this, though, you're right.

This is just trolling. [about applicative languages being nonproductive] Yeah By Daniel Ehrenberg at Wed, 2005-08-10 19:38 | login or register to post comments

Fun with stacks
One example that comes to mind is the word watch. The implementation isn't more than 3 or 4 lines, and what it does is it prints out the name of the word and the contents of the datastack when the word is called. Obviously, anything which involves dealing directly with the stack will be easiest in a language which gives you direct access to the stack. The question is how many things fall into this category, and whether they're worth the consequences of allowing direct

manipulation of the stack, and in what situations. For example, Forth-like languages are often used in constrained embedded environments, in which case some of these concerns may be balanced by other advantages of these languages. BTW, Common Lisp and many Schemes have something like a "trace" macro that provides similar functionality to the word watch, although the implementation of that is more than 3 or 4 lines. They usually print the incoming arguments and the return value, i.e. both the entry and exit from a traced function. By Anton van Straaten at Wed, 2005-08-10 22:48 | login or register to post comments

Re: Fun with stacks
The question is how many things fall into this category, and whether they're worth the consequences of allowing direct manipulation of the stack, and in what situations. That's actually a good point, but let me turn that question around: how many things fall into the category where you need lexically named variables to do certain things? I used to think many, but you can really do everything without them (but for a few circumstances, dynamically scoped variables help). The concatenative paradigm is not just a way to manipulate the stack directly, it's a whole different paradigm of programming where some things are more elegant and others less. After a while, it tends to feel like most things are more elegant, but from your perspective, everything will look awkward at first. For an example of something which comes out really great, here's the heart of the Factor compiler:
M: compound (compile) compiling dataflow optimize linearize simplify generate ;

Yes, I know that's a terrible argument, but I don't care. It's a reason I use Factor anyway. At this point, rather than feeling that concatenative languages are backwards, I feel like they're in the exact right order. They do reflect the order of evaluation, however important or unimportant that is.

For example, Forth-like languages are often used in constrained embedded environments, in which case some of these concerns may be balanced by other advantages of these languages. Well, Factor isn't really that into constrained embedded environments, it's more for general programming, which can be done better because of it's abstraction capabilities, some of which rest on its being concatenative.

BTW, Common Lisp and many Schemes have something like a "trace" macro that provides similar functionality to the word watch, although the implementation of that is more than 3 or 4 lines. They usually print the incoming arguments and the return value, i.e. both the entry and exit from a traced function. Not only does it take more code to do such a simple task but you have to alter the

original code to do it. In Factor, at the repl, you can just enter one short line of code to watch a word (\ word-name watch). One thing about Factor that's great but unrelated to its concatenativity is that you can mutate stuff like word bodies, though you don't normally do this outside of debugging. There's probably an applicative language that does that. By Daniel Ehrenberg at Thu, 2005-08-11 02:24 | login or register to post comments

Fun with folds
how many things fall into the category where you need lexically named variables to do certain things? "Need"? None. However, the number of situations in which having lexically named variables is useful is high, IME. I used to think many, but you can really do everything without them Similarly, that you "can" do everything without them is not what I'm concerned with. Turing completeness tells me it's possible, the more important questions are how practical it is, how easy it is to deal with code written by other people, etc. The concatenative paradigm is not just a way to manipulate the stack directly, it's a whole different paradigm of programming where some things are more elegant and others less. After a while, it tends to feel like most things are more elegant, but from your perspective, everything will look awkward at first. I implemented and maintained Forth programs for a couple of years. It was fun, but part of the reason I used Forth was because it was in a small, embedded-like control environment, where the alternatives were languages like C and assembler. The points I've raised are not about things being backwards or seeming awkward. For an example of something which comes out really great, here's the heart of the Factor compiler: M: compound (compile) compiling dataflow optimize linearize simplify generate ; I agree, it's great when something works out in a way that seems intuitive. However, my experience is that different things can seem intuitive for different problems. If I wanted to write an expression like the above, I could do it quite easily in many higher-order functional languages, using a fold over a list of procedures, which could easily be made to look something like, e.g. in Scheme:
(concatenate input compiling dataflow optimize linearize simplify generate)

Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable. It'd be interesting to see a Factor (or Kont?) version of that program, for comparison. Well, Factor isn't really that into constrained embedded environments, it's more for general programming, which can be done better because of it's abstraction capabilities, some of which rest on its being concatenative. Since stacks are irrelevant to most problems, unless you can abstract its use away, the need to use one seems to me like a hit against a language's abstraction capabilities.

Not only does it take more code to do such a simple task but you have to alter the original code to do it. In Factor, at the repl, you can just enter one short line of code to watch a word (\ word-name watch). The Lisp/Scheme equivalent, at the repl, is just one short line of code, (trace procname). No alteration of the original code is required. By Anton van Straaten at Thu, 2005-08-11 04:04 | login or register to post comments

Concatenate
If I wanted to write an expression like the above, I could do it quite easily in many higher-order functional languages, using a fold over a list of procedures, which could easily be made to look something like, e.g. in Scheme:
(concatenate input compiling dataflow optimize linearize simplify generate)

How is this any different from embedding an infix language in Factor? The Lisp/Scheme equivalent, at the repl, is just one short line of code, (trace procname). No alteration of the original code is required. But the implementation of Common Lisp's trace is more complicated than the Factor equivalent. By slava at Thu, 2005-08-11 04:45 | login or register to post comments

I don't care enought to make a good title
"Need"? None. However, the number of situations in which having lexically named variables is useful is high, IME. Please provide me with a situation where the solution with variables is much better. I know one, math, but that situation seems to be isolated, so I made a minilanguage (which I'm currently redoing) to use infix syntax for math. Do you think this is a more general problem than that? I'm seriously interested in this.

(concatenate input compiling dataflow optimize linearize simplify generate) I don't think that code would work since the stack effects of many of those words are not ( a -- b ). The only way to make it work would be to have each of those functions take a stack and return a stack, but that's just like implementing a lightweight concatenative language on top of Scheme. Incidentally, I believe someone has done that with Common Lisp...

Since stacks are irrelevant to most problems, unless you can abstract its use away, the need to use one seems to me like a hit against a language's abstraction capabilities. You're right, I guess; there are only a few cases where the stack really matters. It matters like lexically scoped variables matter in normal code, which really is irrelavent to abstraction. But then there are properties of Kont and Factor (but not Forth) that lend

No alteration of the original code is required. and multiple values can typically be returned in various ways. such as lists. it's a much more general problem. then never mind that point. so I made a minilanguage (which I'm currently redoing) to use infix syntax for math. or other kinds of collection. like the use of combinators to replace macros in languages like Lisp and built-in syntax like C. ok. I know one. there are only a few cases where the stack really matters.it to more abstraction. like the use of combinators to replace macros in languages like Lisp and . you're showing signs of being infected by stack-oriented thinking. But then the compiler inlines them to make them as fast as a macro. tuples.. See my other longer response. 2005-08-11 16:07 | login or register to post comments This is not a title Please provide me with a situation where the solution with variables is much better. The Lisp/Scheme equivalent. unless you can abstract its use away. is just one short line of code. Named variables are certainly not irrelevant to abstraction. but that situation seems to be isolated. Really? Oh.b ). You're right. The only way to make it work would be to have each of those functions take a stack and return a stack. Uh-oh. procs) (fold apply input-args procs)) Since stacks are irrelevant to most problems. entitled "reference sense pop".. but that's just like implementing a lightweight concatenative language on top of Scheme. Combinators to the programmer look like ordinary code that just happens to do something with a quotation. math. at the repl. Again. I don't think that code would work since the stack effects of many of those words are not ( a -. It doesn't require "each of those functions take a stack and return a stack" — for a start. and they do function when run like that by the interpreter. By Daniel Ehrenberg at Thu. Yes. which is one of the problems that can be caused by using a language which forces you to think in terms of its implementation details all the time. I believe someone has done that with Common Lisp. though. But then there are properties of Kont and Factor (but not Forth) that lend it to more abstraction. I guess. (trace procname). I'm not explaining them very well. see my other reply. the need to use one seems to me like a hit against a language's abstraction capabilities. is as simple as this: (define (concatenate input-args . A Scheme version which uses lists applied to ordinary procedures with named arguments. which really is irrelavent to abstraction. It matters like lexically scoped variables matter in normal code. Do you think this is a more general problem than that? I'm seriously interested in this. Incidentally. procedures in most applicative languages can receive multiple values using ordinary named parameters. I don't have much experience with Lisp development tools.

which is that you start conceiving of all problems in terms of that datastructure. you're showing signs of being infected by stack-oriented thinking. The sentence after the one you quoted contains the refutation. Combinators to the programmer look like ordinary code that just happens to do something with a quotation.built-in syntax like C. I hope LittleDan didn't take that too personally. Regarding the "infected" comment.) are useful.. for comparison. talking about such a specific structure as a stack when the problem is in fact a much more general one. I should have put a smiley after it. I'm not explaining them very well. I'm not listening".) By Anton van Straaten at Fri. it was certainly intended lightheartedly. but the end result is similar. I agree. However. But then the compiler inlines them to make them as fast as a macro. When you find yourself saying things like "The only way to make it work would be to have each of those functions take a stack and return a stack". and saying "neener. there's an additional risk in using a language which forces you to think in terms of a single datastructure everywhere. though.. However. 2005-08-12 19:02 | login or register to post comments The Swine Before Perl Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable. neener. I'd be especially concerned about exposing inexperienced programmers to languages that require this kind of thinking. they work just as well in the presence of lexical names. . It's an easy mistake to make. it's also a serious point. 2005-08-12 18:15 | login or register to post comments Don't stop reading yet. 2005-08-12 04:55 | login or register to post comments Infected Uh-oh. What a great way to refute somebody's point! This is just like putting your hands over your ears. because you'd be ingraining bad habits in them from the very beginning. those kind of high level features (borrowed from functional programming! . It'd be interesting to see a Factor (or Kont?) version of that program. and they do function when run like that by the interpreter. Perhaps you've been infected by Scheme-oriented thinking? By slava at Fri. and I suspect we all do it to some degree from time to time. By Anton van Straaten at Fri. However. that's a clear sign that you're thinking too much in terms of implementation and too little in terms of specification. (There's a difference in the way inlining tends to work. and certainly help.

parsing POSTPONE: }} POSTPONE: ]] POSTPONE: [[ .. parsing POSTPONE: [[ . and in Kont. which came out a bit cleaner than the Scheme program IMHO. that's just showing that you have a bad implementation of the language. parsing POSTPONE: }} POSTPONE: ]] POSTPONE: }} \ walk-states : final-machine {| init :: CHAR: loop :: CHAR: CHAR: CHAR: end :: CHAR: c a d r r -> -> -> -> -> loop loop loop end end .? ) init swap rot [ >r ?hash r> swap ?hash ] each-with end = .. parsing . Edit: as Slava correctly pointed out on the #concatenative channel. |} . but after doing the non-macro part. POSTPONE: ]] : |} POSTPONE: ]] swons .. SYMBOL: init SYMBOL: loop SYMBOL: end : c[ad]+r #! Initial datastructure {{ [[ init {{ [[ CHAR: c loop ]] }} ]] [[ loop {{ [[ CHAR: a loop ]] [[ CHAR: d loop ]] [[ CHAR: r end ]] }} ]] [[ end {{ [[ CHAR: r end ]] }} ]] }} . syntax extension isn't as common as in Scheme because it's not needed as much. parsing : || POSTPONE: ]] : . : {| POSTPONE: {{ : :: POSTPONE: {| : -> . parsing POSTPONE: [[ . those cosmetic macros are completely stupid and the first version is really the one that should preferably be used. IN: state-machine USING: kernel hashtables sequences lists . Is there something wrong with that code? It seems to be a bit shorter than the Scheme code. I still made a seperate syntax for defining the state machine. The code is below.I started to implement that Swine Before Perl program. || || . I really felt like this is enough. 2005-08-11 19:43 | login or register to post comments btw here's how to activate it . What benefit do you derive from making that a macro? In Factor. though. By Daniel Ehrenberg at Thu. If you're making that macro for a speed boost. there is no syntax extension. : walk-states ( seq states -.

_ic("".g. 3 ghz machine timings are: 10k elements: 0 ms 100k elements: 15 ms . the algorithm should consume inputs and index out the next state."caddr") 2 2 3 2 2 3 2 2 2 3 2 2 2 3 2 2 2 3 2 2 2 2 3) a 0 in the return vector indicates that m has entered the error state.:.e. on my pentium 4. so is krishnamurthi's scheme implementation."cdar"."cdr". the machine has four rows corresponding to the four states: error. corresponding to possible ascii inputs."cadar" final-machine or "cadar" c[ad]+r walk-states By Daniel Ehrenberg at Thu. using two dimensional scalar indexing. a state machine is a matrix."cadr". k = machine[i. (1 1 1 1 1 1 m'("car".3)] m:1 s\_ic e. in this case."adr"."r")."cddr". end.(!0. 2005-08-11 20:18 | login or register to post comments too much code dan.2. then it should enter state k. repeated indexing in k is implemented as: result:index matrix\indices i. rows are states and columns are inputs. and 256 columns. more.indices 0] k1:matrix[k0."c". the algorithm is realized as: s:@'[4 256#0. k0:matrix[index. if the machine is in state i and sees input j.indices 1] k2:matrix[k1. leaving the sequence of states visited as its result (a vector of indices). that's way too much code.indices 2] : in k. init.2 2 3.j].

and you understand indexing. 2005-08-12 17:16 | login or register to post comments Understandable? Flexible? .h> int main(int argc. no need to follow that long and winding road into the metaphysics of abstract objects. By Mackenzie Straight at Fri. obligatory reading: paul benacerraf. 2005-08-13 11:29 | login or register to post comments but what are they really? hey indeed. 2005-08-13 22:30 | login or register to post comments Repent.{['c']=2}.s=1.['r']=3}. which have matrix representations.{['a']=2." By sa at Sat. if you understand +. then it's a small step to knowing how to code up a state-machine. they are anything at all beyond how they are represented in different programming languages.['d']=2.{['r']=3}}. 2005-08-12 18:19 | login or register to post comments FSMs are graphs. "what numbers could not be. indeed. Sloppy language. which in turn is a special case of scanning a function on its input.1m elements: 187 ms state-machine is just a special case of index-scan. By sa at Fri. if(argc Simplicity > Abstraction. but hey. By Philippa Cowderoy at Sat. if. my point was that recursive 2d indexing captures the behavior of fsms. which have m FSMs are graphs. no matter what they "really" are. and you understand summation as repeated application of +. sinners #include <stdio. 2005-08-12 15:52 | login or register to post comments a state machine is a matrix? a state machine is a matrix? By Michael Walter at Fri.char**argv) { char S[4][256]={{0}.

Neither the C. it seems to miss the point fairly completely. [1] At least that's what I believe he's shown. And for what its worth. The Factor version has a bit more punctuation. . unfortunately. I'm only working with the slides. because Dan did not extend the syntax. using lists (including alists) and symbols for everything. and I know just enough Scheme to get myself in trouble -. K. -30By William D. I'd like you to explain why you think that this: (init : (c (more : (a (d (r (end : (r -> -> -> -> -> more)) more) more) end)) end)) Any more flexible than this: : c[ad]+r {{ [[ init {{ [[ CHAR: [[ loop {{ [[ CHAR: [[ CHAR: [[ CHAR: [[ end {{ [[ CHAR: c a d r r loop loop loop end end ]] }} ]] ]] ]] ]] }} ]] ]] }} ]] }} .That's great guys.. he just used Factor's hashtable literals. Neumann at Fri. your solutions would have you hard-coding your new state tables while Shriram's would have you quickly done with the code and onto some other problem. What's more (and probably more important). I don't like the way typical Scheme code is written. What he's shown[1] is a simple syntax extension for generating (fairly efficient) automata from these simple. It might look pretty but it just doesn't scale as well as other data structures for most tasks.feel free to taunt me if I'm wrong. I consider the omission of hashtables from the Scheme standard to be an unacceptable limitation.. 2005-08-12 17:50 | login or register to post comments Flexible? The Factor code that Dan showed is equivalent to the Scheme code. Given the spec for another automata. One of these days I'll have to get over the Lisp allergy I picked up when I was a wee lad and really give Scheme a good look. nor Factor code is quite as understandable as that presented in slide 38 of Shriram's talk. Also he uses character literals instead of symbols. is that neither is as flexible as what he presents either. Recall. clear descriptions via macros. Anton's pointer to the talk said (emphasis mine): Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable.

use an n x 256 matrix m. The Factor equivalent of this (from pg... I believe you're wrong.looks like. : final-machine {| init :: CHAR: loop :: CHAR: CHAR: CHAR: end :: CHAR: c a d r r -> -> -> -> -> loop loop loop end end .. and I couldn't figure out exactly what was going on. By Greg Buchholz at Fri. |} .. (automaton init (init : (c -> more)) (more : (a -> more) (d -> more) (r -> end)) (end : (r -> end))) . assign m[state.... for a machine with n states. I was just about to leave a note that the factor version may be just as flexible. . || || .. I more or less figured out what he was doing after I posted the message. 2005-08-12 18:00 | login or register to post comments understandable.not a lot of difference to my eyes.By slava at Fri... 2005-08-12 18:00 | login or register to post comments Faster than I am.. 2005-08-12 18:08 | login or register to post comments More confusion? Unless I'm confused (which happens on a regular basis). flexible. for each (state : input -> nextstate)... Neumann at Fri. because I am completely unfamiliar with it. i don't think i missed either point.input]:nextstate to run on input i: r:1 m\i . I stand corrected there. -30By William D.. 38).

even if this is a phenomenon I might have contributed to.setting up a particular machine can be done line-by-line. as directly as possible. However. or it can be done all at once. 2005-08-12 18:55 | login or register to post comments Simplicity This particular task does not even call for a state machine at all: : swine ( sequence -. By sa at Fri. if state-machines are matrices.. and not even capable of implementing their own optimizing native compilers. one could even conclude t . no special syntax. It might be interesting to know if there are any patterns that can be used to fake named parameters while maintaining concatenability. and recognition is recursive two-dimensional indexing. then implement it as such. 2005-08-12 17:53 | login or register to post comments As O said. Making oneself look completely ignorant is rhetoric? By Derek Elkins at Fri. as in the scheme example. By slava at Fri. I certainly find it difficult enough. one could even conclude that applicative languages are totally non-productive. It's hyperbole to show up the fact that there are different expressivity/productivity/comprehensibility wins with concatenative and applicative languages. 2005-08-12 17:52 | login or register to post comments . This is just trolling. as my example shows.. even if this is a phenomenon I might have contributed to. By Marcin Tustin at Thu. I interpreted his .. because it taxes my memory. 2005-08-11 14:26 | login or register to post comments Let's not start pointing fing Let's not start pointing fingers and crying "troll" at everyone using a modicum of rhetoric. Let's not start pointing fingers and crying "troll" at everyone using a modicum of rhetoric.? ) "c" ?head >r "r" ?tail r> and [ "ad" contained? ] [ drop f ] ifte . no macros. I suspect that the difficulty of using a form of functional programming without named parameters is a significant problem for many people. despite my ability to remember to API docs.. that I have been discouraged from exploring concatenative programming.

except perhaps in certain specialized domains? By Anton van Straaten at Wed. a GUI toolkit-inprogress. various development tools. although I can say Factor's sequences library is cleaner and more generic than CL's. except for porting a few trivial things back and forth.. that you're willing to put up with other serious limitations in concatenative languages to escape it. . I've tried Scheme and far prefer Common Lisp. I have never developed the same application in CL and Factor side by side. This is a richer level of functionality than offered by most languages discussed on this web site. though? Scheme. I'd say Haskell and ML's lack of a live environment with in-image development tools is a serious limitation. so ironically. and more. Perhaps by "most languages discussed on this web site". 2005-08-10 16:08 | login or register to post comments What serious limitations? I'd say Haskell and ML's lack of a live environment with in-image development tools is a serious limitation..As O said. By slava at Wed. ML? Should we take your comparison to Java as a tacit acknowledgement that concatenative languages can't really compete with more expressive applicative languages.. an improvement on Java boilerplate? Factor has an HTTP server with a continuation-based web framework. Haskell. and not even capable of implementing their own optimizing native compilers. 2005-08-10 16:18 | login or register to post comments Repeat after me. but this sounds completely false. going back to a language like Java with annoyingly handcoded boilerplate loops seems more like a Turing machine. What about all the much more expressive applicative languages. I don't know what you're thinking of here. I wasn't commenting on his other posts. By Marcin Tustin at Sat. What I take from this is that you find Java so restrictive. you might want to tone down the rhetoric. after working with Factor's libraries for sequences and mathematics. you're thinking only of announcements of brandnew or toy languages? Re: "writing a Turing machine program". I interpreted his comment that "one might conclude. so I cannot comment on the merits of CL versus concatenative languages." as hyperbole.. If you expect to be taken seriously. 2005-08-13 08:50 | login or register to post comments Wow. one could even conclude that applicative languages are totally non-productive.

2005-08-11 03:49 | login or register to post comments Type systems language implementation != language Yeah.oP Of course. . I just wanted to say that typing makes things more complicated. 2005-08-11 02:54 | login or register to post comments Toplevel I was just going to say that I quite enjoy O'Caml's toplevel(s). By Daniel Ehrenberg at Thu. 2005-08-11 03:16 | login or register to post comments Slipping? Paul. A more fundamental factor is their higher degree of purity compared to Lisp. By Anton van Straaten at Thu. but Haskell's and ML's type systems make it so that less things can be done at runtime. :-) By Paul Snively at Thu. which makes "interactive update" a more alien concept.language implementation != language language != language implementation By dhopwood at Thu. By Andreas Rossberg at Sat. Smalltalk and the likes. although I've never looked. You forgot to mention Tuareg mode. GHC and SML/NJ also have nice toplevels. PLEEEASE don't get into a type system debate here. I wouldn't be surprised to find IDEs for them. 2005-08-11 16:13 | login or register to post comments hs-plugins certainly makes an hs-plugins certainly makes an interesting tool in that context By Philippa Cowderoy at Thu. I'm disappointed. 2005-08-13 12:09 | login or register to post comments Foreign? . so development tools are more complicated and less useful. 2005-08-11 16:41 | login or register to post comments Not so much due to types I'd say it's only secondarily due to their type systems.

Defining functions without having argument names or let bindings to name your terms gets you into drop swap dup rot shenanigans.. it seems like a tour de force comparable to writing a Turing machine program.Is it just me.method() ).ScannedInAvian. obj.. Up with that.. 2005-08-11 11:37 | login or register to post comments . That kind of stuff is for compilers.method( obj.I can't imagine writing any nontrivial program in a concatenative language...attribute. not programmers.Is it just me.attribute. class.com By shapr at Thu. I will not put.. 2005-08-10 17:34 | login or register to post comments names . Stack scramblers make this perfectly clear. or does that bear a striking resemblance to concatenative code? expressions are easy enough. Borrowing an example from another thread. 2005-08-10 18:54 | login or register to post comments Re: names So why do you troll in this thread? By slava at Wed. Factor uses stack scramblers nowadays also. They look like this: swap = ab-ba drop = adup = a-aa I can never remember which of rollup or rolldown does which of abc-cba or abc-bca.. --Shae Erisson . By James McCartney at Wed. or does that bear a striking resemblance to concatenative code? By Greg Buchholz at Wed. or directly in the lambda calculus using de Bruijn indices.getSomething(). .method().. 2005-08-10 19:05 | login or register to post comments Stack scramblers I like William Tanksley's stack scramblers idea for concatenative languages.

drop. 2005-08-11 16:21 | login or register to post comments The original Java Factor impl The original Java Factor implementation had these stack shuffle words. By Wouter at Wed. swap.. By Daniel Ehrenberg at Thu. The current C version no longer has them IIRC. etcetera. Note that CL code has to be read right to left.baz(). I could never remember which ones those stack shufflers were -. 2005-08-11 22:14 | login or register to post comments Re: Foreign? Compare some typical OOP code in four languages: Common Lisp: (baz (bar (make-instance 'foo))) Java: new Foo(). The original meaning of both words is "hole". which ironically is a common complaint against *postfix* languages. By slava at Wed. (Source: The Alternative Dutch Dictionary) By Sjoerd Visscher at Thu. no Factor uses stack scramblers nowadays also.. 2005-08-10 19:02 | login or register to post comments "kont" means "ass" in dutch. 2005-08-10 21:05 | login or register to post comments As in "arse" or "donkey"? As in "arse" or "donkey"? By Marcin Tustin at Thu. By doublec at Thu. It does? I'm pretty sure it still uses good old dup. Smalltalk: Foo new bar baz. 2005-08-11 15:30 | login or register to post comments .Umm. it was crystal clear.bar. Then. 2005-08-11 14:15 | login or register to post comments Arse The dutch word "kont" is etymologically related to the english word "cunt".until I started actually programming. Factor: <foo> bar baz Factor's concatenative code looks very similar to how Smalltalk unary messages are composed.

a → a × Int.. etc. would be typed ∀a.. their use in programming languages is rather unchartered.. Neumann at Fri. Although as George Carlin has pointed out in one of his routines.. but I don't know how much of the code in the database is in C. It's pretty easy to model this in a functional language (note: this is not a claim of superiority/inferiority). Here's a GHCi session: Prelude> let k = flip (. 2005-08-11 21:45 | login or register to post comments koders. you can treat Forth words as unary functions of the form stack → new_stack. By Scott Johnson at Thu. named after a porn star. you can appeal to polymorphism to guarantee that functions won't interfere with elements beyond a certain depth in the stack. Just think of all the expressivity we could gain. Perhaps we should get started on the research then.. Not to mention Linda.b) = (s. at least one of the more popular words is already seriously overloaded. f a b) . and the arithmetic functions like +. 2005-08-11 15:44 | login or register to post comments Well.TMI: Too Much Information Though cuss words might be considered a valid form of study in the field of linguistics.a). we've had Brainfuck for some number of years now. I'm sure there are a few other (as yet undiscovered) dirty jokes and double entendres out there. More than half of the occurences is in C code.com could be a start Crap is the most popular cuss word..) Prelude> let lift2 f ((s. a × Int × Int → a × Int. :-) By Chris Rathman at Thu. -30By William D... -. 2005-08-12 14:19 | login or register to post comments Stack-based is point-free? If you represent a stack as nested pairs... With a type system. By Sjoerd Visscher at Fri. Integer constants would have the type ∀a. of the words I can think of right now.. 2005-08-12 08:39 | login or register to post comments Time to get started then..

Integer). Integer) Prelude> :t plus . k 4 :: (a. Integer) Prelude> :t plus . and the return type as the type of the "output stack". k 2 plus . k 2 $ () 6 What's interesting is that arrows in Haskell are defined in a point-free style. k 4 . which means that there is no fundamental expressivity gain to be had in shifting between a combinatory . and that every term corresponds to a morphism. but with a dash of type-system wizardary. you can write most any Joy combinator in Haskell. Integer). (Arrows pass multiple values around with nested tuples. so can be more tree-like than stack-like. y) -> y + z)) which consists primarily of composition and "stack" manipulation. If you like. Integer) Prelude> snd .f -< x z <. Integer). Thus. 2005-08-12 01:24 | login or register to post comments The lambda calculus is the "i The lambda calculus is the "internal language" of a cartesian closed category. plus :: (((a.g -< x returnA -< y + z becomes arr (\ x -> (x. x) -> (x. but they don't prefer one side or the other. y)) >>> first g >>> arr (\ (z. Integer) -> (a. 2005-08-11 23:55 | login or register to post comments Joy in Haskell Things get a little interesting when you get to the recursion combinators.) By Dave Menendez at Thu. k 4 plus . k 4 . plus plus . Integer) -> (a. plus .Prelude> let plus = lift2 (+) Prelude> :t plus plus :: ((a. By Greg Buchholz at Fri. along with a special syntax involving local names which is translated into the point-free style. In turn. Integer) Prelude> :t plus . this means that you can convert any program in the lambda calculus into an equivalent program consisting entirely of a composition of combinators (and you can do it in O(1) in either direction). k 4 . proc x -> y <. you can think of the types of the set of free variables of a term as the type of the "input stack". x)) >>> first f >>> arr (\ (y. k 2 :: a -> (a. Integer) -> (a. This means that every type in the lambda calculus corresponds to an object of a CCC.

o directamente en el cálculo lambda con De Bruijn índices. ala Forth. Por Chris en 08/08/2005 16:17 | LTU foro | tema anterior del foro | tema siguiente foro | otros blogs | 13663 lecturas Opciones de visualización de comentarios Roscado lista . ¿Cómo se supone que debes ser capaz de recordar o hacer un seguimiento de lo que está en la pila en un momento dado? ¿Cómo se puede construir abstracciones encapsuladas reutilizables? No me puedo imaginar la escritura de cualquier programa no trivial en un idioma concatenativa. no puedo ver el tipo de punto. etc. las funciones de alias. Un comentario sobre las lenguas en general. Un lenguaje de concatenación es un lenguaje en el que los programas están formados por la concatenación de pequeñas primitivas. Kont salió de un intento de diseñar un lenguaje de programación en el que se expresó en cada programa estilo continuación de paso. usted sólo tiene que tratar a las palabras como cajas negras que llevan de entrada y dar salida. Pero los entusiastas de Forth. I think that being able to name variables explicitly is a genuine advantage. a pesar de que se utiliza un sistema HP-41 y ha programado) El truco es simplemente usar palabras pequeñas. ¿Cómo? Por dhopwood el Mar. 09/08/2005 20:25 | conectarte o regístrese para enviar comentarios Con pequeños y bien educados palabras (Nota: No utilizar cualquier lenguaje de concatenación. funcionales (es decir. parece un tour de force comparable a escribir un programa de máquina de Turing. mileage varies. Como lenguajes de bajo nivel para ser utilizado como una compilación de los objetivos. By neelk at Fri. De esta manera. Cuando usted comienza a tener para hacer un seguimiento de la . but obviously.language and the lambda calculus.antiguos primero Guardar la configuración Seleccione la forma que prefiera para mostrar los comentarios y haga clic en "Guardar configuración" para activar los cambios.se expandió 200 comentarios por página Fecha . pila locales). 2005-08-12 19:32 | login or register to post comments ------------------------------------------------------------------------------- (TRADUCCIÓN) Lambda de la última Inicio » foros » Foro LTU Concatenativa Kont Idioma Un interesante proyecto . efectos. parecen estar diciendo que escribir programas no triviales de la aplicación en estos idiomas. concatenativa No entiendo por qué alguien considera idiomas concatenativa ser adecuado para programación de alto nivel.

minusb radical) divisor)]) (Cons root1 root2))))) La estructura del código Esquema refleja directamente la estructura de la fórmula..(* bb) (* 4 (* ac)))) divisor = * 2 un root1 = / (+ minusb radical) divisor root2 = / (.net Páginas Manfred von Thun de Joy también trata este tema en algunos de los artículos. Por pkhuong el Mar. Su única en la fórmula cuadrática..edu.sourceforge.latrobe.(* bb) (* 4 (* ac))))] [Divisor (* 2 a)]) que ([root1 (/ (+ minusb radical) divisor)] [Root2 (/ (. "Pensar Forth 'tiene un montón de buenos consejos en este ámbito: http://thinking-forth.sqrt]] # radical [I] mapa] ternaria i [[[+ Swap /] # root1 [. pero creo que solo apoya mi punto de vista. De hecho. 09/08/2005 23:21 | conectarte o regístrese para enviar comentarios Un montón de factoring El truco está en las palabras pequeñas. pop.sqrt (b ^ 2 .4 * a * c) ----------------------------2 * a (Definir la fórmula cuadrática (Lambda (abc) (Let ([minusb (. 2 *] # divisor [Pop 0 swap -] # minusb [* Dup intercambio de resumen * 4 * .. Cada vez que hacer un montón de manipulaciones de la pila es una señal de que necesita de refactorizar. b. como podemos ver por escrito la fórmula con las mismas variables auxiliares y en la notación de prefijo: cuadrática-fórmula (a. que es probablemente un buen indicio de lo que necesita para romper la palabra en un par de palabras más intuitivos (o que su interfaz para que la palabra es muy complicado).0 b)] [Radical (sqrt (.0 b radical = sqrt (.. 09/08/2005 23:28 | conectarte o regístrese para enviar comentarios El ejemplo de segundo grado en que la última dirección URL es un buen ejemplo .Swap /]] # root2 [I] mapa] . root2) donde minusb = .au/philosophy/phimvt/joy/jp-quadratic. -B + / . sólo hay diferencias triviales de notación entre la fórmula y el código. por ejemplo: http://www. fácilmente comprobables.html Por doublec el Mar.pila. c) def = (root1.minusb radical) divisor Compare eso con la 2 ª versión de la Alegría (el que sugirió a ser "el mejor de los tres en la presente nota"): cuadrática-2 == # abc => [root1 root2] [[[Pop. .

por supuesto. Ya existe. la fórmula cuadrática es un problema que no. sobre el potencial error de la propensión de la pila de forma implícita la introducción de variables sin nombres) no son específicos de este caso. He encontrado que el tiempo que va de señalar un error. ver contrib / álgebra / en la distribución. Acerca de la tasa de errores que son más altos. es posible para mitigar este problema reduciendo al mínimo el tamaño de la pila en un momento dado. Al igual que todo el software de Java. diversas herramientas de seguimiento y. Es muy fácil escribir un lenguaje que compila a código concatenativa que luego pasa por compilador nativo Factor. el REPL. Es imposible entender lo que este código está haciendo sin pensar en cómo se utiliza una pila que no está presente en el problema original (y que pueden corresponderse con el problema de muchas maneras diferentes). Una proporción de esos errores no se pueden encontrar por medio de pruebas. para resolverlo.b" a ". que es probable que se suman a un riesgo inaceptable. Aceptar.ternario. y la depuración es pura alegría con herramientas como nuestro inspector interfaz gráfica de usuario. Es muy fácil escribir un lenguaje que compila a código concatenativa que luego pasa por compilador nativo Factor. 10/08/2005 03:51 | conectarte o regístrese para enviar comentarios Re: fórmula cuadrática En Factor . ** ¿Eh? ** Yo no creo que sea sólo mi falta de familiaridad con la alegría que está en juego aquí: la estructura del código es simplemente muy diferente de la fórmula. sin embargo. Para que un programa grande. . y mi experiencia no es concluyente en ambos sentidos. pero el riesgo de cometer un error va a ser mayor para cualquier número dado de variables que en un programa equivalente que utiliza nombres. debido a la no-interactivo de Java. he tenido unos cuantos de varios días de duración maratones de depuración. y siempre encuentro nuevos errores y misteriosos que son casi imposibles de resolver. Estos comentarios no son equivalentes a la utilización de nombres en el código . las críticas (por ejemplo. es un dolor de mantener. Y entonces usted no está escribiendo la aritmética en un lenguaje de concatenación. el gran padre de todas ellas. Muchos errores de la pila puede ser capturado de forma estática.¿Qué pasa si se equivocaron? Las variables tienen que ser referido por el seguimiento de su posición en la pila (que es lo que estaba recibiendo menos en la referencia a los índices de De Bruijn por encima). la naturaleza estática y laboriosos edición / compilación / ejecución del ciclo. La diferencia que más se destaca es que ninguna de las variables se mencionan explícitamente los nombres de la derecha son sólo comentarios. mediante el efecto chimenea inferencer.0 b"] Por dhopwood el Mié. Debo admitir. 08/10/2005 06:39 | conectarte o regístrese para enviar comentarios ¿No es el punto de Sólo integrar un lenguaje de dominio específico para la aritmética infijo y acabar de una vez. Por slava el Mié. la otra pieza grande de software que mantener. y así sucesivamente. de un solo paso a paso. [Edit: corregido "0 . El ejemplo que acaba de pasar a utilizar la aritmética. Unidad de flujo de las pruebas con facilidad. Sólo integrar un lenguaje de dominio específico para la aritmética infijo y acabar de una vez. Por otro lado. pero temas como la reubicación de fallos en el generador de código del compilador que lleva al código sobreescrito o incorrectas reglas de reescritura en el optimizador . estos no tenían nada que ver con la pila. sin embargo. para arreglarlo es muy corto en el factor. jEdit está escrito en Java.

intercambiar. por lo general. si usted nota el error. Y entonces usted no está escribiendo funciones en un lenguaje puro. por ejemplo: * Postfix vs prefijo * Pila de manipulación de las variables con nombre frente a los * Dejando de lado de los paréntesis (a pesar de que podría hacer para una mejor lectura) Esquema de idiomas y otros (C) Por supuesto. si estás dirigidas a un equipo basado en registros). como si de una expresión como: (Let ((x 33)) (Foo) . .. DUP. Y en los idiomas aplicativos. puede utilizar una pila. Vamos a tratar de volver a escribir que un poco diferente . el programador depende en gran medida abstracciones que el lenguaje no cumplir ni siquiera sabía acerca: cada vez que utilice el pop. así. Sólo tiene que utilizar las mónadas (como un embebido de dominio específico del lenguaje) para la secuenciación de los efectos secundarios y que hacer con ella. Al igual que todo el software de Java. Y entonces usted no está escribiendo la aritmética en un lenguaje de concatenación.. como el pop.Yo no he dicho que las lenguas concatenativa no son adecuados como lenguajes intermedios (aunque me pregunto por qué los usaría en lugar de un IL basado en registros. Además. para arreglarlo es muy corto en el factor. que está haciendo una suposición sobre lo que está en la pila. .. 08/10/2005 18:02 | conectarte o regístrese para enviar comentarios Estoy de acuerdo Estoy de acuerdo.. sino que sólo se traten de manera diferente. 08/10/2005 15:31 | conectarte o regístrese para enviar comentarios Mónadas Sólo integrar un lenguaje de dominio específico para la aritmética infijo y acabar de una vez. jEdit está escrito en Java. Por Greg Buchholz el Mié. Eso es un signo clásico de un lenguaje de bajo nivel (pensar en ensamblador). en los idiomas concatenativa.. El corolario a su punto acerca de los nombres es la presencia de todos los nombres en el código de la alegría que nada tienen que ver con el dominio del problema.Derecho . para resolverlo. como algo más fácil de razonar acerca de que una máquina de registro con sede en? Parece que hay unos cuantos idiomas formas ortogonales como Forth difieren de régimen. He encontrado que el tiempo que va de señalar un error. [Cualquier persona que utilice un lenguaje que utiliza postfix variables con nombre?] Por dbfaken el Mié. 10/08/2005 14:07 | conectarte o regístrese para enviar comentarios "Orden superior" lenguaje intermedio? Tal vez podría funcionar de esta manera. es un dolor para mantener. y el resumen. pero esa suposición podría ser violada por relación código.. ¿Yo sin querer defender a Java? Por dhopwood el Mié.

este tipo de comportamiento se conoce como "inseguro": que una abstracción no está protegido de la interferencia externa no autorizada.. Eso no es un buen argumento desde la perspectiva del usuario del lenguaje. de varios valores de vinculación y setf en los programas comunes de Lisp? También tienen nada que ver con el dominio del problema. Este tipo de efecto secundario que no es local para los insectos es una reminiscencia de algo así como un error de puntero. eso es un problema para la comprensión del código. y que viola su contrato por mutación del objeto en un estado incorrecto. devolver los valores correctos. de varios valores de vinculación y setf en los programas comunes de Lisp? También tienen nada que ver con el dominio del problema. eso sólo sería un buen argumento si los programadores no necesitan depender en gran medida de falsificación de enlaces locales en los idiomas concatenativa. ¿Qué lógica se utiliza para justificar la idea de que sólo puede tener nombres globales? Todo se reduce a algo así como "porque es fácil de implementar un lenguaje de esa manera. muchos de los nombres que se mencionan se utilizan para introducir los nombres que son relevantes para el dominio del problema. como ensamblador"? En primer lugar. En otros contextos. como el pop. sin embargo. me refiero en parte a la frecuencia de ocurrencia. siguen siendo más significativa para el problema a resolver que los operadores de la pila son. Incluso las lenguas concatenativa reconocer que los nombres son importantes. 08/10/2005 16:11 | conectarte o regístrese para enviar comentarios Incorrecto Correcto empuje del pop ¿Qué pasa con nombres como vamos. Supongamos que escribir una función que toma un objeto mutable como entrada. ya que todos ellos admiten nombres globales. las etiquetas. como un implementador de un lenguaje. Factor tiene un efecto de chimenea inferencer que podría ser utilizado para comprobar que se loquesea. Sin embargo.. y el paquete de continuación de ¿Qué pasa con nombres como vamos. intercambiar. de hecho. Es el nivel CL baja ". En segundo lugar. DUP. Esto podría explicar por qué. Es el nivel CL baja ". Cuando usted mira a una pieza de código. Por Anton van Straaten el Mié. lo que más destaca? Si usted ve los nombres de muy pocos que se relacionan con el dominio del problema. como ensamblador"? Este tipo de efecto secundario que no es local para los insectos es una reminiscencia de algo así como un error de puntero. si foo tiene un error. 08/10/2005 15:48 | conectarte o regístrese para enviar comentarios Incorrecto El corolario a su punto acerca de los nombres es la presencia de todos los nombres en el código de la alegría que nada tienen que ver con el dominio del problema. este tipo de comportamiento se conoce como "inseguro": que una abstracción no está protegido de la interferencia externa no autorizada. En el contexto de concatenación.x) . no se está violando. se puede jugar abogado de lenguaje y afirman que puesto que el lenguaje no tiene la idea de una unión local. y muchos nombres que se relacionan con una abstracción en el lenguaje de programación. Podría devolver un valor distinto de 33. y puede salirse con la suya y de trabajar alrededor de ella". Por lo tanto. son entusiastas acerca de ellos. las etiquetas.En otros contextos. . ¿cómo es esto diferente de una función con un efecto de chimenea no válida? ¿Se va a argumentar en favor de las lenguas puramente funcionales. que son exclusivamente el dominio de los académicos? Por slava el Mié.

pero no vamos a convencer a mucha gente por fanfarroneando acerca de ello y haciendo over-the-top críticas de otros idiomas y probadas. Si el factor puede apoyar tales afirmaciones. debo mencionar que he escrito en Forth sistemas. y es un lenguaje puramente funcional. es demostrablemente falsa de que son "exclusivamente el dominio de los académicos". Si ese es el caso. ¿Sabía usted siquiera se molestó en mirarlo? Podría ser utilizado? Esto implica que esto no es algo que ocurre de forma automática. Simple refutación: Erlang se utiliza para ejecutar los interruptores de telecomunicaciones. que de otro modo no hay que preocuparse.Factor tiene un efecto de chimenea inferencer que podría ser utilizado para comprobar que se loquesea.no es un caso en que una función esencialmente sin relación puede destruir una abstracción que no tiene conexión a. Sin embargo. pero no creo que los idiomas pueden apoyar este tipo de afirmaciones que parecen querer hacer. hago uso de las lenguas que fomenten y apoyen el control de los efectos secundarios. Es difícil ver cómo eso sería un beneficio. mientras que no se usan lenguajes puramente funcionales en todos los contextos. para garantizar de manera transparente la seguridad de los enlaces relacionados "" (o como quiera llamarlos en un idioma concatenativa). me gustaría señalar que aquí . 08/10/2005 17:02 | conectarte o regístrese para enviar comentarios Más reclamos incorrectos ¿Qué lógica se utiliza para justificar la idea de que sólo puede tener nombres globales? No estoy seguro de lo que la lógica se usa. Para que no se tomará como totalmente negativa sobre las lenguas concatenativa. que de otro modo no hay que preocuparse. Hay muchos más ejemplos de dónde salió eso. porque yo no lo sigue. para garantizar de manera transparente la seguridad de los enlaces relacionados "" (o como quiera llamarlos en un idioma concatenativa). ¿cómo es esto diferente de una función con un efecto de chimenea no válida? Es diferente en que la persona que llama sabe que ha pasado un objeto mutable a esa función . entonces esto crea un área que el usuario tenga que preocuparse. y puede ser divertido y útil en ciertos tipos de aplicaciones. Si ese es el caso. Esto tiene numerosas ventajas demostrables . y lo hago escribir código que evita los efectos secundarios en su mayor parte. entonces esto crea un área que el usuario tenga que preocuparse. Por Anton van Straaten el Mié. y ha escrito un intérprete de la alegría de juguete. Factor tiene variables y espacios de nombres anidados y alcance. La función de todos los programas dependen implícitamente en una pila que puede ser directamente lado-a cabo mediante cualquier función es un paso atrás a este respecto. Supongamos que escribir una función que toma un objeto mutable como entrada. Es difícil ver cómo eso sería un beneficio.si usted desea comenzar a discutir en contra de ellos. . es cierto que los efectos secundarios son una causa importante de problemas. Creo que son lenguajes muy interesantes. ¿Se va a argumentar en favor de las lenguas puramente funcionales. por lo que las lenguas más potentes proporcionan maneras de controlar los efectos secundarios. y que viola su contrato por mutación del objeto en un estado incorrecto. que son exclusivamente el dominio de los académicos? En primer lugar. En segundo lugar. eso sería interesante. devolver los valores correctos. experimentado con alegría. de hecho. Podría ser utilizado? Esto implica que esto no es algo que ocurre de forma automática.

como esquema. puede llegar a un punto en el que se hace evidente que sólo abordar el tema a nivel del lenguaje es una buena idea? Para que no se tomará como totalmente negativa sobre las lenguas concatenativa. Mostrar donde he estado "fanfarrón" y haciendo over-the-top críticas. a continuación. Ya he respondido a casos específicos. y ha escrito un intérprete de la alegría de juguete. Eso suena como si fuera a ser útil. no me digan claramente. debo mencionar que he escrito en Forth sistemas. Factor tiene variables y espacios de nombres anidados y alcance.¿Tiene factor de ofrecer esta característica? Yo podría añadir algunas herramientas para hacer esto automáticamente para cada definición de la palabra nueva. He mirado brevemente los factores. experimentado con alegría. que va a ser interesante ver cómo resulta con el tiempo. Yo sostengo que la combinación de mis experiencias con Forth y Alegría. pero no vamos a convencer a mucha gente por fanfarroneando acerca de ello y haciendo over-the-top críticas de otros idiomas y probadas. y ha escrito un intérprete de la alegría de juguete. observe que este intérprete de juguete es difícil de trabajar. tenemos que ser claros acerca de si estamos hablando de verdaderos idiomas concatenativa en general. Mostrar donde he estado "fanfarrón" y haciendo over-the-top críticas. experimentado con alegría. que no ofrecen esta característica. debo concluir que lenguas aplicativos en su conjunto son inútiles? Si el factor puede apoyar tales afirmaciones. porque yo no lo sigue. Para que no se tomará como totalmente negativa sobre las lenguas concatenativa. pero dentro de los procedimientos individuales. en cualquier caso. hace que sea posible para mí hacer comparaciones y sacar conclusiones relacionadas con ciertas propiedades de estos idiomas. 08/10/2005 17:09 | conectarte o regístrese para enviar comentarios ¿No es / está tan títulos son aburridas No estoy seguro de lo que la lógica se usa. Lo que me refiero es que estos idiomas demostrar que reconocer que el apoyo a los enlaces seguros entre los nombres y los valores es importante. entonces le sugiero que abandone el mal definido término "concatenación" y cambie a algo así como "directos idiomas Manipulación de la pila". El debate se inició de forma más general. Así que su única experiencia con lenguas concatenativa es haber escrito un intérprete de la alegría del juguete? Si yo escribo un intérprete de lenguaje de juguete para un aplicativo simple. pero algunas de las citas en cuestión son los siguientes: . Por slava el Mié.Yo podría añadir algunas herramientas para hacer esto automáticamente para cada definición de la palabra nueva. ¿Sabía usted siquiera se molestó en mirarlo? Bueno. Una cuestión es que a medida que agrega características semejantes. pero no he encontrado que suficientemente en cuenta el tipo de problemas que he mencionado. y decir que no es Forth concatenativa? Si es así. hace unos meses. lo que es más significativo. debo mencionar que he escrito en Forth sistemas. es decir. combinado con el conocimiento de la semántica del lenguaje de programación y experiencias con una variedad de otros idiomas. eso sería interesante. temporales de nombre / valor enlaces que puede ser invocado por la vida de un procedimiento. Así que su única experiencia con lenguas concatenativa es haber escrito un intérprete de la alegría del juguete? ¿Es su intención de entrar en una discusión de definiciones ahora. o de factores. en particular. Ya que es todavía en desarrollo. En cuanto a mi punto de vista acerca de los nombres a nivel mundial.

Entonces. se decidió para hacer de troll en su lugar. Creo que eso es cierto. . y ni siquiera capaz de implementar sus propios compiladores nativos de optimización. y he defendido que en los intercambios con los demás. ¿por qué haces lo equivalente aquí? Por slava el Mié. en lugar de discutir el lenguaje Kont usted mismo. Usted ni siquiera se molestan refutar mis puntos ¿Cuáles son los puntos? AFAICT. y los idiomas de investigación no califica. 08/10/2005 19:55 | conectarte o regístrese para enviar comentarios No eres más que arrastre Ya he respondido a casos específicos. Yo le respondí a otro puesto que hizo un punto que estaba de acuerdo con. En lugar de discutir el lenguaje Kont. Le sugiero que relea el hilo con más cuidado. pero supongo que a partir de la reacción general que no está de acuerdo. según algunas definiciones. Su suposición es incorrecta. el primer post de este hilo era su reclamo despectiva que las lenguas concatenativa no son adecuados para el desarrollo de aplicaciones. idiomas aplicativas. Usted es libre de discutir mis puntos. ya que no se han ocupado de mis puntos. y en lugar de sacar conclusiones generales y las generalizaciones basadas en su experiencia limitada con la alegría y el Forth. por favor Usted ve. pero atacando a la academia. alegando que los tipos estáticos es demasiado restrictiva. Estoy teniendo dificultades para discernir las reglas que creo que deberían seguir aquí. Jeh. No estoy de arrastre. el primer post de este hilo era su reclamo despectiva que las lenguas concatenativa no son adecuados para el desarrollo de aplicaciones. califica como un lenguaje de investigación. con argumentos racionales. alegando que los tipos estáticos es demasiado restrictiva. y en lugar de sacar conclusiones generales y las generalizaciones basadas en su experiencia limitada con la alegría y el Forth. usted decidió hablar de factor. Usted ni siquiera se molestan refutar mis puntos. pero algunas de las citas en cuestión son los siguientes: Usted ve. En lugar de discutir el lenguaje Kont. Me dijo idiomas concatenativa muestran un signo particular de ser un lenguaje de bajo nivel. se decidió para hacer de troll en su lugar. he respondido a cada uno de sus puntos fundamentales. Es particularmente irónico teniendo en cuenta que en su propio idioma que. me di cuenta de que.Este es un nivel más rico de la funcionalidad que ofrecen la mayoría de las lenguas tratadas en este sitio web incluso se podría concluir que las lenguas aplicativos son totalmente improductivos. Sé que no sería muy feliz si me fui y se metió en temas donde la discusión de la ML y Haskell está llevando a cabo. Sé que no sería muy feliz si me fui y se metió en temas donde la discusión de la ML y Haskell está llevando a cabo. en el supuesto de que lo que tienes que decir tiene más base en el argumento racional que sus comentarios sobre esos idiomas hasta el momento. que son exclusivamente el dominio de los académicos? Por Anton van Straaten el Mié. 08/10/2005 22:29 | conectarte o regístrese para enviar comentarios De sustancias. Sin embargo. ¿Se va a argumentar en favor de las lenguas puramente funcionales. "la mayoría de los idiomas discutidos en este sitio web". Ni siquiera estoy seguro de si está de acuerdo.

Más bien. sólo diferentes. yo creo que es posible que tenga algunas ideas interesantes sobre el asunto. Creo que este tema es uno de los factores que subyace una reacción negativa al usuario común a estos idiomas. Pero lo más importante.Por supuesto.la mina han cambiado mucho a lo largo de los años. usted no ha optado por ofrecer a aquellos que aún no. de una manera que otros idiomas pasar a usar como una forma intermedia. Brian Mastenbrook ya ha escuchado mi opinión en este tema). si usted no entiende Slava (a pesar de que él está siendo muy claro). me gustaría recordarles que no convencerá a Slava o me deje de usar lenguas concatenativa porque somos perfectamente cómodo con ellos. Suena casi como si estuviera nerviosa que podría tener éxito! . Más bien. sin embargo.Esto no significa en absoluto que es peor. Estoy interesado en la semántica de los lenguajes de programación. Acaban de manejar las cosas de manera diferente. Creo que este tema es uno de los factores que subyace una reacción negativa al usuario común a estos idiomas. Me dijo idiomas concatenativa muestran un signo particular de ser un lenguaje de bajo nivel. como estos se relacionan con la semántica de la experiencia de usuario de programación. pero por alguna razón. No. Mi post original en este tema no fue pensado como una crítica de Kont específicamente (y.) Pero lo que realmente no tienen ningún interés en cambiar su elección de lenguaje de programación. fue un intento de caracterizar uno de los problemas semánticos que distinguen idiomas concatenación de lenguajes basados en nombre con localesprocedimiento de abstracciones (también conocidas como variables locales). ¿Cómo son abstracciones variables locales? ¿Podría explicar eso? ¿En qué son más abstractos y flexibles que los operadores de la pila arrastrando los pies? Por Daniel Ehrenberg el Jue. Por Anton van Straaten el Jue. no importa que tan bajo nivel que demuestran que ellos sean. Como alguien que se interesa en los idiomas concatenativa. una buena comprensión de las características de PL y cómo afectan a los programas y la programación puede hacer un mejor programador en cualquier idioma. 11/08/2005 17:33 | conectarte o regístrese para enviar comentarios Referencia del pop sentido En primer lugar. ¿eso significa que C de alto nivel que cualquier otro tipo de forma de asignación única? Por supuesto que no. Otras personas tienen. y entre otras cosas. el punto esentender más acerca de las características del lenguaje de programación y sus consecuencias. que es la razón por la que estoy aquí. el estilo de programación. me gustaría recordarles que no convencerá a Slava o me deje de usar lenguas concatenativa porque somos perfectamente cómodo con ellos. no importa que tan bajo nivel que demuestran que ellos sean. 08/11/2005 00:20 | conectarte o regístrese para enviar comentarios Permítanme reiterar las subestaciones Permítanme reiterar los puntos substatiative. esto puede llevar a cambios en las preferencias. ¿por qué haces lo equivalente aquí? Este es un foro para la discusión de los lenguajes de programación. además.Entonces. También puede ayudar en la evaluación de la idoneidad de una . Si un compilador de C utiliza una forma intermedia que es la asignación de un solo. No creo que los idiomas son más concatenación de bajo nivel. fue un intento de caracterizar uno de los problemas semánticos que distinguen idiomas concatenación de lenguajes basados en nombre con locales-procedimiento de abstracciones (también conocidas como variables locales). etc . En primer lugar.

Un nombre actúa como una forma de referirse a un valor. de una manera que otros idiomas pasar a usar como una forma intermedia. Al principio del hilo.lengua en una situación dada. si los nombres son tan útiles e importantes cuando las escalas de código más allá de un procedimiento único. Si su preocupación es con la generalización. ¿Cómo son abstracciones variables locales? ¿Podría explicar eso? ¿En qué son más abstractos y flexibles que los operadores de la pila arrastrando los pies? Una variable local es una abstracción de la misma manera que cualquier nombre es una abstracción. efectivamente. Acaban de manejar las cosas de manera diferente. que es también una especie de abstracción. Esto no significa en absoluto que es peor. es decir. Cuando se presiona un valor en una pila y después aplicar alguna operación con ese valor. sin duda por lo general de más alto nivel que cualquier interno de una sola asignación de forma que es probable que ser compilado para. cualquier tipo de forma de asignación única". por supuesto. Esta cuestión en particular es diferente de una manera que sea más bajo nivel. un nombre . Si un compilador de C utiliza una forma intermedia que es la asignación de un solo.. Usted ha sugerido en otro lugar que lo mismo puede decirse de los nombres de léxico. Así que una pregunta es. Esa es la abstracción. para hacer frente a las limitaciones de la asignación única . ¿no podrían ser de utilidad a nivel local. No creo que los idiomas son más concatenación de bajo nivel. extraer conclusiones acerca de ". e indica que la forma de una sola asignación es menor nivel. Esto ha sido cubierto en unos pocos puestos. en la mayoría de los casos. los cuales (implementado correctamente) son más escalables. eso no es lo que estoy haciendo.Manipulación de la pila directa por sí sola no escala muy bien. dentro de un procedimiento? Y. y la conclusión de que esta es una manera de bajo nivel de lidiar con la abstracción sobre los valores que el uso de nombres. ¿Y qué haces cuando refactorizar? Para crear los nombres. ¿eso significa que C de alto nivel que cualquier otro tipo de forma de asignación única? Por supuesto que no. y ayuda con la corte a través de una campaña sobre los lenguajes de programación específicos.el hecho de que esas operaciones adicionales no son necesarias en el código fuente en C indica que son irrelevantes para la expresión del problema original. Código C es. de muchos idiomas demostrar que son. pero he tratado este tema en mi respuesta a su último punto más adelante. Puesto que los procedimientos se hacen más grandes. sólo diferentes. El nombre se refiere a otra cosa. Estoy buscando a un determinado idioma que regularmente integrar directos operadores de manipulación de la pila en su código. Una de las características fundamentales de los nombres es que. Sin embargo. no todas las abstracciones son iguales. como todos los programadores concatenativa ya lo sabe. y podemos usar el nombre y manipular lo que se refiere a sin saber qué cosa específica que se refiere. más seguras que las abstracciones almacenamiento de valores en una pila. La forma en que se puede decir que es mirar a las operaciones adicionales que se están realizando en el código de un solo destino. es decir. hacer el seguimiento de los valores a través de manipulación de la pila se vuelve más complejo. Lo irrelevante en este caso es la manipulación directa de pila. y se conecta a la observación de Alan Perlis "que bajo nivel implica que" los programas requieren la atención a lo irrelevante ".. la que ha reconocido: "sólo hay unos pocos casos en que la pila que realmente importa". se nos recordó que "cada vez que hacer un montón de manipulaciones de la pila es una señal de que es necesario refactorizar". puede servir a dos propósitos: 1.

Es por esto que tratamos de elegir los nombres de informativos. Un nombre puede proporcionar información a los programadores sobre el valor. Por Anton van Straaten el Vie. no locales los nombres usados en conjunción con la pila a nivel local funciona muy bien la mayor parte del tiempo. y por qué la expresión que se dio en otras partes de este tema fue compiling dataflow optimize linearize simplify generate . Yo podría hacerme: no es necesario debido a los nombres locales de factoring mantiene procedimientos lo suficientemente pequeñas para ser manejables. En la expresión antes citada. Cuando omitimos los nombres de nuestro código. es decir. Si una lengua común obliga a omitir los nombres. Estoy seguro de que hay mucho en lo que he escrito arriba de un ventilador concatenativa que objetar. un nombre también puede tener un "sentido" o "connotación". y siempre que ello sustituye el uso de nombres que podrían ser informativo. Uso de los operadores de la pila barajar es un detalle de bajo nivel no importa cómo se mire. la omisión de los nombres es una cosa y su sustitución por los operadores que manipulan una abstracción (la pila) que no es otra cosa directamente relacionados con la computación es algo completamente distinto. valores de la función de retorno sólo para ser capaz de cambiar su posición para pasar a otra función similar se oscurece la solución al problema. Los argumentos más convincentes. y la mayoría de los idiomas admiten este tipo de omisión de nombres en una forma u otra. Antón escribió: . eso es algo que vale la pena echar un vistazo de cerca. que puede tener varios beneficios . y eso es algo que debe hacerse cuidadosamente. estamos omitiendo una de las pocas cosas que conecta el código para el problema que está resolviendo. Sin embargo.2. que tiene una doble pérdida de la capacidad del programa para expresar su algoritmo para el lector humano. no es necesario nombrar a los valores intermedios. lo que implica un vacío en nuestra comprensión. ambas expresiones podrían tener el efecto exacto de cálculo misma. en vez de abcdef . pero una es mucho más significativo para nosotros que el otro. o se puede decir que "denotan" cierto valor. ya sea. esencialmente es un enfoque que tiene sentido en sí mismo. Usando una pila de valores abstractos casi nunca sirve al propósito segundos arriba. Tenga en cuenta que he programado en estos idiomas. los idiomas que te obligan a nombrar por ejemplo. creo. etc etc Mi principal interés está en la caracterización de las diferencias de una manera más específica que la que acaba de decir algo en la línea de " No me gusta esto ". el trabajo de la implementación del lenguaje se ha simplificado. 12/08/2005 03:55 | ingresar o registrarse para enviar comentarios 2Variable En # comment-8723 . En general. o" Creo que esta es una forma divertida de programa ". Obviamente. hay diferencias. es una "referencia". nombrando a todos los valores no es necesaria o apropiada. o su papel en el cálculo. y estoy familiarizado con los argumentos. es difícil argumentar que la expresión de la mayoría de los problemas en términos de una pila LIFO. pero si no podemos describir con claridad el efecto que no sea simplemente hacer una lista de las características técnicas. Sin embargo. tienen que ver con los beneficios de ese enfoque de la implementación del lenguaje: empujando parte del trabajo de arreglar el mecanismo de abstracción en el usuario. Definido apropiadamente.

The original poster likened concatenative programming to "writing a Turing machine program. Can you give an example? . the variables are simply assigned useless placeholder names. I/O handling (mostly for accessing files). in languages with traditional local variables. núm. not everyone considers Haskell and friends to be the pinnacle of language design or expressive power. Aside from the fact that several concatenative languages do actually support local variables. object-oriented extensions. aug 2005 (not yet online ): The CF [ColdForth] manual has other interesting chapters to describe its features: numbers/parameters (CF supports local variables via stack frames). though. What logic is used to justify the idea that you can only have global names? It boils down to something like "because it's easy to implement a language that way. the reason they're frowned upon is because in most cases they are an impediment to proper factoring. That's not a good argument from the language user's perspective. 8. that would be interesting. as an implementor of such a language. How do you define power? The APL dialects and derivatives. I ran into it while skimming through Forth Sorts Fruit Down Under by Paul Frenger in ACM SIGPLAN Notices . and it's a purely functional language. those names are unnecessary. but you're not going to convince many people by blustering about it and making over-the-top criticisms of other. I find it hard to see how names are an impediment. This should indicate something to you: most of the time. 2005-09-14 12:11 | login or register to post comments 2drop Even concatenative languages acknowledge that names are important. dentro de un procedimiento? Y. the list goes on). or directly in the lambda calculus using de Bruijn indices. By el-vadimo at Wed. 2005-08-10 23:38 | login or register to post comments Stacks of responses Aside from the fact that several concatenative languages do actually support local variables Do those local variables protect against the issue I've raised. which is why the most powerful languages provide ways to control side effects. are all much more expressive than any purely functional language. for example. de muchos idiomas demostrar que son. However. ie are they safe from being changed by unrelated stack operations? the reason they're frowned upon is because in most cases they are an impediment to proper factoring.Así que una pregunta es. ¿no podrían ser de utilidad a nivel local. Is that an issue specific to the concatenative languages? Otherwise. por supuesto. By Mackenzie Straight at Wed. It might explain why you. I'm not sure if the following quote supports your contention. In a great deal of applicative code. mnesia. strings. for example. the memory manager. proven languages. Believe it or not. If Factor can support such claims." Perhaps you should reconsider whose claims are 'over the top'. dets. and possible to get away with it and work around it". si los nombres son tan útiles e importantes cuando las escalas de código más allá de un procedimiento único. Erlang is not purely functional (ets. 40. are enthusiastic about them. What do you think of tacit programming in J? Simple refutation: Erlang is used to run telecom switches. it's true that side effects are a major cause of problems. It's worrying to me that this claim of "most powerful" is accepted here essentially on faith. vol. process dictionary. since they all support global names. TCP/IP capability and the multi-tasker.

Ideally. Having the option to use de Bruijn indices might be an improvement over having no alternative to direct stack manipulation. especially as expressions scale up. Believe it or not. for the reasons stated elsewhere in this thread. which is difficult to formalize satisfactorily. such as declaring that a method cannot side-effect the object it's associated with. There are cases where a stack is certainly the right abstraction to use. Ada — languages which provide qualifiers like "const" that allow the programmer to guard in a meaningful way against unwanted side effects. process dictionary. mnesia. the variables are simply assigned useless placeholder names. Define it however you like — very functional? Do you consider Haskell purely functional. which is why the most powerful languages provide ways to control side effects. the traditional concatenative answer to that is that you should factor larger expressions into multiple words. so that the appropriate one can be picked in a given situation. in most cases. those names are unnecessary. That's a fair point. The APL dialects and derivatives. all of these things have pros and cons. I consider the definition of "purely" here to be a quibble — eg anything that interacts with a traditional database is ultimately impure. I can see his point. I didn't say that. Also. including eg C++. The cons tend to have to do with being more difficult to reason about. are all much more expressive than any purely functional language. I don't see direct stack manipulation as one that's likely to be the best choice in most situations. I don't see how using "push" and "pop" to abstract values helps address that. What do you think of tacit programming in J? I consider tacit programming — which has strong similarities to point-free style — to be higherlevel than direct stack manipulation. not just at the language level but in the design of systems. It's worrying to me that this claim of "most powerful" is accepted here essentially on faith. However. although if you focus purely on how local value abstraction works. 2005-08-11 01:18 | login or register to post comments ¿Qué hay en un nombre? Aside from the fact that several concatenative languages do actually support local variables. Functional languages just implement this at the language level on a more comprehensive basis. that means you're relying on names for abstraction again. By Anton van Straaten at Thu. for example. a language should be able to support a variety of styles. However. dets. Obviously. the list goes on). the reason they're frowned upon is because in most cases they are an impediment to proper factoring." Perhaps you should reconsider whose claims are 'over the top'.In a great deal of applicative code. On the subject of scaling up expressions. and I don't think it's over the top to say that. not everyone considers Haskell and friends to be the pinnacle of language design or expressive power. . Controlling of side effects is a major theme in very demanding systems. This should indicate something to you: most of the time. like "expressiveness". How do you define power? Hopefully my response above gives a better idea of what I was getting at. The original poster likened concatenative programming to "writing a Turing machine program. preferably demonstrated in practice. or directly in the lambda calculus using de Bruijn indices." I would include many imperative languages in that list. How does this reconcile with the idea that using local names is an impediment to refactoring? Erlang is not purely functional (ets. of course. Of all of these. "power" is one of those things. just on a scale greater than the local procedure. Java. I said that "it's true that side effects are a major cause of problems. even with the I/O monad and the things it can talk to? My real point was that a strong emphasis on avoidance of side effects is not something that's solely the domain of academics. the original poster did also make some other real points. not just on individual variables but also over larger scopes. when considered as a whole system. but it could perhaps be characterized as the ability to handle very demanding tasks.

in imperative-applicative languages (some more than others) is indeed a valid criticism of them. it's almost always possible to avoid this. but that assumption could be violated by unrelated code That sounds like a plea for static typing. And in better languages.every time you use pop. Held at Thu. etc. That's a classic sign of a low-level language (think of assembler). . dup. you don't actually have to name those.In a great deal of applicative code. The need for temporaries with useless names.. you're making an assumption about what's on the stack. 2005-08-12 17:36 | login or register to post comments Types? Estoy de acuerdo. and rollup. those names are unnecessary. but part of the essence of reasoning within an imperative paradigm is knowing the current state.. I think. differ considerably in how many named intermediate variables they use (personally I find the number of intermediates in the above Scheme code a bit excessive). dup. Do you consider not being able to not name part of the state a weakness? The only way to avoid it in many imperative languages would require programming in a dramatically different style than the the language supports. I disagree that temporaries have "useless names". how do you know you're calling it with the arguments in the correct order? Especially in the presence of macros? (apply quadratic-formula '(1 0 -4)) (apply quadratic-formula (reverse '(1 0 -4)) By Greg Buchholz at Wed. Are the stack manipulation functions that you mention (pop. swap. the variables are simply assigned useless placeholder names. Loop indices may not be referenced other than as a control structure. .> By David B. By Derek Elkins at Fri. By dhopwood at Thu.. you're making an assumption about what's on the stack. 2005-08-11 03:52 | login or register to post comments Functional languages can "nam Functional languages can "name part of the state". 2005-08-11 01:26 | login or register to post comments A temporary by any other name. The only useless names I can think of is for function arguments that aren't used. like pop. but that assumption could be violated by unrelated code Is it really that much different from the applicative language example? If your function takes three integers. eg loop indices. The need for temporaries with useless names. Not being able to name part of that state is what I would consider to be a weakness.) a sign of a low-level language or a linear language (like Linear Lisp )? Or are all linear langauges low-level by definition? Also.. the programmer depends heavily on abstractions which the language doesn't enforce or even know about: every time you use pop. 2005-08-10 17:08 | login or register to post comments . and typical programming styles in various languages. But it's generally agreed . The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain. eg loop indices. swap. In functional-applicative languages. that introducing variables with useless names is bad style. in concatenative languages. Programmers. This should indicate something to you: most of the time. in imperative-applicative languages (some more than others) is indeed a valid criticism of them.

In the static typing case. I'm not saying that any language with named bindings solves all such problems. The question is what the costs of introducing it are. dup. 2005-08-10 18:37 | login or register to post comments The Joy of obfuscated abstractions Well I don't know if I can define "low-level" either. but it doesn't necessarily make up for all of its problems. how do you know you're calling it with the arguments in the correct order? It's different at least in the sense that that's a local effect: the error is confined to the interface between the caller and the callee. Well I don't know if I can define "low-level" either. I'll admit I can't give a formal definition of "low-level" off the top of my head. but of the cuff. and that a language with named bindings which can make some guarantees about those bindings is both safer and higher-level than a language that doesn't have those features. and avoiding it in others. and arguably not insignificant. but I'd be interested to hear (reasoned) arguments about how something like Linear Lisp or the concatenative languages are not lowerlevel. Is it really that much different from the applicative language example? If your function takes three integers. I'd point to higher order functions and a clean algebra of programs as indicators of higher-levelness. I can easily justify avoiding that in most cases. but of the cuff. That sounds like a plea for static typing. swap. and doesn't compromise unrelated abstractions elsewhere in the program. That moves a language like Joy up the spectrum I mentioned. 2005-08-10 18:10 | login or register to post comments low vs. In the case of relying primarily on direct interaction with a stack to store values. but I'd be interested to hear (reasoned) arguments about how something like Linear Lisp or the concatenative languages are not lowerlevel. I find the costs high enough that I can easily justify using it in some cases. Maybe the assembly language remark was aimed more at Forth and less at something like Joy ? By Greg Buchholz at Wed. The costs of introducing a safe name abstraction are negative. lower I would say that Linear Lisp is certainly lower-level than ordinary Lisp. etc. 2005-08-10 17:44 | login or register to post comments Las diferencias Are the stack manipulation functions that you mention (pop.) a sign of a low-level language or a linear language (like Linear Lisp)? Or are all linear langauges low-level by definition? I would say that Linear Lisp is certainly lower-level than ordinary Lisp.More Linear For better reference to linear lanugages (which also mentions the quadradic formula!) see Linear Logic and Permutation Stacks--The Forth Shall Be First By Greg Buchholz at Wed. I'd point to higher order functions and a cleanalgebra of programs as indicators of higher-levelness. Sí. yes. The costs of introducing static typing are positive. The . I'll admit I can't give a formal definition of "low-level" off the top of my head. Maybe the assembly language remark was aimed more at Forth and less at something like Joy? I agree that HOFs and algebraic compability are high-level indicators. lo es. I'm just saying that there's a spectrum of safety and levels of abstraction. yes. By Anton van Straaten at Wed.

renamed combinators. Sounds a lot like type errors in dynamically checked languages. (let ((x 33)) (foo) x) can return something other than 33. 2005-08-10 17:31 | login or register to post comments The semantics of Joy Indeed.Joy code sample near the beginning of this thread provides an example of low-level code. In the concatenative context. Likewise. despite the fact that there's no stack in your problem specification. HOFs are ubiquitous in Joy. . by my definition and Alan Perlis'. They are used more frequently than HOFs in any applicative language I've seen.. which is Manfred's fundamental insight. but cannot be changed at run time. However. specifically. Check out the Joy and Factor websites for more details. monads result in low-level code. Likewise.. 2005-08-11 21:43 | login or register to post comments "Low level" I'll admit I can't give a formal definition of "low-level" off the top of my head There's always Alan Perlis's definition: A programming language is low level when its programs require attention to the irrelevant. But now I guess I'm the one trolling. concatenative languages do provide both of those things in your definition of high level languages. 2005-08-10 19:30 | login or register to post comments I agree with everything you w I agree with everything you wrote. 2005-08-10 20:05 | login or register to post comments Analogy. Factor and Kont. nothing is being violated. Global words can be defined at read time. Anyway. by that definition. :) By Anton van Straaten at Wed. that would only be a good argument if programmers didn't need to rely heavily on faking local bindings in concatenative languages. As for theory. . but really. Although I don't think it's really completely correct to label languages high or low level. it can return ⊥ if foo does not terminate. there's tons of concatenative theory. because you're forced to think about category theory just to print "hello" :-) By Dan Winship at Wed. Joy is different from other concatenative languages because it is functional: it is impossible to make any changes of state except through the file functions (the fact that read. This interpretation depends on the view that the words of concatenative languages are functions from sequences to other sequences. you can play language lawyer and claim that since the language doesn't have the notion of a local binding.. do not pop the file object off the stack constitutes the concatenative analogue of the I/O monad). 2005-08-10 20:04 | login or register to post comments Not low level Though I don't particularly like that Joy code. At most you can say that writing in a given language generally results in high or low level code .) By Matt Hellige at Wed.. By Anton van Straaten at Wed. executing pop on an empty stack likewise produces ⊥... etc. there's tons of this stuff. thus they are analogous to function definitions rather than global variables. write. By Daniel Ehrenberg at Thu. concatenative code is low-level because it forces you to write your solution in terms of a stack.

The cases that are problematic are when the stack is not empty. depending on a conditional. I'm not saying that this issue alone makes concatenative languages unfit for human consumption. Dynamic The cases that are problematic are when the stack is not empty. The cases that are problematic are when the stack is not empty. Is that a problem caused by concatenativityness (!). since this problem applies to all useful general-purpose languages. But it seems like you should be able to prevent getting "out-of-sync" with static analysis. . because it can be detected and flagged when it happens. executing pop on an empty stack likewise produces ⊥ Empty stack is a special case that's not as problematic. By Anton van Straaten at Wed. The documentation mentions combining unit testing with stack effect inferencing to check the stack effect of procedures (words). because it can be detected and flagged when it happens. Like requiring both branches of an "if" statement have the same stack effect. or by dynamicism? If your language allows you to push 1 or 2 things on the stack.By johnwcowan at Wed. 2005-08-10 20:40 | login or register to post comments The Joy of the next 700 titles Indeed. executing pop on an empty stack likewise produces ⊥ Empty stack is a special case that's not as problematic. then I'll agree it has the potential to become a mess. 2005-08-10 21:05 | login or register to post comments Static analysis The Factor language apparently includes a stack effect inference tool which performs such analysis. In this particular case. I think the negative reaction to the tractability of these languages that's been expressed by some posters in this thread is not an uncommon one. but irrelevant. However. I'm saying that even if you get past the lack of procedure-local name/value bindings. specifically. it can return ⊥ if foo does not terminate. This seems like a lot of trouble to go to to achieve a kind of safety that other languages get for free. (let ((x 33)) (foo) x) can return something other than 33. but is out of sync with the program's expectations. but is out of sync with the program's expectations. but is out of sync with the program's expectations. True. 2005-08-10 20:50 | login or register to post comments Static vs. Likewise. Me estoy perdiendo algo? By Greg Buchholz at Wed. That's when the programmer's implicit abstractions are violated. 2005-08-10 22:35 | login or register to post comments empty stacks Likewise. and I've attempted to identify a couple of the semantic issues which underly this reaction. so doesn't affect a relative comparison of features between languages. By Anton van Straaten at Wed. that the approach these languages take to local value abstraction is less safe and requires more care than languages with name-based local abstraction. That's when the programmer's implicit abstractions are violated.

because of effects . Sí. All this stuff about ⊥ is useless outside of research. That's a classic sign of a low-level language (think of assembler). it's caught automatically and printed out. we might as well mention the original thread that spawned the quadratic formula article. map.) By Anton van Straaten at Thu. but complex The corollary to your point about names is the presence of all the names in the Joy code which have nothing to do with the problem domain. dup. Here is another example of non-local bugs: a badly-formed HTML post in a naive weblog system can break the whole page.exceptions. one can rely on a value of 33 being returned from that expression. Should this happen. triggering a segfault if there's underflow. By Greg Buchholz at Thu. because of effects . that's fine. And some might be interested in Pointless Haskell . and presumably happens for a reason.). 2005-08-11 17:17 | login or register to post comments there's nothing to stop you ( there's nothing to stop you (or rather. Factor solves the stack underflow problem by mprotect ing (or something like that) the memory directly underneath the stack. ternary) in such a simple example. By dhopwood at Thu.exceptions. nontermination. By Andris Birkmanis at Thu. . and rollup. also like any other exception. etc. nontermination. such a PL is less safe than reasonable? Here is another example of non-local bugs: a badly-formed HTML post in a naive weblog system can break the whole page. I meant that assuming normal completion of foo. in otuto you'd have something like . continuations. rollup.). dup. The case I'm pointing to as undesirable is if the expression ends up returning 42 or the string "gotcha" instead. like pop. By Daniel Ehrenberg at Thu. the segfault can be caught like any other exception.There are no problems at all about empty stacks. 2005-08-11 17:03 | login or register to post comments No special machinery required I guess you meant that though it's absolutely possible to have a PL in which the value of (let ((x 33)) (foo) x) is not 33 (eg. No-one in their right mind would defend such a system. 2005-08-11 00:48 | login or register to post comments The original thread As long as we're alread discussing it. 2005-08-11 17:50 | login or register to post comments Not just low-level and unsafe. Actually I think the more important point is why you should have to use six of these (pop. etc. a language implementer) from labelling items on the stack. ie the program produces an incorrect result. Also note a previous discussion on point-free programming on LtU. If foo has an exception. An infinite loop has a very different outcome than stack underflow. and it the toplevel of the repl. 2005-08-11 01:45 | login or register to post comments Effects&type system for Scheme? :-) I guess you meant that though it's absolutely possible to have a PL in which the value of (let ((x 33)) (foo) x) is not 33 (eg. swap. such a PL is less safe than reasonable? No. continuations. swap.

By slava at Wed. For example if you were to add names for items on the stack as an extension of the Joy language. [edit: otuto is very interesting. that simply holds references to both quotations. By andrew cooke at Wed. that syntax is a very simple "template" for rewriting the stack (actually. then each quotation would need a pointer to its lexical scope. 2005-08-11 19:13 | login or register to post comments there is no lexical scope dur there is no lexical scope during evaluation. 2005-08-10 19:08 | login or register to post comments Scopes are concatenative If quotations were first-class types in Joy. 2005-08-10 20:01 | login or register to post comments concrete example OK perhaps you can have hidden lexical scope pointers and use a cord. by the way. => * 4 * ac * bb * 2 a } { / + xyz / . and when evaluated. 2 [x] [x 1 +] let so that the above returns 3. 2005-08-10 16:50 | login or register to post comments no se puede.xyz } apart from the RPN.] By James McCartney at Wed. followed by the second one.{ quadratic | abc } { roots ~ b sqrt donde { roots | xyz } => which seems clear enough. rather than lists of words. where lambdas are first-class too) are not all about cons cells and lists. Appending two quotations could be implemented with a 'cord' data structure. so you'd define dup as: { dup | x } => { | xx } there's some syntactic sugar involving implicit quoting that means you can write that as . stacks). they could hold a pointer to their lexical context. But this seems to create a pretty confusing language. For a simple example suppose we have a Joy-like language plus an operator 'let' that takes a value. I hadn't realized what language your example was from.i can't remember the exact details of otuto v1. You can no longer compose functions by concatenating lists of words because the two quotations may come from different lexical environments. in each case using the correct lexical context. and v2 is stalled until i gain enough patience to return to the uml tool (i'm trying to implement it in c++ for various (vaguely financial) reasons). [xx +] i returns 3 By James McCartney at Thu. ahora: 1 [x] [[x]] let 2 [x] [[x +]] let concat this returns the concatenated function: [xx +] however each x is bound to a different value. scopes are not concatenative Once you add names then the code is no longer concatenative. iterates over the first one. disclaimer . Concatenative languages (and Lisp. a quoted symbol. and another quotation which is evaluated in an environment where that symbol is bound to the value.

the rules are restricted ..{ dup | x } => { xx } but that's beside the point.5 ^ [1 -1] * + a 2 * % } . now if you accept. but i would be amazed if it were not true). to programs which consist of an initial reordering of items on the stack. someone added something similar to another language there. all that the otuto definitions describe is how you rearrange the stack(s). compile . I'm not sure what it would mean to split or join functions in otuto. so is XY . as i argued above. not simple sequences of operations.they always match a single value on the left hand stack. (this breaks down with meta-programming. Here's one version of quadratic in that language. that the variables are just syntactic sugar. roll etc etc) (i believe . that there is a simple mapping from otuto to concatenative languages. a definition like: { foo | a } => { bar baz | aa } is equivalent to defining foo as bar baz dup in a concatenative language. to map items from the stack to multiple locations in the body of the code): . the rules are restricte well. 2005-08-14 01:43 | login or register to post comments concatenative is . so the top value on that stack can be interpreted as the current instruction.i've never bothered to prove it. A language in which the concatenation of programs denote the composition of functions has been called a concatenative language. . I first heard this terminology from Billy Tanksley. when i mentioned this on the joy email list. Billy Tanksley has suggested a notation (supported in XY) in which an initial "shuffle-pattern" is followed by name-free code. 2005-08-13 16:32 | login or register to post comments well. 2005-08-12 22:01 | login or register to post comments otuto As I understand it. regarding your proposal for cross-compilation.Manfred von Thun otuto is concatenative. i think it would be sufficient to compile programs like quadratic . a long time back. By andrew cooke at Sun. then that implies. By andrew cooke at Fri. you could implement them by cross-compiling to an intermediate representation without variable names (using swap. but i'm pretty sure that those variable names are just sugar. which uses names to similar effect (that is. if a language is concatenative then functions are sequences of operators where you can take any function and split it at any point and you have two valid functions. so i can't say otuto is concatenative. By James McCartney at Sat. quadratic { [abc] b -: ac * 4 * b 2 ^ -. i think. -. in which names are used to map items from the stack to multiple locations. since they are rules with 4 separate sections. if you then take the right hand stack as "values" then you can think of a rule as saying how to apply the intruction (top of the left stack) to the values. followed by code which is name-free. For example. since you can change the assumptions made above). or you can join two functions and have a valid function. i'm not 100% convinced i understand what concatenative is. ok. though. now if you continue with that.

2005-08-11 01:48 | login or register to post comments The code is not applicative. Subroutines (quotations) in Joy are lists of functions and you interpret them by folding in a 'compose' and applying to a stack. 2005-08-13 23:37 | login or register to post comments Monads as concatenative PLs? If we squint our eyes enough to see bind as concatenation. None of the tutorials on the web I have read. By Daniel Ehrenberg at Thu. then illustrate with reference to examples like lists with mapping. 2005-08-15 22:57 | login or register to post comments Looks applicative to me I don't know whether otutu as a whole is applicative or a hybrid. and I think you might be on your way to removing much of the mystery behing monads (or at least you've given them an opportunity to see monads that aren't tied up in Haskell syntax and type-classes). but the above code is definitely applicative. in their common recursive definitions have a defined evaluation order.. The code is not applicative. in fact I am the lead developer of the Factor programming language. Well.) By dhopwood at Thu. the burden of bridging the gap . (RPN vs prefix vs infix is a separate. fold compose id [1 4 dup * +] Replace 'compose' with 'bind' for your favorite monad. and factorial. which are familiar functions that. in imperative PLs one can concatenate statements (usually using '.'). ignoring associativity information. 2005-08-11 16:14 | login or register to post comments Re: A comment about concatenative languages in general I consider concatenative languages suitable for high-level programming. it's just reverse RPN (just polish notation) and it uses named variables. By Marcin Tustin at Mon. There is still a stack. then how are monadic expressions not concatenative? Say. 2005-08-15 14:25 | login or register to post comments They recently made much more They recently made much more sense to me when I combined the two pieces of information that monads are (1) an algebraic structure that (2) forces a particular evaluation order. and much less significant.. issue.. In fact.{ [abc] ab * ac * + } a abc--abac * [*] dip + [edited to show an example of compilation from pattern-notation to shuffle-notation] By sa at Sat. I might understand "composition of functions" a bit wrongly. even I think some Simon Peyton-Jones stuff really mention both of those facts. and quite often "imperative" means working in some compound monad. lately I've been thinking that there might be a benefit for newbies by writing a monad tutorial using a language like Joy. As always.. By Andris Birkmanis at Mon. 2005-08-15 06:03 | login or register to post comments Squinting I don't think squinting is necessary at all. By Greg Buchholz at Mon.

. various development tools. and more. I'm not sure what you mean by "How can you build reusable encapsulated abstractions?". so ironically. Factor with Java.. And also beside the point. and the simplicity of concatenative languages allows one to develop such tools more easily than with other languages.between the programmer and the language lies squarely on the development tools at one's disposal.. The compiler takes maximal advantage of the simple semantics to implement the concatenative equivalent of "lambda lifting". I'm not particularly interested in comparing.] an HTTP server with a continuation-based web framework. also used by the compiler. various development tools.. and various other optimizations such as partial evaluation. you will see a very high degree of abstraction and code reuse. Well.. A meta-circular interpreter is a page of code in Factor. and not even capable of implementing their own optimizing native compilers. a GUI toolkit-in-progress. I'm interested in the effects of concatenative vs.] is a richer level of functionality than offered by most languages discussed on this web site Even though this web site disproportionately discusses research languages and prototype language implementations. and more [. While it's true that there are few complex concatenative languages. there are plenty of equally simple applicative ones. Re: "writing a Turing machine program". 2005-08-10 06:30 | login or register to post comments Re: A comment about concatenative languages in general . 2005-08-10 14:31 | login or register to post comments Irrelevant .. By slava at Wed. since the maturity of language implementations is not the topic of discussion. and not even capable of implementing their own optimizing native compilers. still I think that assertion is very likely false. notwithstanding the clear fact that there is enough commercial demand to keep several Forth vendors in business. This is a richer level of functionality than offered by most languages discussed on this web site. going back to a language like Java with annoyingly hand-coded boilerplate loops seems more like a Turing machine. say. a GUI toolkit-in-progress.. it is used to implement a single-stepper. applicative semantics for otherwise comparable languages. after working with Factor's libraries for sequences and mathematics. one could even conclude that applicative languages are totally non-productive. and it is not an academic exercise. [. Your emphasis on the word "seem" suggests that you don't believe that concatenative languages are used to develop non-trivial applications. one could even conclude that applicative languages are totally non-productive. There is no "boilerplate" code. Factor has an HTTP server with a continuation-based web framework. the simplicity of concatenative languages allows one to develop such tools more easily than with other languages. This is just trolling. If you look at Factor's library. There is a static stack effect inferencer tool. I'd like to see a single-stepper in another language that is equally clear. By dhopwood at Wed. ..

"Research language" is a euphemism for "useless language". I'm not particularly interested in comparing. However. there are plenty of equally simple applicative ones. 2005-08-10 16:13 | login or register to post comments Research is a Good Thing "Research language" is a euphemism for "useless language". As lothed as Slava is to admit it. I can't imagine Factor being applicative. but that technique is less flexible. You can discuss semantics. Even though this web site disproportionately discusses research languages and prototype language implementations. I write code. And also beside the point. static type systems. since the maturity of language implementations is not the topic of discussion. Factor with Java. so I made a new watch-after thing. They're good for research. In Haskell or ML. The point is. The closest parallel I can find is Common Lisp. say. still I think that assertion is very likely false. I. In Common Lisp. weakly final coalgebras and other academic concerns until you are blue in the face. but . I'm really only interested in practical concerns. I could truthfully say "for me. By slava at Wed. By Anton van Straaten at Wed. The implementation isn't more than 3 or 4 lines. 2005-08-11 02:07 | login or register to post comments things Factor can do While it's true that there are few complex concatenative languages. and I like to write stable code quickly. thinking in terms of a stack is not a problem. You can discuss semantics. It's been really useful for me and I've been able to get rid of all the debugging prints in my code. One example that comes to mind is the word watch. the next person who has to deal with your code may indeed have a problem. 2005-08-10 16:08 | login or register to post comments For me. unlike Slava. am OK with research languages.. since the maturity of language implementations is not the topic of discussion. I needed to see what was on the stack when leaving the word. it is intended for use. I'm interested in the effects of concatenative vs. It also only took 4 lines and not much thought. still I think that assertion is very likely false. Tal vez. but there are many things about Factor that make it much better. but it will not change the fact that for me . thinking in terms of a stack is not a problem. weakly final coalgebras and other academic concerns until you are blue in the face. making a debugging tool like this is even harder. dealing with unrestricted pointers in C is not a problem". One time. involving complicated templating libraries. And also beside the point.Even though this web site disproportionately discusses research languages and prototype language implementations. but the broader consequences of everyone holding that opinion are not pretty. with the additional advatange that writing tools is easier. And where do you think the ideas for features in 'mainstream' languages come from? By dhopwood at Thu. you can't do a lot of the stuff Factor does in an applicative language. static type systems. Factor isn't really suitable for most applications yet. and what it does is it prints out the name of the word and the contents of the datastack when the word is called. applicative semantics for otherwise comparable languages. Of course. this would probably take the form of a new macro for when defining a function or macro.. and I find that concatenative languages let me do this just as easily as applicative ones. but it will not change the fact that for me.

For example. We really shouldn't discuss this. but you can really do everything without them (but for a few circumstances. For example. 2005-08-10 22:48 | login or register to post comments Re: Fun with stacks The question is how many things fall into this category. ie both the entry and exit from a traced function. however important or unimportant that is. 2005-08-10 19:38 | login or register to post comments Fun with stacks One example that comes to mind is the word watch. here's the heart of the Factor compiler: M: compound (compile) compiling dataflow optimize linearize simplify generate . especially crucial ones like the GUI library. although the implementation of that is more than 3 or 4 lines. I feel like they're in the exact right order. They usually print the incoming arguments and the return value. Forth-like languages are often used in constrained embedded environments. I know that's a terrible argument. but that's not because it's concatenative. The concatenative paradigm is not just a way to manipulate the stack directly. though. it's a whole different paradigm of programming where some things are more elegant and others less. They do reflect the order of evaluation. For an example of something which comes out really great. [about applicative languages being nonproductive] Sí By Daniel Ehrenberg at Wed. everything will look awkward at first. . At this point. The implementation isn't more than 3 or 4 lines. Yes. but let me turn that question around: how many things fall into the category where you need lexically named variables to do certain things? I used to think many. By Anton van Straaten at Wed. but from your perspective. Forth-like languages are often used in constrained embedded environments. it tends to feel like most things are more elegant. This is just trolling. and what it does is it prints out the name of the word and the contents of the datastack when the word is called. in which case some of these concerns may be balanced by other advantages of these languages. After a while. and in what situations. and whether they're worth the consequences of allowing direct manipulation of the stack. The question is how many things fall into this category. you're right. in which case some of these concerns may be balanced by other advantages of these languages. Common Lisp and many Schemes have something like a "trace" macro that provides similar functionality to the word watch. rather than feeling that concatenative languages are backwards. dynamically scoped variables help). It's a reason I use Factor anyway. That's actually a good point. but I don't care. Factor has a pretty good FFI. anything which involves dealing directly with the stack will be easiest in a language which gives you direct access to the stack.Factor's libraries aren't mature enough. BTW. Obviously. and whether they're worth the consequences of allowing direct manipulation of the stack. and in what situations.

BTW. Not only does it take more code to do such a simple task but you have to alter the original code to do it. eg in Scheme: (concatenate input compiling dataflow optimize linearize simplify generate) Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable. By Daniel Ehrenberg at Thu. 2005-08-11 02:24 | login or register to post comments Fun with folds how many things fall into the category where you need lexically named variables to do certain things? "Need"? Ninguno. There's probably an applicative language that does that. but from your perspective. it's more for general programming. although the implementation of that is more than 3 or 4 lines. the number of situations in which having lexically named variables is useful is high. you can just enter one short line of code to watch a word ( \ wordname watch ). IME. it tends to feel like most things are more elegant. though you don't normally do this outside of debugging. some of which rest on its being concatenative. One thing about Factor that's great but unrelated to its concatenativity is that you can mutate stuff like word bodies. The points I've raised are not about things being backwards or seeming awkward. . I agree. Common Lisp and many Schemes have something like a "trace" macro that provides similar functionality to the word watch. However. here's the heart of the Factor compiler: M: compound (compile) compiling dataflow optimize linearize simplify generate . In Factor. Factor isn't really that into constrained embedded environments. I could do it quite easily in many higher-order functional languages. the more important questions are how practical it is.Well. For an example of something which comes out really great. everything will look awkward at first. After a while. but part of the reason I used Forth was because it was in a small. that you "can" do everything without them is not what I'm concerned with. it's a whole different paradigm of programming where some things are more elegant and others less. which could easily be made to look something like. how easy it is to deal with code written by other people. using a fold over a list of procedures. If I wanted to write an expression like the above. They usually print the incoming arguments and the return value. it's great when something works out in a way that seems intuitive. It'd be interesting to see a Factor (or Kont?) version of that program. The concatenative paradigm is not just a way to manipulate the stack directly. at the repl. where the alternatives were languages like C and assembler. which can be done better because of it's abstraction capabilities. but you can really do everything without them Similarly. I used to think many. my experience is that different things can seem intuitive for different problems. embedded-like control environment. etc. It was fun. I implemented and maintained Forth programs for a couple of years. ie both the entry and exit from a traced function. for comparison. However. Turing completeness tells me it's possible.

b ). However. which really is irrelavent to abstraction. (trace proc-name). which can be done better because of it's abstraction capabilities. Do you think this is a more general problem than that? I'm seriously interested in this. so I made a minilanguage (which I'm currently redoing) to use infix syntax for math.. using a fold over a list of procedures. which could easily be made to look something like. the need to use one seems to me like a hit against a language's abstraction capabilities. . the number of situations in which having lexically named variables is useful is high. I could do it quite easily in many higher-order functional languages. 2005-08-11 04:45 | login or register to post comments I don't care enought to make a good title "Need"? Ninguno. but that's just like implementing a lightweight concatenative language on top of Scheme. 2005-08-11 04:04 | login or register to post comments Concatenar If I wanted to write an expression like the above. is just one short line of code. But then there are properties of Kont and Factor (but not Forth) that lend it to more abstraction. I believe someone has done that with Common Lisp. No alteration of the original code is required. eg in Scheme: (concatenate input compiling dataflow optimize linearize simplify generate) How is this any different from embedding an infix language in Factor? The Lisp/Scheme equivalent. at the repl. Since stacks are irrelevant to most problems. In Factor. Incidentally. I know one. you can just enter one short line of code to watch a word (\ wordname watch). Not only does it take more code to do such a simple task but you have to alter the original code to do it.Well. at the repl. is just one short line of code. IME. It matters like lexically scoped variables matter in normal code. The only way to make it work would be to have each of those functions take a stack and return a stack. Since stacks are irrelevant to most problems. unless you can abstract its use away. Please provide me with a situation where the solution with variables is much better. By slava at Thu. You're right. math. (concatenate input compiling dataflow optimize linearize simplify generate) I don't think that code would work since the stack effects of many of those words are not ( a -. the need to use one seems to me like a hit against a language's abstraction capabilities. there are only a few cases where the stack really matters. No alteration of the original code is required. By Anton van Straaten at Thu. Combinators to the programmer look like ordinary code that just happens to do something with a quotation. at the repl. unless you can abstract its use away. but that situation seems to be isolated. The Lisp/Scheme equivalent. Factor isn't really that into constrained embedded environments. some of which rest on its being concatenative.. I guess. it's more for general programming. like the use of combinators to replace macros in languages like Lisp and built-in syntax like C. But the implementation of Common Lisp's trace is more complicated than the Factor equivalent. (trace proc-name) .

I'm not explaining them very well. Again. you're showing signs of being infected by stack-oriented thinking. though. But then there are properties of Kont and Factor (but not Forth) that lend it to more abstraction. 2005-08-12 04:55 | login or register to post comments Infectado Uh-oh. you're showing signs of being infected by stack-oriented thinking. Combinators to the programmer look like ordinary code that just happens to do something with a quotation. By Daniel Ehrenberg at Thu.. but that's just like implementing a lightweight concatenative language on top of Scheme. at the repl. But then the compiler inlines them to make them as fast as a macro. I don't think that code would work since the stack effects of many of those words are not ( a -. See my other longer response. entitled "reference sense pop". (There's a difference in the way inlining tends to work. or other kinds of collection. those kind of high level features (borrowed from functional programming! . there are only a few cases where the stack really matters. procedures in most applicative languages can receive multiple values using ordinary named parameters.b ). Uh-oh. so I made a minilanguage (which I'm currently redoing) to use infix syntax for math. ¿En serio? Oh. which is one of the problems that can be caused by using a language which forces you to think in terms of its implementation details all the time. and multiple values can typically be returned in various ways. A Scheme version which uses lists applied to ordinary procedures with named arguments. then never mind that point.. such as lists. 2005-08-11 16:07 | login or register to post comments This is not a title Please provide me with a situation where the solution with variables is much better. though. and they do function when run like that by the interpreter. which really is irrelavent to abstraction. tuples. However. but the end result is similar. Incidentally. unless you can abstract its use away. math. It doesn't require "each of those functions take a stack and return a stack" — for a start. The Lisp/Scheme equivalent.and they do function when run like that by the interpreter.) By Anton van Straaten at Fri. procs) (fold apply input-args procs)) Since stacks are irrelevant to most problems. It matters like lexically scoped variables matter in normal code. I know one. (trace proc-name). is as simple as this: (define (concatenate input-args . I believe someone has done that with Common Lisp. I guess. see my other reply. Named variables are certainly not irrelevant to abstraction. You're right. they work just as well in the presence of lexical names. No alteration of the original code is required. and certainly help. is just one short line of code.) are useful. But then the compiler inlines them to make them as fast as a macro. I agree. . The only way to make it work would be to have each of those functions take a stack and return a stack. Do you think this is a more general problem than that? I'm seriously interested in this. Yes. the need to use one seems to me like a hit against a language's abstraction capabilities. ok. I'm not explaining them very well. it's a much more general problem. like the use of combinators to replace macros in languages like Lisp and built-in syntax like C. but that situation seems to be isolated. I don't have much experience with Lisp development tools.

Perhaps you've been infected by Scheme-oriented thinking? By slava at Fri. talking about such a specific structure as a stack when the problem is in fact a much more general one. there is no syntax extension. By Anton van Straaten at Fri. I still made a seperate syntax for defining the state machine. I really felt like this is enough.What a great way to refute somebody's point! This is just like putting your hands over your ears. SYMBOL: init SYMBOL: loop SYMBOL: end : c[ad]+r #! Initial datastructure {{ [[ init {{ [[ CHAR: c loop ]] }} ]] [[ loop {{ [[ CHAR: a loop ]] [[ CHAR: d loop ]] [[ CHAR: r end ]] }} ]] [[ end {{ [[ CHAR: r end ]] }} ]] }} . though. However. there's an additional risk in using a language which forces you to think in terms of a single datastructure everywhere. I'd be especially concerned about exposing inexperienced programmers to languages that require this kind of thinking. and saying "neener. which came out a bit cleaner than the Scheme program IMHO. IN: state-machine USING: kernel hashtables sequences lists . It's an easy mistake to make. because you'd be ingraining bad habits in them from the very beginning. but after doing the non-macro part. which is that you start conceiving of all problems in terms of that datastructure. and in Kont. If you're making that macro for a speed boost. I'm not listening". for comparison. and I suspect we all do it to some degree from time to time. I started to implement that Swine Before Perl program. it was certainly intended lightheartedly. it's also a serious point. It'd be interesting to see a Factor (or Kont?) version of that program. However. What benefit do you derive from making that a macro? In Factor. that's a clear sign that you're thinking too much in terms of implementation and too little in terms of specification. 2005-08-12 18:15 | login or register to post comments Don't stop reading yet. The sentence after the one you quoted contains the refutation. that's just showing that you have a bad implementation of the language. syntax extension isn't as common as in Scheme because it's not needed as much. 2005-08-12 19:02 | login or register to post comments The Swine Before Perl Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable. Regarding the "infected" comment. El código está por debajo. When you find yourself saying things like "The only way to make it work would be to have each of those functions take a stack and return a stack".. . neener.. I hope LittleDan didn't take that too personally. I should have put a smiley after it.

in this case. : {| POSTPONE: {{ : :: POSTPONE: {| : -> . parsing POSTPONE: }} POSTPONE: ]] POSTPONE: [[ . By Daniel Ehrenberg at Thu. and 256 columns. parsing POSTPONE: [[ . the algorithm should consume inputs and index out the next state. parsing : || POSTPONE: ]] : . Edit: as Slava correctly pointed out on the #concatenative channel. init. end. using two dimensional scalar indexing. so is krishnamurthi's scheme implementation. leaving the sequence of states visited as its result (a vector of indices).indices 2] . that's way too much code. end :: CHAR: r -> end |} . Is there something wrong with that code? It seems to be a bit shorter than the Scheme code.: walk-states ( seq states -. POSTPONE: ]] : |} POSTPONE: ]] swons .? ) init swap rot [ >r ?hash r> swap ?hash ] each-with end = . repeated indexing in k is implemented as: result:index matrix\indices es decir. if the machine is in state i and sees input j.indices 0] k1:matrix[k0. k0:matrix[index.. then it should enter state k. the machine has four rows corresponding to the four states: error. corresponding to possible ascii inputs. k = machine[i. more..j].indices 1] k2:matrix[k1. those cosmetic macros are completely stupid and the first version is really the one that should preferably be used. rows are states and columns are inputs. parsing . a state machine is a matrix. parsing POSTPONE: }} POSTPONE: ]] POSTPONE: }} \ walk-states : final-machine {| init :: CHAR: c -> loop . parsing POSTPONE: [[ . loop :: CHAR: a -> loop || CHAR: d -> loop || CHAR: r -> end . 2005-08-11 19:43 | login or register to post comments btw here's how to activate it "cadar" final-machine o "cadar" c[ad]+r walk-states By Daniel Ehrenberg at Thu.. 2005-08-11 20:18 | login or register to post comments too much code dan.

2005-08-13 22:30 | login or register to post comments Repent.char**argv) { char S[4][256]={{0}. By sa at Fri.3)] m:1 s\_ic por ejemplo.{['r']=3}}. "what numbers could not be. then it's a small step to knowing how to code up a statemachine. m'("car"."adr". they are anything at all beyond how they are represented in different programming languages. 2005-08-13 11:29 | login or register to post comments but what are they really? hey indeed. if you understand +. the algorithm is realized as: s:@'[4 256#0. indeed. By Philippa Cowderoy at Sat. and you understand indexing. obligatory reading: paul benacerraf. sinners # Include int main(int argc." By sa at Sat. ."cddr".['d']=2.s=1. which have m FSMs are graphs. Sloppy language.: in k."caddr") (1 2 2 3 1 2 2 3 1 2 2 2 3 1 2 2 2 3 1 2 2 2 3 1 2 2 2 2 3) a 0 in the return vector indicates that m has entered the error state.['r']=3}. but hey.{['a']=2._ic(""."cadr". my point was that recursive 2d indexing captures the behavior of fsms. no matter what they "really" are.2 2 3. which in turn is a special case of scanning a function on its input."c".{['c']=2}.2.(!0. 2005-08-12 15:52 | login or register to post comments a state machine is a matrix? a state machine is a matrix ? By Michael Walter at Fri."r"). 3 ghz machine timings are: 10k elements: 0 ms 100k elements: 15 ms 1m elements: 187 ms state-machine is just a special case of index-scan. on my pentium 4. if. 2005-08-12 18:19 | login or register to post comments FSMs are graphs."cdar". no need to follow that long and winding road into the metaphysics of abstract objects. which have matrix representations. and you understand summation as repeated application of +."cdr".:.

I don't like the way typical Scheme code is written.. 2005-08-12 17:16 | login or register to post comments Understandable? Flexible? That's great guys. I'm only working with the slides. and I know just enough Scheme to get myself in trouble -. Given the spec for another automata. -30 By William D. Also he uses character literals instead of symbols. clear descriptions via macros. Neither the C. One of these days I'll have to get over the Lisp allergy I picked up when I was a wee lad and really give Scheme a good look. is that neither is as flexible as what he presents either. it seems to miss the point fairly completely. And for what its worth. [1] At least that's what I believe he's shown. I'd like you to explain why you think that this: (init : (c -> more)) (more : (a -> more) (d -> more) (r -> end)) (end : (r -> end)) Any more flexible than this: : c[ad]+r {{ [[ init {{ [[ CHAR: c loop ]] }} ]] [[ loop {{ [[ CHAR: a loop ]] [[ CHAR: d loop ]] [[ CHAR: r end ]] }} ]] [[ end {{ [[ CHAR: r end ]] }} ]] }} . I consider the omission of hashtables from the Scheme standard to be an unacceptable limitation. he just used Factor's hashtable literals. It might look pretty but it just doesn't scale as well as other data structures for most tasks. By slava at Fri. K. your solutions would have you hard-coding your new state tables while Shriram's would have you quickly done with the code and onto some other problem. By Mackenzie Straight at Fri. Neumann at Fri. because Dan did not extend the syntax. 2005-08-12 18:00 | login or register to post comments . nor Factor code is quite as understandable as that presented in slide 38 of Shriram's talk.feel free to taunt me if I'm wrong. Anton's pointer to the talk said (emphasis mine): Shriram Krishnamurthi's talk The Swine Before Perl provides a nice example of how powerful abstraction capabilities can help make code understandable . unfortunately..if(argc Simplicity > Abstraction. 2005-08-12 17:50 | login or register to post comments Flexible? The Factor code that Dan showed is equivalent to the Scheme code. using lists (including alists) and symbols for everything. The Factor version has a bit more punctuation. What's more (and probably more important). Recall. What he's shown [1] is a simple syntax extension for generating (fairly efficient) automata from these simple.

-30 By William D. end :: CHAR: r -> end |} .Faster than I am. or it can be done all at once. as in the scheme example..looks like. Neumann at Fri. I was just about to leave a note that the factor version may be just as flexible. (automaton init (init : (c -> more)) (more : (a -> more) (d -> more) (r -> end)) (end : (r -> end))) .. flexible. loop :: CHAR: a -> loop || CHAR: d -> loop || CHAR: r -> end . 2005-08-12 18:55 | login or register to post comments Sencillez This particular task does not even call for a state machine at all: : swine ( sequence -. and recognition is recursive twodimensional indexing.. The Factor equivalent of this (from pg.. as my example shows. 38). no special syntax. use an nx 256 matrix m. I stand corrected there..... . no macros... By sa at Fri. assign m[state. because I am completely unfamiliar with it. for each (state : input -> nextstate).? ) "c" ?head >r "r" ?tail r> and [ "ad" contained? ] [ drop f ] ifte . as directly as possible. . 2005-08-12 18:08 | login or register to post comments More confusion? Unless I'm confused (which happens on a regular basis). and I couldn't figure out exactly what was going on. I believe you're wrong. for a machine with n states.input]:nextstate to run on input i: r:1 m\i setting up a particular machine can be done line-by-line. if state-machines are matrices.. then implement it as such. By Greg Buchholz at Fri.. i don't think i missed either point..not a lot of difference to my eyes. : final-machine {| init :: CHAR: c -> loop . I more or less figured out what he was doing after I posted the message. 2005-08-12 18:00 | login or register to post comments understandable..

and not even capable of implementing their own optimizing native compilers. 2005-08-13 08:50 | login or register to post comments Wow. because it taxes my memory. I certainly find it difficult enough. one could even conclude that applicative languages are totally non-productive. despite my ability to remember to API docs. except perhaps in certain specialized domains? By Anton van Straaten at Wed.. you're thinking only of announcements of brand-new or toy languages? Re: "writing a Turing machine program". you might want to tone down the rhetoric. By Marcin Tustin at Thu. even if this is a phenomenon I might have contributed to." as hyperbole.. If you expect to be taken seriously. I don't know what you're thinking of here. I suspect that the difficulty of using a form of functional programming without named parameters is a significant problem for many people. after working with Factor's libraries for sequences and mathematics. 2005-08-12 17:53 | login or register to post comments As O said. one could even conclude t .. By Marcin Tustin at Sat. Let's not start pointing fingers and crying "troll" at everyone using a modicum of rhetoric. What I take from this is that you find Java so restrictive. ML? Should we take your comparison to Java as a tacit acknowledgement that concatenative languages can't really compete with more expressive applicative languages. and more. 2005-08-10 16:08 | login or register to post comments . going back to a language like Java with annoyingly hand-coded boilerplate loops seems more like a Turing machine. various development tools. but this sounds completely false. I wasn't commenting on his other posts. It's hyperbole to show up the fact that there are different expressivity/productivity/comprehensibility wins with concatenative and applicative languages. that you're willing to put up with other serious limitations in concatenative languages to escape it. I interpreted his comment that "one might conclude. I interpreted his As O said.. though? Scheme. one could even conclude that applicative languages are totally non-productive. a GUI toolkit-in-progress. Making oneself look completely ignorant is rhetoric? By Derek Elkins at Fri. Perhaps by "most languages discussed on this web site". This is a richer level of functionality than offered by most languages discussed on this web site. However. so ironically. This is just trolling. What about all the much more expressive applicative languages. 2005-08-12 17:52 | login or register to post comments . and not even capable of implementing their own optimizing native compilers.By slava at Fri. Haskell. that I have been discouraged from exploring concatenative programming.. even if this is a phenomenon I might have contributed to. It might be interesting to know if there are any patterns that can be used to fake named parameters while maintaining concatenability.. an improvement on Java boilerplate? Factor has an HTTP server with a continuation-based web framework. 2005-08-11 14:26 | login or register to post comments Let's not start pointing fing Let's not start pointing fingers and crying "troll" at everyone using a modicum of rhetoric.

but Haskell's and ML's type systems make it so that less things can be done at runtime.. so I cannot comment on the merits of CL versus concatenative languages. I'm disappointed. GHC and SML/NJ also have nice toplevels. I have never developed the same application in CL and Factor side by side. Smalltalk and the likes. 2005-08-11 02:54 | login or register to post comments Toplevel I was just going to say that I quite enjoy O'Caml's toplevel(s). . You forgot to mention Tuareg mode . or directly in the lambda calculus using de Bruijn indices. except for porting a few trivial things back and forth. By Daniel Ehrenberg at Thu. although I've never looked. I just wanted to say that typing makes things more complicated. I'd say Haskell and ML's lack of a live environment with in-image development tools is a serious limitation. so development tools are more complicated and less useful. 2005-08-10 16:18 | login or register to post comments Repita después de mí . By Andreas Rossberg at Sat.oP Of course. By slava at Wed. it seems like a tour de force comparable to writing a Turing machine program. 2005-08-11 03:49 | login or register to post comments Los sistemas de tipo language implementation != language Yeah. I wouldn't be surprised to find IDEs for them. A more fundamental factor is their higher degree of purity compared to Lisp..What serious limitations? I'd say Haskell and ML's lack of a live environment with in-image development tools is a serious limitation. By Anton van Straaten at Thu. 2005-08-11 16:13 | login or register to post comments hs-plugins certainly makes an hs-plugins certainly makes an interesting tool in that context By Philippa Cowderoy at Thu. although I can say Factor's sequences library is cleaner and more generic than CL's. :-) By Paul Snively at Thu. 2005-08-11 03:16 | login or register to post comments Slipping? Paul. 2005-08-11 16:41 | login or register to post comments Not so much due to types I'd say it's only secondarily due to their type systems. I've tried Scheme and far prefer Common Lisp. language implementation != language language != language implementation By dhopwood at Thu. 2005-08-13 12:09 | login or register to post comments Foreign? I can't imagine writing any nontrivial program in a concatenative language. PLEEEASE don't get into a type system debate here. which makes "interactive update" a more alien concept. .

. I will not put. Up with that. Then. it was crystal clear. 2005-08-10 18:54 | login or register to post comments Re: names So why do you troll in this thread? By slava at Wed..com By shapr at Thu. etcetera.until I started actually programming. 2005-08-11 16:21 | login or register to post comments The original Java Factor impl The original Java Factor implementation had these stack shuffle words.method() ). By James McCartney at Wed. drop.Is it just me. 2005-08-10 17:34 | login or register to post comments nombres . Stack scramblers make this perfectly clear. The current C version no longer has them IIRC. By Daniel Ehrenberg at Thu. --Shae Erisson . 2005-08-10 19:05 | login or register to post comments Stack scramblers I like William Tanksley's stack scramblers idea for concatenative languages...attribute. Defining functions without having argument names or let bindings to name your terms gets you into drop swap dup rot shenanigans.. not programmers. or does that bear a striking resemblance to concatenative code? expressions are easy enough. It does? I'm pretty sure it still uses good old dup...ScannedInAvian. I could never remember which ones those stack shufflers were -..Borrowing an example from another thread . They look like this: swap = ab-ba drop = adup = a-aa I can never remember which of rollup or rolldown does which of abc-cba or abc-bca. 2005-08-11 11:37 | login or register to post comments Umm ...Is it just me. class.. That kind of stuff is for compilers. Factor uses stack scramblers nowadays also.method(). obj.method( obj. . no Factor uses stack scramblers nowadays also.getSomething(). swap.attribute. or does that bear a striking resemblance to concatenative code? By Greg Buchholz at Wed.

of the words I can think of right now..By doublec at Thu. named after a porn star. ( Source: The Alternative Dutch Dictionary ) By Sjoerd Visscher at Thu.. 2005-08-11 14:15 | login or register to post comments Arse The dutch word "kont" is etymologically related to the english word "cunt". Note that CL code has to be read right to left.. By Wouter at Wed.. By Scott Johnson at Thu. 2005-08-11 15:44 | login or register to post comments Bueno . Perhaps we should get started on the research then. we've had Brainfuck for some number of years now. 2005-08-10 19:02 | login or register to post comments "kont" means "ass" in dutch. Smalltalk: Foo new bar baz. :-) By Chris Rathman at Thu. 2005-08-11 15:30 | login or register to post comments TMI: Too Much Information Though cuss words might be considered a valid form of study in the field of linguistics... The original meaning of both words is "hole". By Sjoerd Visscher at Fri. 2005-08-12 08:39 | login or register to post comments Time to get started then. Just think of all the expressivity we could gain.. which ironically is a common complaint against *postfix* languages. . 2005-08-10 21:05 | login or register to post comments As in "arse" or "donkey"? As in "arse" or "donkey"? By Marcin Tustin at Thu.. Factor: <foo> bar baz Factor's concatenative code looks very similar to how Smalltalk unary messages are composed. their use in programming languages is rather unchartered. By slava at Wed.. Although as George Carlin has pointed out in one of his routines..baz().. Not to mention Linda.bar. but I don't know how much of the code in the database is in C. 2005-08-11 21:45 | login or register to post comments koders. at least one of the more popular words is already seriously overloaded . I'm sure there are a few other (as yet undiscovered) dirty jokes and double entendres out there. More than half of the occurences is in C code.com could be a start Crap is the most popular cuss word. 2005-08-11 22:14 | login or register to post comments Re: Foreign? Compare some typical OOP code in four languages: Common Lisp: (baz (bar (make-instance 'foo))) Java: new Foo().

Integer) -> (a.) By Dave Menendez at Thu. Integer). Integer) Prelude> :t plus . With a type system. a → a × Int. fab) Prelude> let plus = lift2 (+) Prelude> :t plus plus :: ((a. but they don't prefer one side or the other. Neumann at Fri. x) -> (x. k 4 . Integer). Integer) Prelude> :t plus . Integer constants would have the type ∀a. k 2 plus . k 4 . Integer) -> (a. 2005-08-12 01:24 | login or register to post comments The lambda calculus is the "i . Integer) Prelude> snd . It's pretty easy to model this in a functional language (note: this is not a claim of superiority/inferiority). k 2 $ () 6 What's interesting is that arrows in Haskell are defined in a point-free style. you can treat Forth words as unary functions of the form stack → new_stack. 2005-08-12 14:19 | login or register to post comments Stack-based is point-free? If you represent a stack as nested pairs. Integer) -> (a. a × Int × Int → a × Int. would be typed ∀a. along with a special syntax involving local names which is translated into the point-free style. k 4 .. -.-30 By William D. so can be more tree-like than stack-like.f -< x z <. etc. Por lo tanto. By Greg Buchholz at Fri. (Arrows pass multiple values around with nested tuples. proc x -> y <.b) = (s.) Prelude> let lift2 f ((s. and the arithmetic functions like +. Integer). you can appeal to polymorphism to guarantee that functions won't interfere with elements beyond a certain depth in the stack. plus . but with a dash of typesystem wizardary . Integer) Prelude> :t plus . k 4 :: (a. y)) >>> first g >>> arr (\ (z. x)) >>> first f >>> arr (\ (y. más plus . you can write most any Joy combinator in Haskell. plus :: (((a. y) -> y + z)) which consists primarily of composition and "stack" manipulation.a). 2005-08-11 23:55 | login or register to post comments Joy in Haskell Things get a little interesting when you get to the recursion combinators. k 2 :: a -> (a. k 4 plus .g -< x returnA -< y + z se convierte en arr (\ x -> (x. Here's a GHCi session: Prelude> let k = flip (.

which means that there is no fundamental expressivity gain to be had in shifting between a combinatory language and the lambda calculus. this means that you can convert any program in the lambda calculus into an equivalent program consisting entirely of a composition of combinators (and you can do it in O(1) in either direction). I think that being able to name variables explicitly is a genuine advantage. and that every term corresponds to a morphism. you can think of the types of the set of free variables of a term as the type of the "input stack". but obviously. and the return type as the type of the "output stack". 2005-08-12 19:32 | login or register to post comments . In turn.The lambda calculus is the "internal language" of a cartesian closed category. This means that every type in the lambda calculus corresponds to an object of a CCC. mileage varies. By neelk at Fri. If you like.