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
>
>
>
>