# Re: [stack] Digest Number 28

## Mark van Gulik — 2000-06-02 23:54:18

    "Samuel A. Falvo II" <kc5tja@...> wrote:

     >

    > On Wed, 31 May 2000, Mark van Gulik wrote:

    >

    >> Please show me a proof (hand waving is allowed) that any Forth program which

    >> doesn't crash without GC still will not crash when GC is present.  Then I

    >> will consider calling the garbage collector "conservative".  Without that I

    >> will call it "guessing".

    >

    > The problems you cited with a CGC are problems which must be *explicitly

    > coded for*, so it is NOT my responsibility to show you proof of any kind,

    > any more than it is for me to show you proof of my identification.  As

    > I've indicated more than once before, if you want more information on

    > Forth-specific implementations of things, comp.lang.forth is the place to

    > be.

     I'm sorry.  I didn't mean I wanted *you* to show me the proof, only that I'm

    not satisfied by a CGC unless it exhibits that proof as a precondition.  I'm

    just saying that the definition of CGC that I'm most comfortable with is

    simply GC but without the constraint that "all garbage will eventually be

    recycled".  Unfortunately, industry seems to treat as CGC anything that acts

    like a CGC for some subset of a language, but will completely fail if the

    full language is used.  Thus, what you call a Forth GC is really a GC on a

    particular *subset* of Forth.  Using the whole language is an incompatible

    activity with expecting the garbage collector to work.  That's all.  I'm

    sorry I didn't express this correctly in my previous comments (I probably

    shouldn't have hit "send", but I was in a rush).

     > Furthermore, the type of GC "conservative" describes is very well

    > understood in the computer science and engineering worlds; *don't* just

    > arbitrarily re-define the meaning of certain words, or even re-label a

    > well known design practice; it gives you a very stuck-up image and *will*

    > cause major communications problems with others.

    >

    > If you don't like my use of the term "conservative", well, too damned bad.

    > Deal with it.  It's what everyone else out in the real world uses, so

    > that's what I'm going to use.  We can't change history, so let's just put

    > it behind us, and move on.

     No problem.

## Mark van Gulik — 2000-06-03 00:40:37

    wtanksley@... wrote:

     >

    > From: Mark van Gulik [mailto:ghoul6@...]

    >>Massimo Dentico <m.dentico@...> wrote:

    >>> Mark van Gulik on Concatenative mailing-list wrote:

     [...SNIP stuff about scale issue of Forth in response to...]

     >>> Forth: IMHO the approach

    >>> "the language is the type system", that you also seem to

    >>> embrace with Avail, looks very promising.

    >

    > BTW, I've been talking with the guy who implemented the strong typesystem

    > for Forth, and it turns out that the language IS the typesystem for him.  He

    > is using the Forth way of doing things after all.  You can include any Forth

    > code in the type declarations.

     Cool.

     >>The biggest

    >>difference I see is that Smalltalk *hides* layers better than

    >>what I recall of Forth.

    >

    > Smalltalk has many, many layers to hide, even just with nothing but the VM

    > running.  Forth doesn't.  This doesn't mean that Forth is worse at hiding

    > layers; however, it does mean that it doesn't bother hiding the language

    > layers.

    >

    > As part of writing a system or application in Forth, you're supposed to

    > write words which effectively hide their implementation (and the language

    > layers) and expose an interface which is appropriate to the nature of the

    > problem.  It's recommended that you don't try to hide the Forthness of the

    > solution (for example, by writing a C parser which outputs Forth code), but

    > it's certainly possible to do that.

     I stand corrected.  This is, of course, a "best practice", but that's what I

    was looking for.

     >>In other words, Smalltalk works much, much better

    >>when building upwards than when building downwards.

    >

    > I'm not sure how to take this.  Do you mean that Smalltalk is good at

    > bottom-up design?  Forth is also renowned for that.

     No, I was referring to building higher level constructs on top of existing

    ones, versus rebuilding lower level constructs to better support existing

    ones.

     >>I can understand *implementing* another language in Forth, but

    >>embedding it seems kind of awkward.

    >

    > That's the huge advantage of concatenative languages -- because the language

    > itself has no parser (or almost none), the words can act as parsers without

    > interference from the language.  For example, someone implemented a FORTRAN

    > embedded in Forth (which later was reduced to just a formula translator, but

    > originally had an almost complete FORTRAN).  In use, it looked like this:

    >

    > VARIABLE x

    > : myWord  i" 3*4/x+sin(x)" ;

    >

    > As you see, it just fits right into the language, and allows some things to

    > be expressed in a manner more appropriate to certain problem domains.

    >

    > In short, i-quote (i") is a Forth word which is set to execute immediately,

    > regardless of whether Forth is compiling.  Its job is to search ahead in the

    > input stream until it finds the quote which marks the end of its input, and

    > then it has to parse the expression and emit Forth code for it.  It's

    > actually pleasantly simple to implement, but who cares about implementation

    > when it's so easy to use.

     In Avail syntax I would probably be able to embed the syntax directly,

    without resorting to quoting (even though the quotes have effectively

    dissolved by runtime in your example).

     >>GC in Forth is a big surprise to me.

    >

    > Why?  It's natural.

     The more detailed control a non-GC'ed language has over memory, the harder

    it is to retrofit a reliable, plausible garbage collector.  By plausible I

    mean that the restrictions that the GC places on a user's code are minimal.

    I expect that a Forth GC would be extremely limiting, but probably not as

    much as attempting to garbage collect C (no, I don't mean C++).

    [...trivial code that will fail with GC but succeed without...]

     > You seem to be confusing GC with memory protection.  In a language which

    > allows stores to arbitary addresses, memory corruption is always possible.

    > You don't need to add GC to allow it, and adding GC doesn't change anything

    > about it.

     Ah, but if GC turns a working program into a non-working one, then GC is the

    *cause* of the failure -- i.e., the GC is not working.  If you restrict the

    language features to allow GC to function in all cases, you've effectively

    implemented GC on a subset of the language, which is different from (but not

    necessarily worse than) supporting GC in the full language.

     > If you're coding at a low level with Forth and GC is enabled, you can do

    > things that will kill the GC.  They will hurt.  Don't do them.  If you're

    > coding at a high level, though, such things are impossible.  That "high

    > level" may appear very much like the low level Forth code you're used to

    > writing, but if it has memory protections, it's a higher level.

     Sounds fair, until you try to combine code from multiple sources.  E.g., "Is

    the code in that library compatible with that other library's garbage

    collector's language restrictions?"

     >>[...]Is it common practice

    >>(yet) to use assertions in the language?

    >

    > Not really.  It's far more common to use compile-time unit tests/regression

    > tests.  The problem with assertions is that they _require_ application: you

    > have to be able to remove them when you're about to distribute.  It's

    > possible to do that by building a special sublanguage which handles the

    > assertions applicatively, but most people don't bother.

    >

    > As an example of what I mean, consider a Forth word ABORT" (abort-quote),

    > which takes a flag on the stack and dies if it's true (printing out a

    > message in the process).  You could put an assert of the form:

    >

    > : myWord  dup 0 > ABORT" my param must be bigger than zero."

    >     3 swap /

    >    ;

    >

    > ...but you can clearly see that this adds considerable bulk to the word, and

    > there's no way to optimise it out (without using dataflow and assuming that

    > anything having to do with ABORT" is a waste of time).

    >

    > An example of the right way to do this is provided by a fictional word,

    > "ASSERT|".

    >

    > : myWord ASSERT| dup 0 > " my param must be bigger than zero." |

    >     3 swap /

    >    ;

    >

    > Now we can define ASSERT to skip over everything up to the next | when we

    > don't want the asserts in the code.  This is very simple to implement -- but

    > few Forth programmers use it.

    >

    > There are two replacements.  First, compile-time unit tests are a

    > phenominally powerful means for documenting code and discovering errors.

    > Second, interactivity allows for considerable examination of code in ways

    > not appropriate for unit tests.  The two together allow for expressivity at

    > _least_ equal (if not better than) the expressivity given by Design By

    > Contract (assertions).

     Personally, I never disable assertions except one-at-a-time, and only when

    looking at actual times with a profiler.  A compile-time unit test sounds

    intriguing.  The Avail modules are already kind of structured that way,

    where many modules have a corresponding test module that can be compiled and

    executed very easily.

     >>That's why Avail was designed from the ground up to support dynamic

    >>optimization.  The current implementation has a stack-oriented

    >>nybblecode representation for space, which is dynamically

    >>translated, only when used heavily, into a wordcode representation

    >>that's RTL-like.  All optimizations are reversible, even for

    >>existing stack frames.  Basically, the wordcode interpreter is

    >>*completely* hidden from application developers (it can be

    >>omitted entirely from the VM to save space on tiny

    >>platforms).

    >

    > This is very similar to what I plan for the high level of my Joylike

    > languages, except that I'll use wordcode where you use nibblecode, and

    > native code where you use wordcode.  At a low level, though, no optimization

    > will EVER  be secret; you have to ask for it in order to make it happen

    > (there will be words which carry out the optimizations).  In other words,

    > the compiler itself will be written in the low level code, and it'll be very

    > simple indeed.

     Avail doesn't necessarily keep secret which optimizations have been

    performed.  I'm planning a call-back from the VM to the current running

    process (or some other software-interrupt architecture) in which

    optimization requests can be handled by actual Avail code.  This, of course,

    is to leverage the safety and flexibility of the language over having to use

    Smalltalk or C++ to implement optimization rules.  BTW, I don't recommend

    leaving it up to the application-level programmer to decide which areas to

    apply optimizations.  For a terrifically bad example, look at the way

    inlining is specified in C++.  An inlining hint actually alters the

    semantics!

     >>Actually, I don't know of a language for with 10x productivity is *not*

    >>claimed by its advocates!

    >

    > Correct.  Hardly suprising -- the difference between a good programmer and a

    > bad one is 25x.  In other words, 10x is noise.  Chuck Moore claims 1000x for

    > Forth -- not 1000x productivity, but rather 1000x quicker speed and smaller

    > size without the need for any more budget.  I don't speak for him; check his

    > work at http://www.ultratechnology.com

     Hm.  Most of the time 1000x quicker would be meaningless for what I do

    (I.e., almost everything I write runs faster than I can detect visually).

    In my current work (large scale databases) it sure would be nice, but this

    is a very rare exception.  I doubt, however, that Forth would significantly

    improve disk latency within OODB requests (certainly not 1000x).

     >>> Don't Complexify

     [...]

     >>Ah, but that assumes you will never be asked to solve the

    >>general problem.

    >

    > No, it assumes _nothing_.  That's the beauty of it.  It only solves the

    > problem at hand -- and it leaves you with _real_ experience of what the

    > specific problem is actually like.  If you are later asked to solve the

    > general problem (and that does sometimes happen), you'll be able to

    > confidently write the general solution, knowing that you have a specific

    > solution to test it against (or perhaps even to base it on).  If you aren't

    > asked for that, you haven't spent any extra time or effort on it.

     Ok.  One test case (or two, as XP implies) will help make sure of the

    applicability of a general solution.  But the specificity (and complexity)

    of these cases might be much higher than similarly "contrived" test cases

    would have.  Also, after the general solution is implemented, the specific

    solutions would have to be completely rewritten within the context of the

    general solution to be useful as test cases.

     > But consider the best case for your argument: the times when you actually

    > _are_ asked for the general solution.  Did you _really_ test your generic

    > code for all of the cases in the general solution?  Are you so certain that

    > it's the best solution?  I've never seen first-draft generic code which

    > actually worked.  I have seen first-draft specific code, though.  And the

    > experience granted by writing that working specific code will certainly lead

    > the programmer to choose wisely when it comes to the choice between

    > rewriting and refactoring.

     Getting it right the first time (or soon thereafter) is what professionals

    do.  Some people reason well with pure mathematical frameworks ("the

    rules"), other people have to deal with single concrete problems ("the

    example"), and other people have to look at both at the same time to get

    good solutions.  In my experience there is a gender correlation (women have

    a moderate tendency to deal better with the example side, and men favor the

    rules side).  Some experimental studies I read about (long ago, sorry no

    links) seem to confirm this mild trend.

     >>I disagree with the level of "fix it up later" that XP

    >>advocates.

    >

    > And I strongly agree -- with the caveat that "fix it" implies that it's

    > broken now, which is the opposite of what XP advocates.

     I did intentionally avoid saying "fix it later", and chose to insert

    "...up...", trying to give it a connotation of something like cleanliness,

    luxury, or maybe attention to detail.  Yes, make sure everything is

    maximally tested (and working) early on, keeping it that way.  No, I don't

    think one should do that to the exclusion of elegant design from

    generalization.

     >>At first,

    >>when I read the Charles Moore quote I thought "so, writing ten

    >>times as much code doesn't mean it took 10x longer to do".

    >

    > Correct.  You can spend 10x more time per line, so you can quite possibly

    > wind up in a tie, in terms of time spent, with a person writing bulkier

    > code.  The difference is that your code will be able to be written and

    > maintained by a single person instead of requiring a team; and THAT can

    > suddenly start saving a _lot_ of time and grief.

     Shorter code does not imply fewer people are required for maintenance.  With

    any refactoring tools (even a multi-file search & replace) one person can

    maintain denormalized code within 10x the cost of normalized code.  There

    are much bigger issues to the maintenance cost, e.g., how much early

    generalization was present (also called Frameworks), etc.

     > At any rate, it's clear that a concatenative language _can_ be vastly

    > simpler and more transparent than an applicative one.  At this point we have

    > to ask whether it's neccessary or good.  I believe that it is good, and I'm

    > designing the first of my two concatenative languages on the basis of that

    > assumption.

     How do the assertions fit in with Joy?  Maybe an operation like:

        assert == i

    for debugging, and

        assert == pop

    for maximum speed would be appropriate (e.g., "[2 2 + 4 =] assert").

## Mark van Gulik — 2000-06-03 01:43:57

    Massimo Dentico <m.dentico@...> wrote:

     > Mark van Gulik wrote:

    >> I'm positive that Forth is applicable over an enormous range of domains,

    >> mostly due to its core simplicity and extreme extensibility.  I'm mostly

    >> concerned, however, with the ability to build *restrictions* in the

    >> language.

    >

    > I completely agree with this. In particular, the key concept is

    > ".. the ability to build *restrictions* in the language". This means

    > that *you*, the programmer, build the restrictions when you really

    > need it and it's not the language designer that in arbitrary way

    > restricts you.

     I almost agree.  The language designer also has the responsibility of

    building the right restrictions *into* the language, such that it will have

    clean semantics and high reliability (the two tend to go together).  For

    example, in another thread I argued that conservative garbage collection

    (CGC) in Forth is really CGC in some proper subset of Forth.  That's because

    Forth's semantics are too strongly defined in terms of machine

    representation to allow CGC (in the full language).  A redesign of Forth is

    possible to accomodate CGC for the full language, but it wouldn't look much

    like Forth afterwards.  Basically issues like GC, type systems,

    optimization, and design-by-contract must be *designed into* a language, not

    added later (typically by subtractive synthesis as with CGC and retrofitted

    type systems).

    But I agree completely with the part about being able to build restrictions

    *in* the language (to produce "dialects" that have stronger properties).

    I used to think that the "ideal language" (hey, I was young) was a language

    in which it was particularly easy to write other languages, each one

    tailored to solving a particular class of problems.  When I proposed this

    theory to my teacher Wilf LaLonde, he said [deeply paraphrasing] "Smalltalk

    already does that.  The protocol of a class is effectively the syntax of a

    language unique to its instances, and the framework of Smalltalk allows

    these objects to work together on a common substrate."  That was one of

    those world-view-changing moments for me.

     > The ability to restrict a language is crucial to reconcile

    > extensibility and safety. Plan-P is such an example:

     [...excellent example snipped...]

     > Safety and security. Because the language is restricted, many properties

    > are automatically verifiable. For exemple PLAN-P ensures global termination

    > and guarantees no packet loss or exponential duplication.

     This sounds like an excellent solution for the problem it's trying to solve

    (proving a certain type of reliability within some class of algorithms).

     >> I've long felt that the power of a programming language depends

    >> in two nearly opposite was on how restrictive it is.

     [...]

     >

    > A concatenative language (but I thik this is true for other laguages too)

    > should suggest, in any case, to use 1 or 2 and not more than 3 parameters,

    > like Moore recommend for Forth, so that the name of the word (function)

    > define the meaning of the parameter(s) in an implicit way. However, simple

    > checking mechanisms are possible via annotations: you annotate the expression

    > tree nodes during definition and you check it during actual use. These

     annotations

     > could be types but not only. Pratically this means the introduction of

     auxiliary

     > stack(s). I think other on this list can express this idea better than me.

     Ah, but is the advice to use very few parameters a general maxim of

    programming, discovered by the magnification of the effect in a stack-based

    language, or is it a manifestation of a shortcoming of stack-based

    languages?  I suspect the latter, but I'm sure it's tied in to cognition and

    short term memory (the old 7+-2 argument).

     >> As for "the language is the type system" in Avail...  that's only because I

    >> got to the implementation of the type system before most of the other things

    >> in my stacks of notes.  Hm, maybe you meant it in the sense of "the type

    >> declarations of Avail are written in Avail code".  I think I was

    >> interpreting it more like "everything interesting in Avail has to do with

    >> the type system" when I first read it.

    >

    > This is what I meant: "the type declarations of Avail are written in Avail

     code".

     > Another way to express it is: "you blur the distinction between expression

    > languages for values and types". This means that you reduce the number of

    > different syntactic *and* semantic elements in the language. This is closely

    > related to staged computations in my mind:

    >

    > a type system in a language (statically or dynamically checked) is useful

    > for restricting run-time values of expressions (and in case variables);

    > a static typing ensures at compile-time that the program  will satisfy these

    > restrictions; but, in a language where type declarations are written in

    > the language itself, the only element that differentiates these (type

    > declarations) and other code is the stage (compile-time vs run-time).

    > In a language which offers explicit stage annotations (as in Forth with

    > words like IMMDEDIATE) the distinction between the language and the type

    > checker is completely blur (the code for the checker is not different

    > from other IMMEDIATE code).

     An example from Avail:

    --------------------------------------------------------------------------

    Forward "_+_" for [extended integer, extended integer]->extended integer;

    /* Helper method to define + without the benefit of - in the returns

    clause... */

    Method "_privateMinus_" is [a : extended integer, b : extended integer |

     Primitive 2;

     Failed;

    ] : extended integer;

    Method "_+_" is [a : extended integer, b : extended integer |

     Primitive 1;

     if a is infinite & b is infinite & a not = b then [

      Crash "Can't add positive infinity to negative infinity";

     ] else [

      Crash "Unknown problem in addition primitive";

     ];

    ] : extended integer

    returns [aT : integerType, bT : integerType |

     /* The range calculation below is ok with respect to infinite bounds,

        because a bound can only be exclusive if it is infinite. */

     range from (aT lower bound + bT lower bound) privateMinus 1

      inclusive (aT lower inclusive & aT lower bound is infinite)

       | (bT lower inclusive & bT lower bound is infinite)

      to aT upper bound + bT upper bound + 1

      inclusive (aT upper inclusive & aT upper bound is infinite)

       | (bT upper inclusive & bT upper bound is infinite);

    ] : integerType;

    --------------------------------------------------------------------------

    In the "_+_" method's "returns" clause, I invoke the very "_+_" method I'm

    defining.  The purpose of a "returns" clause is to restrict the return type

    of a method invocation, based on the static types of the arguments *at a

    call site*.  Since it was forward declared previously, the call site(s) for

    "_+_" found within the "returns" clause is only as precise as the forward

    declaration specified.  Immediately after executing the defining word

    "Method_is_returns_" (passing in the string "_+_" and two closures as

    arguments), any new invocations of "_+_" will be compiled with the more

    precise type calculations.

    This issue with "helical" (circular, but offset in time) definitions arose

    in many places within Avail, due to the fact that there are no keywords at

    all in the language.  The first bootstrap module uses a pragma to provide

    the two method names needed to bootstrap the rest of the system (I consider

    this a kind of "cheating", but there's no other way).  In case you're

    interested, the method names are "Special Object_" and "Method_is_".  The

    first one lets me get to special constants (e.g., built-in types), and the

    second one lets me extend the system.  In Forth, the second one would be the

    equivalent of defining : and ; as ordinary words!

    One reason for this extreme minimalism at early bootstrap is to allow the

    language to be translated into syntaxes based on other natural languages

    (e.g., a Spanish Avail and a French Avail).  Also, I want to allow other

    syntaxes to be layered on top of Avail (not interpreted or separately

    parsed, like the i" word in Forth that someone described).  Basically, if I

    import two clashing syntaxes I should be able to use some kind of disjoint

    union of the two to express a program.  Avail's syntax is very very modular,

    so this should be a plausible scenario.  In the case of an ambiguous

    statement, the user will be notified at compile time, as with any

    ambiguities not automatically resolved by elimination of type-incorrect

    interpretations.

    Maybe I should write a simple extension of Avail to support Joy syntax.  I

    think I'd have to use a thread-variable to hold the implicit stack.  I could

    define the "__" operation (i.e., two arguments with only whitespace between

    them) as function composition, and make it left-associative (to avoid

    ambiguous parsing, despite the unuseable guarantee of associativity).

    Hm, maybe concatenative function composition is the only thing I need.  If

    the word "pop" evaluates to a function of type [stack]->stack, I don't need

    the thread-variable mechanism (it also yields a functional implementation).

    I think this will work!  I'll post a Joy interpreter in Avail in the next

    day or so...

     > I want only to add that Forth quotation seems less intrusive in comparison

    > to the quotation mechanism of Joy and more appropriate to absorb other

    > syntaxes. I would like hear your (list participants) opinion regard this

     subject.

    Quotation should be as explicit as possible, as it represents a form of

    "escape" from a language.  If a language construct can be directly embedded,

    no quotation is necessary, but if quotation really is necessary then it

    should not be concealed under any circumstances.

     > I don't like assertion: they are usually intended as dynamically checked

    > invariants instead I prefer statically checked invariants when possible.

     I also don't like having to resort to runtime checks.  A very rich type

    system allows many assertions to be expressed as type-assertions, which are

    guaranteed to be correct at compile time.  That's a direction that Avail has

    explicitly taken.

    [...example comparing OCaml and C...]

     > Contrary to popular belief *size matters* and *the language make the

     difference*.

    I would say the language makes much of the difference, but discipline can

    compensate for a small but significant part of it.

     >> Anyhow, *finding* the appropriate abstraction level is most of my effort when

    >> working with Smalltalk, both in reading it and writing it, but in different

     ways

     >> that I'm not sure I can describe well.

    >

    > Probably this is related to the fact that a single notation is not enough,

    > see my post on Tunes mailing list:

     [snip]

    Ah, but this relates to my paraphrased conversation with Wilf LaLonde (up a

    couple of pages).

     > "Meta-programming important for Psychology of Programming"

    > - http://lists.tunes.org/list/tunes/0005/msg00000.html

    >

    > Beacuse metaprogramming seems more simple with a concatenative

    > language than with applicative languages, I think they are a valuable

    > option as a minimal canonical notation on which construct different

    > views (abstractions) via metaprograms.

     But what kinds of sublanguages are possible (and useful)?  Is it possible to

    create a useful subset of Joy that doesn't use metaprogramming?  Probably

    not.  Since "meta" in this context means "unusual" or "atypical" (often with

    circularity as the triggering criterion), is it "a good thing" for a

    language to rely on metaprogramming for the simplest of tasks?  At this

    point I doubt it (but of course I still want to explore this area for a few

    more decades).  Maybe relabelling it as something other than

    "metaprogramming" would ease my mind (did I just prescribe myself an obvious

    placebo?).

## wtanksley@bigfoot.com — 2000-06-05 16:44:58

    From: Mark van Gulik [mailto:ghoul6@...]

     >Ah, but is the advice to use very few parameters a general maxim of

    >programming, discovered by the magnification of the effect in

    >a stack-based

    >language, or is it a manifestation of a shortcoming of stack-based

    >languages?  I suspect the latter, but I'm sure it's tied in to

    >cognition and short term memory (the old 7+-2 argument).

     It's primarily tied to the fact that all computer resources are limited.  A

    function with a large number of parameters will use a lot of resources

    (regardless of whether the language is concatenative or applicative).

    Conjointly, human memory is also limited; you cite 7 for short-term memory,

    but there's another limit: 3 items can be instantly recognised as a gestalt.

    With more than three items, you have to count and parse.  With three or

    less, you can just glance and recognise.

    I do, however, suspect that there may be a stronger tie to human

    comprehension in stack languages.  In that respect it might be a defect in

    stack languages.  There's no research on this, though, and the phenomenon

    seems adequately explained by the above paragraph.

     >I think this will work!  I'll post a Joy interpreter in Avail

    >in the next day or so...

     Impressive.

     >> I want only to add that Forth quotation seems less intrusive

    >> in comparison

    >> to the quotation mechanism of Joy and more appropriate to

    >> absorb other

    >> syntaxes. I would like hear your (list participants) opinion

    >> regard this subject.

    >Quotation should be as explicit as possible, as it represents a form of

    >"escape" from a language.  If a language construct can be

    >directly embedded,

    >no quotation is necessary, but if quotation really is necessary then it

    >should not be concealed under any circumstances.

     Forth's quotation is essentially a switch between compile-mode and run-mode.

    This means that it can't be nested.  Joy's quotation actually forms a list

    out of the words contained, and those lists may be nested.  Forth's

    quotation is useless for forming other languages.  Joy's quotation is mostly

    useless for that.

    Forth includes a different construct which is useful for forming other

    languages: the ability for a word to parse ahead of itself in the source

    where it occurs.  This ability is unique to concatenative languages (it's

    completely unresonable in a language which has to be parsed before it's

    executed).

     >> Beacuse metaprogramming seems more simple with a concatenative

    >> language than with applicative languages, I think they are a valuable

    >> option as a minimal canonical notation on which construct different

    >> views (abstractions) via metaprograms.

    >But what kinds of sublanguages are possible (and useful)?  Is

    >it possible to create a useful subset of Joy that doesn't use

    >metaprogramming? Probably not.

     Why not?  You don't even have to use the list operators if you don't want

    to.

     >Since "meta" in this context means "unusual" or

    >"atypical" (often with

    >circularity as the triggering criterion), is it "a good thing" for a

    >language to rely on metaprogramming for the simplest of tasks?

     "meta" has never, to my knowledge, meant that.  "meta" means "above" or

    "beyond".  When you metaprogram, you're writing programs which manipulate

    and create other programs.

    -Billy

## wtanksley@bigfoot.com — 2000-06-05 18:41:24

    From: Mark van Gulik [mailto:ghoul6@...]

     >wtanksley@... wrote:

    >> From: Mark van Gulik [mailto:ghoul6@...]

    >>>Massimo Dentico <m.dentico@...> wrote:

    >>>In other words, Smalltalk works much, much better

    >>>when building upwards than when building downwards.

    >> I'm not sure how to take this.  Do you mean that Smalltalk is good at

    >> bottom-up design?  Forth is also renowned for that.

    >No, I was referring to building higher level constructs on top

    >of existing

    >ones, versus rebuilding lower level constructs to better

    >support existing ones.

     How does that differ from bottom-up design?  It sounds identical.

     >>>I can understand *implementing* another language in Forth, but

    >>>embedding it seems kind of awkward.

    >> That's the huge advantage of concatenative languages --

    >> because the language

    >> itself has no parser (or almost none), the words can act as

    >> parsers without

    >> interference from the language.  For example, someone

    >> implemented a FORTRAN

    >> embedded in Forth (which later was reduced to just a formula

    >> translator, but

    >> originally had an almost complete FORTRAN).  In use, it

    >> looked like this:

    >> VARIABLE x

    >> : myWord  i" 3*4/x+sin(x)" ;

    >> As you see, it just fits right into the language, and allows

    >> some things to

    >> be expressed in a manner more appropriate to certain problem domains.

    >> In short, i-quote (i") is a Forth word which is set to

    >> execute immediately,

    >> regardless of whether Forth is compiling.  Its job is to

    >> search ahead in the

    >> input stream until it finds the quote which marks the end of

    >> its input, and

    >> then it has to parse the expression and emit Forth code for it.  It's

    >> actually pleasantly simple to implement, but who cares about

    >> implementation

    >> when it's so easy to use.

    >In Avail syntax I would probably be able to embed the syntax directly,

    >without resorting to quoting (even though the quotes have effectively

    >dissolved by runtime in your example).

     I'm mildly confused.  First, you seem to have confused the presence of

    quotes with the action of quoting.  There's no quoting going on; I could

    have just as easily named the word "I(" and had it parse all the input, and

    stop when it reached an unbalanced ")" (which would appear to be a matching

    parenthesis to the reader).  The syntax IS directly embedded; Forth knows

    nothing of it.

      : myWord  i( 3*4/x+sin(x)) ;

    I could also write a C compiler which simply parsed the entire rest of the

    file as a C program.

     >[...trivial code that will fail with GC but succeed without...]

    >> You seem to be confusing GC with memory protection.  In a

    >> language which

    >> allows stores to arbitary addresses, memory corruption is

    >> always possible.

    >> You don't need to add GC to allow it, and adding GC doesn't

    >> change anything about it.

    >Ah, but if GC turns a working program into a non-working one,

    >then GC is the

    >*cause* of the failure -- i.e., the GC is not working.  If you

    >restrict the

    >language features to allow GC to function in all cases, you've

    >effectively

    >implemented GC on a subset of the language, which is different

    >from (but not

    >necessarily worse than) supporting GC in the full language.

     I think I see what you're saying.  Yes, that makes sense.

    Fortunately, it's easy enough to fix -- simply make MALLOC and FREE the only

    words which can't be used in GC-able Forth programs.  This fits perfectly

    with what all other GC-able languages do, and it harms almost no Forth

    programs.

    You can get more sophisticated, but as you point out, getting more

    sophisticated adds edge effects.  This solution is certain to work.

     >>>[...]Is it common practice

    >>>(yet) to use assertions in the language?

    >> Not really.  It's far more common to use compile-time unit

    >> tests/regression

    >> tests.  The problem with assertions is that they _require_

    >> application: you

    >> have to be able to remove them when you're about to distribute.  It's

    >> possible to do that by building a special sublanguage which

    >> handles the assertions applicatively, but most people don't bother.

    >> There are two replacements.  First, compile-time unit tests are a

    >> phenominally powerful means for documenting code and

    >> discovering errors.

    >> Second, interactivity allows for considerable examination of

    >> code in ways

    >> not appropriate for unit tests.  The two together allow for

    >> expressivity at

    >> _least_ equal (if not better than) the expressivity given by

    >> Design By Contract (assertions).

    >Personally, I never disable assertions except one-at-a-time,

    >and only when looking at actual times with a profiler.

     I can't imagine distributing assertion-loaded code to users.  The assertions

    are of no use to them.  However, as I mentioned, assertions have their

    problems as well, and a big one is disabling them, as you mention.

     >A compile-time unit test sounds

    >intriguing.  The Avail modules are already kind of structured that way,

    >where many modules have a corresponding test module that can

    >be compiled and executed very easily.

     It's suprisingly useful -- you might want to build something like that into

    Avail.

     >> This is very similar to what I plan for the high level of my Joylike

    >> languages, except that I'll use wordcode where you use

    >> nibblecode, and

    >> native code where you use wordcode.  At a low level, though,

    >> no optimization

    >> will EVER  be secret; you have to ask for it in order to

    >> make it happen

    >> (there will be words which carry out the optimizations).  In

    >> other words,

    >> the compiler itself will be written in the low level code,

    >> and it'll be very simple indeed.

    >Avail doesn't necessarily keep secret which optimizations have been

    >performed.

     Yes, but it does them without asking you.  My initial language won't do any

    optimizations except for ones which cause semantics changes; if you want to

    apply space or time optimizations, you have to apply them yourself.

     >BTW, I don't recommend

    >leaving it up to the application-level programmer to decide

    >which areas to apply optimizations.

     I'm actually not -- it's up to the systems programmer.  If anyone writes an

    application in my initial low-level language, they'll actually be writing a

    system, and deserve what they get :-); for example, they won't get any GC.

     >For a terrifically bad example, look at the way

    >inlining is specified in C++.  An inlining hint actually alters the

    >semantics!

     C++ is, as usual, a spectacularly bad example.  The problems you're looking

    at there involve the fact that the programmer can apply semantics-changing

    optimizations *inconsistently*.  In my low-level language, I'm going to have

    a set of semantics-changing optimizations which will be applied

    automatically and consistently -- for example, tail calls will be optimised

    to jumps.  Because it happens every time, it'll be perfectly predictable.

     >>>Actually, I don't know of a language for with 10x

    >>>productivity is *not*

    >>>claimed by its advocates!

    >> Correct.  Hardly suprising -- the difference between a good

    >> programmer and a

    >> bad one is 25x.  In other words, 10x is noise.  Chuck Moore

    >> claims 1000x for

    >> Forth -- not 1000x productivity, but rather 1000x quicker

    >> speed and smaller

    >> size without the need for any more budget.  I don't speak

    >> for him; check his work at http://www.ultratechnology.com

    >Hm.  Most of the time 1000x quicker would be meaningless for what I do

    >(I.e., almost everything I write runs faster than I can detect

    >visually).

     Lucky :-).

     >In my current work (large scale databases) it sure would be

    >nice, but this

    >is a very rare exception.  I doubt, however, that Forth would

    >significantly

    >improve disk latency within OODB requests (certainly not 1000x).

     It certainly wouldn't -- but Chuck would try to find something to replace

    the entire OODB with which would solve the specific problem 1000x faster.

    That's the point of his work.

    It's not at all a rare exception, though.

    One "recent" example in Chuck's own work was when he implemented a VLSI

    design workstation, complete with analog-precision simulation.

     >>>> Don't Complexify

    >[...]

    >>>Ah, but that assumes you will never be asked to solve the

    >>>general problem.

    >> No, it assumes _nothing_.  That's the beauty of it.  It only

    >> solves the

    >> problem at hand -- and it leaves you with _real_ experience

    >> of what the

    >> specific problem is actually like.  If you are later asked

    >> to solve the

    >> general problem (and that does sometimes happen), you'll be able to

    >> confidently write the general solution, knowing that you

    >> have a specific

    >> solution to test it against (or perhaps even to base it on).

    >> If you aren't

    >> asked for that, you haven't spent any extra time or effort on it.

    >Ok.  One test case (or two, as XP implies) will help make sure of the

    >applicability of a general solution.

     Specific, not general.  You can't possibly test the general case without

    first solving *all* of the specific cases.

     >But the specificity (and complexity)

    >of these cases might be much higher than similarly "contrived"

    >test cases

    >would have.  Also, after the general solution is implemented,

    >the specific

    >solutions would have to be completely rewritten within the

    >context of the

    >general solution to be useful as test cases.

     I may be missing something, but why would they have to be rewritten?  On the

    contrary, you don't want to rewrite them -- they're known to work, so you

    can run them, and then run your general solution, and compare the outputs.

     >> But consider the best case for your argument: the times when

    >> you actually

    >> _are_ asked for the general solution.  Did you _really_ test

    >> your generic

    >> code for all of the cases in the general solution?  Are you

    >> so certain that

    >> it's the best solution?  I've never seen first-draft generic

    >> code which

    >> actually worked.  I have seen first-draft specific code,

    >> though.  And the

    >> experience granted by writing that working specific code

    >> will certainly lead

    >> the programmer to choose wisely when it comes to the choice between

    >> rewriting and refactoring.

    >Getting it right the first time (or soon thereafter) is what

    >professionals do.

     Which professionals would that be?  I haven't met any of them.  I thought

    professionals were simply people who were willing to be identified by what

    they do.

     >>>I disagree with the level of "fix it up later" that XP

    >>>advocates.

    >> And I strongly agree -- with the caveat that "fix it"

    >> implies that it's

    >> broken now, which is the opposite of what XP advocates.

    >I did intentionally avoid saying "fix it later", and chose to insert

    >"...up...", trying to give it a connotation of something like

    >cleanliness,

    >luxury, or maybe attention to detail.  Yes, make sure everything is

    >maximally tested (and working) early on, keeping it that way.

     XP doesn't recommend skimping on attention to detail, or pretty code, or

    anything like that.  Frankly, I don't see how you can justify implying --

    no, not implying, but rather explicitly stating -- that about XP.

     >No, I don't

    >think one should do that to the exclusion of elegant design from

    >generalization.

     And I think design from generalization (elegant or otherwise) is the worst

    mistake you can make, and you should go to almost any lengths to avoid it.

    Design from generalization solves many problems which you don't have, almost

    always adds bloat, and makes claims which are inherently untestable.

    It's much better to design a solution which solves the problem you have.

     >>>At first,

    >>>when I read the Charles Moore quote I thought "so, writing ten

    >>>times as much code doesn't mean it took 10x longer to do".

    >> Correct.  You can spend 10x more time per line, so you can

    >> quite possibly

    >> wind up in a tie, in terms of time spent, with a person

    >> writing bulkier

    >> code.  The difference is that your code will be able to be

    >> written and

    >> maintained by a single person instead of requiring a team;

    >> and THAT can

    >> suddenly start saving a _lot_ of time and grief.

    >Shorter code does not imply fewer people are required for

    >maintenance.

     Yes, it does.

     >With

    >any refactoring tools (even a multi-file search & replace) one

    >person can

    >maintain denormalized code within 10x the cost of normalized

    >code.

     I'm sorry, I've never heard that word used that way.  Normalized code?

     >There

    >are much bigger issues to the maintenance cost, e.g., how much early

    >generalization was present (also called Frameworks), etc.

     Ah, well, yes.  If your code is a nest of cut'n'paste design it's quite

    possible that you'll be able to spend time writing tools to help you

    maintain your code -- and if the cut'n'paste code is done in a standard way,

    you can even buy tools to do it for you.

     >How do the assertions fit in with Joy?  Maybe an operation like:

     You could use quotations, as you suggested, or you can use preparsing (as I

    suggested).  I think experience with Forth indicates that compile-time unit

    tests work better and are easier to use.

    -Billy

## Massimo Dentico — 2000-06-05 18:58:33

    Sorry for the delay Mark, but I'm busy in these days and I need much time

    to write in English. Some subjects are already addressed by Bill, I agree

    with him thus I do not intend to be redundant.

    Mark van Gulik wrote:

     >

    > Massimo Dentico <m.dentico@...> wrote:

    > > Mark van Gulik wrote:

    > >> I'm positive that Forth is applicable over an enormous range of domains,

    > >> mostly due to its core simplicity and extreme extensibility.  I'm mostly

    > >> concerned, however, with the ability to build *restrictions* in the

    > >> language.

    > >

    > > I completely agree with this. In particular, the key concept is

    > > ".. the ability to build *restrictions* in the language". This means

    > > that *you*, the programmer, build the restrictions when you really

    > > need it and it's not the language designer that in arbitrary way

    > > restricts you.

    >

    > I almost agree.  The language designer also has the responsibility of

    > building the right restrictions *into* the language, such that it will have

    > clean semantics and high reliability (the two tend to go together).  For

    > example, in another thread I argued that conservative garbage collection

    > (CGC) in Forth is really CGC in some proper subset of Forth.  That's because

    > Forth's semantics are too strongly defined in terms of machine

    > representation to allow CGC (in the full language).  A redesign of Forth is

    > possible to accomodate CGC for the full language, but it wouldn't look much

    > like Forth afterwards.  Basically issues like GC, type systems,

    > optimization, and design-by-contract must be *designed into* a language, not

    > added later (typically by subtractive synthesis as with CGC and retrofitted

    > type systems).

     I disagree here. The advantage of a meta-programming (constructing

    programs that inspects/manipulates other programs) tool with reflective

    capabilities (ability to inspect/modify itself even if, in Forth, is fairly

    ad-hoc) like Forth is exactly this: the tool have the ability to absorb and

    arrange disparate syntaxes/semantics.

    For example, redefining the semantics of some words (creating new contexts

    for old programs) probably it's possible to accommodate GC better than in

    traditional languages (without GC); it's even possible to imagine a metaprogram

    that takes as input a Forth program with direct memory management and gives as

    output a Forth program integrated with GC. Some research on static (compile-

    time) automatic memory management exists also.

    However, I consider Forth more a conceptual model than a language in itself:

    it's defined more by "concepts" like words, staks, dictionaries, text input

    buffer than by a particular set of primitives.

     > This issue with "helical" (circular, but offset in time) definitions arose

    > in many places within Avail, due to the fact that there are no keywords at

    > all in the language.  The first bootstrap module uses a pragma to provide

    > the two method names needed to bootstrap the rest of the system (I consider

    > this a kind of "cheating", but there's no other way).  In case you're

    > interested, the method names are "Special Object_" and "Method_is_".  The

    > first one lets me get to special constants (e.g., built-in types), and the

    > second one lets me extend the system.  In Forth, the second one would be the

    > equivalent of defining : and ; as ordinary words!

     I downloaded the source to take a look.

    --

    Massimo Dentico

## Massimo Dentico — 2000-06-05 19:14:45

    wtanksley@... wrote:

     > [...]

    > >> I want only to add that Forth quotation seems less intrusive in comparison

    > >> to the quotation mechanism of Joy and more appropriate to absorb other

    > >> syntaxes. I would like hear your (list participants) opinion

    > >> regard this subject.

    >

    > >Quotation should be as explicit as possible, as it represents a form of

    > >"escape" from a language.  If a language construct can be directly embedded,

    > >no quotation is necessary, but if quotation really is necessary then it

    > >should not be concealed under any circumstances.

    >

    > Forth's quotation is essentially a switch between compile-mode and run-mode.

    > This means that it can't be nested.  Joy's quotation actually forms a list

    > out of the words contained, and those lists may be nested.  Forth's

    > quotation is useless for forming other languages.  Joy's quotation is mostly

    > useless for that.

     I call staging the switch between compile-mode and run-mode (in accord

    with CS literature).

     > Forth includes a different construct which is useful for forming other

    > languages: the ability for a word to parse ahead of itself in the source

    > where it occurs.  This ability is unique to concatenative languages (it's

    > completely unresonable in a language which has to be parsed before it's

    > executed).

     This is what I call quotation: the ability to reify the rest of the program

    source text. Besides the terminology, seems that we agree. Am I wrong?

    --

    Massimo Dentico

## Massimo Dentico — 2000-06-05 19:18:11

    wtanksley@... wrote:

     >

    > From: Mark van Gulik [mailto:ghoul6@...]

    > >wtanksley@... wrote:

    > >> From: Mark van Gulik [mailto:ghoul6@...]

    > >>>Massimo Dentico <m.dentico@...> wrote:

     ^^^^^^

     > >>>In other words, Smalltalk works much, much better

    > >>>when building upwards than when building downwards.

    > [...]

    > >>>I can understand *implementing* another language in Forth, but

    > >>>embedding it seems kind of awkward.

    > [...]

     This is not me but Mark.

    --

    Massimo Dentico

## wtanksley@bigfoot.com — 2000-06-05 21:55:40

    From: Massimo Dentico [mailto:m.dentico@...]

     >wtanksley@... wrote:

    >> Forth's quotation is essentially a switch between

    >> compile-mode and run-mode.

    >> This means that it can't be nested.  Joy's quotation

    >> actually forms a list

    >> out of the words contained, and those lists may be nested.  Forth's

    >> quotation is useless for forming other languages.  Joy's

    >> quotation is mostly

    >> useless for that.

    >I call staging the switch between compile-mode and run-mode (in accord

    >with CS literature).

     I've never heard of that.  Can you clarify?

     >> Forth includes a different construct which is useful for

    >> forming other

    >> languages: the ability for a word to parse ahead of itself

    >> in the source

    >> where it occurs.  This ability is unique to concatenative

    >> languages (it's

    >> completely unresonable in a language which has to be parsed

    >> before it's executed).

    >This is what I call quotation: the ability to reify the rest

    >of the program

    >source text. Besides the terminology, seems that we agree. Am I wrong?

     Probably.  Joy defines quotation as a syntactic operation which reifies an

    enclosed section of text, subject to that enclosed text consisting of valid

    Joy code, including nested quotations but excluding definition-related

    syntax.

    Forth doesn't use the term 'quotation', but I suppose you could define its

    quotation as delivering the source which is about to be parsed by the

    compiler to the program instead (so only one entity gets to consume the

    text; if the program uses it, the compiler won't ever see it).

    I suspect that quotation implies that the compiler has some control over the

    operation, so the word is inappropriate when applied to Forth.

     >Massimo Dentico

     -Billy

## Massimo Dentico — 2000-06-05 23:04:21

    wtanksley@... wrote:

     >

    > > > Massimo Dentico [mailto:m.dentico@...]

    > > wtanksley@... wrote:

    >

    > > > Forth's quotation is essentially a switch between compile-mode and run-mode.

    > > > This means that it can't be nested.  Joy's quotation actually forms a list

    > > > out of the words contained, and those lists may be nested.  Forth's

    > > > quotation is useless for forming other languages.  Joy's quotation is mostly

    > > > useless for that.

    >

    > >I call staging the switch between compile-mode and run-mode (in accord

    > >with CS literature).

    >

    > I've never heard of that.  Can you clarify?

     Surely. With a citation from [1] by members of OGI Mustang Project [2]:

    ----------------------------------------------------------------------------

    [...]

    2 Why Multistage Programs?

    The concept of a stage arises naturally in a wide variety

    of situations. For a compiled language, there are two dis

    tinct stages: compiletime, and runtime. But three distinct

    stages appear in the context of program generation: gen

    eration, compilation, and execution. For example, the Yacc

    parser generator first reads a grammar and generates C code;

    second, this program is compiled; third, the user runs the

    object code.

    [...]

    3 Relationship to Partial Evaluation

    [...] The relationship between partialevaluation and multi

    stage programming is that the intermediate data structure

    between the two steps [of a partialevaluation] is a twostage

    annotated program, and that the specialization phase is (the

    first stage in) the execution of the twostage annotated program

    produced by  BTA. [BindingTime Analysis] [...]

    ----------------------------------------------------------------------------

     > > > Forth includes a different construct which is useful for forming other

    > > > languages: the ability for a word to parse ahead of itself in the source

    > > > where it occurs.  This ability is unique to concatenative languages (it's

    > > > completely unresonable in a language which has to be parsed

    > > > before it's executed).

    >

    > > This is what I call quotation: the ability to reify the rest of the program

    > > source text. Besides the terminology, seems that we agree. Am I wrong?

    >

    > Probably.  Joy defines quotation as a syntactic operation which reifies an

    > enclosed section of text, subject to that enclosed text consisting of valid

    > Joy code, including nested quotations but excluding definition-related

    > syntax.

    >

    > Forth doesn't use the term 'quotation', but I suppose you could define its

    > quotation as delivering the source which is about to be parsed by the

    > compiler to the program instead (so only one entity gets to consume the

    > text; if the program uses it, the compiler won't ever see it).

    >

    > I suspect that quotation implies that the compiler has some control over the

    > operation, so the word is inappropriate when applied to Forth.

     Ok, if I understand your discrimination you assert that to speak about

    quotation it needs to pass at least the lexing phase. mmm .. I don't know.

    Forth, with its open interpreter, is quite unusual so I am not sure that a

    possible technical definition of the term exclude the use that I have done

    of it. Anyway, if you have a reference at hand I will correct me (no time

    to do a search in this moment, sorry).

    References

    [1] Walid Taha, Tim Sheard, "Multi-Stage Programming with Explicit Annotations"

        - http://cse.ogi.edu/~sheard/papers/PepmMulStg97.ps

    [2] The OGI Mustang Project

        - http://www.cse.ogi.edu/PacSoft/projects/Mustang/Overview.html

    --

    Massimo Dentico

## wtanksley@bigfoot.com — 2000-06-05 23:36:24

    From: Massimo Dentico [mailto:m.dentico@...]

     >wtanksley@... wrote:

    >> > wtanksley@... wrote:

    >> > > Forth's quotation is essentially a switch between

    >> > > compile-mode and run-mode.

    >> > > This means that it can't be nested.  Joy's quotation

    >> > > actually forms a list

    >> > > out of the words contained, and those lists may be

    >> > > nested.  Forth's

    >> > > quotation is useless for forming other languages.  Joy's

    >> > > quotation is mostly useless for that.

    >> >I call staging the switch between compile-mode and run-mode

    >> >(in accord with CS literature).

    >> I've never heard of that.  Can you clarify?

    >Surely. With a citation from [1] by members of OGI Mustang Project [2]:

     I'm still confused -- this citation uses "stage" as a noun, not a verb (so

    "staging" is wrong); and they use it in a way ENTIRELY inappropriate to

    Forth.  A stage is a distinct step in a process.  To Forth, however,

    compilation is not a stage, but rather an action.  Compilation can take

    place at any time, and the Forth parser has a special state to make it easy.

     >> > This is what I call quotation: the ability to reify the

    >> > rest of the program

    >> > source text. Besides the terminology, seems that we agree.

    >> > Am I wrong?

    >> Probably.  Joy defines quotation as a syntactic operation

    >> which reifies an

    >> enclosed section of text, subject to that enclosed text

    >> consisting of valid

    >> Joy code, including nested quotations but excluding

    >> definition-related

    >> syntax.

    >> Forth doesn't use the term 'quotation', but I suppose you

    >> could define its

    >> quotation as delivering the source which is about to be parsed by the

    >> compiler to the program instead (so only one entity gets to

    >> consume the

    >> text; if the program uses it, the compiler won't ever see it).

    >>

    >> I suspect that quotation implies that the compiler has some

    >> control over the

    >> operation, so the word is inappropriate when applied to Forth.

    >Ok, if I understand your discrimination you assert that to speak about

    >quotation it needs to pass at least the lexing phase.

     Ah.  Let's see...  I think I can accept that.  Of course, in Joy it passes

    much more then that (it's almost completely parsed).

     >Forth, with its open interpreter, is quite unusual so I am not

    >sure that a

    >possible technical definition of the term exclude the use that

    >I have done of it.

    >Anyway, if you have a reference at hand I will correct

    >me (no time to do a search in this moment, sorry).

     The quickest reference, and the one most appropriate for this project, would

    be the Joy pages, where quotation is defined for the Joy language.

    At this point, though, I have to admit that I'm at somewhat of a loss --

    what were we arguing about :-)?  I seem to recall a comparison of Forth's

    quoting and Joy's quoting; I see I'm responding to it above, using very

    ambiguous terms.

    I would say that Joy's quoting (using Joy's definition of quoting) is

    actually a "list literal" which happens to contain quotation (by our

    definition).  Forth's quotation is operated by changing the state of the

    system.

    Suppose we were to add two new syntactic elements to Joy: the quoted

    function and the quoted list.  A quoted function would look like this: 'dup.

    A quoted list would look like this: '[2 dup].  I'm borrowing syntax from

    Lisp, as you see.

    A normal (unquoted) list looking like this: [2 dup] would actually have

    contents something like this: [2 2].

    The result of "'[dup dup] first" would be 'dup.

     >Massimo Dentico

     -Billy

## stevan apter — 2000-06-06 00:34:08

    >

    > Suppose we were to add two new syntactic elements to Joy: the quoted

    > function and the quoted list.  A quoted function would look like this: 'dup.

    > A quoted list would look like this: '[2 dup].  I'm borrowing syntax from

    > Lisp, as you see.

    >

    > A normal (unquoted) list looking like this: [2 dup] would actually have

    > contents something like this: [2 2].

    >

    > The result of "'[dup dup] first" would be 'dup.

     now i'm confused, since

        joy>[dup dup]first

        joy>dup

    at least, that is so according to my implementation.

    i note, in particular, that

        joy>10 [dup dup] first i

        joy>10 10

    i suspect that this violates some semantic rule in joy, since

    an intermediate state of the computation above may be (in some

    sense) "illegal":

        joy>10 [dup dup] first

        joy>10 dup

    hmmm.

     >

    >

    > -Billy

    >

    > ------------------------------------------------------------------------

    > CLICK HERE***SPECIAL OFFER***$60 in FREE calls

    > ***SPECIAL OFFER***CLICK HERE

    > http://click.egroups.com/1/4127/6/_/_/_/960248194/

    > ------------------------------------------------------------------------

    >

    > To unsubscribe from this group, send an email to:

    > concatenative-unsubscribe@egroups.com

    >

    >

    >

    >

## wtanksley@bigfoot.com — 2000-06-06 00:45:19

    From: stevan apter [mailto:apter@...]

     >> Suppose we were to add two new syntactic elements to Joy: the quoted

    >> function and the quoted list.  A quoted function would look

    >> like this: 'dup.

    >> A quoted list would look like this: '[2 dup].  I'm borrowing

    >> syntax from Lisp, as you see.

    >> A normal (unquoted) list looking like this: [2 dup] would

    >> actually have contents something like this: [2 2].

    >> The result of "'[dup dup] first" would be 'dup.

    >now i'm confused, since

    >    joy>[dup dup]first

    >    joy>dup

    >at least, that is so according to my implementation.

     This is true (and it's also true for the canonical Joy implementation) --

    but the documentation doesn't discuss this, and more importantly the

    language provides no means for manipulating these "function" entities.

    Note that Joy's [] construct is identical to the behavior of my proposed '[]

    construct: that is, both form a quoted list.  My [ construct forms a stack

    and sets it to be the current stack; ] later on ends that stack and places

    it on the former stack as a list (if that makes any sense).  The purpose is

    to allow some means of constructing a pure list (which is not a quotation).

    As such, it's completely unneeded.

    I'd be completely happy with the specification of a new type of literal, the

    "function literal".

     >i suspect that this violates some semantic rule in joy, since

    >an intermediate state of the computation above may be (in some

    >sense) "illegal":

    >    joy>10 [dup dup] first

    >    joy>10 dup

     Exactly.  I'd like to make that into

       joy>10 [dup dup] first

       joy>10 'dup

    I believe there's good reason to allow 'i' in Joy to execute function

    literals, even though technically they're not quotations; in my initial

    language, quotations and functions will be very different things, so 'i'

    will probably not work on them equally.  OTOH, I _might_ be able to make

    them work identically; I'll only do that if the result is simple.

    -Billy

## Massimo Dentico — 2000-06-06 00:53:37

    wtanksley@... wrote:

     >

    > From: Massimo Dentico [mailto:m.dentico@...]

    > > wtanksley@... wrote:

    > > > > wtanksley@... wrote:

    > > > > > Forth's quotation is essentially a switch between

    > > > > > compile-mode and run-mode.

    > > > > > This means that it can't be nested.  Joy's quotation

    > > > > > actually forms a list

    > > > > > out of the words contained, and those lists may be

    > > > > > nested.  Forth's

    > > > > > quotation is useless for forming other languages.  Joy's

    > > > > > quotation is mostly useless for that.

    >

    > > > >I call staging the switch between compile-mode and run-mode

    > > > >(in accord with CS literature).

    >

    > > > I've never heard of that.  Can you clarify?

    >

    > > Surely. With a citation from [1] by members of OGI Mustang Project [2]:

    >

    > I'm still confused -- this citation uses "stage" as a noun, not a verb (so

    > "staging" is wrong);

     This confirm that I express myself in a very bad English. :-)

     > and they use it in a way ENTIRELY inappropriate to Forth.  A stage is a

    > distinct step in a process.  To Forth, however, compilation is not a stage,

    > but rather an action.  Compilation can take place at any time, and the Forth

    > parser has a special state to make it easy.

     Again, it seems not pertinent because Forth is an unusual language.

    When a definition, which contains an immediate word, is compiled,

    IMHO is possible distinguish 2 stage clearly: the compilation stage

    (when the immediate word is performed and the rest are compiled) and

    the execution stage. The word IMMEDIATE acts as a stage annotation:

    "to execute at compile time". Of course, the context is the single

    definition.

    --

    Massimo Dentico

## stevan apter — 2000-06-06 02:14:39

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

    From: <wtanksley@...>

    To: <concatenative@egroups.com>

    Sent: Monday, June 05, 2000 8:45 PM

    Subject: RE: [stack] Digest Number 28

    > From: stevan apter [mailto:apter@...]

    >

    > >> Suppose we were to add two new syntactic elements to Joy: the quoted

    > >> function and the quoted list.  A quoted function would look

    > >> like this: 'dup.

    > >> A quoted list would look like this: '[2 dup].  I'm borrowing

    > >> syntax from Lisp, as you see.

    >

    > >> A normal (unquoted) list looking like this: [2 dup] would

    > >> actually have contents something like this: [2 2].

    >

    > >> The result of "'[dup dup] first" would be 'dup.

    >

    > >now i'm confused, since

    >

    > >    joy>[dup dup]first

    > >    joy>dup

    >

    > >at least, that is so according to my implementation.

    >

    > This is true (and it's also true for the canonical Joy implementation) --

    whew.  ;-)

    > but the documentation doesn't discuss this, and more importantly the

    > language provides no means for manipulating these "function" entities.

    >

    > Note that Joy's [] construct is identical to the behavior of my proposed '[]

    > construct: that is, both form a quoted list.  My [ construct forms a stack

    > and sets it to be the current stack; ] later on ends that stack and places

    > it on the former stack as a list (if that makes any sense).  The purpose is

    > to allow some means of constructing a pure list (which is not a quotation).

    > As such, it's completely unneeded.

    >

    > I'd be completely happy with the specification of a new type of literal, the

    > "function literal".

    >

    > >i suspect that this violates some semantic rule in joy, since

    > >an intermediate state of the computation above may be (in some

    > >sense) "illegal":

    >

    > >    joy>10 [dup dup] first

    > >    joy>10 dup

    >

    > Exactly.  I'd like to make that into

    >

    >    joy>10 [dup dup] first

    >    joy>10 'dup

    i think i see what you're after, but i'm not altogether sure i understand

    why.  i must confess, it bothers me that

        joy>dup

    is a stack which cannot be achived directly, although here too, i cannot

    say exactly *why* that bothers me.

    in my implementation, i can add two functions which allow me to

    do some elementary manipulations of naked joy functions:

        value:One[.:]        / return the value of a symbol

        string:One[$:]       / turns anything into a string

    so now:

        joy>5 3 +

        joy>8

        joy>pop

        joy>

        joy>[-][+]first string is

        joy>+

        joy>5 3 +

        joy>2

        joy>[+]first value

        joy>[-]

    which would, if i were sufficiently deranged, allow me to redefine

    primitives.

    >

    > I believe there's good reason to allow 'i' in Joy to execute function

    > literals, even though technically they're not quotations; in my initial

    > language, quotations and functions will be very different things, so 'i'

    > will probably not work on them equally.  OTOH, I _might_ be able to make

    > them work identically; I'll only do that if the result is simple.

    offhand, without further evidence of the cash value of the bifurcated

    ontology, i can't say the proposal appeals.

    >

    > -Billy

    >

    > ------------------------------------------------------------------------

    > Best friends, most artistic, class clown Find 'em here:

    > http://click.egroups.com/1/4054/6/_/_/_/960252317/

    > ------------------------------------------------------------------------

    >

    > To unsubscribe from this group, send an email to:

    > concatenative-unsubscribe@egroups.com

    >

    >

    >

    >

## stevan apter — 2000-06-06 12:54:39

    >     value:One[.:]        / return the value of a symbol

     defined this way, value has the unpleasant effect of revealing

    the underlying implementation:

        joy>[+]first value

        joy>{(,Dot[x;2#y]),2 _ y}[{(_ci;::)[(b~z)&a~y]x[b:Ic z;a:Ic y]}[+]]

    not something anyone wants to see before breakfast.

    better to punt when the value is functional:

        value:One[{:[7=4:v:. x;x;v]}]

    i.e., if the type of the value of x is functional, return x, else

    return the value.

        joy>[+] first value

        joy>+

        joy>[unswons] first value

        joy>+ [uncons swap]

    by the way, does anyone have an opinion on the behavior of the

    joy console as i have implemented it?  should i prefix "joy>" to

    both the input prompt and the output as i am now doing?  or should

    i forego the prefix on output (the behavior of the k and APL

    consoles -

        joy>2 3 +

        5

        joy>

## stevan apter — 2000-06-06 13:17:03

    > by the way, does anyone have an opinion on the behavior of the

    > joy console as i have implemented it?  should i prefix "joy>" to

    > both the input prompt and the output as i am now doing?  or should

    > i forego the prefix on output (the behavior of the k and APL

    > consoles -

    >

    >     joy>2 3 +

    >     5

    >     joy>

    >

     i think this is self-answering - i should forego the prefix on

    output.  the console history is much easier to read this way,

    especially when the stack-trace option is selected:

        joy>\

        joy>2 3 + 4 -

        2

        2 3

        5

        5 4

        1

        joy>

    i've been mulling over whether to fork off a second implementation,

    one which implements at least, and possibly only the k primitives,

    minus assignment.  this version would break out all the overloading

    ("puns") in k into separate keywords.  i'm thinking of doing this

    primarily for my own benefit, since my brain seems to have become

    permanantly warped in the direction of list-oriented algorithms.

    secondarily, i'm thinking that forth programmers might find it

    easier to acquire that habit (pathology?) if we strip away the

    symbolic notation.  finally, i'm curious about the extent to which

    the highly compressed applicative notation of k contributes to

    productivity, and having the identical semantics in a concatenative

    framework might go some distance to answer this question.

    any opinons?  and, what should i call the resulting language?

    i'm leaning in the direction of 'kon' (for "koncatenative").

## wtanksley@bigfoot.com — 2000-06-06 20:24:58

    From: stevan apter [mailto:apter@...]

     >> by the way, does anyone have an opinion on the behavior of the

    >> joy console as i have implemented it?  should i prefix "joy>" to

    >> both the input prompt and the output as i am now doing?  or should

    >> i forego the prefix on output (the behavior of the k and APL

    >> consoles -

    >i think this is self-answering - i should forego the prefix on

    >output.  the console history is much easier to read this way,

    >especially when the stack-trace option is selected:

     I agree.

     >i've been mulling over whether to fork off a second implementation,

    >one which implements at least, and possibly only the k primitives,

    >minus assignment.  this version would break out all the overloading

    >("puns") in k into separate keywords.  i'm thinking of doing this

    >primarily for my own benefit, since my brain seems to have become

    >permanantly warped in the direction of list-oriented algorithms.

    >secondarily, i'm thinking that forth programmers might find it

    >easier to acquire that habit (pathology?) if we strip away the

    >symbolic notation.  finally, i'm curious about the extent to which

    >the highly compressed applicative notation of k contributes to

    >productivity, and having the identical semantics in a concatenative

    >framework might go some distance to answer this question.

     I'd love to see this.  I've always thought that k and J's manipulations

    would be very useful in a stack language, and I also harbor the same

    curiosity you express.

    It's interesting that you're thinking of using keywords rather than symbols;

    of course, you _could_ use the symbols if you wanted, but the result would

    be different from k, so it's probably best that you don't.

    It's notable that although Forth has a lot of symbols in it, Forth

    programmers invariably pronounce them as though they were words -- "@" is

    pronounced "fetch", and "R>" is pronounced "r-from".  I know that k

    programmers also have names for all of their symbols, and I believe that

    Forth programmers would understand perfectly how to pronounce them.

     >any opinons?  and, what should i call the resulting language?

    >i'm leaning in the direction of 'kon' (for "koncatenative").

     I like that.

    -Billy

## stevan apter — 2000-06-07 01:20:32

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

    From: <wtanksley@...>

    To: <concatenative@egroups.com>

    Sent: Tuesday, June 06, 2000 4:24 PM

    Subject: RE: [stack] Digest Number 28

    > From: stevan apter [mailto:apter@...]

    >

    > >> by the way, does anyone have an opinion on the behavior of the

    > >> joy console as i have implemented it?  should i prefix "joy>" to

    > >> both the input prompt and the output as i am now doing?  or should

    > >> i forego the prefix on output (the behavior of the k and APL

    > >> consoles -

    >

    > >i think this is self-answering - i should forego the prefix on

    > >output.  the console history is much easier to read this way,

    > >especially when the stack-trace option is selected:

    >

    > I agree.

    yes - this is much nicer.

    >

    > >i've been mulling over whether to fork off a second implementation,

    > >one which implements at least, and possibly only the k primitives,

    > >minus assignment.  this version would break out all the overloading

    > >("puns") in k into separate keywords.  i'm thinking of doing this

    > >primarily for my own benefit, since my brain seems to have become

    > >permanantly warped in the direction of list-oriented algorithms.

    > >secondarily, i'm thinking that forth programmers might find it

    > >easier to acquire that habit (pathology?) if we strip away the

    > >symbolic notation.  finally, i'm curious about the extent to which

    > >the highly compressed applicative notation of k contributes to

    > >productivity, and having the identical semantics in a concatenative

    > >framework might go some distance to answer this question.

    >

    > I'd love to see this.  I've always thought that k and J's manipulations

    > would be very useful in a stack language, and I also harbor the same

    > curiosity you express.

    i will implement this beast over the weekend.  rather than post it

    directly here, i'll maintain it (and related materials) on

        www.kx.com/technical/contribs/stevan

    >

    > It's interesting that you're thinking of using keywords rather than symbols;

    > of course, you _could_ use the symbols if you wanted, but the result would

    > be different from k, so it's probably best that you don't.

    i promise to exercise due restraint.  ;-)

    >

    > It's notable that although Forth has a lot of symbols in it,

    so i've noticed - it surprised me.

    > Forth

    > programmers invariably pronounce them as though they were words -- "@" is

    > pronounced "fetch", and "R>" is pronounced "r-from".  I know that k

    > programmers also have names for all of their symbols, and I believe that

    > Forth programmers would understand perfectly how to pronounce them.

    true - we like to read code out loud.  for example, the composition

        (,/,/:\:)/

    is pronounced:  raze join each-right each-left (pause) over.  ;-)

    >

    > >any opinons?  and, what should i call the resulting language?

    > >i'm leaning in the direction of 'kon' (for "koncatenative").

    >

    > I like that.

    i'm leaning in the direction of 'conk' (for concatenated k).

    thanks for your interest.

    >

    > -Billy

    >

    > ------------------------------------------------------------------------

    > Old school buds here:

    > http://click.egroups.com/1/4057/6/_/_/_/960323040/

    > ------------------------------------------------------------------------

    >

    > To unsubscribe from this group, send an email to:

    > concatenative-unsubscribe@egroups.com

    >

    >

    >

    >