# Another patch

## John Cowan — 2001-03-26 13:16:15

    This one makes the tailrec combinator properly tail recursive.  As currently

    implemented, it eats the C stack on every recursion to no purpose.

    At lines 1358 and 1365 of interp.c:

    1358a1361

     >     tailrec:

     1365c1368

    <       tailrecaux(); }

    ---

     >       goto tailrec; }

     --

    John Cowan                                   cowan@...

    One art/there is/no less/no more/All things/to do/with sparks/galore

    	--Douglas Hofstadter

## Manfred von Thun — 2001-03-29 07:46:46

    On Mon, 26 Mar 2001, John Cowan wrote:

    [two patch posts]

    I have looked at your two posts. You have gone throught the

    Joy sources with great care, thank you. Here are my comments:

    First patch:

      1)  In scan.c fix line 40 with extra parens.

          You are right, a definite improvement. Some other

          contributors remarked on something similar elsewhere

          a few months back.  Accepted, thank you.

          I have modified my working source and the web source.

      2)  In scan.c line 165 allow "DEFINE" instead of "LIBRA".

          Well, OK, I don't mind, so I accept.

          I have modified my working source and the web source.

      3)  In interp.c after line 825 you recommend that

          "If an attempt is made to execute an undefined symbol,

          a runtime error should occur."

          I am not so sure about that. Certainly, in most other

          languages this is the most sensible thing to do. I was

          toying with the idea years ago, but then I rejected it.

          My reason was, roughly, this. Consider the definitions

                LIBRA

                  square  ==  dup * ;

                  nothing  ==  ;

                  double  ==  2 * .

          The most reasonable behaviour for "nothing" should be that

          if it is ever executed it should do what the definition

          says: everyting between the "==" and the ";" and that

          is the empty program which is the identity of concatenation.

          So at runtime "nothing" should not do anything. But, you

          say, at least "nothing" was defined to be the empty program.

          OK, so now consider a list,

                [ peter paul mary ]

          which, when first used, cause the three names to be entered

          into the symbol table. No runtime behaviour has been defined

          for them if they were executed by, say,

                [ peter paul mary ]  i

          Now it seems to me that no runtime behaviour defined should

          mean that the three names behave just like empty programs.

          That was my reasoning.

               I still think this is right, but _only_ in a concatenative

          language, because the empty program really is the identity

          element for program concatenation. It would not make sense

          in an applicative language. What could a nothing-function

          applied to, say, two parameters, return? The pair of those

          parameters?

               It would be good to hear what other people think,

          especially the Forth people. What do the Forth implementations

          do, and what reason is given for whatever that behaviour is?

          I am willing to be persuaded one way or another.

    Second Post:

          In interp.c you recommended to make "tailrec" tail recursive.

          Agreed, accept, and thank you.

          I have modified my working source and the web source.

    Your other proposals:

          a) allow user symbols in set literals if they evaluate to

             a small integer or a char ( less than 32, I suppose).

          When I first read this I thought: "Well, why not in list

          literals, too?" Is your reasoning that a list literal is

          after all a special case of a program, and hence might be

          executed by some combinator? Maybe that was your thought.

          Another option would be to introduce what in Pascal and in

          some other languages are enumeration types:

              TrafficLights = (red, green, yellow)

          which in most respects would be equivalent to something

          which in (current) Joy be

              red == 0; green == 1; yellow == 3;

          and similarly in old K&R C. I seem to remember that the

          enumeration type was not included in Oberon (am I right,

          Soren?), for some reason to do with type extensions or

          something. Anyhow, enumeration types like "TrafficLights"

          might be a useful addition to Joy, possibly more so that

          just symbols in set literals.

          b) generic functions. I toyed with (text-)macros a bit, using

          (contrary to the advice of some members of the group) M4

          for lack of something better and available. It 1) gave the

          ability to inline some functions (and therefore increase

          efficiency a little bit), 2) allowed debugging info to be

          inserted/deleted at the flick of an M4 macro, without

          runtime cost, and 3) was _intended_ to provide some

          genericity - but I never got very far there. And, since

          M4 of course only provides text macros, errors can only

          be caught at macro expansion time. Maybe you should write

          some small generic functions in your imagined extension

          of Joy and let us have a look at them.

    Best wishes, and thank you again for your interest

       - Manfred

## Dirk-Ulrich Heise — 2001-03-29 09:22:55

    -----Ursprüngliche Nachricht-----

    Von: "Manfred von Thun" <phimvt@...>

    An: <concatenative@yahoogroups.com>

    Gesendet: Donnerstag, 29. März 2001 09:46

    Betreff: Re: [stack] Another patch

     >            It would be good to hear what other people think,

    >       especially the Forth people. What do the Forth implementations

    >       do, and what reason is given for whatever that behaviour is?

     A Forth first tries to find a definition for each word -

    where a word might be any combination of non-spaces, so

      12345

    can be the name of a definition as well.

    If it doesn't find one, it tries to resolve the word as a number.

    Depending on the Forth, various syntaxes might be allowed

    for numbers, e.g. one might accept 0x35 as a hex number or not,

    depending on the implementation.

    If this fails as well, you'll get an error message saying

    "undefined word" or so.

    Reasons? Well. You find your typos.

    Recently, i wrote a Forth program that needed something

    similar to your [ Peter Paul Mary ] example. The program had a list of

    words and it's purpose was to generate a new Forth

    source code where it wrote some data down in a way that

    it could later be interpreted by another Forth program.

    My solution was to generate a source code looking

    like

    0 constant Peter

    1 constant Paul

    2 constant Mary

    ; thus creating an enumeration from the strings.

    I don't see much sense in defining [ Peter Paul Mary ]

    as a list of three empty functions, really. What use could

    that have? Would it make sense to define Peter as a function

    that returns a string constant "Peter" ? But seriously,

    i'd expect an error message.

    Dirk Heise

    It's 0 degrees Celsius in Braunschweig, and we had 10 cm

    snow on Sunday!

## Dirk-Ulrich Heise — 2001-03-29 09:27:29

    An afterthought, more mathematically inspired:

    When hitting an unknown variable in a mathematical

    expression, like in

       5 + x = 0

    we first assume it to be unknown, until we know its

    value.

    Would it make sense to define an unknown symbol as

    an "unbound function" that can be manipulated (e.g.

    using function composition) but not executed as long

    as we don't know its value? So, as soon as you try

    to evaluate it, you'll get a runtime error.

    Dirk Heise

    What's a life and where do i get one?

## John Cowan — 2001-03-29 12:51:18

    Manfred von Thun scripsit:

     > I have looked at your two posts. You have gone throught the

    > Joy sources with great care, thank you. Here are my comments:

     I will have some more safety-related patches soon.  For example,

    "cons" does not currently check, when its top argument is a string,

    that the bottom argument is a character, or even numeric.  There

    are several other defects of this kind.

     >   3)  In interp.c after line 825 you recommend that

    >       "If an attempt is made to execute an undefined symbol,

    >       a runtime error should occur."

     [snip]

     >            It would be good to hear what other people think,

    >       especially the Forth people. What do the Forth implementations

    >       do, and what reason is given for whatever that behaviour is?

     AFAIK it is not allowed to even mention, in the definition of a Forth

    word, any word whose definition has not yet begun.  So Joy has this

    advantage over Forth (from the standpoint of flexibility), that

    you may mention not-yet-defined words and define them later.

    From a practical point of view, though, I find it obnoxious that

    when I type (as I so often do)

    	[something] helpdetails.

    I get nothing (in standard Joy) rather than an error message.

    Of course the correct word is "helpdetail", but for some reason

    I find this hard to remember.  (I could define "helpdetails"

    as "helpdetail" in my usrlib.joy, but that does not meet the

    general point).

    I agree that an empty definition should be executed successfully

    by doing nothing, but I cannot agree that an empty definition

    is the same as no definition.  This is analogous to the attitude

    to variables taken by Fortran or Basic or Perl without 'use strict',

    and it has long ago been seen to lead to practical trouble:

    a misspelled identifier makes a correct but useless program.

     > Your other proposals:

    >       a) allow user symbols in set literals if they evaluate to

    >          a small integer or a char ( less than 32, I suppose).

    >       When I first read this I thought: "Well, why not in list

    >       literals, too?" Is your reasoning that a list literal is

    >       after all a special case of a program, and hence might be

    >       executed by some combinator?

     Just so.  Whereas set literals are handled purely by the lexer,

    and so using meaningful names in them is impossible at present.

     >       Another option would be to introduce what in Pascal and in

    >       some other languages are enumeration types:

    >           TrafficLights = (red, green, yellow)

    >       which in most respects would be equivalent to something

    >       which in (current) Joy be

    >           red == 0; green == 1; yellow == 3;

     My proposal allows red, green, yellow to be defined just like

    this, and then used to create sets such as {red, green}

    rather than having to write, as at present,

    {} red swons green swons.

     >       Anyhow, enumeration types like "TrafficLights"

    >       might be a useful addition to Joy, possibly more so that

    >       just symbols in set literals.

     True, but right now Joy does not have user-defined first-class

    types.  All in good time...

     >	b) generic functions.

     I will post more on this later.  My desire is to make it possible

    for people using user-level types such as queue and bigset to

    write functions which are generic across several of them.

    I think this can be done with a single rather strange low-level

    word, but the details are not firm in my head yet.

     > Best wishes, and thank you again for your interest

     I am also thinking about a large extension, about 60 words,

    to add ANSI C programming support, allowing Joy to do about

    anything than C can do (other than link in modules in C,

    to be sure).  This would involve three new types: floats,

    FILEs, and something I call "ocseq"s for "octet sequences".

    These last are like strings, but are counted rather than

    null-terminated, and are used for binary file I/O.

    I will start posting patches for parts of this effort

    as I get it done.

    That will leave the biggest limitation on practical Joy programming

    to be the fact that there is no garbage collection for strings:

    they are allocated with malloc, but never freed.  So a Joy version

    of cat(1) would in effect have to keep the whole input memory-resident

    but garbage, unless it copied using getch and putch alone.

    Anyone feel interested in tackling this problem?  I understand

    stop-and-copy GC in principle, but have not tried to analyze the

    Joy implementation.

    BTW, I presume the Joy source is Open Source, but a formal

    license such as the BSD license (available at

    http://www.opensource.org/licenses/bsd-license.html)

    would be appreciated.

    --

    John Cowan                                   cowan@...

    One art/there is/no less/no more/All things/to do/with sparks/galore

    	--Douglas Hofstadter

## John Cowan — 2001-03-29 14:34:34

    Dirk-Ulrich Heise wrote:

     > Would it make sense to define an unknown symbol as

    > an "unbound function" that can be manipulated (e.g.

    > using function composition) but not executed as long

    > as we don't know its value?

     That is indeed the effect of my patch.  You can define

    "foo" thus:

    	DEFINE foo == bar dup +.

    even though "bar" is not known.  Likewise, you can

    create quotations involving "bar" and manipulate them

    like other quotations.  (Thus far standard Joy.)

    But the minute you try to execute such a quotation, or

    execute foo, you get an error.

    --

    There is / one art             || John Cowan <jcowan@...>

    no more / no less              || http://www.reutershealth.com

    to do / all things             || http://www.ccil.org/~cowan

    with art- / lessness           \\ -- Piet Hein

## Martin Young — 2001-03-29 15:54:38

    On Mar 29,  9:34am, cowan@... wrote:

     > That is indeed the effect of my patch.  You can define

    > "foo" thus:

    >

    > 	DEFINE foo == bar dup +.

    >

    > even though "bar" is not known.  Likewise, you can

    > create quotations involving "bar" and manipulate them

    > like other quotations.  (Thus far standard Joy.)

    >

    > But the minute you try to execute such a quotation, or

    > execute foo, you get an error.

     So you're going to allow new words to be defined during program execution?

    By allowing words to be defined at runtime you have to define some semantics

    about when definitions are bound to their names i.e. you have to choose lexical

    binding or dynamic binding.

    AFAICS you're proposing dynamic, where the binding is resolved when the word is

    executed.  This means that your function "foo" may have completely different

    semantics on different invocations.  Lexical binding, OTOH, makes the word's

    semantics static but requires an appropriate definition of bar when the

    definition is made and thus won't let you realise your premise.

    If you choose dynamic binding then you're effectively giving the language

    global state.  This will make it very hard to analyse programs and to optimise

    them becuase it won't be possible to always replace a word by it's definition

    before execution.

    For example a program such as:

    foo == [ 2 ]

    bar == [ foo foo + ]

    ...could be trivially optimised to

    bar == [ 4 ]

    ...as the program is being read however if you allow redefinition then this

    can't be done because foo may not always be [ 2 ].

    --

    Martin Young  working for  STMicroelectronics at     `(o)_(o)' The fat wise /

    1000 Aztec West, Almondsbury, Bristol, BS32 4SQ.      (  V  ) owl eats only >

    +44 1454 462 523    `v'      Martin.Young@...      `.___,' clean mice.  /

                       _(_)_                             -="==="=============='

## John Cowan — 2001-03-29 17:21:36

    Martin Young wrote:

     > So you're going to allow new words to be defined during program execution?

     No, although this capability is already present in Joy thanks to the "include"

    word.  What is being discussed is 1) whether an unbound word should be

    permitted in a definition at all (Forth no, Joy yes), and 2) what the effects

    are of executing such a word (standard Joy, no effect; my version of Joy, error).

    --

    There is / one art             || John Cowan <jcowan@...>

    no more / no less              || http://www.reutershealth.com

    to do / all things             || http://www.ccil.org/~cowan

    with art- / lessness           \\ -- Piet Hein

## Martin Young — 2001-03-29 17:58:05

    On Mar 29, 12:21pm, cowan@... wrote:

     > Martin Young wrote:

    > > So you're going to allow new words to be defined during program execution?

    >

    > No, although this capability is already present in Joy thanks to the

     "include"

     > word.

     Hmm.  I wouldn't have included "include" in "the language" myself.  It's more

    of an environment thing.

     > What is being discussed is 1) whether an unbound word should be

    > permitted in a definition at all (Forth no, Joy yes), and 2) what the effects

    > are of executing such a word (standard Joy, no effect; my version of Joy,

    > error).

     So all you're discussing is whether (a) forward references should be allowed in

    programs, and (b) what happens if you try to run them before the reference is

    resolved?

    Ho-hum.

    --

    Martin Young  working for  STMicroelectronics at     `(o)_(o)' The fat wise /

    1000 Aztec West, Almondsbury, Bristol, BS32 4SQ.      (  V  ) owl eats only >

    +44 1454 462 523    `v'      Martin.Young@...      `.___,' clean mice.  /

                       _(_)_                             -="==="=============='

## Billy Tanksley — 2001-03-29 22:34:54

    From: Manfred von Thun [mailto:phimvt@...]

     >  3)  In interp.c after line 825 you recommend that

    >      "If an attempt is made to execute an undefined symbol,

    >      a runtime error should occur."

    >      I am not so sure about that. Certainly, in most other

    >      languages this is the most sensible thing to do. I was

    >      toying with the idea years ago, but then I rejected it.

     I find this shocking :-).  I'm VERY glad I found Joy; it's good to see some

    different thought from what I've always known.

     >      My reason was, roughly, this. Consider the definitions

    >            LIBRA

    >              square  ==  dup * ;

    >              nothing  ==  ;

    >              double  ==  2 * .

    >      The most reasonable behaviour for "nothing" should be that

    >      if it is ever executed it should do what the definition

    >      says: everyting between the "==" and the ";" and that

    >      is the empty program which is the identity of concatenation.

     Perfectly reasonable.

     >      OK, so now consider a list,

    >            [ peter paul mary ]

    >      which, when first used, cause the three names to be entered

    >      into the symbol table.

     What???  Why?  Why should "using" a list cause anything inside the list to

    be entered into the symbol table?  I think that only a (1) symbol literal or

    (2) definition should cause anything to be entered into the symbol table.

    So [ `peter `paul `mary ] could cause what you're asking for.  Or to borrow

    from Scheme, `[peter paul mary] would work very well.

     >      No runtime behaviour has been defined

    >      for them if they were executed by, say,

    >            [ peter paul mary ]  i

    >      Now it seems to me that no runtime behaviour defined should

    >      mean that the three names behave just like empty programs.

    >      That was my reasoning.

     Even accepting your initial premise on the behavior of identifiers appearing

    inside a list-literal, that doesn't make sense to me.  Undefined runtime

    behavior doesn't mean _no_ runtime behavior.  IMO _doing_ something makes

    more sense; and an error makes the most sense of all.

     >           It would be good to hear what other people think,

    >      especially the Forth people. What do the Forth implementations

    >      do, and what reason is given for whatever that behaviour is?

    >      I am willing to be persuaded one way or another.

     Forth compilers ALWAYS emit an error on reading an undefined word which

    isn't parsable as a number.  This allows:

     - immediate errors when you make a mistake.

     - TONS of optimizations, including the obvious generation of trivial native

    code (subrouting-threaded).

     - ease of reading: you KNOW everything's defined somewhere above where it's

    written.

    Now, sometimes (rarely) you need to use a word before it's defined; most

    commonly that would happen when defining mutually recursive words, but any

    programmer might want to do something like that in order to make the

    presentation clearer.  This would be trivial in Joy if it were possible to

    declare functions before defining them.

    Printing no error, and doing nothing at runtime, opens one up to terrible

    debugging experiences, and gives no advantages of any kind (I'm going out on

    a limb).  I would recommend disallowing any undeclared word at compile-time

    (in the Forth style), but I could probably be convinced that runtime errors

    are okay if someone would come up with an advantage.

     >      b) generic functions. I toyed with (text-)macros a bit, using

    >      (contrary to the advice of some members of the group) M4

    >      for lack of something better and available. It 1) gave the

    >      ability to inline some functions (and therefore increase

    >      efficiency a little bit), 2) allowed debugging info to be

    >      inserted/deleted at the flick of an M4 macro, without

    >      runtime cost, and 3) was _intended_ to provide some

    >      genericity - but I never got very far there. And, since

    >      M4 of course only provides text macros, errors can only

    >      be caught at macro expansion time. Maybe you should write

    >      some small generic functions in your imagined extension

    >      of Joy and let us have a look at them.

     I believe he's talking about function overloading, not genericism.  I'd like

    overloading, as provided in strongForth (q.v.).

    I don't care for M4, not because I don't like M4, but rather because a

    concatenative language should be able to do everything M4 possibly can.

    Simply add two new concepts to the Joy language:

    1) immediate words, which execute as soon as they're parsed (even in the

    middle of a definition)

    and

    2) access to the source from a Joy word, together with parsing words.

    So, for example:

    HIDE

      reverse (immediate) == parse-token parse-token insert-into-source

    insert-into-source;

    IN

      test == reverse print "Hello world!";

    'reverse', of course, is silly and pointless; however, it illustrates the

    point: it parses source which appears in definitions in front of it, and

    modifies the definition in which it appears.  One could imagine defining a

    word which would read an algebraic or k expression and insert the equivalent

    RPN one.

     >   - Manfred

     -Billy

## Billy Tanksley — 2001-03-29 22:55:48

    From: John Cowan [mailto:cowan@...]

     >AFAIK it is not allowed to even mention, in the definition of a Forth

    >word, any word whose definition has not yet begun.  So Joy has this

    >advantage over Forth (from the standpoint of flexibility), that

    >you may mention not-yet-defined words and define them later.

     Not much of an advantage -- all Forth needs to catch up is a way to declare

    words without defining them.  In fact, most Forths use DEFER for that

    (although it's not in the ANSI standard, it's ancient common use).

     >>       Anyhow, enumeration types like "TrafficLights"

    >>       might be a useful addition to Joy, possibly more so that

    >>       just symbols in set literals.

    >True, but right now Joy does not have user-defined first-class

    >types.  All in good time...

     Another chance to plug strongForth: rah! rah!  :-)

     >>	b) generic functions.

    >I will post more on this later.  My desire is to make it possible

    >for people using user-level types such as queue and bigset to

    >write functions which are generic across several of them.

    >I think this can be done with a single rather strange low-level

    >word, but the details are not firm in my head yet.

     I'd like to hear more.  I suspected that you were talking about function

    overloading, and it looks like I'm right.

     >> Best wishes, and thank you again for your interest

    >I am also thinking about a large extension, about 60 words,

    >to add ANSI C programming support, allowing Joy to do about

    >anything than C can do (other than link in modules in C,

    >to be sure).  This would involve three new types: floats,

    >FILEs, and something I call "ocseq"s for "octet sequences".

    >These last are like strings, but are counted rather than

    >null-terminated, and are used for binary file I/O.

    >I will start posting patches for parts of this effort

    >as I get it done.

     Exciting!  I especially like how you're replacing C's annoying and

    inappropriate use of null-termination with some counted strings.

    One comment: Forth used to use bytecounts for all of its strings, but this

    was a mistake.  It meant that no Forth words could accept strongs longer

    than 255 characters, and it meant that in order to use an ordinary C string

    Forth had to copy it.  Modern Forths, ever since the ANSI standard, now

    assume that the counts are stored seperate from the strings; in other words,

    any function which accepts a byte pointer also accepts a count.  The pair

    together make up a string.  This allows strings to be stored in the old,

    compact format, but also allows you to use very long strings and/or

    null-terminated strings.

     >That will leave the biggest limitation on practical Joy programming

    >to be the fact that there is no garbage collection for strings:

    >they are allocated with malloc, but never freed.  So a Joy version

    >of cat(1) would in effect have to keep the whole input memory-resident

    >but garbage, unless it copied using getch and putch alone.

    >Anyone feel interested in tackling this problem?

     If you manage to implement generic functions, it should be easy to define

    special cases for destructive words which, instead of simply discarding the

    address of a string, actually delete it.

     >BTW, I presume the Joy source is Open Source, but a formal

    >license such as the BSD license (available at

    >http://www.opensource.org/licenses/bsd-license.html)

    >would be appreciated.

     That's true.  BSD would be best; if you want to guard your work, LGPL would

    also be generally acceptable.  GPL, on the other hand, would keep your work

    in the educational domain (which might not be unacceptable).

     >John Cowan                                   cowan@...

     -Billy

## John Cowan — 2001-03-29 23:08:28

    Billy Tanksley wrote:

     > I find this shocking :-).  I'm VERY glad I found Joy;

     And may we all find Joy!

     > What???  Why?  Why should "using" a list cause anything inside the list to

    > be entered into the symbol table?

     It doesn't.  Merely typing in a word causes it to go on the symbol

    table with a null definition, as in Lisp or Scheme.

     > I think that only a (1) symbol literal or

    > (2) definition should cause anything to be entered into the symbol table.

     Except there are no symbol literals in Joy, only list literals.  To get

    a symbol on the stack, you have to say

    	[foo] first.

    Forth AFAIK has no symbols on its stack in this sense.

     > This would be trivial in Joy if it were possible to

    > declare functions before defining them.

     In fact, Joy allows defining functions in any order, as long as they

    are defined before they are executed.

     > I believe he's talking about function overloading, not genericism.  I'd like

    > overloading, as provided in strongForth (q.v.).

     We already have overloading in primitive words; for example, "concat"

    works equally well with a pair of strings, a pair of lists, or a pair

    of sets.  I would like user words to have the same power *without*

    having to be written with knowledge of all user-level types in advance.

    In this context, a user-level type is identified by an arbitrary predicate,

    such as "list of size 3" or "list whose first element is 'foo'" or

    "string ending in '$'".

     > 1) immediate words, which execute as soon as they're parsed (even in the

    > middle of a definition)

    > and

    > 2) access to the source from a Joy word,

     This we have:  [foo] first body will push the definition of

    foo on the stack.  But there is a firewall in Joy against allowing words

    to define other words (except by way of "include") that I think assists

    in reasoning about Joy programs.  Arguably "include" should never be used

    in "application time" words.

     > One could imagine defining a

    > word which would read an algebraic or k expression and insert the equivalent

    > RPN one.

     One shudders.  :-)

    --

    There is / one art             || John Cowan <jcowan@...>

    no more / no less              || http://www.reutershealth.com

    to do / all things             || http://www.ccil.org/~cowan

    with art- / lessness           \\ -- Piet Hein

## Billy Tanksley — 2001-03-29 23:37:57

    From: John Cowan [mailto:cowan@...]

     >Billy Tanksley wrote:

    >> I think that only a (1) symbol literal or

    >> (2) definition should cause anything to be entered into the

    >> symbol table.

    >Except there are no symbol literals in Joy, only list literals.  To get

    >a symbol on the stack, you have to say

    >	[foo] first.

    >Forth AFAIK has no symbols on its stack in this sense.

     As we've discussed, Joy really has no symbols either.  When you say "[foo]

    first", as mentioned, you don't get a symbol on the stack; you get a

    function which represents the symbol.  Forth calls this a 'word'.

    I'm suggesting that if Joy wants to pretend to have symbols, it should

    _actually_ support them, via literals and so on.  It shouldn't require that

    every symbol represent a function.

    It's notable that Joy also doesn't support functions as such -- "[foo]

    first" wasn't something the author had planned for, it just sort of

    _happens_ to work.  There are no functions to help with it.

     >> This would be trivial in Joy if it were possible to

    >> declare functions before defining them.

    >In fact, Joy allows defining functions in any order, as long as they

    >are defined before they are executed.

     This is true -- but it does this by means of a HORRIBLE hack, which forever

    prohibits Joy from simple optimization.  This would be fine if there were

    some justification -- but there's not.

     >> I believe he's talking about function overloading, not

    >> genericism.  I'd like overloading, as provided in

    >> strongForth (q.v.).

    >We already have overloading in primitive words; for example, "concat"

    >works equally well with a pair of strings, a pair of lists, or a pair

    >of sets.

     This is not overloading; it's merely runtime type information.

     >I would like user words to have the same power *without*

    >having to be written with knowledge of all user-level types in advance.

     That's overloading.  You can do it staticly, as in strongForth, or

    dynamicly, as in any of the object-oriented languages or extensions.

     >In this context, a user-level type is identified by an

    >arbitrary predicate,

    >such as "list of size 3" or "list whose first element is 'foo'" or

    >"string ending in '$'".

     That's a great idea, but it's uncomputable.  It's better to keep types

    simple.

     >> 1) immediate words, which execute as soon as they're parsed

    >> (even in the middle of a definition)

    >> and

    >> 2) access to the source from a Joy word,

    >This we have:  [foo] first body will push the definition of

    >foo on the stack.

     This does absolutely nothing of the sort -- it's not even faintly, obliquely

    related.  It can only access stuff which has already been parsed _and

    compiled_.  At that point it's redundant information.  If this is to be

    useful as a macro language, it has to access the source before the parser

    has even had a chance to look at it.

     >But there is a firewall in Joy against allowing words

    >to define other words (except by way of "include") that I think assists

    >in reasoning about Joy programs.  Arguably "include" should

    >never be used in "application time" words.

     Agreed.  I'm not yet suggesting adding defining words, though; I'm only

    suggesting source manipulation.  Now, a full source manipulator could be

    used to create defining words, but that's unavoidable, by the nature of

    macros.  The nice thing about these defining words, though, is that they're

    immediate; they CANNOT be used at runtime, because they always execute at

    compile-time.

    "include" could be converted to an immediate word.

     >> One could imagine defining a

    >> word which would read an algebraic or k expression and

    >> insert the equivalent RPN one.

    >One shudders.  :-)

     Indeed.  :-)  May Forth programmers before you have shuddered at the thought

    -- then, finally, someone implemented such a thing, and hey presto!, it

    wasn't as bad as we thought it'd be.  Nor was it as neccessary as some

    anti-RPN people thought, but that's to be expected.

     >There is / one art             || John Cowan <jcowan@...>

     -Billy

## John Cowan — 2001-03-30 03:47:58

    Billy Tanksley scripsit:

     > As we've discussed, Joy really has no symbols either.  When you say "[foo]

    > first", as mentioned, you don't get a symbol on the stack; you get a

    > function which represents the symbol.  Forth calls this a 'word'.

     Granted.  I must confess I have not read all the archives yet.

     > It's notable that Joy also doesn't support functions as such -- "[foo]

    > first" wasn't something the author had planned for, it just sort of

    > _happens_ to work.  There are no functions to help with it.

     What functions would you want?  Ask now, and they might get implemented!

     > This is true -- but it does this by means of a HORRIBLE hack, which forever

    > prohibits Joy from simple optimization.  This would be fine if there were

    > some justification -- but there's not.

     It doesn't prohibit it, it just means it can't be applied in every case.

    You are free to inline any definition you already know, since there is

    no runtime redefinition.  (If the programmer redefines things, though,

    you will have to decide what to do with inlined code.)

     > That's overloading.  You can do it staticly, as in strongForth, or

    > dynamicly, as in any of the object-oriented languages or extensions.

     It is the latter I have in mind.

     > >In this context, a user-level type is identified by an

    > >arbitrary predicate,

    > >such as "list of size 3" or "list whose first element is 'foo'" or

    > >"string ending in '$'".

    >

    > That's a great idea, but it's uncomputable.  It's better to keep types

    > simple.

     What do you mean "uncomputable"?  If general types are too slow for you,

    use simple ones that can be computed quickly.  But if I want to define

    a type "prime number", I see no reason why I can't have it.

     > >This we have:  [foo] first body will push the definition of

    > >foo on the stack.

    >

    > This does absolutely nothing of the sort -- it's not even faintly, obliquely

    > related.  It can only access stuff which has already been parsed _and

    > compiled_.  At that point it's redundant information.  If this is to be

    > useful as a macro language, it has to access the source before the parser

    > has even had a chance to look at it.

     I have no interest in implementing a macro language for Joy.

    --

    John Cowan                                   cowan@...

    One art/there is/no less/no more/All things/to do/with sparks/galore

    	--Douglas Hofstadter

## Reuben Thomas — 2001-03-30 10:04:54

    > Modern Forths, ever since the ANSI standard, now

    > assume that the counts are stored seperate from the strings; in other words,

    > any function which accepts a byte pointer also accepts a count.

     However, old-style words that accept counted strings (where the count is

    stored before the string) still, unfortunately (but understandably) dictate

    that the count is one character in size.

    --

    http://sc3d.org/rrt/ | violence, n.  bravery for cowards

## John Cowan — 2001-03-30 17:57:38

    Billy Tanksley wrote:

     > Not much of an advantage -- all Forth needs to catch up is a way to declare

    > words without defining them.  In fact, most Forths use DEFER for that

    > (although it's not in the ANSI standard, it's ancient common use).

     So much for instant inlining, though!  In fact, no one can do any better

    than "inline words whose definitions you know, don't inline if you don't".

     > Another chance to plug strongForth: rah! rah!  :-)

     It's an interesting effort, and I'd like to see some such facility in

    Joy eventually, but it's beyond my current scope.  Of course, each

    Joy datum already carries its (dynamic) type with it; that's how the

    Joy overloaded words work.

     >> [...] and something I call "ocseq"s for "octet sequences".

    >> These last are like strings, but are counted rather than

    >> null-terminated, and are used for binary file I/O.

    >> I will start posting patches for parts of this effort

    >> as I get it done.

    >

    > Exciting!  I especially like how you're replacing C's annoying and

    > inappropriate use of null-termination with some counted strings.

     Actually, I think null-termination is perfectly appropriate for

    strings, which are sequences of characters, because NUL is not

    really a useful character.  0x00 *is* a useful octet, though.

    Conceptually, an ocseq is a list whose elements are small integers

    (range 0-255), whereas a string is a list whose elements are

    characters.  Separating these concepts, as Joy already separates

    characters from integers, is the foundation of the proper treatment

    of strings.

     > One comment: Forth used to use bytecounts for all of its strings, but this

    > was a mistake.

     Internally an ocseq is represented as a pointer to raw octets and a 32-bit

    length.  Allowing ocseqs and floats means that each Joy stack element

    gets bigger, but they are already 3 x 32 bits, so going to 4 x 32 is not

    that bad.

     > If you manage to implement generic functions, it should be easy to define

    > special cases for destructive words which, instead of simply discarding the

    > address of a string, actually delete it.

     Ugh.  Joy shares strings: if you say "foo" dup uncons, then the stack

    looks like "foo" 'f "oo", but "foo" and "oo" share storage.  Allowing

    explicit deletion in that environment is the road to Hell, unpaved.

    I am now looking into the Boehm-Demers-Weiser conservative garbage collector

    in place of Joy's native GC.  This would be a C-compile-time option,

    since the BDW collector is not quite portable (though in fact portable

    to all commercially important platforms, there does not seem to be a

    VMS port).

     > That's true.  BSD would be best; if you want to guard your work, LGPL would

    > also be generally acceptable.  GPL, on the other hand, would keep your work

    > in the educational domain (which might not be unacceptable).

     Or the Free Software domain generally: not all Free Software is uncommercial.

    (Ask Cygnus.)  Joy is currently fairly uncommercial, though.

    --

    There is / one art             || John Cowan <jcowan@...>

    no more / no less              || http://www.reutershealth.com

    to do / all things             || http://www.ccil.org/~cowan

    with art- / lessness           \\ -- Piet Hein

## Billy Tanksley — 2001-03-30 19:45:00

    From: John Cowan [mailto:cowan@...]

     >Billy Tanksley scripsit:

    >> It's notable that Joy also doesn't support functions as such

    >> -- "[foo]

    >> first" wasn't something the author had planned for, it just sort of

    >> _happens_ to work.  There are no functions to help with it.

    >What functions would you want?  Ask now, and they might get

    >implemented!

     The main thing which would help is some standard for what happens when

    you're juggling a function.  For example, "i" should be documented to be

    able to take a function as an input.  We also should have a syntax for

    literal functions.

     >> That's overloading.  You can do it staticly, as in strongForth, or

    >> dynamicly, as in any of the object-oriented languages or extensions.

    >It is the latter I have in mind.

     I'd personally like to do both.  Either one alone has problems.

     >> >In this context, a user-level type is identified by an

    >> >arbitrary predicate,

    >> >such as "list of size 3" or "list whose first element is 'foo'" or

    >> >"string ending in '$'".

    >> That's a great idea, but it's uncomputable.  It's better to

    >> keep types simple.

    >What do you mean "uncomputable"?  If general types are too

    >slow for you, use simple ones that can be computed quickly.

    >But if I want to define a type "prime number", I see no reason

    >why I can't have it.

     I'm sorry, I meant uncomputable at compile-time.  I'd definitely like to

    support arbitrary type dispatch; the problem is that it adds immensely to

    overhead, when such overhead isn't really needed 95% of the time.  If you

    can compute the type at compile-time, it's a solid win; if you have to do

    something like primality tests at runtime, though, you lose performace with

    every call.

     >> If this is to be

    >> useful as a macro language, it has to access the source

    >> before the parser has even had a chance to look at it.

    >I have no interest in implementing a macro language for Joy.

     Okay.  I do.  Or more accurately, I want Joy to be its own macro language.

     >John Cowan                                   cowan@...

     -Billy

## John Cowan — 2001-03-30 20:15:24

    Billy Tanksley wrote:

     > The main thing which would help is some standard for what happens when

    > you're juggling a function.  For example, "i" should be documented to be

    > able to take a function as an input.  We also should have a syntax for

    > literal functions.

     Okay, so you want combinators to accept functions.  Easily done.

    Currently, of course, you can make it happen thus:

    	DEFINE I == [i] [[] swons i] iflist.

    and then use I instead of i.

     > I'd definitely like to

    > support arbitrary type dispatch; the problem is that it adds immensely to

    > overhead, when such overhead isn't really needed 95% of the time.

     *shrug*  Joy is not Forth.  It already has runtime dispatching in

    almost every primitive.  Static typing is orthogonal to dynamic

    typing, I agree; what I want is user-level dynamic typing.

     > Okay.  I do.  Or more accurately, I want Joy to be its own macro language.

     Full steam ahead, then.

    --

    There is / one art             || John Cowan <jcowan@...>

    no more / no less              || http://www.reutershealth.com

    to do / all things             || http://www.ccil.org/~cowan

    with art- / lessness           \\ -- Piet Hein

## Billy Tanksley — 2001-03-30 20:17:09

    From: John Cowan [mailto:cowan@...]

     >*shrug*  Joy is not Forth.

     Something we can agree on :-).

     >> Okay.  I do.  Or more accurately, I want Joy to be its own

    >> macro language.

    >Full steam ahead, then.

     Yup.  :-)

     >There is / one art             || John Cowan <jcowan@...>

     -Billy

## Manfred von Thun — 2001-04-11 01:24:59

    On Thu, 29 Mar 2001, John Cowan wrote:

    ...

    > BTW, I presume the Joy source is Open Source, but a formal

    > license such as the BSD license (available at

    > http://www.opensource.org/licenses/bsd-license.html)

    > would be appreciated.

    Yes, you presume correctly. I did look at the page you mention,

    and also at the other licenses. I even joined the license discussion

    group (of which I note you are a contributor), but I have not

    had time to read, and even less to really understand what is going

    on.

    Do I have to go through that process of discussion ?

    Or is it sufficient to edit the BSD license template

    and include a link "license" on the Joy home page ?

    Since you know these things, could you just tell me

    what to do - please.

      - Manfred

## John Cowan — 2001-04-11 04:22:47

    Manfred von Thun scripsit:

     > Do I have to go through that process of discussion ?

     No, not at all!  If you plan to use a pre-existing license such as the

    BSD license, you can just *use* it.  The only reasons to belong to

    license-discuss are these:

    1) the subject is intrinsically interesting to you

    2) you enjoy reviewing other people's licenses to see if they are Open Source

    3) you are trying to get your very own license classified as Open Source compliant.

    None of these apply in this case.

     > Or is it sufficient to edit the BSD license template

    > and include a link "license" on the Joy home page ?

     That is sufficient.  You should also add it to each of the source code files

    so that if they get separated from the home page, the copyright status

    and license are clear.

    --

    John Cowan                                   cowan@...

    One art/there is/no less/no more/All things/to do/with sparks/galore

    	--Douglas Hofstadter

## Billy Tanksley — 2001-04-11 18:31:20

    From: Manfred von Thun [mailto:phimvt@...]

     >On Thu, 29 Mar 2001, John Cowan wrote:

    >> BTW, I presume the Joy source is Open Source, but a formal

    >> license such as the BSD license (available at

    >> http://www.opensource.org/licenses/bsd-license.html)

    >> would be appreciated.

    >Do I have to go through that process of discussion ?

    >Or is it sufficient to edit the BSD license template

    >and include a link "license" on the Joy home page ?

    >Since you know these things, could you just tell me

    >what to do - please.

     No discussion needed; simply do what you've said, and include a copyright

    notice at the head of each .c and .h file, and one in the executable

    (probably at startup).

     >  - Manfred

     -Billy