# Re: [stack] Definitions at run-time

## phimvt@lurac.latrobe.edu.au — 2005-03-11 07:32:42

    On Thu, 10 Mar 2005, Ivan Tomac wrote:

     > For some strange reason some of the recent posts to this message board

    > made me dig through the archives and re-read some of the old posts as

    > well as go through most of the papers on Joy again.

    >

    > I've noticed one thing that I haven't seen earlier that just doesn't

    > seem to add up. On the "Further Frequently Asked Questions about Joy"

    > page (http://www.latrobe.edu.au/philosophy/phimvt/joy/faq1.html) Manfred

    > talks about the reasons why having defining words avaliable at run-time

    > is a bad idea. The reason he states in the end is one relating to

    > creation of variables that act the same way as they would in imperative

    > languages.

    >

    > I have one question and one (obvious) observation:  1) Wouldn't this

    > only be a problem with dynamically scoped languages? If Joy was

    > lexically scoped this wouldn't be an issue.

     Early Lisps were dynamically scoped, but since Landin's ISWIM both

    Scheme and Common Lisp are statically scoped, and so is Joy.  All of

    them are dynamically typed: type checking occurs at run time.  In Scheme

    and Common Lisp the static scoping is extensive: there are the global

    definitions of functions, the names of the formal parameters, LET

    expressions, lambda variables (and variables for assignment). With all

    these the scoping is an intricate affair due to the possible nesting. So

    the symbol table management becomes rather complex.  In Joy there are

    just the global definitions, including those in HIDE's and MODULE's, and

    all the other things don't occur. So it is all very simple.  For all

    these statically scoped languages a symbol means what it meant when the

    program started running, and in the case of complex nesting in Scheme or

    Common Lisp a symbol means what the enclosing scopes defined it to mean.

    This ignores macros in Scheme and Common Lisp.  However, I do believe that

    some of the macro facilities available change matters somewhat. But I do

    not understand them well enough to really tell. Google "Oleg Scheme" for

    some wonderful stuff.

     > 2) The imperative notion of variables can be simulated with files as

    > well. Furthermore the whole concept of binding names to values and

    > functions is analogous to concepts of filesystems and databases.

     I think you are might be right here. But consider this:

    Assume the definition:  DEFINE foo == 111 .  (Note the space after the

    number - without it the scanner expects digits after the decimal point.)

    At runtime, put the string "DEFINE foo == 222 ." on the stack, write that

    string to a file, include that file, finally do "foo put.".  All this in

    the same run. What do you get? 222 or 111 ?  You get 111, because you are

    still in the same run. The new definition will only be read when the Joy

    interpreter is ready to read something, after it has executed the code for

    the current run.  For the next run the included file will have been

    processed, of course, and foo will mean 222.  And all this is how it

    should be, I think.

    Maybe John Cowan has something to say on this topic.

      - Manfred

## Ivan Tomac — 2005-03-12 12:27:09

    --- In concatenative@yahoogroups.com, phimvt@l... wrote:

     > On Thu, 10 Mar 2005, Ivan Tomac wrote:

    > > I've noticed one thing that I haven't seen earlier that just doesn't

    > > seem to add up. On the "Further Frequently Asked Questions about Joy"

    > > page (http://www.latrobe.edu.au/philosophy/phimvt/joy/faq1.html) Manfred

    > > talks about the reasons why having defining words avaliable at run-time

    > > is a bad idea. The reason he states in the end is one relating to

    > > creation of variables that act the same way as they would in imperative

    > > languages.

    > >

    > > I have one question and one (obvious) observation:  1) Wouldn't this

    > > only be a problem with dynamically scoped languages? If Joy was

    > > lexically scoped this wouldn't be an issue.

    >

    >

    > Early Lisps were dynamically scoped, but since Landin's ISWIM both

    > Scheme and Common Lisp are statically scoped, and so is Joy.  All of

    > them are dynamically typed: type checking occurs at run time.  In Scheme

    > and Common Lisp the static scoping is extensive: there are the global

    > definitions of functions, the names of the formal parameters, LET

    > expressions, lambda variables (and variables for assignment). With all

    > these the scoping is an intricate affair due to the possible nesting. So

    > the symbol table management becomes rather complex.  In Joy there are

    > just the global definitions, including those in HIDE's and MODULE's, and

    > all the other things don't occur. So it is all very simple.  For all

    > these statically scoped languages a symbol means what it meant when the

    > program started running, and in the case of complex nesting in Scheme or

    > Common Lisp a symbol means what the enclosing scopes defined it to mean.

    >

     Oh, right. What confuses me is the execution of the following piece of code:

    LIBRA

    a == "a";

    b == a;

    a == "b".

    b.

    In most statically scoped languages it would return "a" - in Joy it returns "b".

    Anyway I'm still curious and somewhat puzzled as to why you think having defining words

    at run-time is a bad idea?

    I don't see why it wouldn't be possible to have a language that includes a word such as

    DEF2 that still does not allow creation imperative variables?

    Expanding on your example using current-item:

    [current-item  1]   DEF2

    current-item  3  +  []  cons  [current-item]  swoncat  DEF2

    (* at this point current-item is 4 *)

    [5] [[current-item [current-item 8] DEF2] times] infra

    At this point the result could either be [4 4 4 4 4] or [4 8 8 8 8] depending on whether

    [current-item [current-item 8] DEF2] quotation compiles and uses the definition of

    current-item at the time the quotation was entered or whether it uses the most recent

    definition of it.

    The latter case resembles a variable in an imperative language but the former is purely

    functional.

     > This ignores macros in Scheme and Common Lisp.  However, I do believe that

    > some of the macro facilities available change matters somewhat. But I do

    > not understand them well enough to really tell. Google "Oleg Scheme" for

    > some wonderful stuff.

    >

    > > 2) The imperative notion of variables can be simulated with files as

    > > well. Furthermore the whole concept of binding names to values and

    > > functions is analogous to concepts of filesystems and databases.

    >

    > I think you are might be right here. But consider this:

    >

    > Assume the definition:  DEFINE foo == 111 .  (Note the space after the

    > number - without it the scanner expects digits after the decimal point.)

    > At runtime, put the string "DEFINE foo == 222 ." on the stack, write that

    > string to a file, include that file, finally do "foo put.".  All this in

    > the same run. What do you get? 222 or 111 ?  You get 111, because you are

    > still in the same run. The new definition will only be read when the Joy

    > interpreter is ready to read something, after it has executed the code for

    > the current run.  For the next run the included file will have been

    > processed, of course, and foo will mean 222.  And all this is how it

    > should be, I think.

    >

    > Maybe John Cowan has something to say on this topic.

    >

     Yes but you could still save a value (let's say it's an integer) to a file, and later read it back

    in and convert it back to an integer. You could do the same with strings, lists, pretty much

    anything else. You don't need to include a file to create imperative variables.

    As for the analogy, the main point of it was that I think it would be interesting if there was

    a way to make files and words one and the same (by files I don't necessarily mean real files

    in the filesystem but a structure that could be used in the same (or similar) way). It would

    be even more interesting if there was a way to implement something like

    that in a pure functional way that doesn't break concatenativity (not too much anyway).

    I'm sure most of you have thought about something like this at one point or another or at

    least thought about something similar or related to this.

    Assuming you have access to defining words at run time you could do something like this

    however doing it in a pure functional way is obviously problematic unless you recompile/

    redefine every word that uses/reads a certain word/file every time that particular word/file

    changes.

     >   - Manfred

     Ivan

## John Cowan — 2005-03-12 15:33:50

    Ivan Tomac scripsit:

     > Oh, right. What confuses me is the execution of the following piece

    > of code:

    >

    > LIBRA

    > a == "a";

    > b == a;

    > a == "b".

    > b.

    >

    > In most statically scoped languages it would return "a" - in Joy it

    > returns "b".

     Actually, I couldn't find a single language in which this returns anything

    but "b" (Perl, Scheme) or a compiler error (C, C++, Java).  What language

    did you have in mind?

    Perl version:

    sub a {return "a"}

    sub b {a();}

    sub a {return "b"}

    print b();

    Scheme version (for Common Lisp, change "define" to "defun"):

    (define (a) "a")

    (define (b) (a))

    (define (a) "b")

    (b)

    C/C++ version:

    # include <stdio.h>

    char *a() {return "a";}

    char *b() {return a();}

    char *a() {return "b";}

    main()) {puts(b();}

    Java version:

    class x {

    private static String a() {return "a";}

    private static String b() {return a();}

    private static String a() {return "b";}

    public static void main(String argv[]) { System.out.print(b()); }

    }

     > Yes but you could still save a value (let's say it's an integer) to a

    > file, and later read it back in and convert it back to an integer. You

    > could do the same with strings, lists, pretty much anything else. You

    > don't need to include a file to create imperative variables.

     Absolutely correct.  However, you cannot change the meaning of any word

    thereby.

    --

    LEAR: Dost thou call me fool, boy?      John Cowan

    FOOL: All thy other titles              http://www.ccil.org/~cowan

                 thou hast given away:      jcowan@...

          That thou wast born with.         http://www.reutershealth.com

## Ivan Tomac — 2005-03-12 16:52:09

    --- In concatenative@yahoogroups.com, John Cowan <cowan@c...> wrote:

     > Ivan Tomac scripsit:

    >

    > > Oh, right. What confuses me is the execution of the following piece

    > > of code:

    > >

    > > LIBRA

    > > a == "a";

    > > b == a;

    > > a == "b".

    > > b.

    > >

    > > In most statically scoped languages it would return "a" - in Joy it

    > > returns "b".

    >

    > Actually, I couldn't find a single language in which this returns anything

    > but "b" (Perl, Scheme) or a compiler error (C, C++, Java).  What language

    > did you have in mind?

    >

    > Perl version:

    >

    > sub a {return "a"}

    > sub b {a();}

    > sub a {return "b"}

    > print b();

    >

    > Scheme version (for Common Lisp, change "define" to "defun"):

    >

    > (define (a) "a")

    > (define (b) (a))

    > (define (a) "b")

    > (b)

    >

    > C/C++ version:

    >

    > # include <stdio.h>

    > char *a() {return "a";}

    > char *b() {return a();}

    > char *a() {return "b";}

    > main()) {puts(b();}

    >

    > Java version:

    >

    > class x {

    > private static String a() {return "a";}

    > private static String b() {return a();}

    > private static String a() {return "b";}

    > public static void main(String argv[]) { System.out.print(b()); }

    > }

    >

     Hmm.. good point. I should have been more clear. I was thinking functional languages

    along the lines of Caml and SML (and Haskell but then later I remembered that the

    example wouldn't work in Haskell at all - not without changing the structure of the

    example). I forgot about Scheme and I definitley wasn't even thinking of imperative

    languages.

    Either way I was wrong as clearly it's only a small subset of programming languages that

    behave that way.

    By the way your C version of the example wouldn't work (or rather compile) either as long

    as it was compiled using a strict ANSI C compiler.

     > > Yes but you could still save a value (let's say it's an integer) to a

    > > file, and later read it back in and convert it back to an integer. You

    > > could do the same with strings, lists, pretty much anything else. You

    > > don't need to include a file to create imperative variables.

    >

    > Absolutely correct.  However, you cannot change the meaning of any word

    > thereby.

    >

     True. However I still can't see why having defining words at run time is not a good idea?

     > --

    > LEAR: Dost thou call me fool, boy?      John Cowan

    > FOOL: All thy other titles              http://www.ccil.org/~cowan

    >              thou hast given away:      jcowan@r...

    >       That thou wast born with.         http://www.reutershealth.com

     Ivan

## John Cowan — 2005-03-12 17:06:24

    Ivan Tomac scripsit:

     > By the way your C version of the example wouldn't work (or rather

    > compile) either as long as it was compiled using a strict ANSI

    > C compiler.

     Absolutely.  The C and Java versions both generate compiler errors:

    neither language allows procedures/methods to be redefined in the same

    scope.  C++ of course inherits C's rules in this respect.

     > True. However I still can't see why having defining words at run time

    > is not a good idea?

     It's actually runtime *redefinition* that's problematic; runtime

    definition of novel words wouldn't be a problem.  If words can be

    redefined at runtime, we have self-modifying code, which is not amenable

    to static analysis.

    --

    John Cowan  www.ccil.org/~cowan  www.reutershealth.com  jcowan@...

    We want more school houses and less jails; more books and less arsenals;

    more learning and less vice; more constant work and less crime; more

    leisure and less greed; more justice and less revenge; in fact, more of

    the opportunities to cultivate our better natures.  --Samuel Gompers

## Ivan Tomac — 2005-03-12 17:43:46

    --- In concatenative@yahoogroups.com, John Cowan <cowan@c...> wrote:

     > Ivan Tomac scripsit:

    > It's actually runtime *redefinition* that's problematic; runtime

    > definition of novel words wouldn't be a problem.  If words can be

    > redefined at runtime, we have self-modifying code, which is not amenable

    > to static analysis.

    >

     I realize that, however there is no need to redefine existing words as I've tried to show

    with an example. It is sufficient to bind names to new bindings - all the quotations that

    have been defined with the previous definition keep using the previous definition.

    Think about it as having the current state of the environment associated with each symbol

    - if the environment changes the symbol keeps using the environment which existed at

    the time when the quotation was created.

    Obviously storing the whole state of the environment isn't necessary - just the actual

    binding for that particular symbol.

     > --

    > John Cowan  www.ccil.org/~cowan  www.reutershealth.com  jcowan@r...

    > We want more school houses and less jails; more books and less arsenals;

    > more learning and less vice; more constant work and less crime; more

    > leisure and less greed; more justice and less revenge; in fact, more of

    > the opportunities to cultivate our better natures.  --Samuel Gompers

     Ivan

## Ehrenberg Daniel — 2005-03-12 20:37:22

    > It's actually runtime *redefinition* that's problematic; runtime

    > definition of novel words wouldn't be a problem.  If words can be

    > redefined at runtime, we have self-modifying code, which is not amenable

    > to static analysis.

     In Factor, words can be redefined at parsetime or runtime, yet Factor

    has more static analysis implemented than Joy. How is this?

    Redefinitions aren't reflected in compiled Factor code that uses the

    redefined word. Example:

    : x "a" ;

    : y x ; compiled

    : x "b" ;

    y . ! "a"

    x . ! "b"

    You could add compiled declarations to x and it would do the same

    thing. This isn't the best aspect of the Factor compiler, but it comes

    up extremely rarely, and you can always declare it interpret-only.

    Anyway, for data that changes, it's almost always better to use

    Factor's dynamically scoped variables. These can hold quotations, if

    you want, though then code won't be statically analyzable anyway if

    you call a statically unknown quotation. The biggest time redefinition

    really *needs* to be used is for something like holding a random

    number seed. Joy has an ad-hoc mechanism for this, and either

    redefining words or a full-fledged variable system would help, I

    think.

    Daniel Ehrenberg

## John Cowan — 2005-03-13 06:27:56

    Ivan Tomac scripsit:

     > I realize that, however there is no need to redefine existing words

    > as I've tried to show with an example. It is sufficient to bind names

    > to new bindings - all the quotations that have been defined with the

    > previous definition keep using the previous definition.  Think about

    > it as having the current state of the environment associated with

    > each symbol - if the environment changes the symbol keeps using the

    > environment which existed at the time when the quotation was created.

    > Obviously storing the whole state of the environment isn't necessary -

    > just the actual binding for that particular symbol.

     I see no particular objection to this, but no particular benefit from

    it either.

    --

    It was dreary and wearisome.  Cold clammy winter still held way in this

    forsaken country.  The only green was the scum of livid weed on the dark

    greasy surfaces of the sullen waters.  Dead grasses and rotting reeds loomed

    up in the mists like ragged shadows of long-forgotten summers.

            --"The Passage of the Marshes"          http://www.ccil.org/~cowan

## Ehrenberg Daniel — 2005-03-13 15:59:28

    I failed to mention that there's a reason for all this. It's so when

    developing/testing at the repl, you could load a file that contains

    definitions for some of the words used in another file, without

    reloading that other file. When doing stuff at the repl, things

    normally aren't compiled, so this incongruity doesn't come up. In my

    experience, Factor seems much better suited for interactive

    development than Joy in general, and this is just one of many features

    that helps it.

    Daniel Ehrenberg

     On Sat, 12 Mar 2005 15:37:22 -0500, Ehrenberg Daniel <microdan@...> wrote:

    > > It's actually runtime *redefinition* that's problematic; runtime

    > > definition of novel words wouldn't be a problem.  If words can be

    > > redefined at runtime, we have self-modifying code, which is not amenable

    > > to static analysis.

    >

    > In Factor, words can be redefined at parsetime or runtime, yet Factor

    > has more static analysis implemented than Joy. How is this?

    > Redefinitions aren't reflected in compiled Factor code that uses the

    > redefined word. Example:

    > : x "a" ;

    > : y x ; compiled

    > : x "b" ;

    > y . ! "a"

    > x . ! "b"

    > You could add compiled declarations to x and it would do the same

    > thing. This isn't the best aspect of the Factor compiler, but it comes

    > up extremely rarely, and you can always declare it interpret-only.

    > Anyway, for data that changes, it's almost always better to use

    > Factor's dynamically scoped variables. These can hold quotations, if

    > you want, though then code won't be statically analyzable anyway if

    > you call a statically unknown quotation. The biggest time redefinition

    > really *needs* to be used is for something like holding a random

    > number seed. Joy has an ad-hoc mechanism for this, and either

    > redefining words or a full-fledged variable system would help, I

    > think.

    >

    > Daniel Ehrenberg

    >

## Ivan Tomac — 2005-03-14 04:47:30

    --- In concatenative@yahoogroups.com, John Cowan <cowan@c...> wrote:

     > I see no particular objection to this, but no particular benefit from

    > it either.

    >

     Well the FAQ stated that the reason for having infix defining word was

    because it was not a run-time operator so in an attempt to make that

    fact more explicit it was made infix.

    And the reason for it not being available at run-time was because it

    would allow for mutable variables to be created, which may or may not

    be the case depending on the scoping rules of the language.

    So doing it this way would allow you to have defining words available

    at run-time and there would be no need to have infix defining words.

     > --

    > It was dreary and wearisome.  Cold clammy winter still held way in this

    > forsaken country.  The only green was the scum of livid weed on the dark

    > greasy surfaces of the sullen waters.  Dead grasses and rotting

     reeds loomed

     > up in the mists like ragged shadows of long-forgotten summers.

    >         --"The Passage of the Marshes"

     http://www.ccil.org/~cowan

    Ivan

## phimvt@lurac.latrobe.edu.au — 2005-03-16 04:52:46

    On Sat, 12 Mar 2005, Ivan Tomac wrote:

    [..]

    > Anyway I'm still curious and somewhat puzzled as to why you think

    having

    > defining words at run-time is a bad idea?  I don't see why it wouldn't

    > be possible to have a language that includes a word such as DEF2 that

    > still does not allow creation imperative variables?

    It would certainly be possible to have such a language that allows a DEF2,

    and in some ways the early Lisps were just like that. But in some paper

    the inventor of Lisp, John McCarthy, confessed that the early

    implementations of Lisp had dynamic scope because he had misunderstood

    Church's lambda calculus. I con't have a reference to that paper.

    The accepted difficulty withh dynamic scope is that it is hard to reason

    about programs.

    [..]

    > Yes but you could still save a value (let's say it's an integer) to

    a file, and later read it back

    > in and convert it back to an integer. You could do the same with strings, lists, pretty much

    > anything else. You don't need to include a file to create imperative variables.

    Yes, but the net effect is no different from just saving something on the

    stack, and using it later, with a possibly long piece of code in between.

    Suppose you wanted what in a procedural language would be an assignment "x

    := 123", and later use x somewhere. In a stack language this might look

    like this: "123 >>x", meaning "push 123, move top-of-stack to variabe x".

    Later use x somewhere, where x now means "push 123".  And as you say

    rightly, instead of doing ">>x", open a file called "x"  for writing,

    write the top-of-stack to the file, close the file.  Do something else,

    say, P, which does not involve the value stored in "x".  Then open file

    "x" for reading, read its content and push it onto the stack. Close the

    file. This will do what you want. But instead of using a file you could do

    the following:

            123  [P] dip

    After the dip has executed, the original 123 will still be there. If you

    want to save more than one value, say three in all, you could write

            123 [] cons cons cons  [P] dip

    and now all three will be available in a list from which you can take

    the wanted items. To take an extreme case, where you want to restore

    the entire stack (as a list), do this:

            123  stack  [P] dip

    Hence, whatever can be done by using named files can be done by dip.

    So, since Joy is purely functional without files, it remains purely

    functional with files. (Thanks John Cowan.)

    [..]

      - Manfred

## Ivan Tomac — 2005-03-17 13:21:57

    --- In concatenative@yahoogroups.com, phimvt@l... wrote:

     > > Anyway I'm still curious and somewhat puzzled as to why you think

    > having

    > > defining words at run-time is a bad idea?  I don't see why it wouldn't

    > > be possible to have a language that includes a word such as DEF2 that

    > > still does not allow creation imperative variables?

    >

    > It would certainly be possible to have such a language that allows a

     DEF2,

     > and in some ways the early Lisps were just like that. But in some paper

    > the inventor of Lisp, John McCarthy, confessed that the early

    > implementations of Lisp had dynamic scope because he had misunderstood

    > Church's lambda calculus. I con't have a reference to that paper.

    > The accepted difficulty withh dynamic scope is that it is hard to reason

    > about programs.

    >

     Interesting.

    However it's possible to have a word such as DEF2 and still have a

    lexically scoped language without mutable variables as I've tried to

    explain in the last few posts.

    Although I haven't looked at the source code for Joy, I get the

    feeling that it stores all definitions in a hashtable or something

    similar. Any new definition seems to overwrite any previous definition

    of the same name and every quotation that contains a reference to that

    particular name starts using the new definition.

    Alternatively you could use a stack for definitions. New definitions

    are simply pushed on stack and any quotation that refers to old

    bindings continues to use the old bindings.

    Existing bindings do not change so there are no mutable variables and

    so new bindings can get created at run-time without affecting any

    existing quotations and definitions.

    Defining words in such a language are no different to any other word

    and there is no reason to separate them from the rest of the language.

     > > Yes but you could still save a value (let's say it's an integer) to

    > a file, and later read it back

    > > in and convert it back to an integer. You could do the same with

     strings, lists, pretty much

     > > anything else. You don't need to include a file to create

     imperative variables.

     >

    > Yes, but the net effect is no different from just saving something

     on the

     > stack, and using it later, with a possibly long piece of code in

     between.

     > Suppose you wanted what in a procedural language would be an

     assignment "x

     > := 123", and later use x somewhere. In a stack language this might look

    > like this: "123 >>x", meaning "push 123, move top-of-stack to

     variabe x".

     > Later use x somewhere, where x now means "push 123".  And as you say

    > rightly, instead of doing ">>x", open a file called "x"  for writing,

    > write the top-of-stack to the file, close the file.  Do something else,

    > say, P, which does not involve the value stored in "x".  Then open file

    > "x" for reading, read its content and push it onto the stack. Close the

    > file. This will do what you want. But instead of using a file you

     could do

     > the following:

    >

    >         123  [P] dip

    >

    > After the dip has executed, the original 123 will still be there. If you

    > want to save more than one value, say three in all, you could write

    >

    >         123 [] cons cons cons  [P] dip

    >

    > and now all three will be available in a list from which you can take

    > the wanted items. To take an extreme case, where you want to restore

    > the entire stack (as a list), do this:

    >

    >         123  stack  [P] dip

    >

    > Hence, whatever can be done by using named files can be done by dip.

    > So, since Joy is purely functional without files, it remains purely

    > functional with files. (Thanks John Cowan.)

    >

     I don't doubt that Joy is purely functional - you, Billy and John

    already convinced me Joy can be thought of as purely functional about

    3-4 years ago when I joined this message board :)

    I'm still thinking about your analogy between saving values on stack

    and saving them to a file.

    The problem with that is how would you simulate a self-contained

    program that takes no parameters on the stack, reads a file, waits for

    some user input and then writes something to a file?

    The only way to do that without files would be to pass some sort of a

    data structure that resembles a filesystem to every word that needs to

    read or write files. Every such word would need to return the modified

    filesystem structure as well.

    This would be very inconveniant though so passing the filesystem

    implicitly to every word makes sense. But at the same time it

    introduces mutable variables.

    What I'm curious about is why go to such an extent to eliminate

    mutable variables (like separating defining words from the rest of the

    language) when effectively files are mutable variables?

    On another note here's a little state transformer in Joy (inspired by

    monads, I decided to go back to playing with Haskell now that 6.4 is

    out) - quite useless considering how you could easily do the same

    thing by just using the stack but I thought it was still amusing:

    LIBRA

    checkSymbol == [] cons [intern =] concat [[list][false]] dip ifte ;

    checkGet == [["get" checkSymbol] [pop dup]] dip ifte ;

    checkSet == [["set" checkSymbol] [pop pop]] dip ifte ;

    runS == [[[dip] checkSet] checkGet] step .

    5 2 [[7 +] get [+ 55] set [5] get [+]] runS .

    (* final result on stack: 14 60 55 *)

     >   - Manfred

     Ivan

## John Cowan — 2005-03-17 13:43:13

    Ivan Tomac scripsit:

     > Although I haven't looked at the source code for Joy, I get the

    > feeling that it stores all definitions in a hashtable or something

    > similar. Any new definition seems to overwrite any previous definition

    > of the same name and every quotation that contains a reference to that

    > particular name starts using the new definition.

     Correct.  This is the usual Lisp/Scheme/APL style, what I called

    "whacking on a workspace".

     > Alternatively you could use a stack for definitions. New definitions

    > are simply pushed on stack and any quotation that refers to old

    > bindings continues to use the old bindings.

     Yes, we could.  But that implements lexical scoping if and only if

    there are no defining words at run time (as is the case in MLish

    languages).  Indeed, the strict interpretation of such a feature

    renders it useless.  Suppose we write the definition of a word A

    which at runtime defines the word B.  But there is no way for A

    or any pre-existing word to invoke B, since it was not already

    defined when A was compiled.  So now we need a new word meaning

    "invoke the most recent (dynamic) definition of a specified word",

    and that breaks lexical scoping completely.

     > The only way to do that without files would be to pass some sort of a

    > data structure that resembles a filesystem to every word that needs to

    > read or write files. Every such word would need to return the modified

    > filesystem structure as well.

     Quite right, which is why the Joy words that do I/O leave the file

    objects on the stack (the Joy version of a monad, and much simpler

    than the lazy-functional version!).

     > What I'm curious about is why go to such an extent to eliminate

    > mutable variables (like separating defining words from the rest of the

    > language) when effectively files are mutable variables?

     When Manfred wrote Joy0, he was concerned mainly with proof of concept.

    When I extended it to make Joy1 (the current reference implementation),

    I wanted Joy to have all the capabilities of ANSI C, so files and floats

    arrived in the language despite their well-known theoretical difficulties.

    --

    Is a chair finely made tragic or comic? Is the          John Cowan

    portrait of Mona Lisa good if I desire to see           jcowan@...

    it? Is the bust of Sir Philip Crampton lyrical,         www.ccil.org/~cowan

    epical or dramatic?  If a man hacking in fury           www.reutershealth.com

    at a block of wood make there an image of a cow,

    is that image a work of art? If not, why not?               --Stephen Dedalus

## Ivan Tomac — 2005-03-17 15:51:10

    --- In concatenative@yahoogroups.com, John Cowan <cowan@c...> wrote:

     > > Alternatively you could use a stack for definitions. New

     definitions

     > > are simply pushed on stack and any quotation that refers to old

    > > bindings continues to use the old bindings.

    >

    > Yes, we could.  But that implements lexical scoping if and only if

    > there are no defining words at run time (as is the case in MLish

    > languages).  Indeed, the strict interpretation of such a feature

    > renders it useless.  Suppose we write the definition of a word A

    > which at runtime defines the word B.  But there is no way for A

    > or any pre-existing word to invoke B, since it was not already

    > defined when A was compiled.  So now we need a new word meaning

    > "invoke the most recent (dynamic) definition of a specified word",

    > and that breaks lexical scoping completely.

    >

     While it doesn't add any expressive power  to the language it

    basically makes defining words no different from any other word which

    means there is no need to make them stand out - makes the syntax more

    consistent so I wouldn't say it's useless.

    There is no need to add a new word to invoke the most recent

    definition of the specified word - that would clearly add dynamic

    scoping to the language.

    I see nothing wrong with B being defined at run-time by A even if A

    cannot use it. Anyway I think such a thing would be quite rare - to

    have a word defined within another rather then at the top level - but

    the whole point of it is that it wouldn't break lexical scoping rules

    of the language even if it was used within a quotation like that.

     > > The only way to do that without files would be to pass some sort

     of a

     > > data structure that resembles a filesystem to every word that

     needs to

     > > read or write files. Every such word would need to return the

     modified

     > > filesystem structure as well.

    >

    > Quite right, which is why the Joy words that do I/O leave the file

    > objects on the stack (the Joy version of a monad, and much simpler

    > than the lazy-functional version!).

    >

     I'm not sure that can be compared to a monad, or at least not for that

    reason. You could say the same thing about imperative languages: all C

    functions that operate on files take a file handle or a stream as one

    of the arguments.

    The problem with that is what happens once the file is closed? The

    file object or the handle disappears while the monad persists and gets

    passed on as a continuation.

    I think a better analogy would be that the whole filesystem gets

    implicitly passed as an argument to every word. Or rather that the

    whole state of the world or the environment gets passed as an argument

    to every word.

     > > What I'm curious about is why go to such an extent to eliminate

    > > mutable variables (like separating defining words from the rest

     of the

     > > language) when effectively files are mutable variables?

    >

    > When Manfred wrote Joy0, he was concerned mainly with proof of

     concept.

     > When I extended it to make Joy1 (the current reference

     implementation),

     > I wanted Joy to have all the capabilities of ANSI C, so files and

     floats

     > arrived in the language despite their well-known theoretical

     difficulties.

     >

     Fair enough. That makes sense.

     > --

    > Is a chair finely made tragic or comic? Is the          John Cowan

    > portrait of Mona Lisa good if I desire to see           jcowan@r...

    > it? Is the bust of Sir Philip Crampton lyrical,

     www.ccil.org/~cowan

     > epical or dramatic?  If a man hacking in fury

     www.reutershealth.com

     > at a block of wood make there an image of a cow,

    > is that image a work of art? If not, why not?

     --Stephen Dedalus

    Ivan

## phimvt@lurac.latrobe.edu.au — 2005-03-18 08:49:04

    I have added a new item to the Joy page, in section 2 towards the end,

    the third-last item. Alternatively, view it directly:

        http://www.latrobe.edu.au/philosophy/phimvt/joy/jp-reprod.html

    It isn't quite finished, and there still are lots of typos due to

    key-bounce. I don't quite know when I can work on it again.

    In the meantime,  enJoy.

      - Manfred

## Narcoleptic Electron — 2005-03-18 15:56:26

    Ivan Tomac wrote:

     > Or rather that the

    > whole state of the world or the environment gets passed as an argument

    > to every word.

     This is what the Clean language does.

    http://www.cs.ru.nl/~clean/