# Yet another?

## Don Groves — 2007-08-16 03:45:35

    Hello all,

    The trouble with languages such as Joy, which I fell in love with a

    couple of years ago, is that, when I hang around them long enough,

    they get under my skin. They get into my mind and after a while, take

    on a life of their own. My only relief from this situation is to write

    one myself, so I am hereby announcing the birth of Catenate, yet

    another concatenative language.

    My selection of the name Catenate is two-fold. First is the obvious

    one that catenate (cat) is the UNIX command for concatenating strings.

    The second is more complex. In Catenate, memory is not allocated in

    the usual way, instead it is pre-allocated as an array of fixed-size

    "cells" and data and programs are represented as groups of cells. In

    Botany, the term "catenate" refers to plant structures that are a

    series or group of biological cells -- hence the similarity and the name.

    Catenate is based on (1) Joy in particular and concatenative languages

    in general; (2) my 35+ years of professional programing during which I

    kept notes on things I would like to try after retirement; and (3) my

    Forth experience during that time.

    Catenate is written in C and compiles under the GCC environment. It is

    not intended for speed, rather for completeness, safety, and for my

    own research in mathematical topics (my university degree is in math).

    If Catenate becomes useful for anyone else, that will be icing on the

    cake.

    Although it is coming along nicely, I haven't anything yet to publish

    for others to try but I wanted to introduce myself to the group and

    start joining in on the discussions of this highly interesting topic.

    Sincerely,

    Don Groves

    Portland, Oregon, US.

## pml060912 — 2007-08-16 13:06:13

    --- In concatenative@yahoogroups.com, "Don Groves" <dgroves@...> wrote:

     >

    > Hello all,

    >

    > The trouble with languages such as Joy, which I fell in love with a

    > couple of years ago, is that, when I hang around them long enough,

    > they get under my skin. They get into my mind and after a while, take

    > on a life of their own. My only relief from this situation is to write

    > one myself, so I am hereby announcing the birth of Catenate, yet

    > another concatenative language.

     .

    .

    .

     > Although it is coming along nicely, I haven't anything yet to publish

    > for others to try but I wanted to introduce myself to the group and

    > start joining in on the discussions of this highly interesting topic.

    >

    > Sincerely,

    >

    > Don Groves

     That's roughly how I got here. My occasional work on my own

    concatenative language, Furphy, is on the page

    http://member.netlink.com.au/~peterl/furphy.html (though that might

    not be true after next week, when I may have to change ISPs - buy now

    while stocks last). So far I don't have a whole language, just paper

    models and constructs I have tested out on top of Forth. The next

    stage, if I get around to it, is to implement that in an Eforth like

    way on top of Perl or Euphoria to snarf (piggyback) their garbage

    collection while I prototype a bit more, and maybe their associative

    indexing too. It doesn't seem worth committing to a more efficient

    machine code implementation including the work of implementing garbage

    collection etc. until I'm sure I know what I've got. I've got some of

    Henry Baker's ideas in mind about that, as food for thought (e.g. an

    instruction stack instead of a return stack, and making a whole new

    copy on any DUP to simplify freeing up).

    There is one construct I found that I really like, so far. That is to

    compile new words anonymously, using unrecognised words to flag both

    termination and naming, with end of source terminating the final

    anonymous word which is then executed/evaluated. That allows a simple

    compile and go behaviour without modes or immediate words, although I

    shall probably provide some for implementing syntactic sugar more

    conveniently (a preprocessor could provide it, so this doesn't break

    the fundamental model).

    Another construct is more fundamental but not as aesthetically

    pleasing to my eyes, the pair FREEZE and THAW to cause and complete

    partial evaluation so that IF - which has to be eager - can have a

    workaround for lazy evaluation that works a bit like the referencing

    workaround in plain vanilla C to make argument passing by value

    achieve the effect of passing by name. And I am considering making a

    user interface that is somewhat spreadsheet oriented, drawing on work

    done for the Z88 and the Canon Cat, though that is further down the

    track and I may never get there. P.M.Lawrence.

## Christopher Diggins — 2007-08-16 16:17:39

    These are very interesting posts, I love hearing about new languages, thanks

    for sharing them Peter and Don. I would be interested in seeing this thread

    grow into a summary of the concatenative community and who's doing what, so

    I want to encourage you to introduce (or reintroduce) yourself and your

    language research on this thread. In that vein, here is a brief introduction

    of myself and my language:

    =

    My name is Christopher Diggins and I am currently developing a language

    derived from Joy called Cat (http://www.cat-language.com). Cat's notable

    features are static typing, type-inference, macro term-rewriting system, and

    lambda expressions with named parameters. Cat is being developed for two

    purposes: 1) a language for teaching, 2) an intermediate language for

    translation, compilation, optimization, and analysis of other languages. I

    have been working on Cat for over a year and a half.

    All code for Cat is public domain, and the main project is in C# (Mono

    compatible, so it *is* multi-platform), and a translator for a subset of the

    language is also available in C++.

    - Christopher

    [Non-text portions of this message have been removed]

## Don Groves — 2007-08-16 19:42:31

    Thanks, Christopher and Peter for your kind replies.

    I've looked at Cat before, Christopher, and found it very impressive!

    I'll be

    most pleased if Catenate ever approaches Cat's level of sophistication.

    I just tried to read up on Furphy but the url wasn't found, so Peter

    may be

    changing his ISP even sooner that he thought.

    Peter mentioned Euphoria which is another impressive language but its

    Pascal-like syntax seems overly verbose after becoming used to Joy-type

    syntax. However, Euphoria is the fastest (blazing fast!) full-featured

    interpreter I've ever seen. I've corresponded with the author and he

    said

    the internals are Forth-inspired.

    Happy to be aboard,

    Don

     On Aug 16, 2007, at 19:17 , Christopher Diggins wrote:

    > These are very interesting posts, I love hearing about new

    > languages, thanks

    > for sharing them Peter and Don. I would be interested in seeing

    > this thread

    > grow into a summary of the concatenative community and who's doing

    > what, so

    > I want to encourage you to introduce (or reintroduce) yourself and

    > your

    > language research on this thread. In that vein, here is a brief

    > introduction

    > of myself and my language:

    >

    > =

    >

    > My name is Christopher Diggins and I am currently developing a

    > language

    > derived from Joy called Cat (http://www.cat-language.com). Cat's

    > notable

    > features are static typing, type-inference, macro term-rewriting

    > system, and

    > lambda expressions with named parameters. Cat is being developed

    > for two

    > purposes: 1) a language for teaching, 2) an intermediate language for

    > translation, compilation, optimization, and analysis of other

    > languages. I

    > have been working on Cat for over a year and a half.

    >

    > All code for Cat is public domain, and the main project is in C# (Mono

    > compatible, so it *is* multi-platform), and a translator for a

    > subset of the

    > language is also available in C++.

    >

    > - Christopher

    >

    >

    > [Non-text portions of this message have been removed]

    >

    >

    >

    >

    > Yahoo! Groups Links

    >

    >

    >

    >

## Don Groves — 2007-08-16 20:14:50

    A few more Catenate features:

    Dynamic typing:

    Data is typed; names are not. A name can hold any type of data.

    Linearity:

    Every memory cell has exactly one reference. When de-referenced, a

    cell is cleared and is immediately available for re-allocation. Thus,

    garbage collection is trivial (marking without sweeping ;-)

    Unicode:

    UTF8 encoding is used throughout.

    Syntax:

    Probably best described as a math-inspired, Lispish Joy. For example,

    here is a sample terminal session:

    stack: { }

    => 3

    stack: {3}

    => 4 *

    stack: {12}

    => _

    And a more complex one calculating the area of a circle of radius 3:

    stack: { }

    => 3.1459 defcon π

    π defined

    stack: { }

    => [dup *] defun ^2

    ^2 defined

    stack: { }

    => [^2 π *] defun πr^2

    πr^2 defined

    stack: { }

    => 3 πr^2

    stack: {28.3131 }

    => _

    Questions, comments, and suggestions will be gladly received,

    Don Groves

## Daniel Ehrenberg — 2007-08-16 20:45:02

    I'm not sure if I understand your no-garbage-collection idea properly.

    How do you plan to make useful compound data structures when two

    things cannot point to the same object in memory? It sounds like there

    would be a lot of copying involved. If two functions want to index the

    same array, will they each need a copy of that array? What about for

    more complicated things, like binary trees; won't balancing require

    more copying than is necessary in other languages?

    Daniel Ehrenberg

     On 8/16/07, Don Groves <dgroves@...> wrote:

    > A few more Catenate features:

    >

    > Dynamic typing:

    > Data is typed; names are not. A name can hold any type of data.

    >

    > Linearity:

    > Every memory cell has exactly one reference. When de-referenced, a

    > cell is cleared and is immediately available for re-allocation. Thus,

    > garbage collection is trivial (marking without sweeping ;-)

    >

    > Unicode:

    > UTF8 encoding is used throughout.

    >

    > Syntax:

    > Probably best described as a math-inspired, Lispish Joy. For example,

    > here is a sample terminal session:

    >

    > stack: { }

    > => 3

    >

    > stack: {3}

    > => 4 *

    >

    > stack: {12}

    > => _

    >

    > And a more complex one calculating the area of a circle of radius 3:

    >

    > stack: { }

    > => 3.1459 defcon π

    >

    > π defined

    >

    > stack: { }

    > => [dup *] defun ^2

    >

    > ^2 defined

    >

    > stack: { }

    > => [^2 π *] defun πr^2

    >

    > πr^2 defined

    >

    > stack: { }

    > => 3 πr^2

    >

    > stack: {28.3131 }

    > => _

    >

    > Questions, comments, and suggestions will be gladly received,

    > Don Groves

    >

    >

    >

    >

    > Yahoo! Groups Links

    >

    >

    >

    >

## Don Groves — 2007-08-16 21:37:46

    Hi Daniel,

    Yes, Catenate will require more copying than non-linear languages but

    the benefits of linearity outweigh the extra copying in my opinion.

    I haven't considered the idea of two functions wanting to index the same

    array but that doesn't sound like something I'd need to do anyway, at

    least

    it's never come up for me before ;-)

    There still may be serious problems I haven't foreseen with my approach,

    I'm no expert in all this and there's a lot of learning as I go

    along. Kinda

    what makes it so much fun!

    --

    Don Groves

     On Aug 16, 2007, at 19:45 , Daniel Ehrenberg wrote:

    > I'm not sure if I understand your no-garbage-collection idea properly.

    > How do you plan to make useful compound data structures when two

    > things cannot point to the same object in memory? It sounds like there

    > would be a lot of copying involved. If two functions want to index the

    > same array, will they each need a copy of that array? What about for

    > more complicated things, like binary trees; won't balancing require

    > more copying than is necessary in other languages?

    >

    > Daniel Ehrenberg

    >

    > On 8/16/07, Don Groves <dgroves@...> wrote:

    >> A few more Catenate features:

    >>

    >> Dynamic typing:

    >> Data is typed; names are not. A name can hold any type of data.

    >>

    >> Linearity:

    >> Every memory cell has exactly one reference. When de-referenced, a

    >> cell is cleared and is immediately available for re-allocation. Thus,

    >> garbage collection is trivial (marking without sweeping ;-)

    >>

    >> Unicode:

    >> UTF8 encoding is used throughout.

    >>

    >> Syntax:

    >> Probably best described as a math-inspired, Lispish Joy. For example,

    >> here is a sample terminal session:

    >>

    >> stack: { }

    >> => 3

    >>

    >> stack: {3}

    >> => 4 *

    >>

    >> stack: {12}

    >> => _

    >>

    >> And a more complex one calculating the area of a circle of radius 3:

    >>

    >> stack: { }

    >> => 3.1459 defcon π

    >>

    >> π defined

    >>

    >> stack: { }

    >> => [dup *] defun ^2

    >>

    >> ^2 defined

    >>

    >> stack: { }

    >> => [^2 π *] defun πr^2

    >>

    >> πr^2 defined

    >>

    >> stack: { }

    >> => 3 πr^2

    >>

    >> stack: {28.3131 }

    >> => _

    >>

    >> Questions, comments, and suggestions will be gladly received,

    >> Don Groves

    >>

    >>

    >>

    >>

    >> Yahoo! Groups Links

    >>

    >>

    >>

    >>

    >

    >

    >

    > Yahoo! Groups Links

    >

    >

    >

## William Tanksley, Jr — 2007-08-16 22:57:55

    Don Groves <dgroves@...> wrote:

     > I haven't considered the idea of two functions wanting to index the same

    > array but that doesn't sound like something I'd need to do anyway, at

    > least it's never come up for me before ;-)

     If the functions need to do that sequentially, there's no problem --

    you pass the reference to the first function, then the second

    function. If they need to operate in parallel you have to make a copy.

     > There still may be serious problems I haven't foreseen with my approach,

    > I'm no expert in all this and there's a lot of learning as I go

    > along. Kinda what makes it so much fun!

     Obviously you've read your Henry Baker,

    http://home.pipeline.com/~hbaker1/ForthStack.html (I cite this for the

    benefit of others interested). He explains how linear logic works and

    why it insists on only one reference per object.

     > Don Groves

     -Billy

## Don Groves — 2007-08-17 01:53:59

    Hi Billy,

    Yes, I've read Baker's papers and they obviously affected my thinking

    about languages.

    Thanks for the tip on the other topic.

    --

    Don

     On Aug 16, 2007, at 19:57 , William Tanksley, Jr wrote:

    > Don Groves <dgroves@...> wrote:

    >> I haven't considered the idea of two functions wanting to index

    >> the same

    >> array but that doesn't sound like something I'd need to do anyway, at

    >> least it's never come up for me before ;-)

    >

    > If the functions need to do that sequentially, there's no problem --

    > you pass the reference to the first function, then the second

    > function. If they need to operate in parallel you have to make a copy.

    >

    >> There still may be serious problems I haven't foreseen with my

    >> approach,

    >> I'm no expert in all this and there's a lot of learning as I go

    >> along. Kinda what makes it so much fun!

    >

    > Obviously you've read your Henry Baker,

    > http://home.pipeline.com/~hbaker1/ForthStack.html (I cite this for the

    > benefit of others interested). He explains how linear logic works and

    > why it insists on only one reference per object.

    >

    >> Don Groves

    >

    > -Billy

    >

    >

    >

    > Yahoo! Groups Links

    >

    >

    >

    >

## pml060912 — 2007-08-17 10:00:09

    --- In concatenative@yahoogroups.com, Don Groves <dgroves@...> wrote:

     >

    > Thanks, Christopher and Peter for your kind replies.

    >

    > I've looked at Cat before, Christopher, and found it very impressive!

    > I'll be

    > most pleased if Catenate ever approaches Cat's level of sophistication.

    >

    > I just tried to read up on Furphy but the url wasn't found, so Peter

    > may be

    > changing his ISP even sooner that he thought.

     I checked, and it's actually at

    http://member.netlink.com.au/~peterl/furphy.htm - I was quoting an

    earlier version from before the ISP moved everything around to suit

    itself. If you get there you'll see that I too looked at a fair bit of

    Henry Baker's thinking on linearity. The idea of not having to make

    repeated copies by passing a reference to one function after another

    sort of works, but it forces you into continuation passing (or

    something very like it), which may not suit the internal logic of the

    functions - or your own personal style. There's no real saving if the

    function effectively has to copy to have something to work with itself.

    One thing I thought of that would help with linearity is to define

    Forth style @ and ! in terms of DUP, DROP and an inherently

    conservative/linear MEMSWAP ( newconts addr --- oldconts addr ) or

    possibly with stack effects the other way around, and maybe in terms

    of SWAP and other inherently conservative/linear stuff too. Then a

    wide range of behaviour can be built on the @ and ! even if those

    don't get made publicly available in the main language, and you only

    need to get DUP and DROP respecting the linearity to carry everything

    else. You can implement dedicated efficient versions later, but this

    lets you have everything in a prototype carried on a small base that

    you can more easily test fully. This is paper model stuff I have only

    sketched out so far, not prototyped yet.

    The thing that reminded me of that is, MEMSWAP does naturally work in

    that continuation passing way just to be conservative/linear. You have

    to throw away an unwanted address on purpose, separately. PML.

## Don Groves — 2007-08-17 19:07:06

    Hi Peter,

    I found it last evening by resorting to Google. You've got some

    intriguing

    ideas in Furphy, several things I haven't even considered yet. I've only

    been working on Catenate since June, so it'll take a while for me to

    catch

    up with the rest of you. At the moment, I'm in major assimilation mode.

    --

    Don Groves

    Programmer (n): An organism that turns coffee and cookies into software.

     On Aug 17, 2007, at 19:00 , pml060912 wrote:

    > --- In concatenative@yahoogroups.com, Don Groves <dgroves@...> wrote:

    >>

    >> Thanks, Christopher and Peter for your kind replies.

    >>

    >> I've looked at Cat before, Christopher, and found it very impressive!

    >> I'll be

    >> most pleased if Catenate ever approaches Cat's level of

    >> sophistication.

    >>

    >> I just tried to read up on Furphy but the url wasn't found, so Peter

    >> may be

    >> changing his ISP even sooner that he thought.

    >

    > I checked, and it's actually at

    > http://member.netlink.com.au/~peterl/furphy.htm - I was quoting an

    > earlier version from before the ISP moved everything around to suit

    > itself. If you get there you'll see that I too looked at a fair bit of

    > Henry Baker's thinking on linearity. The idea of not having to make

    > repeated copies by passing a reference to one function after another

    > sort of works, but it forces you into continuation passing (or

    > something very like it), which may not suit the internal logic of the

    > functions - or your own personal style. There's no real saving if the

    > function effectively has to copy to have something to work with

    > itself.

    >

    > One thing I thought of that would help with linearity is to define

    > Forth style @ and ! in terms of DUP, DROP and an inherently

    > conservative/linear MEMSWAP ( newconts addr --- oldconts addr ) or

    > possibly with stack effects the other way around, and maybe in terms

    > of SWAP and other inherently conservative/linear stuff too. Then a

    > wide range of behaviour can be built on the @ and ! even if those

    > don't get made publicly available in the main language, and you only

    > need to get DUP and DROP respecting the linearity to carry everything

    > else. You can implement dedicated efficient versions later, but this

    > lets you have everything in a prototype carried on a small base that

    > you can more easily test fully. This is paper model stuff I have only

    > sketched out so far, not prototyped yet.

    >

    > The thing that reminded me of that is, MEMSWAP does naturally work in

    > that continuation passing way just to be conservative/linear. You have

    > to throw away an unwanted address on purpose, separately. PML.

    >

    >

    >

    >

    > Yahoo! Groups Links

    >

    >

    >

    >

## Manfred Von Thun — 2007-09-07 08:06:57

    For a long time I have been interested in the difference

    between the standard kind of lambda calculus languages

    and the concatenative languages. Only recently did it

    occur to me that there is a third class which has been around

    for some time. The three differ in how they treat actual

    and formal parameters in definitions of functions and in

    calls of functions. At one extreme are the concatenative

    languages, at the other extreme those in the third class.

    The standard lambda calculus languages are half way

    between these two extremes.

    Most programming languages belong in the class of

    lambda calculus languages. Definitions look more or

    less like this:

    DEFINE foo(x,y,z)        # head of definition

       = ...x...y...z...          # body of definition

    So there is a list of formal parameters (x,y,z) in the

    head, and an expression ...x...y...z... which is the body.

    In the body each of the formal parameters occurs one

    or more times, or even not at all. The various occurrences

    can be in any order. (This is one of the strengths of

    lambda calculus notation.) Once you have written the

    entire definition, you can change your mind about the

    parameter list: you can change it to (y,z,x) and there

    is no need to change the body in any way. In a call

    to the function, foo(a,b,c), with actual parameters (a,b,c)

    the values of the actual parameters are given to the

    corresponding formal parameters. Of course the effect

    of the call depends on whether the original definition with

    (x,y,z) or the revised definition with (y,z,x)  is in force.

    The order of the actual parameters is taken to match

    the order of the formal parameters. To summarise:

    In the body the formal parameters are used as names,

    irrespective of their order in the parameter list;

    in a call the order of the actuals and the formals are

    the same, irrespective of the names of the formals.

    In concatenative languages there are no formal parameter

    lists. Definitions look like this:

    DEFINE foo                        # head of definition

      =  ...dup...swap... pop...   # body of definition

    Instead of  being able to refer to the actual parameters

    by the name of the corresponding formal parameter,

    it is now necessary to take the actual parameters as

    they are on the stack, and do some shuffling to get

    everything right in the body. Once you have written the

    entire definition, you cannot just change the parameter

    list because there isn¹t one. You also have to change the body of

    the definition. In a call the order of the actual parameters

    on the stack has to be in the order in which the body

    of the definition expects them. To summarise:

    In the body of the definition there is an expected order

    of the  actual parameters on the stack; in a call

    the actual parameters have to be in the in the order

    in which the body expects them.

    So at the one extreme we can have the concatenative

    method: there are no names, body and call

    are done by order (on the stack). In the middle we have the

    standard lambda calculus notation: there are names

    which are used in the body, but calls use positions

    that match the order of the formals in the parameter

    list. At the other extreme there should be languages

    which do not use  order at all but rely on names both

    in the body and in calls. Are there such beasts?

    In such languages definitions would again look as in

    lambda calculus languages:

    DEFINE foo(x,y,z)        # head of definition

       = ...x...y...z...          # body of definition

    As before, you can change the order of the parameters

    without any need to change the body of the definition.

    But a call would look quite different: instead of relying

    on the order of the formal parameters, use their names

    as assignment statements, and make the assignments

    in any order. Hence any of the following would be OK

    as a call:

    foo(x=a; y=b; z=c)

    foo(y=b; z=c; x=a)

    foo(z=c; y=b; x=a)

    and so forth, a total of six possible combinations. All such

    calls would be equivalent. To summarise: body and call

    are done by using the names of the formal parameters.

    My understanding is that there are some languages which

    allow this kind of notation (Common Lisp ?, Ada ?) but

    I cannot remember any details --- anyone?? But as far

    as I know these languages use standard positional notation

    by default and allow this other notation only as a

    convenient variation. I have never heard of a language

    in which this way of calling is standard. Anyone??

    BEGIN COMMENT:

    These languages can allow default parameters, and

    definitions would look like this:

    DEFINE foo(x=1,y=0,z=5)        # head of definition

       = ...x...y...z...          # body of definition

    Calls can then omit giving a value to a particular formal

    parameter, in which case the default is used. Example:

    foo(x=42,z=3)   is  equivalent to foo(z=3,x=42,y=0)

    In Unix just about all of the utilities have many parameters

    which default to sensible values. Consequently casual

    users rarely need to know about them, but they

    are there to be modified if one needs it.

    END COMMENT

    So, we seem to have three possiblities:

    (1) bodies and calls rely on position

    (2) bodies rely on names, calls rely on position

    (3) bodies and calls rely on names

    Nice to know that concatenative languages are pure,

    isn¹t it. I thought this grouping of classes of languages

    might be of interest to other language smiths.

      - Manfred

    [Non-text portions of this message have been removed]

## rahul — 2007-09-07 09:07:55

    |On 9/7/07, Manfred Von Thun <m.vonthun@...> wrote:

    |...

    |But as far

    |as I know these languages use standard positional notation

    |by default and allow this other notation only as a

    |convenient variation. I have never heard of a language

    |in which this way of calling is standard. Anyone??

    SmallTalk? (and its descendants - ObjectiveC and ruby)

    though in ruby this is not the default.

    (the unix model of options, being the other, but it is not an enforced

    standard.)

    a SmallTalk example.

    ======================================

    multiply: i1 with: i2 and: i3

        "pointless multiply"

        | mul |

        mul := i1 * i2 * i3.

        ^mul

    ======================================

    Usage:

     >multiply 3 with:2 and: 5

     =30

    SmallTalk is also pure in its other aspects (much more than any of its

    descendants). ie: the control structures are built on top of this

    model.

## John Cowan — 2007-09-07 14:32:40

    Manfred Von Thun scripsit:

     > My understanding is that there are some languages which

    > allow this kind of notation (Common Lisp ?, Ada ?) but

    > I cannot remember any details --- anyone??

     Common Lisp (as well as some other Lisps such as DSSSL and Dylan)

    does indeed allow keyword arguments.  They must physically follow

    the positional arguments (if any) both in declarations and in calls.

    It is also possible to capture unknown keyword arguments for analysis

    at runtime.

    In certain domains keyword arguments are used by default.  For example,

    CL object constructors are normally keyword-based: you specify the

    fields of a class by name, and the default constructor will accept

    keyword arguments that initialize the fields.  (It's also possible to

    write non-default constructors that work like ordinary functions, by

    order of arguments -- these are known as BOA constructors.)

    Python has a unified model: parameters are declared by name, and calls

    may use keywords, but non-keyworded arguments are assigned positionally.

    However, in calls non-keyword arguments must precede keyword ones.

    Again, it is possible to capture unknown keyword arguments.

    Ada also has a unified model, but there are no constraints on ordering

    in calls, and there is no provision for unknown keywords.  Fortran 90

    and 95 also use this model.

    Lua provides modest syntactic sugar for keyword-only calls: this is

    declared as a single argument representing a table mapping keywords

    to their values, so all analysis must be done at run time.  In Perl,

    there is no special sugar, but passing a hash is common.

    Algol 60 allowed calls of the form:

    	multiply(x) by: (y)

    but this meant the same as "multiply(x, y)" and the keywords had no

    significance to the compiler.

    Smalltalk is keyword-only, as has been pointed out, except in the cases of

    unary operators (postfix) and binary operators (infix).  Binary operators

    are syntactically restricted to use symbol characters only.

    --

    John Cowan    http://ccil.org/~cowan    cowan@...

    SAXParserFactory [is] a hideous, evil monstrosity of a class that should

    be hung, shot, beheaded, drawn and quartered, burned at the stake,

    buried in unconsecrated ground, dug up, cremated, and the ashes tossed

    in the Tiber while the complete cast of Wicked sings "Ding dong, the

    witch is dead."  --Elliotte Rusty Harold on xml-dev

## Rodney D Price — 2007-09-07 17:11:56

    This classification confuses me a bit.  Are we talking about compile

    time

    or run time?  There are lots of evaluation strategies that occur at

    run time;

    see http://en.wikipedia.org/wiki/Call_by_name for a nice summary.  Given

    that the code, whether written out as function calls with parameters

    called

    out by name or by position, compiles to one of the run time behaviors

    listed in the article above, what difference does it make whether the

    syntax

    calls out the parameters by name or by position?  That syntax

    question is

    independent of the semantics question about evaluation strategies.

    So which is it?  Syntax or semantics?

    -Rod

     On Sep 7, 2007, at 8:32 AM, John Cowan wrote:

    > Manfred Von Thun scripsit:

    >

    > > My understanding is that there are some languages which

    > > allow this kind of notation (Common Lisp ?, Ada ?) but

    > > I cannot remember any details --- anyone??

    >

    > Common Lisp (as well as some other Lisps such as DSSSL and Dylan)

    > does indeed allow keyword arguments. They must physically follow

    > the positional arguments (if any) both in declarations and in calls.

    > It is also possible to capture unknown keyword arguments for analysis

    > at runtime.

    >

    > In certain domains keyword arguments are used by default. For example,

    > CL object constructors are normally keyword-based: you specify the

    > fields of a class by name, and the default constructor will accept

    > keyword arguments that initialize the fields. (It's also possible to

    > write non-default constructors that work like ordinary functions, by

    > order of arguments -- these are known as BOA constructors.)

    >

    > Python has a unified model: parameters are declared by name, and calls

    > may use keywords, but non-keyworded arguments are assigned

    > positionally.

    > However, in calls non-keyword arguments must precede keyword ones.

    > Again, it is possible to capture unknown keyword arguments.

    >

    > Ada also has a unified model, but there are no constraints on ordering

    > in calls, and there is no provision for unknown keywords. Fortran 90

    > and 95 also use this model.

    >

    > Lua provides modest syntactic sugar for keyword-only calls: this is

    > declared as a single argument representing a table mapping keywords

    > to their values, so all analysis must be done at run time. In Perl,

    > there is no special sugar, but passing a hash is common.

    >

    > Algol 60 allowed calls of the form:

    >

    > multiply(x) by: (y)

    >

    > but this meant the same as "multiply(x, y)" and the keywords had no

    > significance to the compiler.

    >

    > Smalltalk is keyword-only, as has been pointed out, except in the

    > cases of

    > unary operators (postfix) and binary operators (infix). Binary

    > operators

    > are syntactically restricted to use symbol characters only.

    >

    > --

    > John Cowan http://ccil.org/~cowan cowan@...

    > SAXParserFactory [is] a hideous, evil monstrosity of a class that

    > should

    > be hung, shot, beheaded, drawn and quartered, burned at the stake,

    > buried in unconsecrated ground, dug up, cremated, and the ashes tossed

    > in the Tiber while the complete cast of Wicked sings "Ding dong, the

    > witch is dead." --Elliotte Rusty Harold on xml-dev

    >

    >

    [Non-text portions of this message have been removed]

## William Tanksley, Jr — 2007-09-07 18:05:46

    Rodney D Price <rodprice@...> wrote:

     > So which is it?  Syntax or semantics?

     Both. It's about mapping syntax onto semantics. That's what a

    programming language does.

    I do agree with you that I'm not sure about the significance of this.

    The actual difference is limited entirely to the function call

    itself... That's a tiny part of a language.

    BTW, I'd say that as much as I like Smalltalk selectors, they don't

    qualify for this: they can't be used out of order, and in fact they're

    part of the method name, not the parameters.

     > -Rod

     -Billy

## Christopher Diggins — 2007-09-07 18:19:04

    It is possible in C++ with library support:

    http://www.boost.org/libs/parameter/doc/html/index.html

     On 9/7/07, Manfred Von Thun <m.vonthun@...> wrote:

    >

    >   For a long time I have been interested in the difference

    > between the standard kind of lambda calculus languages

    > and the concatenative languages. Only recently did it

    > occur to me that there is a third class which has been around

    > for some time. The three differ in how they treat actual

    > and formal parameters in definitions of functions and in

    > calls of functions. At one extreme are the concatenative

    > languages, at the other extreme those in the third class.

    > The standard lambda calculus languages are half way

    > between these two extremes.

    >

    > Most programming languages belong in the class of

    > lambda calculus languages. Definitions look more or

    > less like this:

    >

    > DEFINE foo(x,y,z) # head of definition

    > = ...x...y...z... # body of definition

    >

    > So there is a list of formal parameters (x,y,z) in the

    > head, and an expression ...x...y...z... which is the body.

    > In the body each of the formal parameters occurs one

    > or more times, or even not at all. The various occurrences

    > can be in any order. (This is one of the strengths of

    > lambda calculus notation.) Once you have written the

    > entire definition, you can change your mind about the

    > parameter list: you can change it to (y,z,x) and there

    > is no need to change the body in any way. In a call

    > to the function, foo(a,b,c), with actual parameters (a,b,c)

    > the values of the actual parameters are given to the

    > corresponding formal parameters. Of course the effect

    > of the call depends on whether the original definition with

    > (x,y,z) or the revised definition with (y,z,x) is in force.

    > The order of the actual parameters is taken to match

    > the order of the formal parameters. To summarise:

    > In the body the formal parameters are used as names,

    > irrespective of their order in the parameter list;

    > in a call the order of the actuals and the formals are

    > the same, irrespective of the names of the formals.

    >

    > In concatenative languages there are no formal parameter

    > lists. Definitions look like this:

    >

    > DEFINE foo # head of definition

    > = ...dup...swap... pop... # body of definition

    >

    > Instead of being able to refer to the actual parameters

    > by the name of the corresponding formal parameter,

    > it is now necessary to take the actual parameters as

    > they are on the stack, and do some shuffling to get

    > everything right in the body. Once you have written the

    > entire definition, you cannot just change the parameter

    > list because there isn¹t one. You also have to change the body of

    > the definition. In a call the order of the actual parameters

    > on the stack has to be in the order in which the body

    > of the definition expects them. To summarise:

    > In the body of the definition there is an expected order

    > of the actual parameters on the stack; in a call

    > the actual parameters have to be in the in the order

    > in which the body expects them.

    >

    > So at the one extreme we can have the concatenative

    > method: there are no names, body and call

    > are done by order (on the stack). In the middle we have the

    > standard lambda calculus notation: there are names

    > which are used in the body, but calls use positions

    > that match the order of the formals in the parameter

    > list. At the other extreme there should be languages

    > which do not use order at all but rely on names both

    > in the body and in calls. Are there such beasts?

    >

    > In such languages definitions would again look as in

    > lambda calculus languages:

    >

    > DEFINE foo(x,y,z) # head of definition

    > = ...x...y...z... # body of definition

    >

    > As before, you can change the order of the parameters

    > without any need to change the body of the definition.

    > But a call would look quite different: instead of relying

    > on the order of the formal parameters, use their names

    > as assignment statements, and make the assignments

    > in any order. Hence any of the following would be OK

    > as a call:

    >

    > foo(x=a; y=b; z=c)

    > foo(y=b; z=c; x=a)

    > foo(z=c; y=b; x=a)

    >

    > and so forth, a total of six possible combinations. All such

    > calls would be equivalent. To summarise: body and call

    > are done by using the names of the formal parameters.

    > My understanding is that there are some languages which

    > allow this kind of notation (Common Lisp ?, Ada ?) but

    > I cannot remember any details --- anyone?? But as far

    > as I know these languages use standard positional notation

    > by default and allow this other notation only as a

    > convenient variation. I have never heard of a language

    > in which this way of calling is standard. Anyone??

    >

    > BEGIN COMMENT:

    > These languages can allow default parameters, and

    > definitions would look like this:

    >

    > DEFINE foo(x=1,y=0,z=5) # head of definition

    > = ...x...y...z... # body of definition

    >

    > Calls can then omit giving a value to a particular formal

    > parameter, in which case the default is used. Example:

    >

    > foo(x=42,z=3) is equivalent to foo(z=3,x=42,y=0)

    >

    > In Unix just about all of the utilities have many parameters

    > which default to sensible values. Consequently casual

    > users rarely need to know about them, but they

    > are there to be modified if one needs it.

    > END COMMENT

    >

    > So, we seem to have three possiblities:

    > (1) bodies and calls rely on position

    > (2) bodies rely on names, calls rely on position

    > (3) bodies and calls rely on names

    >

    > Nice to know that concatenative languages are pure,

    > isn¹t it. I thought this grouping of classes of languages

    > might be of interest to other language smiths.

    >

    > - Manfred

    >

    > [Non-text portions of this message have been removed]

    >

    >

    >

    [Non-text portions of this message have been removed]

## Stevan Apter — 2007-09-07 21:36:49

    off the top of my head, i can imagine a construct like this

    (i'm assuming iverson notation, in which the combinator is

    what he would call a conjunction):

    O is a combinator that takes a subset of a permutation

    of the names of the arguments of f (on the left) and a

    lambda containing those arguments (on the right), and

    returns a function which binds those arguments to values.

        f:{[a;b;c]a+b*c}

        f . 10 20 30

      610

        (`c`b`a O f) . 10 20 30

      230

    then, for example,

        (`c`a O f) . 10 20

    returns a function of one argument b in which c is bound to

    10 and a to 20.

    my first reaction is that i shouldn't know anything about f

    except the mapping of arguments to result, least of all what

    names the programmer chose for the arguments.  my second

    reaction is that every function should be documented, and

    that it might be thought that well-chosen argument names

    should be exposed to the user of the function.

    what about primitives, like -?  i suppose the language could

    just say that every primitive of one argument names its

    argument x, of two x and y, &c.  then

        2(`y`x O -)3

      1

    it's not hard to write O in k.

     ----- Original Message -----

    From: "Manfred Von Thun" <m.vonthun@...>

    To: <concatenative@yahoogroups.com>

    Sent: Friday, September 07, 2007 3:06 AM

    Subject: [stack] Parameters: ordered versus named

    For a long time I have been interested in the difference

    between the standard kind of lambda calculus languages

    and the concatenative languages. Only recently did it

    occur to me that there is a third class which has been around

    for some time. The three differ in how they treat actual

    and formal parameters in definitions of functions and in

    calls of functions. At one extreme are the concatenative

    languages, at the other extreme those in the third class.

    The standard lambda calculus languages are half way

    between these two extremes.

    Most programming languages belong in the class of

    lambda calculus languages. Definitions look more or

    less like this:

    DEFINE foo(x,y,z)        # head of definition

       = ...x...y...z...          # body of definition

    So there is a list of formal parameters (x,y,z) in the

    head, and an expression ...x...y...z... which is the body.

    In the body each of the formal parameters occurs one

    or more times, or even not at all. The various occurrences

    can be in any order. (This is one of the strengths of

    lambda calculus notation.) Once you have written the

    entire definition, you can change your mind about the

    parameter list: you can change it to (y,z,x) and there

    is no need to change the body in any way. In a call

    to the function, foo(a,b,c), with actual parameters (a,b,c)

    the values of the actual parameters are given to the

    corresponding formal parameters. Of course the effect

    of the call depends on whether the original definition with

    (x,y,z) or the revised definition with (y,z,x)  is in force.

    The order of the actual parameters is taken to match

    the order of the formal parameters. To summarise:

    In the body the formal parameters are used as names,

    irrespective of their order in the parameter list;

    in a call the order of the actuals and the formals are

    the same, irrespective of the names of the formals.

    In concatenative languages there are no formal parameter

    lists. Definitions look like this:

    DEFINE foo                        # head of definition

      =  ...dup...swap... pop...   # body of definition

    Instead of  being able to refer to the actual parameters

    by the name of the corresponding formal parameter,

    it is now necessary to take the actual parameters as

    they are on the stack, and do some shuffling to get

    everything right in the body. Once you have written the

    entire definition, you cannot just change the parameter

    list because there isn¹t one. You also have to change the body of

    the definition. In a call the order of the actual parameters

    on the stack has to be in the order in which the body

    of the definition expects them. To summarise:

    In the body of the definition there is an expected order

    of the  actual parameters on the stack; in a call

    the actual parameters have to be in the in the order

    in which the body expects them.

    So at the one extreme we can have the concatenative

    method: there are no names, body and call

    are done by order (on the stack). In the middle we have the

    standard lambda calculus notation: there are names

    which are used in the body, but calls use positions

    that match the order of the formals in the parameter

    list. At the other extreme there should be languages

    which do not use  order at all but rely on names both

    in the body and in calls. Are there such beasts?

    In such languages definitions would again look as in

    lambda calculus languages:

    DEFINE foo(x,y,z)        # head of definition

       = ...x...y...z...          # body of definition

    As before, you can change the order of the parameters

    without any need to change the body of the definition.

    But a call would look quite different: instead of relying

    on the order of the formal parameters, use their names

    as assignment statements, and make the assignments

    in any order. Hence any of the following would be OK

    as a call:

    foo(x=a; y=b; z=c)

    foo(y=b; z=c; x=a)

    foo(z=c; y=b; x=a)

    and so forth, a total of six possible combinations. All such

    calls would be equivalent. To summarise: body and call

    are done by using the names of the formal parameters.

    My understanding is that there are some languages which

    allow this kind of notation (Common Lisp ?, Ada ?) but

    I cannot remember any details --- anyone?? But as far

    as I know these languages use standard positional notation

    by default and allow this other notation only as a

    convenient variation. I have never heard of a language

    in which this way of calling is standard. Anyone??

    BEGIN COMMENT:

    These languages can allow default parameters, and

    definitions would look like this:

    DEFINE foo(x=1,y=0,z=5)        # head of definition

       = ...x...y...z...          # body of definition

    Calls can then omit giving a value to a particular formal

    parameter, in which case the default is used. Example:

    foo(x=42,z=3)   is  equivalent to foo(z=3,x=42,y=0)

    In Unix just about all of the utilities have many parameters

    which default to sensible values. Consequently casual

    users rarely need to know about them, but they

    are there to be modified if one needs it.

    END COMMENT

    So, we seem to have three possiblities:

    (1) bodies and calls rely on position

    (2) bodies rely on names, calls rely on position

    (3) bodies and calls rely on names

    Nice to know that concatenative languages are pure,

    isn¹t it. I thought this grouping of classes of languages

    might be of interest to other language smiths.

      - Manfred

    [Non-text portions of this message have been removed]

## rahul — 2007-09-07 21:53:27

    [William Tanksley, Jr <wtanksleyjr@...>]:

     > BTW, I'd say that as much as I like Smalltalk selectors, they don't

    > qualify for this: they can't be used out of order, and in fact they're

    > part of the method name, not the parameters.

     True, SmallTalk does not fit the bill - (had missed it.) though it seems

    an arbitrary restriction for SmallTalk since it is enforcing the keys.

## John Cowan — 2007-09-07 23:11:44

    rahul scripsit:

     > True, SmallTalk does not fit the bill - (had missed it.) though it seems

    > an arbitrary restriction for SmallTalk since it is enforcing the keys.

     You can override this if you want by defining withFoo:withBar: to mean

    the same as withBar:withFoo:, and such a feature could be integrated

    into the Smalltalk code browser if it seemed useful.  However, method

    overriding becomes tricky.

    --

    What asininity could I have uttered     John Cowan <cowan@...>

    that they applaud me thus?              http://www.ccil.org/~cowan

            --Phocion, Greek orator

## kuwabatake — 2007-09-08 00:32:14

    --- In concatenative@yahoogroups.com, Manfred Von Thun <m.vonthun@...>

    wrote:

     > foo(x=a; y=b; z=c)

    > foo(y=b; z=c; x=a)

    > foo(z=c; y=b; x=a)

     Huh. This is very interesting.

    One thing that springs to mind is that some parts of assembly

    languages behave like this, using registers to hold arguments:

    MOVE x <- a

    MOVE y <- b

    MOVE z <- c

    CALL foo

    ..where the first three lines can be permuted any which way.

    In an even purer version of this idea, expressions might not be

    allowed on the right side of assignments (another `order matters'

    `anonymous temp value' kind of technique) so instead of

    MOVE x <- y + bar(1)

    you would need to write

    MOVE barIn <- 1

    CALL bar

    MOVE +In1 <- y

    MOVE +In2 <- barOut

    CALL +

    MOVE x <- +Out

    ~Daniel

## William Tanksley, Jr — 2007-09-08 00:47:28

    kuwabatake <kuwabatake@...> wrote:

     > One thing that springs to mind is that some parts of assembly

    > languages behave like this, using registers to hold arguments:

     That's true, but it doesn't fit this model, because this model is

    about function calls, while those assignments have global effect.

     > ~Daniel

     -Billy

## Don Groves — 2007-09-08 02:11:37

    On Sep 7, 2007, at 19:06 , Manfred Von Thun wrote:

    ...

    > In concatenative languages there are no formal parameter

    > lists. Definitions look like this:

    >

    > DEFINE foo                        # head of definition

    >   =  ...dup...swap... pop...   # body of definition

    >

    > Instead of  being able to refer to the actual parameters

    > by the name of the corresponding formal parameter,

    > it is now necessary to take the actual parameters as

    > they are on the stack, and do some shuffling to get

    > everything right in the body. Once you have written the

    > entire definition, you cannot just change the parameter

    > list because there isn’t one. You also have to change the body of

    > the definition.

    I believe it was sci-fi writer Robert Heinlein who coined the phrase,

    "There

    ain't no such thing as a free lunch." The price we pay for the

    simplicity of

    concatenative syntax is the amount of parameter checking we must do at

    run-time which other languages to at compile-time.

    The parametric details in DEFINE foo (int x, char y,void *z), etc.

    are explicit

    whereas they are implicit in DEFINE foo = ...dup...swap, etc. To give

    a truly

    realistic picture of a concatenative foo, shouldn't we also give its

    stack effect,

    as in this for map:

    [a b ...] [f] map ==> [af bf ...] (where xf denotes the application

    of f to x)

    This makes it explicit that map must ensure the stack contains at

    least two

    parameters, that they are lists, and that xf makes sense for each x.

    One beauty of concatenative notation is the hiding of information

    such as

    described here, but we all know that hidden info must be dealt with

    eventually,

    unless the language is so primitive as to not care about these matters.

    --

    Don Groves

## William Tanksley, Jr — 2007-09-08 03:03:13

    Don Groves <dgroves@...> wrote:

     > I believe it was sci-fi writer Robert Heinlein who coined the phrase,

    > "There ain't no such thing as a free lunch."

     Possibly -- that's where I read it too.

     > The price we pay for the

    > simplicity of

    > concatenative syntax is the amount of parameter checking we must do at

    > run-time which other languages to at compile-time.

     Not true. Concatenative semantics don't require parameter passing, so

    there is nothing to do to parameters at runtime. There are, of course,

    other prices we must pay; but that's not one of them.

     > The parametric details in DEFINE foo (int x, char y,void *z), etc.

    > are explicit

    > whereas they are implicit in DEFINE foo = ...dup...swap, etc. To give

     There are concatenative languages that require explicit type

    specifications; Cat, Factor, and strongForth are three very different

    examples. In general, most strongly statically typed concatenative

    languages have defined a syntax something like this

    "DEFINE foo ( int char pointer-to-void -- int )". The syntax is

    similar to Forth's classical stack diagrams.

     > a truly

    > realistic picture of a concatenative foo, shouldn't we also give its

    > stack effect, as in this for map:

    > [a b ...] [f] map ==> [af bf ...] (where xf denotes the application

    > of f to x)

     We definitely should -- it's a good habit, even if the language you're

    using doesn't use static types, you should put that in a comment.

     > One beauty of concatenative notation is the hiding of information

    > such as described here,

     Nothing's hidden.

     > but we all know that hidden info must be dealt with

    > eventually,

    > unless the language is so primitive as to not care about these matters.

     But this is true. (Well, mostly -- Cat does type inferencing so you

    don't always have to describe the types, while Enchilada defines its

    semantics so that all its types are compatible.)

     > Don Groves

     -Billy

## Joe Bowbeer — 2007-09-08 03:38:13

    On 9/7/07, Manfred Von Thun <m.vonthun@...> wrote:

     >

    > In such languages definitions would again look as in

    > lambda calculus languages:

    >

    > DEFINE foo(x,y,z)        # head of definition

    >    = ...x...y...z...          # body of definition

    >

    > As before, you can change the order of the parameters

    > without any need to change the body of the definition.

    > But a call would look quite different: instead of relying

    > on the order of the formal parameters, use their names

    > as assignment statements, and make the assignments

    > in any order. Hence any of the following would be OK

    > as a call:

    >

    > foo(x=a; y=b; z=c)

    > foo(y=b; z=c; x=a)

    > foo(z=c; y=b; x=a)

    >

     Python has optional keyword arguments with default values:

     http://docs.python.org/tut/node6.html#SECTION006720000000000000000

    E.g., eggs(x=a, y=b, z=c)

    See also:

     http://en.wikipedia.org/wiki/Named_parameter

    --Joe

    PS - This also reminds me of dynamic binding in LISP, where you could

    do something degenerative like:

    (let ((x a) (y b) (z c)) foo())

## Don Groves — 2007-09-08 04:39:15

    On Sep 7, 2007, at 19:03 , William Tanksley, Jr wrote:

     > Don Groves <dgroves@...> wrote:

    >

    >> The price we pay for the

    >> simplicity of

    >> concatenative syntax is the amount of parameter checking we must

    >> do at

    >> run-time which other languages to at compile-time.

    >

    > Not true. Concatenative semantics don't require parameter passing, so

    > there is nothing to do to parameters at runtime. There are, of course,

    > other prices we must pay; but that's not one of them.

     While it's true there's nothing to do "to" parameters, we still must

    check for

    their existence, yes? If you want to trap stack underflow before it

    happens,

    for example. And what do we do when a user enters a string and a number

    then types "/"?

     >> One beauty of concatenative notation is the hiding of information

    >> such as described here,

    >

    > Nothing's hidden.

    >

    >> but we all know that hidden info must be dealt with

    >> eventually,

    >> unless the language is so primitive as to not care about these

    >> matters.

    >

    > But this is true. (Well, mostly -- Cat does type inferencing so you

    > don't always have to describe the types, while Enchilada defines its

    > semantics so that all its types are compatible.)

     Afraid I'm confused here. You say nothing is hidden, yet you agree (at

    least partially) with my next statement.

    As always, any corrections or advice is greatly appreciated. I'm here to

    learn! So don't take any questions or statements on my part as anything

    other than trying to understand ;-)

     > -Billy

     --

    Don Groves

    PS - Anyone know why my posts are so jagged looking? When I send

    them, they are evenly formatted. Could it be caused by my email program,

    mail.app on OS X?

## Christopher Diggins — 2007-09-08 15:55:02

    On 9/8/07, Don Groves <dgroves@...> wrote:

     >

    > On Sep 7, 2007, at 19:03 , William Tanksley, Jr wrote:

    >

    > > Don Groves <dgroves@...> wrote:

    > >

    > >> The price we pay for the

    > >> simplicity of

    > >> concatenative syntax is the amount of parameter checking we must

    > >> do at

    > >> run-time which other languages to at compile-time.

    > >

    > > Not true. Concatenative semantics don't require parameter passing, so

    > > there is nothing to do to parameters at runtime. There are, of course,

    > > other prices we must pay; but that's not one of them.

    >

    > While it's true there's nothing to do "to" parameters, we still must

    > check for

    > their existence, yes? If you want to trap stack underflow before it

    > happens,

    > for example. And what do we do when a user enters a string and a number

    > then types "/"?

     This is where a static type system with type inference comes in

    useful. You can do all of this without annotation or runtime checks in

    the compiler. See Cat (http://www.cat-language.com).

    - Christopher

## William Tanksley, Jr — 2007-09-08 17:18:43

    Don Groves <dgroves@...> wrote:

     > William Tanksley, Jr wrote:

    > > Don Groves <dgroves@...> wrote:

    > >> The price we pay for the

    > >> simplicity of

    > >> concatenative syntax is the amount of parameter checking we must

    > >> do at run-time which other languages to at compile-time.

    > > Not true. Concatenative semantics don't require parameter passing, so

    > > there is nothing to do to parameters at runtime. There are, of course,

    > > other prices we must pay; but that's not one of them.

    > While it's true there's nothing to do "to" parameters, we still must

    > check for

    > their existence, yes? If you want to trap stack underflow before it

    > happens,

    > for example. And what do we do when a user enters a string and a number

    > then types "/"?

     If you want to stop it before it happens, you're going to do static

    analysis. That can be done in a concatenative language using a

    linear-time algorithm plus some annotations (and provide typechecking

    as a bonus), or it can be done using type inference (using the same

    algorithms that many modern functional languages use). StrongForth

    uses the former; Cat uses the latter.

     > >> One beauty of concatenative notation is the hiding of information

    > >> such as described here,

    > > Nothing's hidden.

    > >> but we all know that hidden info must be dealt with

    > >> eventually,

    > >> unless the language is so primitive as to not care about these

    > >> matters.

    > > But this is true. (Well, mostly -- Cat does type inferencing so you

    > > don't always have to describe the types, while Enchilada defines its

    > > semantics so that all its types are compatible.)

    > Afraid I'm confused here. You say nothing is hidden, yet you agree (at

    > least partially) with my next statement.

     That's because concatenative languages, in general, don't hide

    information; but I agree that if you do hide information, you have to

    pay the price. I was also illustrating that the price to be paid

    wasn't what you thought it was -- Cat pays the price not by being more

    primitive, but by having a sophisticated static type inference system

    (which can, of course, slow some things down, but is undeniably NOT

    primitive and is a desirable feature for many purposes).

     > Don Groves

     -Billy

## Christopher Diggins — 2007-09-08 18:08:29

    > That's because concatenative languages, in general, don't hide

    > information; but I agree that if you do hide information, you have to

    > pay the price. I was also illustrating that the price to be paid

    > wasn't what you thought it was -- Cat pays the price not by being more

    > primitive, but by having a sophisticated static type inference system

    > (which can, of course, slow some things down, but is undeniably NOT

    > primitive and is a desirable feature for many purposes).

     A static type inference system certainly slows down compilation, but

    all things given equal should speed up runtime execution because it

    removes the need for runtime checks. Furthermore a static type

    inference system makes it easier to optimize code, because you can

    take advantage of properties that you have elucidated about the

    runtime behaviour. However, every implementation is different.

    A simple static type system has the disadvantage that typed terms will

    disallow unbalanced stacks. You can't say things like:

    if_tuesday [1] [1 2] ifte // does stack have one or two elements?

    - Christopher

## William Tanksley, Jr — 2007-09-08 18:24:30

    Christopher Diggins <cdiggins@...> wrote:

     > A simple static type system has the disadvantage that typed terms will

    > disallow unbalanced stacks. You can't say things like:

    > if_tuesday [1] [1 2] ifte // does stack have one or two elements?

     Correct. I hadn't intended to imply that static typing was bad; I was

    just conceding his point that there are costs (no free lunch).

     > - Christopher

     -Billy

## Don Groves — 2007-09-08 19:36:46

    On Sep 8, 2007, at 19:55 , Christopher Diggins wrote:

     > On 9/8/07, Don Groves <dgroves@...> wrote:

    >>

    >> On Sep 7, 2007, at 19:03 , William Tanksley, Jr wrote:

    >>

    >>> Don Groves <dgroves@...> wrote:

    >>>

    >>>> The price we pay for the

    >>>> simplicity of

    >>>> concatenative syntax is the amount of parameter checking we must

    >>>> do at

    >>>> run-time which other languages to at compile-time.

    >>>

    >>> Not true. Concatenative semantics don't require parameter

    >>> passing, so

    >>> there is nothing to do to parameters at runtime. There are, of

    >>> course,

    >>> other prices we must pay; but that's not one of them.

    >>

    >> While it's true there's nothing to do "to" parameters, we still must

    >> check for

    >> their existence, yes? If you want to trap stack underflow before it

    >> happens,

    >> for example. And what do we do when a user enters a string and a

    >> number

    >> then types "/"?

    >

    > This is where a static type system with type inference comes in

    > useful. You can do all of this without annotation or runtime checks in

    > the compiler. See Cat (http://www.cat-language.com).

    >

    > - Christopher

     Thanks, I'll study what you've done with Cat.

    --

    Don

## Don Groves — 2007-09-08 19:41:32

    On Sep 8, 2007, at 19:18 , William Tanksley, Jr wrote:

     > Don Groves <dgroves@...> wrote:

    >> William Tanksley, Jr wrote:

    >>> Don Groves <dgroves@...> wrote:

    >>>> The price we pay for the

    >>>> simplicity of

    >>>> concatenative syntax is the amount of parameter checking we must

    >>>> do at run-time which other languages to at compile-time.

    >

    >>> Not true. Concatenative semantics don't require parameter

    >>> passing, so

    >>> there is nothing to do to parameters at runtime. There are, of

    >>> course,

    >>> other prices we must pay; but that's not one of them.

    >

    >> While it's true there's nothing to do "to" parameters, we still must

    >> check for

    >> their existence, yes? If you want to trap stack underflow before it

    >> happens,

    >> for example. And what do we do when a user enters a string and a

    >> number

    >> then types "/"?

    >

    > If you want to stop it before it happens, you're going to do static

    > analysis. That can be done in a concatenative language using a

    > linear-time algorithm plus some annotations (and provide typechecking

    > as a bonus), or it can be done using type inference (using the same

    > algorithms that many modern functional languages use). StrongForth

    > uses the former; Cat uses the latter

     Just before falling asleep last night, it hit me what has caused my

    confusion

    about all this: I've been thinking of the interactive user, not

    running an already

    compiled program. Of course, when a program has been fed through the

    interpreter without errors, stack- and type checking is no longer

    necessary.

    Thanks for you help!

     >>>> One beauty of concatenative notation is the hiding of information

    >>>> such as described here,

    >

    >>> Nothing's hidden.

    >

    >>>> but we all know that hidden info must be dealt with

    >>>> eventually,

    >>>> unless the language is so primitive as to not care about these

    >>>> matters.

    >

    >>> But this is true. (Well, mostly -- Cat does type inferencing so you

    >>> don't always have to describe the types, while Enchilada defines its

    >>> semantics so that all its types are compatible.)

    >

    >> Afraid I'm confused here. You say nothing is hidden, yet you agree

    >> (at

    >> least partially) with my next statement.

    >

    > That's because concatenative languages, in general, don't hide

    > information; but I agree that if you do hide information, you have to

    > pay the price. I was also illustrating that the price to be paid

    > wasn't what you thought it was -- Cat pays the price not by being more

    > primitive, but by having a sophisticated static type inference system

    > (which can, of course, slow some things down, but is undeniably NOT

    > primitive and is a desirable feature for many purposes).

     Agreed!

    --

    Don

## Don Groves — 2007-09-08 19:52:55

    On Sep 8, 2007, at 19:08 , Christopher Diggins wrote:

     >> That's because concatenative languages, in general, don't hide

    >> information; but I agree that if you do hide information, you have to

    >> pay the price. I was also illustrating that the price to be paid

    >> wasn't what you thought it was -- Cat pays the price not by being

    >> more

    >> primitive, but by having a sophisticated static type inference system

    >> (which can, of course, slow some things down, but is undeniably NOT

    >> primitive and is a desirable feature for many purposes).

    >

    > A static type inference system certainly slows down compilation, but

    > all things given equal should speed up runtime execution because it

    > removes the need for runtime checks. Furthermore a static type

    > inference system makes it easier to optimize code, because you can

    > take advantage of properties that you have elucidated about the

    > runtime behaviour. However, every implementation is different.

    >

    > A simple static type system has the disadvantage that typed terms will

    > disallow unbalanced stacks. You can't say things like:

    >

    > if_tuesday [1] [1 2] ifte // does stack have one or two elements?

    >

    > - Christopher

     Clearly, I need to learn more about type systems. Here's the Catenate

    code implementing ifte, what kind of type system does this represent?

    int ifte_() {	 // [f1] [f2] T|F ifte => (results of f1 if T)

    		 //          		   => (results of f2 if F)

    	if (depth < 3) {

    		StackError("ifte", "underflow");

    		return OK;

    		}

    	if (!islist(Y)) {

    		printf("\nifte: Y must be a list\n");

    		return UNKNOWN;

    		}

    	if (!islist(Z)) {

    		printf("\nifte: Z must be a list\n");

    		return UNKNOWN;

    		}

    	if (X == TRUE) {				// T|F = true?

    		drop_(); drop_();			// (y) drop T and 'else' part (f2)

    		id_();					//     execute 'then' part

    		}

    	else {					// (n) false

    		drop_(); swap_(); drop_();	//     drop F and 'then' part (f1)

    		id_();					//     execute 'else' part

    		}

    	return OK;

    	}

    --

    Don

## Christopher Diggins — 2007-09-08 20:42:12

    On 9/8/07, Don Groves <dgroves@...> wrote:

     > On Sep 8, 2007, at 19:08 , Christopher Diggins wrote:

    >

    > >> That's because concatenative languages, in general, don't hide

    > >> information; but I agree that if you do hide information, you have to

    > >> pay the price. I was also illustrating that the price to be paid

    > >> wasn't what you thought it was -- Cat pays the price not by being

    > >> more

    > >> primitive, but by having a sophisticated static type inference system

    > >> (which can, of course, slow some things down, but is undeniably NOT

    > >> primitive and is a desirable feature for many purposes).

    > >

    > > A static type inference system certainly slows down compilation, but

    > > all things given equal should speed up runtime execution because it

    > > removes the need for runtime checks. Furthermore a static type

    > > inference system makes it easier to optimize code, because you can

    > > take advantage of properties that you have elucidated about the

    > > runtime behaviour. However, every implementation is different.

    > >

    > > A simple static type system has the disadvantage that typed terms will

    > > disallow unbalanced stacks. You can't say things like:

    > >

    > > if_tuesday [1] [1 2] ifte // does stack have one or two elements?

    > >

    > > - Christopher

    >

    > Clearly, I need to learn more about type systems. Here's the Catenate

    > code implementing ifte, what kind of type system does this represent?

    >

    > int ifte_() { // [f1] [f2] T|F ifte => (results of f1 if T)

    > // => (results of f2 if F)

    > if (depth < 3) {

    > StackError("ifte", "underflow");

    > return OK;

    > }

    > if (!islist(Y)) {

    > printf("\nifte: Y must be a list\n");

    > return UNKNOWN;

    > }

    > if (!islist(Z)) {

    > printf("\nifte: Z must be a list\n");

    > return UNKNOWN;

    > }

    > if (X == TRUE) { // T|F = true?

    > drop_(); drop_(); // (y) drop T and 'else' part (f2)

    > id_(); // execute 'then' part

    > }

    > else { // (n) false

    > drop_(); swap_(); drop_(); // drop F and 'then' part (f1)

    > id_(); // execute 'else' part

    > }

    > return OK;

    > }

    > --

    > Don

     This is an example of a runtime checked language, also called a

    dynamically typed language, though some theorists object to the term

    dynamic typing. Personally I have no qualms with it.

    -D

## Christopher Diggins — 2007-09-08 20:44:46

    > Just before falling asleep last night, it hit me what has caused my

    > confusion

    > about all this: I've been thinking of the interactive user, not

    > running an already

    > compiled program. Of course, when a program has been fed through the

    > interpreter without errors, stack- and type checking is no longer

    > necessary.

    > Thanks for you help!

     An interpreter can still be statically typed. Each expression fed into

    the interpreter can be type-checked before it is run, and compared

    with the current stack configuration. AFAIK this is a property

    particular to languages with compositional type systems (e.g.

    statically typed concatenative languages!)

    -D

## Don Groves — 2007-09-09 01:47:20

    On Sep 8, 2007, at 19:44 , Christopher Diggins wrote:

     >> Just before falling asleep last night, it hit me what has caused my

    >> confusion

    >> about all this: I've been thinking of the interactive user, not

    >> running an already

    >> compiled program. Of course, when a program has been fed through the

    >> interpreter without errors, stack- and type checking is no longer

    >> necessary.

    >> Thanks for you help!

    >

    > An interpreter can still be statically typed. Each expression fed into

    > the interpreter can be type-checked before it is run, and compared

    > with the current stack configuration. AFAIK this is a property

    > particular to languages with compositional type systems (e.g.

    > statically typed concatenative languages!)

    >

    > -D

     Thanks for the info. In what ways does Cat's inferred type system

    differ?

    --

    Don

## Don Groves — 2007-09-09 01:52:02

    On Sep 8, 2007, at 19:42 , Christopher Diggins wrote:

     > On 9/8/07, Don Groves <dgroves@...> wrote:

    >> On Sep 8, 2007, at 19:08 , Christopher Diggins wrote:

    >>

    >>>> That's because concatenative languages, in general, don't hide

    >>>> information; but I agree that if you do hide information, you

    >>>> have to

    >>>> pay the price. I was also illustrating that the price to be paid

    >>>> wasn't what you thought it was -- Cat pays the price not by being

    >>>> more

    >>>> primitive, but by having a sophisticated static type inference

    >>>> system

    >>>> (which can, of course, slow some things down, but is undeniably NOT

    >>>> primitive and is a desirable feature for many purposes).

    >>>

    >>> A static type inference system certainly slows down compilation, but

    >>> all things given equal should speed up runtime execution because it

    >>> removes the need for runtime checks. Furthermore a static type

    >>> inference system makes it easier to optimize code, because you can

    >>> take advantage of properties that you have elucidated about the

    >>> runtime behaviour. However, every implementation is different.

    >>>

    >>> A simple static type system has the disadvantage that typed terms

    >>> will

    >>> disallow unbalanced stacks. You can't say things like:

    >>>

    >>> if_tuesday [1] [1 2] ifte // does stack have one or two elements?

    >>>

    >>> - Christopher

    >>

    >> Clearly, I need to learn more about type systems. Here's the Catenate

    >> code implementing ifte, what kind of type system does this represent?

    >>

    >> int ifte_() { // [f1] [f2] T|F ifte => (results of f1 if T)

    >> // => (results of f2 if F)

    >> if (depth < 3) {

    >> StackError("ifte", "underflow");

    >> return OK;

    >> }

    >> if (!islist(Y)) {

    >> printf("\nifte: Y must be a list\n");

    >> return UNKNOWN;

    >> }

    >> if (!islist(Z)) {

    >> printf("\nifte: Z must be a list\n");

    >> return UNKNOWN;

    >> }

    >> if (X == TRUE) { // T|F = true?

    >> drop_(); drop_(); // (y) drop T and 'else' part (f2)

    >> id_(); // execute 'then' part

    >> }

    >> else { // (n) false

    >> drop_(); swap_(); drop_(); // drop F and 'then' part (f1)

    >> id_(); // execute 'else' part

    >> }

    >> return OK;

    >> }

    >> --

    >> Don

    >

    > This is an example of a runtime checked language, also called a

    > dynamically typed language, though some theorists object to the term

    > dynamic typing. Personally I have no qualms with it.

    >

    > -D

     OK, that's what I thought it was. It seems dynamic typing means two

    things: (1) run-time type checking; and (2) data is typed --

    variables are

    not. Clearly (1) allows (2) but (2) is not required. Is this part of

    the source

    of disagreement over the name?

    --

    Don

## pml060912 — 2007-09-09 06:25:44

    --- In concatenative@yahoogroups.com, Manfred Von Thun

    <m.vonthun@...> wrote:

     >

    > For a long time I have been interested in the difference

    > between the standard kind of lambda calculus languages

    > and the concatenative languages. Only recently did it

    > occur to me that there is a third class which has been around

    > for some time. The three differ in how they treat actual

    > and formal parameters in definitions of functions and in

    > calls of functions. At one extreme are the concatenative

    > languages, at the other extreme those in the third class.

    > The standard lambda calculus languages are half way

    > between these two extremes.

     .

    .

    .

    At the other extreme there should be languages

     > which do not use  order at all but rely on names both

    > in the body and in calls. Are there such beasts?

    >

    > In such languages definitions would again look as in

    > lambda calculus languages:

    >

    > DEFINE foo(x,y,z)        # head of definition

    >    = ...x...y...z...          # body of definition

    >

    > As before, you can change the order of the parameters

    > without any need to change the body of the definition.

    > But a call would look quite different: instead of relying

    > on the order of the formal parameters, use their names

    > as assignment statements, and make the assignments

    > in any order. Hence any of the following would be OK

    > as a call:

    >

    > foo(x=a; y=b; z=c)

    > foo(y=b; z=c; x=a)

    > foo(z=c; y=b; x=a)

    >

    > and so forth, a total of six possible combinations. All such

    > calls would be equivalent. To summarise: body and call

    > are done by using the names of the formal parameters.

    > My understanding is that there are some languages which

    > allow this kind of notation (Common Lisp ?, Ada ?) but

    > I cannot remember any details --- anyone?? But as far

    > as I know these languages use standard positional notation

    > by default and allow this other notation only as a

    > convenient variation. I have never heard of a language

    > in which this way of calling is standard. Anyone??

     That looks like something I came across in P.J.Brown's "Writing

    Interactive Compilers and Interpreters", although I forget if he

    stated it explicitly or just implied it. In essence, he suggested

    handling parameters and local variables by a "don't care" method, in

    which they were really global variables like any other, only their

    values were stacked/reinitialised and then restored on call/return.

    Then the function call construct is little more than a subroutine

    that can return a value, and foo(x=a; y=b; z=c) is a macro for the

    pushing and popping of global variables x, y and z on either side of

    gosub foo. The function needs no special declaration, either.

    I actually looked into this approach for its smaller

    implementation "footprint" in two areas:-

    - extending awkward languages like Cobol so that they could

    comfortably support their own compilers (the released version would

    have had the extensions disabled); and

    - making user defined functions easy to implement in a spreadsheet.

    The latter relates to my musings on where to go next in paper

    exploring for Furphy, since a spreadsheet would make a comfortable

    programming interface for a functional programming language. PML.

## Christopher Diggins — 2007-09-09 14:12:18

    On 9/8/07, Don Groves <dgroves@...> wrote:

     > On Sep 8, 2007, at 19:44 , Christopher Diggins wrote:

    >

    > >> Just before falling asleep last night, it hit me what has caused my

    > >> confusion

    > >> about all this: I've been thinking of the interactive user, not

    > >> running an already

    > >> compiled program. Of course, when a program has been fed through the

    > >> interpreter without errors, stack- and type checking is no longer

    > >> necessary.

    > >> Thanks for you help!

    > >

    > > An interpreter can still be statically typed. Each expression fed into

    > > the interpreter can be type-checked before it is run, and compared

    > > with the current stack configuration. AFAIK this is a property

    > > particular to languages with compositional type systems (e.g.

    > > statically typed concatenative languages!)

    > >

    > > -D

    >

    > Thanks for the info. In what ways does Cat's inferred type system

    > differ?

    > --

     From what?

    -Christopher

## Christopher Diggins — 2007-09-09 14:23:19

    > > This is an example of a runtime checked language, also called a

    > > dynamically typed language, though some theorists object to the term

    > > dynamic typing. Personally I have no qualms with it.

    > >

    > > -D

    >

    > OK, that's what I thought it was. It seems dynamic typing means two

    > things: (1) run-time type checking; and (2) data is typed --

    > variables are

    > not. Clearly (1) allows (2) but (2) is not required.

    > Is this part of

    > the source

    > of disagreement over the name?

     I shouldn't speculate too much. I think the disagreement is

    artificial. There were some threads on

    http://www.Lambda-the-Ultimate.org related to the issue, but in

    searching for them, I see many people happily talking about dyanmic

    typing, without complaining about the term.

    Dynamic typing invariably means: runtime checking of tags associated

    with values. All values that are runtime checked would have to have

    tags identifying their type. Of course, you can mix static typing with

    dynamic typing if you want.

    I'm sorry if I have confused the issues for you.

    - Christopher

## Don Groves — 2007-09-09 19:26:51

    On Sep 9, 2007, at 19:12 , Christopher Diggins wrote:

     > On 9/8/07, Don Groves <dgroves@...> wrote:

    >> On Sep 8, 2007, at 19:44 , Christopher Diggins wrote:

    >>

    >>>> Just before falling asleep last night, it hit me what has caused my

    >>>> confusion

    >>>> about all this: I've been thinking of the interactive user, not

    >>>> running an already

    >>>> compiled program. Of course, when a program has been fed through

    >>>> the

    >>>> interpreter without errors, stack- and type checking is no longer

    >>>> necessary.

    >>>> Thanks for you help!

    >>>

    >>> An interpreter can still be statically typed. Each expression fed

    >>> into

    >>> the interpreter can be type-checked before it is run, and compared

    >>> with the current stack configuration. AFAIK this is a property

    >>> particular to languages with compositional type systems (e.g.

    >>> statically typed concatenative languages!)

    >>>

    >>> -D

    >>

    >> Thanks for the info. In what ways does Cat's inferred type system

    >> differ?

    >> --

    >

    > From what?

    >

    > -Christopher

      From an "uninferred" one. I'm thinking a large part of my problem is

    lack of vocabulary. I tried to find a definition of an "inferred" type

    system via Google but was unsuccessful.

    --

    Don

## Don Groves — 2007-09-09 19:29:53

    On Sep 9, 2007, at 19:23 , Christopher Diggins wrote:

     >>> This is an example of a runtime checked language, also called a

    >>> dynamically typed language, though some theorists object to the term

    >>> dynamic typing. Personally I have no qualms with it.

    >>>

    >>> -D

    >>

    >> OK, that's what I thought it was. It seems dynamic typing means two

    >> things: (1) run-time type checking; and (2) data is typed --

    >> variables are

    >> not. Clearly (1) allows (2) but (2) is not required.

    >> Is this part of

    >> the source

    >> of disagreement over the name?

    >

    > I shouldn't speculate too much. I think the disagreement is

    > artificial. There were some threads on

    > http://www.Lambda-the-Ultimate.org related to the issue, but in

    > searching for them, I see many people happily talking about dyanmic

    > typing, without complaining about the term.

    >

    > Dynamic typing invariably means: runtime checking of tags associated

    > with values. All values that are runtime checked would have to have

    > tags identifying their type. Of course, you can mix static typing with

    > dynamic typing if you want.

    >

    > I'm sorry if I have confused the issues for you.

    >

    > - Christopher

     No, my confusion is entirely my own and things are becoming clearer.

    --

    Don

## Christopher Diggins — 2007-09-09 21:06:45

    On 9/9/07, Don Groves <dgroves@...> wrote:

     > >> Thanks for the info. In what ways does Cat's inferred type system

    > >> differ?

    > >> --

    > >

    > > From what?

    > >

    > > -Christopher

    >

    > From an "uninferred" one. I'm thinking a large part of my problem is

    > lack of vocabulary. I tried to find a definition of an "inferred" type

    > system via Google but was unsuccessful.

     Some examples of languages with type inference are ML, OCaML, Haskell,

    F#, Scala, Boo, Nice, Cyclone, and of course Cat.

    Type inference (also known as type reconstruction) is not a property

    of the type system but rather a property of a language. Two languages

    can share a type system, whereas one requires type annotations (a.k.a

    type signatures) wheras another doesn't. Some type systems lend

    themselves to type inference (e.g. ML style type systems). Type

    inference is often achieved using what is known as the Hindley-Milner

    algorithm.

    Your most successful search keywords are going to be "type inference".

    Hope this helps,

    Christopher

## John Cowan — 2007-09-10 00:58:41

    pml060912 scripsit:

     > That looks like something I came across in P.J.Brown's "Writing

    > Interactive Compilers and Interpreters", although I forget if he

    > stated it explicitly or just implied it. In essence, he suggested

    > handling parameters and local variables by a "don't care" method, in

    > which they were really global variables like any other, only their

    > values were stacked/reinitialised and then restored on call/return.

     That's dynamic scoping (not to be confused with dynamic *typing*) and

    it is a Really Really Bad Idea, because reasoning about the behavior

    of programs becomes insanely difficult.  You wind up not being able to

    know where the value of a variable is set unless you know the exact

    path by which it was called, and no procedure can guarantee that the

    values of its parameters are safe from tampering unless it never calls

    any other procedure.  What's more, that particular *implementation*

    of dynamic scoping (known as "shallow binding") only works in a single

    thread of control; if there are multiple threads, it goes horribly wrong

    in all sorts of ways.

    Lexical scoping, in which variables only exist within the particular

    portion of the program that declares them, is a far superior regime.

    There are occasional uses for dynamic scoping here and there, and

    some languages support it as an alternative to lexical scoping for

    restricted use (Perl and Common Lisp, notably; also because of backward

    compatibility).  But it's hard to believe that any modern work on

    interpreters would recommend it.

    --

    "Well, I'm back."  --Sam        John Cowan <cowan@...>

## pml060912 — 2007-09-10 01:28:49

    --- In concatenative@yahoogroups.com, John Cowan <cowan@...> wrote:

     >

    > pml060912 scripsit:

    >

    > > That looks like something I came across in P.J.Brown's "Writing

    > > Interactive Compilers and Interpreters", although I forget if he

    > > stated it explicitly or just implied it. In essence, he suggested

    > > handling parameters and local variables by a "don't care" method,

     in

     > > which they were really global variables like any other, only

     their

     > > values were stacked/reinitialised and then restored on

     call/return.

     >

    > That's dynamic scoping (not to be confused with dynamic *typing*)

     and

     > it is a Really Really Bad Idea, because reasoning about the behavior

    > of programs becomes insanely difficult.  You wind up not being able

     to

     > know where the value of a variable is set unless you know the exact

    > path by which it was called, and no procedure can guarantee that the

    > values of its parameters are safe from tampering unless it never

     calls

     > any other procedure.

     That depends on what else is available to change them. As far as I

    can see, it's less risky in spreadsheets than in other languages

    since - depending on what base you have for building the formulas -

    formula execution needn't change the cells you allocate for that use

    (unless you foolishly use the same cell for one parameter as for the

    formula using the parameter!). But as I said, at this point I'm just

    mulling over ideas.

      What's more, that particular *implementation*

     > of dynamic scoping (known as "shallow binding") only works in a

     single

     > thread of control; if there are multiple threads, it goes horribly

     wrong

     > in all sorts of ways.

    >

    > Lexical scoping, in which variables only exist within the particular

    > portion of the program that declares them, is a far superior regime.

    > There are occasional uses for dynamic scoping here and there, and

    > some languages support it as an alternative to lexical scoping for

    > restricted use (Perl and Common Lisp, notably; also because of

     backward

     > compatibility).  But it's hard to believe that any modern work on

    > interpreters would recommend it.

     P.J.Brown wrote the first edition in 1979, emphasising

    implementation. He wasn't recommending this technique for the

    language design, but as an implementation technique for passing

    parameters to subroutines without having to implement the subroutine

    bodies specially. You would constrain the language in other ways to

    avoid some of these problems, for instance having an extra level of

    indirection in descriptors would allow it to act more like parameter

    handling in C. Brown also suggested having variables associated with

    subroutines and only allowing access to other variables by giving

    them what amounts to pathnames. On checking, I find that Brown only

    recommended this technique for subroutines, not functions, and he

    didn't specify the foo(x=a, y-b, z=c) notation for calling.

    I realised that it wasn't the best way to extend Cobol (say) to make

    it convenient for compiling itself, but it would have been a

    realistic approach if the extended version was only used in house

    with great care and not released. PML.

## Don Groves — 2007-09-10 07:48:19

    On Sep 9, 2007, at 19:06 , Christopher Diggins wrote:

     > On 9/9/07, Don Groves <dgroves@...> wrote:

    >>>> Thanks for the info. In what ways does Cat's inferred type system

    >>>> differ?

    >>>> --

    >>>

    >>> From what?

    >>>

    >>> -Christopher

    >>

    >> From an "uninferred" one. I'm thinking a large part of my problem is

    >> lack of vocabulary. I tried to find a definition of an "inferred"

    >> type

    >> system via Google but was unsuccessful.

    >

    > Some examples of languages with type inference are ML, OCaML, Haskell,

    > F#, Scala, Boo, Nice, Cyclone, and of course Cat.

    >

    > Type inference (also known as type reconstruction) is not a property

    > of the type system but rather a property of a language. Two languages

    > can share a type system, whereas one requires type annotations (a.k.a

    > type signatures) wheras another doesn't. Some type systems lend

    > themselves to type inference (e.g. ML style type systems). Type

    > inference is often achieved using what is known as the Hindley-Milner

    > algorithm.

    >

    > Your most successful search keywords are going to be "type inference".

    >

    > Hope this helps,

    > Christopher

     Yes, it helps a lot! Having fried my brain for the last two hours

    reading

    up on type inference, one thing stands out for the development of

    Catenate:

    if I infer the type of a variable from its initialization literal,

    and restrict that

    variable from ever holding a different type, then I can disable type

    checking

    for compiled programs. I'm not thinking much about execution speed yet,

    but doing this should speed up things considerably down the road.

    --

    Don

    Programmer (n): an organism that turns coffee and cookies into software.

## Robbert van Dalen — 2007-09-07 09:03:23

    Hi Manfred,

    Interesting post as usual.

    You may want to check: http://blog.moertel.com/articles/2006/01/20/

    wondrous-oddities-rs-function-call-semantics

    Function definitions in the R language follow your classification #3:

    bodies and calls rely on names.

    - Robbert

## Manfred Von Thun — 2007-10-02 05:35:41

    Thanks Robbert. Very interesting indeed. There is another feature

    which I have not seen before (and which has nothing to do with

    ordered/named parameters): one and the same procedure can

    use Cartesian or polar coordinates, and their interrelation is

    expressed in the list of (named) parameters. Very clever.

      - Manfred

     On 7/9/07 7:03 PM, "Robbert van Dalen" <robbert.van.dalen@...> wrote:

    > Hi Manfred,

    >

    > Interesting post as usual.

    >

    > You may want to check: http://blog.moertel.com/articles/2006/01/20/

    > wondrous-oddities-rs-function-call-semantics

    > Function definitions in the R language follow your classification #3:

    > bodies and calls rely on names.

    >

    > - Robbert

    >

    >

    [Non-text portions of this message have been removed]