|
View:
New views
18 Messages
—
Rating Filter:
Alert me
|
|
|
stOck[Sean: thought you may be interested.]
Hello concatenators, I would like to exchange about possible drawbacks of a data stack and a weird idea on a possible replacement. Maybe all of this is not new, sorry if ever, but I could not find references. I am fully aware that stack juggling often seems mentally difficult basically because we are not used to it. If we had learnt arithmetics with postfix syntax then probably (1+2*3) would read alien. This point is not part of the issues discussed here. Instead, I think that: * Naming, when carefully done, is an invaluable help to clarity. * Stack operations (swap, dup...) do not mean anything about the mental 'model'. About the latter remark: I think that a good program is one that mirrors the 'model' it expresses. Stack operations do not map to anything in the model (about the problem); instead they are only needed because of the stack limitations as a data structure. In other words, the choice of a stack to pass data from func to func introduces low-level code -- as opposed to high-level languages. Without any advantage of low-level languages, I guess (for instance _this_ does not help programming closer to the machine). Let us imagine a "stOck" instead of a stack ;-); that could be a hash/map/dict, meaning that items are named. Then we get the following advantages: * naming * no stack juggling * no dup For illustration, say we want to compute c * (a+b) / (a-b) :result (c b a -- result) + a b - / * or using only names :result (c b a -- result) a b + a b - / c * Note that this is different of environment or world state variables -- that live outside the stack/stock. To keep more advantages and properties of a stack-based process and data flow, especially that items are consumed when read, I thought at having a func-local temporary dict able to hold copies of used stock items. More precisely, when a stock item is read, then it is erased as usual, like with stack pop, but a copy can still live in the func's scope. The copy dict may hold: * Brutally, a copy of the whole stock. * Items used in the func. * Only tems used more than once in the func. I think this is rather easy to implement, both for interpreted and compiled languages: a common operation at start of every func. As a side-effect, this would also let postfix syntax and concatenation much more appealing to people used to other paradigms, *especially in difficult cases*. I think that it is possible to design a data structure able to act both as a stack and a dict (the reason why I choose 'stock', not 'dict'). Unnamed items would be read and used as usual. An alternative can be that unnamed items silently get an index instead - but then we need a syntax like eg '#n' to denote them. Remains the question of naming: how do we concretely bind names to items? I thought the format used to name funcs can be reused -- provided a token marks the end of a func def (eg ';' or LF). The simple rule may be that the name is bound to the current result -- that probably should remain on the stack: :func op op op :x op op... (where 'op' denotes any possible term) These ideas are partly inspired by Raven: http://aerosuidae.net/raven.html. I would enjoy comments and critics; especially about how such ideas fit the concatenative way. Denis ------ la vita e estrany |
|
|
Re: stOckspir wrote:
> [Sean: thought you may be interested.] Indeed -- Raven is a very interesting language. > Hello concatenators, > I would like to exchange about possible drawbacks of a data stack and > a weird idea on a possible replacement. Maybe all of this is not new, > sorry if ever, but I could not find references. One question: How does this differ from any other semi-concatenative language's support for "local variables"? Okay, one OTHER question: have you looked at Factor's support for the spread/cleave combinator set? They aren't the end-all solution (the many variants are annoying), but they've eliminated almost all stack juggling from Factor's library in favor of a notation which cleanly expresses intent. > Denis -Wm |
|
|
Re: stOckLe Tue, 10 Mar 2009 08:10:32 -0700,
William Tanksley <wtanksleyjr@...> s'exprima ainsi: > spir wrote: > > [Sean: thought you may be interested.] > > Indeed -- Raven is a very interesting language. I like the way one can simply name formal parameters using 'use'. > > Hello concatenators, > > I would like to exchange about possible drawbacks of a data stack and > > a weird idea on a possible replacement. Maybe all of this is not new, > > sorry if ever, but I could not find references. > > One question: How does this differ from any other semi-concatenative > language's support for "local variables"? As I see it, not the same purpose, while there are indeed overlapping use cases. Local vars, as such, are not passed on the stack/stock: they do not belong to the data flow. But there is another drawback of my proposal (I realized a short while after posting ;-). The logic is not the same inside the func def and from the caller point of view. Precisely, the definition will often be genral while the call is specific. As a consequence, proper naming should not be the same. For instance one might define a func that works for any integer and call the arg 'n', while for the caller it should be named 'count', 'pos', or whatever. Denis ------ la vita e estrany |
|
|
Re: stOckOn Mar 10, 2009, at 6:58 AM, spir wrote:
> * Naming, when carefully done, is an invaluable help to clarity. Invaluable? It's unable to be valued? The value of having names can be measured and compared with the value of taking a pointfree approach. I don't think it's a given that we need to have names. > * Stack operations (swap, dup...) do not mean anything about the > mental 'model'. Neither do let statements, intermediate variables, or most anything else. When was the last time you heard a conversation like this: "Jim, we need a program to keep track of our medical records." "So you're saying you want something with lexical scoping?" "Of course; we need to keep track of medical records!" > About the latter remark: I think that a good program is one that > mirrors the 'model' it expresses. You'll have to justify this for me. I'm of the opinion that software should be easier to reason about than "real life". Once you start throwing around phrases like "mirroring the model", you shirk responsibility for coming up with the simplest solution. > In other words, the choice of a stack to pass data from func to func > introduces low-level code -- as opposed to high-level languages. Maybe, but you're not making a convincing case. > Let us imagine a "stOck" instead of a stack ;-); that could be a > hash/map/dict, meaning that items are named. Then we get the > following advantages: > * naming > * no stack juggling > * no dup But you also get the hell that is dynamic scoping. It might be fine for pseudo-globals, but it's a disaster for local variables. There's a reason virtually all Lisps have switched to lexical scoping. > As a side-effect, this would also let postfix syntax and > concatenation much more appealing to people used to other paradigms, > *especially in difficult cases*. I think the best way to make concatenative languages more appealing is to focus on their strengths. Making them into postfix variants of languages people are already using won't do much good. - John |
|
|
Re: stOckOn Mar 10, 2009, at 11:10 AM, William Tanksley wrote:
> spir wrote: > >> Hello concatenators, >> I would like to exchange about possible drawbacks of a data stack and >> a weird idea on a possible replacement. Maybe all of this is not new, >> sorry if ever, but I could not find references. > > One question: How does this differ from any other semi-concatenative > language's support for "local variables"? His proposal is equivalent to dynamic scoping. Locals in Factor are lexically scoped. - John |
|
|
Re: stOck--- In concatenative@..., spir <denis.spir@...> wrote:
> > [Sean: thought you may be interested.] > > Hello concatenators, > > I would like to exchange about possible drawbacks of a data stack and a weird idea on a possible replacement. Maybe all of this is not new, sorry if ever, but I could not find references. > > I am fully aware that stack juggling often seems mentally difficult basically because we are not used to it. If we had learnt arithmetics with postfix syntax then probably (1+2*3) would read alien. This point is not part of the issues discussed here. Instead, I think that: > > * Naming, when carefully done, is an invaluable help to clarity. > * Stack operations (swap, dup...) do not mean anything about the mental 'model'. > > About the latter remark: I think that a good program is one that mirrors the 'model' it expresses. Stack operations do not map to anything in the model (about the problem); instead they are only needed because of the stack limitations as a data structure. In other words, the choice of a stack to pass data from func to func introduces low-level code -- as opposed to high-level languages. Without any advantage of low-level languages, I guess (for instance _this_ does not help programming closer to the machine). > > Let us imagine a "stOck" instead of a stack ;-); that could be a hash/map/dict, meaning that items are named. Then we get the following advantages: > * naming > * no stack juggling > * no dup > > For illustration, say we want to compute > c * (a+b) / (a-b) > > :result (c b a -- result) + a b - / * > > or using only names > :result (c b a -- result) a b + a b - / c * > > Denis > ------ > la vita e estrany > I would like to point out that you can implement lexical scoping in a stack-based concatenative language without any great difficulty. First convert the 'let' expression into an expression using lambdas: :result (c b a -- result) a b + a b - / c * \c \b \a a b + a b - / c * Then convert this into stack-based code as shown in http://tunes.org/~iepos/joy.html#lambda. Also, I think John Nowak is right; you really do want lexical, not dynamic, scoping. Justin |
|
|
Re: stOckLe Tue, 10 Mar 2009 18:23:03 -0400,
John Nowak <john@...> s'exprima ainsi: > His proposal is equivalent to dynamic scoping. Locals in Factor are > lexically scoped. Excuse me to ask something that seems obvious to you: I simply don't understand. My proposal is about a kind of "namable" stack (stock). There are no additional variables, no variables outside the 'stock' (read: data flow from func to func). No locals in the usual sense neither, except if one calls 'locals', simply because they can be named, the data items that will be deleted when used in a func. There is no semantic difference between :div a b / :div / except the programmer does not need worrying about the stack order. (Sure, in this case naming is not very helpful cause the programmer will have to worry about ordering at call time ;-) In a stack-based language (without world/env data outside the stack), there cannot be any lexical scoping, or do I miss a point? One could call that dynamic scoping, as the data available to a func always come from the caller, but this does not make much sense imo in the absence of any other data source. It's kind of talking about composition, no? Adding the possibility to bind names to some of these data items does not change anything about the data flow: the data are the same, they follow the same path and 'die' when and where used as well: simply some are named in the aim of making the programmer's life nicer; by letting him give sensible names, avoiding stack juggling and dup-licating . If I remember well, you stated that a concatenative language needs not beeing stack-based. I understood that you meant the pack of data passed from func to func can be stored in another kind of data structure. Maybe I miss a trivial issue here; anyway, I guess this is precisely what my proposal is about. Denis ------ la vita e estrany |
|
|
Re: stOckOn Mar 11, 2009, at 6:54 AM, spir wrote: > Le Tue, 10 Mar 2009 18:23:03 -0400, > John Nowak <john@...> s'exprima ainsi: > >> His proposal is equivalent to dynamic scoping. Locals in Factor are >> lexically scoped. > > Excuse me to ask something that seems obvious to you: I simply don't > understand. My proposal is about a kind of "namable" stack (stock). This is basically what dynamic scoping is. In fact, dynamic scoping is typically implemented using a stack (or series of stacks). If you're passing along some sort of dictionary, you're emulating dynamic scoping (and the problems that come with it). > In a stack-based language (without world/env data outside the > stack), there cannot be any lexical scoping, or do I miss a point? Dynamic scoping is concatenative; lexical scoping is not. Lexical scoping can be implemented by providing a translation from a non- concatenative language to a concatenative one. This is what is done in Factor. This generally only works if your language has first class functions (as otherwise getting the data into the right places is not possible). - John |
|
|
Re: stOckspir wrote:
> John Nowak <john@...> s'exprima ainsi: > > His proposal is equivalent to dynamic scoping. Locals in Factor > are > > lexically scoped. > Excuse me to ask something that seems obvious to you: I simply don't > understand. My proposal is about a kind of "namable" stack (stock). > There are no additional variables, no variables outside the > 'stock' (read: data flow from func to func). No locals in the usual > sense neither, except if one calls 'locals', simply because they can > be named, the data items that will be deleted when used in a func. If I read this correctly, you're suggesting that in addition to the "standard" stack, we add a dictionary into which name/data bindings can be inserted at runtime. This dictionary is (like the stack) passed from function to function and is always available. Bindings in that dictionary are created by some means (you don't give an example), and are destroyed after their first use (I'm assuming that's what you mean when you say "the data items that will be deleted when used in a func"). Am I even close here? > In a stack-based language (without world/env data outside the stack), > there cannot be any lexical scoping, or do I miss a point? Certainly you can -- for example, you can define a scope as the space inside some arbitrary syntactic form. Implementing that can be complex, depending on how powerful your language is, but it can be done. > Adding the possibility to bind names to some of these data items does > not change anything about the data flow: the data are the same, they > follow the same path and 'die' when and where used as well: simply > some are named in the aim of making the programmer's life nicer; by > letting him give sensible names, Okay, I think I can offer some critiques. First, your proposal is concatenative (as you intended): the associative law still holds, and factoring is still possible. Good. Second, by making the bindings delete themselves at first use, you solve the problem of knowing when a data item goes away. Good. Third, you don't seem to propose a notation for any of this. How does the reader know when bindings are created or destroyed? Perhaps some conventional syntax would help: a! would create a binding named "a" and pop the top stack item as its bound value; using the name later will push the value back on the stack and remove the binding. Fourth, the fundamental problem with dynamic binding is that it's hard to tell where a name's coming from. It might help to provide a notation, to be used like a stack effect comment (and possibly type-inferenced in some languages). I'll use #( -- ) to indicate which bindings the function takes as input, and which it leaves in the dictionary. So a function might start like this: : quadratic ( a b c -- )#( -- root root2 discriminant ) ... ; ...so that function returns nothing on the stack, and instead lets you pull from the dict if you need it. Dunno how excited I am about that, but there you have it -- the possibility of arbitrarily strong typechecking on names. > avoiding stack juggling and dup-licating . If the data "dies" when it's first used, then you will have to "dup" if you use the same data twice -- or you'd have to provide a syntax to get the value of a binding without destroying it. Example: a@. > If I remember well, you stated that a concatenative language needs not > beeing stack-based. I understood that you meant the pack of data > passed from func to func can be stored in another kind of data > structure. Maybe I miss a trivial issue here; anyway, I guess this is > precisely what my proposal is about. I'm certain that structures other than a stack can be added to the standard stack. This (and Forth's dictionary) is just another example. I'm not certain that this idea is useful. Perhaps it needs to be seen in a real-world example. Feel free to proceed... :-) > Denis -Wm |
|
|
Re: stOckLe Wed, 11 Mar 2009 11:22:55 -0700,
William Tanksley <wtanksleyjr@...> s'exprima ainsi: > spir wrote: > > John Nowak <john@...> s'exprima ainsi: > > > His proposal is equivalent to dynamic scoping. Locals in Factor > > are > > > lexically scoped. > > > Excuse me to ask something that seems obvious to you: I simply don't > > understand. My proposal is about a kind of "namable" stack (stock). > > There are no additional variables, no variables outside the > > 'stock' (read: data flow from func to func). No locals in the usual > > sense neither, except if one calls 'locals', simply because they can > > be named, the data items that will be deleted when used in a func. > > If I read this correctly, you're suggesting that in addition to the > "standard" stack, we add a dictionary into which name/data bindings can > be inserted at runtime. This dictionary is (like the stack) passed from > function to function and is always available. Exactly. Except I proposed instead a kind of mixed stack-dict. But the principle is well what you express -- and implementing with a stack and a dict is easier. > Bindings in that dictionary are created by some means (you don't give an > example), and are destroyed after their first use (I'm assuming that's > what you mean when you say "the data items that will be deleted when > used in a func"). I proposed in fact to reuse the existing syntax for naming functions/words. For instance :word 1 + :name 2 * :result (For this to be parsable there should be a distinct token to end func defs, like ';'.) A name is bound to the current result, meaning what's on top of the stack. > Am I even close here? Yes. > > In a stack-based language (without world/env data outside the stack), > > there cannot be any lexical scoping, or do I miss a point? > > Certainly you can -- for example, you can define a scope as the space > inside some arbitrary syntactic form. Implementing that can be complex, > depending on how powerful your language is, but it can be done. All right. > > Adding the possibility to bind names to some of these data items does > > not change anything about the data flow: the data are the same, they > > follow the same path and 'die' when and where used as well: simply > > some are named in the aim of making the programmer's life nicer; by > > letting him give sensible names, > > Okay, I think I can offer some critiques. > > First, your proposal is concatenative (as you intended): the associative > law still holds, and factoring is still possible. Good. > > Second, by making the bindings delete themselves at first use, you solve > the problem of knowing when a data item goes away. Good. > > Third, you don't seem to propose a notation for any of this. How does > the reader know when bindings are created or destroyed? Perhaps some > conventional syntax would help: a! would create a binding named "a" and > pop the top stack item as its bound value; using the name later will > push the value back on the stack and remove the binding. Exactly. And the process is similar to what Raven does; except that it creates local variables, while my proposal is about the "stock of data" that flows from func to func. Actually, there was a notation proposed in the message that started this thread -- see above. Not so important as long as it's not misleading. > Fourth, the fundamental problem with dynamic binding is that it's hard > to tell where a name's coming from. It might help to provide a notation, > to be used like a stack effect comment (and possibly type-inferenced in > some languages). I'll use #( -- ) to indicate which bindings the > function takes as input, and which it leaves in the dictionary. > > So a function might start like this: > > : quadratic ( a b c -- )#( -- root root2 discriminant ) > ... > ; Nice ;-) > ...so that function returns nothing on the stack, and instead lets you > pull from the dict if you need it. > > Dunno how excited I am about that, but there you have it -- the > possibility of arbitrarily strong typechecking on names. > > > avoiding stack juggling and dup-licating . > > If the data "dies" when it's first used, then you will have to "dup" if > you use the same data twice -- or you'd have to provide a syntax to get > the value of a binding without destroying it. Example: a@. What I proposed about that is: when entering a function, the names used twice in the body of this function are copied into a distinct "transient" dict. When leaving the func this one dict is blanked. Names used from the main data dict are erased like the one from a normal stack. So, while the function is executed, names not found in the main stack+dict will be looked up inside the transient dict. > > If I remember well, you stated that a concatenative language needs not > > beeing stack-based. I understood that you meant the pack of data > > passed from func to func can be stored in another kind of data > > structure. Maybe I miss a trivial issue here; anyway, I guess this is > > precisely what my proposal is about. > > I'm certain that structures other than a stack can be added to the > standard stack. This (and Forth's dictionary) is just another example. Forth dictionaries, as I understand them, are kinds of modules like in eg Ruby: distinct namespaces. > I'm not certain that this idea is useful. Perhaps it needs to be seen in > a real-world example. Feel free to proceed... :-) Well, I already found a flaw myself: that naming in a function definition is different from naming at func call. Maybe Raven's way is better. > > Denis > > -Wm > > ------ la vita e estrany |
|
|
Re: stOckspir wrote:
> William Tanksley <wtanksleyjr@...> s'exprima ainsi: > Exactly. Except I proposed instead a kind of mixed stack-dict. But the > principle is well what you express -- and implementing with a stack > and a dict is easier. Sorry, I don't know what "mixed" means in this context. If you mean that the data is actually stored on the stack, that won't work at all -- it's been tried in Forth, and it results in the stack becoming useless whenever anything's put into the dictionary. You can't even use 'swap' if the top item is named. If you mean that the data's not stored on the stack, then what do you mean by "mixed"? Later on you indicate that each word may have its own local dict, in which case how can that even _possibly_ be associated with the data stack (of which there's only one)? What _did_ you mean? > > Bindings in that dictionary are created by some means (you don't give an > > example), and are destroyed after their first use (I'm assuming that's > > what you mean when you say "the data items that will be deleted when > > used in a func"). > I proposed in fact to reuse the existing syntax for naming > functions/words. For instance > :word 1 + :name 2 * :result Ah. Here's the source of my confusion -- you said "existing syntax", but you didn't explain what language you were borrowing the "existing syntax" from. I don't know any language that uses a preceding inflecting colon to define words (Forth uses a colon, but it's a word in its own right, not an inflection). But that's a fine syntax, no problem. Now I understand your proposal. > > So a function might start like this: > > : quadratic ( a b c -- )#( -- root root2 discriminant ) > > ... > > ; > Nice ;-) I'm not sure I'm "sold", but I at least see how to use this in a typesafe way. Type safety doesn't have to mean static type checking -- it's enough for me that the programmer can write a program in which knows the types that can go through are known. > What I proposed about that is: when entering a function, the names > used twice in the body of this function are copied into a distinct > "transient" dict. When leaving the func this one dict is blanked. > Names used from the main data dict are erased like the one from a > normal stack. So, while the function is executed, names not found in > the main stack+dict will be looked up inside the transient dict. This gives a lexical scope to name use that it wouldn't otherwise have, which is nice. It does mean that every call to every word must maintain a dict of its own, which enormously increases the complexity of a function call. It also means that deleting a use of a variable can have potentially enormous effects on the global program (if the variable was accessed twice, deleting one use will change the function to erase the global name). I think the problems with this are far worse than the benefits. It's not a bad idea, but we/you need to work out a better way to indicate "this deletes" versus "this does not delete". I would suggest a simple syntactic token, akin to but opposite from the :definition token you proposed. It would also make sense to place that token in the dict effect comment/type signature. A side effect of this is that you regain the ability to do everything with a single global dict, rather than having to create a lexical dict for every call to every function. > Forth dictionaries, as I understand them, are kinds of modules like in > eg Ruby: distinct namespaces. No. Forth has only one dictionary. It's a data structure that consists of names, code, and data linked together by at least one linked list. The linked lists are called "vocabularies". The vocabularies, in turn, are referenced by a "current vocabulary" variable, which provides the starting point for all name lookups. -Wm |
|
|
Re: stOckWT wrote:-
> have you looked at Factor's support for the > spread/cleave combinator set? I'm don't want to open another canOworms ? Unless it could have been explained in lines < 2, instead of 'go & get it', it's no good. == Chris Glur. PS. stacking doesn't hope to map to the problem domain. It DOES map to how any task is done. All tasks can/are decomposed heirarchically. When the chicken swallows the worm, it does eg: 1. take in beak .... 2. move to throat.... 3. swallow ... But 'swallow' decomposes into a 'tree' of sub-tasks. So too, when you mail this reply, you do a sequence/cat of subtasks,each of which is a tree hence stacked. So every task in the universe uses a stack/tree of sub-tasks by it's 'actor? So the stack will always be there for implimentation. But if you want it more hidden 'we can do that'. OTOH *you do* stcck your actions into sub-actions, so the stack/tree is NOT an un-natural mental model ? |
|
|
Re: stOckOn Apr 1, 2009, at 5:33 AM, chris glur wrote:
> So every task in the universe uses a stack/tree > of sub-tasks by it's 'actor? > > So the stack will always be there for implimentation. > But if you want it more hidden 'we can do that'. > OTOH *you do* stcck your actions into sub-actions, > so the stack/tree is NOT an un-natural mental model ? I've read mad libs more coherent than this. Come on man, at least fire up the spellchecker... - John |
|
|
Re: stOckchris glur wrote:
> WT wrote:- > > have you looked at Factor's support for the > > spread/cleave combinator set? > I'm don't want to open another canOworms ? > Unless it could have been explained in lines < 2, > instead of 'go & get it', it's no good. This is programming. To program you have to tell the computer *exactly* what to do. If it can be explained in 2 lines, it's not programming; it's something else. I do think it's reasonable to ask for a 2-line motivation, so you can know WHY you're looking at whatever library I just mentioned. Here ya go :-): "Factor's spread/cleave/apply combinators allow one to express one's intentions about dataflow rather than having to code in terms of stack shuffling." > == Chris Glur. > PS. stacking doesn't hope to map to the problem domain. > It DOES map to how any task is done. This was very hard to understand. After much thought, I think I might know what you're saying: you're pointing out that a problem isn't a process, but rather an undesired state of affairs. It's therefore not really apt to speak of coding in the problem domain, because (at least in concatenative languages) we're not expressing the problem, but rather a process which is designed to convert the initial state of affairs into the final, desired state of affairs. (I should mention that languages like Prolog actually do allow one to code in the problem domain, by the definition I assumed above... Look around for explanations of "declarative programming languages".) > All tasks can/are decomposed heirarchically. Okay, I suppose that they can. Certainly that's a feature of concatenative languages. What's your point? -Wm |
|
|
Re: stOckWhat's my point ?
Well I've lost the OP's exact wording. But HIS main point was that 'stack doesn't model the problem domain'. Yes, but it models the problem solution method [algorithm] of every 'entity which has evolved to have intentions'. Which you obviously understood, since you gave the apparent counter-example of a declarative language. So yes, once I hand the task to google [or prolog], I skip stacking that part of the task. When google returns data I continue with the stacking process. Interestingly [to me], Turing apparently saw the sequence of instructions as being 'flat' [as a writer 'here' calls it]. But the concept of sub-routine [chuncking] is so natural that abandoning it is absurd. == Chris Glur. PS. sorry about the crappy gmail posting facility ! PSS. I agree with the OP's idea of getting rid of stack shuffling. It's the stacking/storeing that can't be bettered. That's why I wrote stack/tree. On 4/1/09, William Tanksley <wtanksleyjr@...> wrote: > chris glur wrote: >> WT wrote:- >> > have you looked at Factor's support for the >> > spread/cleave combinator set? >> I'm don't want to open another canOworms ? >> Unless it could have been explained in lines < 2, >> instead of 'go & get it', it's no good. > > This is programming. To program you have to tell the computer *exactly* > what to do. If it can be explained in 2 lines, it's not programming; > it's something else. > > I do think it's reasonable to ask for a 2-line motivation, so you can > know WHY you're looking at whatever library I just mentioned. > > Here ya go :-): "Factor's spread/cleave/apply combinators allow one to > express one's intentions about dataflow rather than having to code in > terms of stack shuffling." > >> == Chris Glur. >> PS. stacking doesn't hope to map to the problem domain. >> It DOES map to how any task is done. > > This was very hard to understand. After much thought, I think I might > know what you're saying: you're pointing out that a problem isn't a > process, but rather an undesired state of affairs. It's therefore not > really apt to speak of coding in the problem domain, because (at least > in concatenative languages) we're not expressing the problem, but rather > a process which is designed to convert the initial state of affairs into > the final, desired state of affairs. > > (I should mention that languages like Prolog actually do allow one to > code in the problem domain, by the definition I assumed above... Look > around for explanations of "declarative programming languages".) > >> All tasks can/are decomposed heirarchically. > > Okay, I suppose that they can. Certainly that's a feature of > concatenative languages. > > What's your point? > > -Wm > > > |
|
|
Re: stOckLe Thu, 2 Apr 2009 00:50:45 +0300,
chris glur <crglur@...> s'exprima ainsi: > What's my point ? > Well I've lost the OP's exact wording. > But HIS main point was that 'stack doesn't model the problem domain'. While I don't have a copy of that post at hand, it was actually only a paragraph in a rather long message. And I was not talking of the stack by itself, but of the stack juggling operations. My point was that these operations do not map to anything in the model, or solution, as could be expressed using words, sketches, or other PLs. As such, I view them as annoyance and an unnecessary additional obstacle in the task of programming -- that is already a very difficult one, indeed. This is personal opinion, for sure. It is based on the idea that a *good* programming language is one that lets one express as straightforwardly as possible one's "model" (meaning the way one views the problem to be solved, the system to be simulated, or whatever is the object of a programming task). In the case of a stack, the data are stored in such a structure that it requires juggling in addition to operations that well belong to the operative solution. Compare this to iteration in a collection: In C or Pascal you need an index only because of (wrong) language design. In Python you can write "for item in collection:" directly, in Ruby "collection.each()", in Io "collection foreach ()", all idioms which imo better map the model. > Yes, but it models the problem solution method [algorithm] of > every 'entity which has evolved to have intentions'. I do not see it like you. There is a distinction between stack use and data flow. I like very much the way concatenative languages allow expressing a program as a data *&* process flow. [This reminds me of automation programming languages' notion of "sequensor" (not sure of the word in english).] Unless I misunderstand your point, your talking of the operative process and of the fact that concatenative languages express as a combination of functions/words. This can be seen as orthogonal to the data storage structure. > Which you obviously understood, since you gave the apparent > counter-example of a declarative language. > So yes, once I hand the task to google [or prolog], I skip stacking > that part of the task. > When google returns data I continue with the stacking process. > > Interestingly [to me], Turing apparently saw the sequence of instructions > as being 'flat' [as a writer 'here' calls it]. But the concept of > sub-routine [chuncking] is so natural that abandoning it is absurd. > > == Chris Glur. > > PS. sorry about the crappy gmail posting > facility ! > > PSS. I agree with the OP's idea of getting rid of stack shuffling. > It's the stacking/storeing that can't be bettered. > That's why I wrote stack/tree. That's much closer to the chunk of my original post you're citing! Denis ------ la vita e estrany |
|
|
Re: stOckOn Apr 2, 2009, at 4:40 AM, spir wrote: > My point was that these operations do not map to anything in the > model, or solution, Sure. > As such, I view them as annoyance and an unnecessary additional > obstacle This is a leap. You're forgetting that a language that requires such things may derive benefits from such a design that you're not accounting for. If you think the pointfree approach buys you nothing, then sure, they're strictly an annoyance. > It is based on the idea that a *good* programming language is one > that lets one express as straightforwardly as possible one's "model" The most straightforward expression isn't always the most easy to reason about or the most easy to reuse. If your goal is a language that emphasizes correctness, it is reasonable to think you may have to state things in a manner more explicit or more abstract (e.g. in terms of morphisms instead of general recursion). If your goal is a language that makes programs easier to manipulate and refactor, it may make sense to disallow the use of variables. A good language is one that allows you to be sure that you're writing high quality software and allows you to get there with the least amount of effort possible. Anything else is a means towards that end. > In C or Pascal you need an index only because of (wrong) language > design What else would you do given that the lengths of arrays aren't passed along with them? - John |
|
|
Re: stOck> In the case of a stack, the data are stored in such a structure
> that it requires juggling in addition to operations that well > belong to the operative solution. Compare this to iteration in > a collection: In C or Pascal you need an index only because of > (wrong) language design. No, it's no more WRONG than gromgramming by 'binary switches'. >In Python you can write "for item in collection:" directly, >in Ruby "collection.each()", in Io "collection foreach ()", >all idioms which imo better map the model. Yes, this is just a HIGHER level, which often is better. If I 'program' google to: fetch me urls of all Usenet articles in groups *linux* which have the case-insensitive phrase "formal methods", then I'm 'programming' at a rather HIGH level ? An even higher level is to just delegate the task to your software-engineer. But behind the scenes [the implementation] there's a lot of 'stack operation', because ALL tasks are solved by decomposition, and decomposition means the subtasks are stacked. So because forth is low-level it gives direct access to the stack. C & Pascal are higher, but acknowledge the stack nature by their block-structure. Being able to write "for item in collection:" is a yet higher level of programming: hiding the implementation even more, and allowing you to better mentally-model the problem domain. Googling is still higher. So you are confusing the language IMPLEMENTATION with the 'programming in the problem domain'. The common method of solving [somewhat] the problem which you correctly describe is to 'build a hi-level abstraction on top of the lower-level'. But if you've got hi-level tools that do your task then you'd use them, rather than stack-shuffling. OTOH in many cases 3 wheel-barrows are 'better' than a hi-tech auto-transporter. == Chris Glur. |
| Free embeddable forum powered by Nabble | Forum Help |