Another patch
John Cowan — 2001-03-26 13:16:15
This one makes the tailrec combinator properly tail recursive. As currently
implemented, it eats the C stack on every recursion to no purpose.
At lines 1358 and 1365 of interp.c:
1358a1361
> tailrec:
1365c1368
< tailrecaux(); }
---
> goto tailrec; }
--
John Cowan
cowan@...
One art/there is/no less/no more/All things/to do/with sparks/galore
--Douglas Hofstadter
Manfred von Thun — 2001-03-29 07:46:46
On Mon, 26 Mar 2001, John Cowan wrote:
[two patch posts]
I have looked at your two posts. You have gone throught the
Joy sources with great care, thank you. Here are my comments:
First patch:
1) In scan.c fix line 40 with extra parens.
You are right, a definite improvement. Some other
contributors remarked on something similar elsewhere
a few months back. Accepted, thank you.
I have modified my working source and the web source.
2) In scan.c line 165 allow "DEFINE" instead of "LIBRA".
Well, OK, I don't mind, so I accept.
I have modified my working source and the web source.
3) In interp.c after line 825 you recommend that
"If an attempt is made to execute an undefined symbol,
a runtime error should occur."
I am not so sure about that. Certainly, in most other
languages this is the most sensible thing to do. I was
toying with the idea years ago, but then I rejected it.
My reason was, roughly, this. Consider the definitions
LIBRA
square == dup * ;
nothing == ;
double == 2 * .
The most reasonable behaviour for "nothing" should be that
if it is ever executed it should do what the definition
says: everyting between the "==" and the ";" and that
is the empty program which is the identity of concatenation.
So at runtime "nothing" should not do anything. But, you
say, at least "nothing" was defined to be the empty program.
OK, so now consider a list,
[ peter paul mary ]
which, when first used, cause the three names to be entered
into the symbol table. No runtime behaviour has been defined
for them if they were executed by, say,
[ peter paul mary ] i
Now it seems to me that no runtime behaviour defined should
mean that the three names behave just like empty programs.
That was my reasoning.
I still think this is right, but _only_ in a concatenative
language, because the empty program really is the identity
element for program concatenation. It would not make sense
in an applicative language. What could a nothing-function
applied to, say, two parameters, return? The pair of those
parameters?
It would be good to hear what other people think,
especially the Forth people. What do the Forth implementations
do, and what reason is given for whatever that behaviour is?
I am willing to be persuaded one way or another.
Second Post:
In interp.c you recommended to make "tailrec" tail recursive.
Agreed, accept, and thank you.
I have modified my working source and the web source.
Your other proposals:
a) allow user symbols in set literals if they evaluate to
a small integer or a char ( less than 32, I suppose).
When I first read this I thought: "Well, why not in list
literals, too?" Is your reasoning that a list literal is
after all a special case of a program, and hence might be
executed by some combinator? Maybe that was your thought.
Another option would be to introduce what in Pascal and in
some other languages are enumeration types:
TrafficLights = (red, green, yellow)
which in most respects would be equivalent to something
which in (current) Joy be
red == 0; green == 1; yellow == 3;
and similarly in old K&R C. I seem to remember that the
enumeration type was not included in Oberon (am I right,
Soren?), for some reason to do with type extensions or
something. Anyhow, enumeration types like "TrafficLights"
might be a useful addition to Joy, possibly more so that
just symbols in set literals.
b) generic functions. I toyed with (text-)macros a bit, using
(contrary to the advice of some members of the group) M4
for lack of something better and available. It 1) gave the
ability to inline some functions (and therefore increase
efficiency a little bit), 2) allowed debugging info to be
inserted/deleted at the flick of an M4 macro, without
runtime cost, and 3) was _intended_ to provide some
genericity - but I never got very far there. And, since
M4 of course only provides text macros, errors can only
be caught at macro expansion time. Maybe you should write
some small generic functions in your imagined extension
of Joy and let us have a look at them.
Best wishes, and thank you again for your interest
- Manfred
Dirk-Ulrich Heise — 2001-03-29 09:22:55
-----Ursprüngliche Nachricht-----
Von: "Manfred von Thun" <
phimvt@...>
An: <
concatenative@yahoogroups.com>
Gesendet: Donnerstag, 29. März 2001 09:46
Betreff: Re: [stack] Another patch
> It would be good to hear what other people think,
> especially the Forth people. What do the Forth implementations
> do, and what reason is given for whatever that behaviour is?
A Forth first tries to find a definition for each word -
where a word might be any combination of non-spaces, so
12345
can be the name of a definition as well.
If it doesn't find one, it tries to resolve the word as a number.
Depending on the Forth, various syntaxes might be allowed
for numbers, e.g. one might accept 0x35 as a hex number or not,
depending on the implementation.
If this fails as well, you'll get an error message saying
"undefined word" or so.
Reasons? Well. You find your typos.
Recently, i wrote a Forth program that needed something
similar to your [ Peter Paul Mary ] example. The program had a list of
words and it's purpose was to generate a new Forth
source code where it wrote some data down in a way that
it could later be interpreted by another Forth program.
My solution was to generate a source code looking
like
0 constant Peter
1 constant Paul
2 constant Mary
; thus creating an enumeration from the strings.
I don't see much sense in defining [ Peter Paul Mary ]
as a list of three empty functions, really. What use could
that have? Would it make sense to define Peter as a function
that returns a string constant "Peter" ? But seriously,
i'd expect an error message.
Dirk Heise
It's 0 degrees Celsius in Braunschweig, and we had 10 cm
snow on Sunday!
Dirk-Ulrich Heise — 2001-03-29 09:27:29
An afterthought, more mathematically inspired:
When hitting an unknown variable in a mathematical
expression, like in
5 + x = 0
we first assume it to be unknown, until we know its
value.
Would it make sense to define an unknown symbol as
an "unbound function" that can be manipulated (e.g.
using function composition) but not executed as long
as we don't know its value? So, as soon as you try
to evaluate it, you'll get a runtime error.
Dirk Heise
What's a life and where do i get one?
John Cowan — 2001-03-29 12:51:18
Manfred von Thun scripsit:
> I have looked at your two posts. You have gone throught the
> Joy sources with great care, thank you. Here are my comments:
I will have some more safety-related patches soon. For example,
"cons" does not currently check, when its top argument is a string,
that the bottom argument is a character, or even numeric. There
are several other defects of this kind.
> 3) In interp.c after line 825 you recommend that
> "If an attempt is made to execute an undefined symbol,
> a runtime error should occur."
[snip]
> It would be good to hear what other people think,
> especially the Forth people. What do the Forth implementations
> do, and what reason is given for whatever that behaviour is?
AFAIK it is not allowed to even mention, in the definition of a Forth
word, any word whose definition has not yet begun. So Joy has this
advantage over Forth (from the standpoint of flexibility), that
you may mention not-yet-defined words and define them later.
From a practical point of view, though, I find it obnoxious that
when I type (as I so often do)
[something] helpdetails.
I get nothing (in standard Joy) rather than an error message.
Of course the correct word is "helpdetail", but for some reason
I find this hard to remember. (I could define "helpdetails"
as "helpdetail" in my usrlib.joy, but that does not meet the
general point).
I agree that an empty definition should be executed successfully
by doing nothing, but I cannot agree that an empty definition
is the same as no definition. This is analogous to the attitude
to variables taken by Fortran or Basic or Perl without 'use strict',
and it has long ago been seen to lead to practical trouble:
a misspelled identifier makes a correct but useless program.
> Your other proposals:
> a) allow user symbols in set literals if they evaluate to
> a small integer or a char ( less than 32, I suppose).
> When I first read this I thought: "Well, why not in list
> literals, too?" Is your reasoning that a list literal is
> after all a special case of a program, and hence might be
> executed by some combinator?
Just so. Whereas set literals are handled purely by the lexer,
and so using meaningful names in them is impossible at present.
> Another option would be to introduce what in Pascal and in
> some other languages are enumeration types:
> TrafficLights = (red, green, yellow)
> which in most respects would be equivalent to something
> which in (current) Joy be
> red == 0; green == 1; yellow == 3;
My proposal allows red, green, yellow to be defined just like
this, and then used to create sets such as {red, green}
rather than having to write, as at present,
{} red swons green swons.
> Anyhow, enumeration types like "TrafficLights"
> might be a useful addition to Joy, possibly more so that
> just symbols in set literals.
True, but right now Joy does not have user-defined first-class
types. All in good time...
> b) generic functions.
I will post more on this later. My desire is to make it possible
for people using user-level types such as queue and bigset to
write functions which are generic across several of them.
I think this can be done with a single rather strange low-level
word, but the details are not firm in my head yet.
> Best wishes, and thank you again for your interest
I am also thinking about a large extension, about 60 words,
to add ANSI C programming support, allowing Joy to do about
anything than C can do (other than link in modules in C,
to be sure). This would involve three new types: floats,
FILEs, and something I call "ocseq"s for "octet sequences".
These last are like strings, but are counted rather than
null-terminated, and are used for binary file I/O.
I will start posting patches for parts of this effort
as I get it done.
That will leave the biggest limitation on practical Joy programming
to be the fact that there is no garbage collection for strings:
they are allocated with malloc, but never freed. So a Joy version
of cat(1) would in effect have to keep the whole input memory-resident
but garbage, unless it copied using getch and putch alone.
Anyone feel interested in tackling this problem? I understand
stop-and-copy GC in principle, but have not tried to analyze the
Joy implementation.
BTW, I presume the Joy source is Open Source, but a formal
license such as the BSD license (available at
http://www.opensource.org/licenses/bsd-license.html)
would be appreciated.
--
John Cowan
cowan@...
One art/there is/no less/no more/All things/to do/with sparks/galore
--Douglas Hofstadter
John Cowan — 2001-03-29 14:34:34
Dirk-Ulrich Heise wrote:
> Would it make sense to define an unknown symbol as
> an "unbound function" that can be manipulated (e.g.
> using function composition) but not executed as long
> as we don't know its value?
That is indeed the effect of my patch. You can define
"foo" thus:
DEFINE foo == bar dup +.
even though "bar" is not known. Likewise, you can
create quotations involving "bar" and manipulate them
like other quotations. (Thus far standard Joy.)
But the minute you try to execute such a quotation, or
execute foo, you get an error.
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Martin Young — 2001-03-29 15:54:38
On Mar 29, 9:34am,
cowan@... wrote:
> That is indeed the effect of my patch. You can define
> "foo" thus:
>
> DEFINE foo == bar dup +.
>
> even though "bar" is not known. Likewise, you can
> create quotations involving "bar" and manipulate them
> like other quotations. (Thus far standard Joy.)
>
> But the minute you try to execute such a quotation, or
> execute foo, you get an error.
So you're going to allow new words to be defined during program execution?
By allowing words to be defined at runtime you have to define some semantics
about when definitions are bound to their names i.e. you have to choose lexical
binding or dynamic binding.
AFAICS you're proposing dynamic, where the binding is resolved when the word is
executed. This means that your function "foo" may have completely different
semantics on different invocations. Lexical binding, OTOH, makes the word's
semantics static but requires an appropriate definition of bar when the
definition is made and thus won't let you realise your premise.
If you choose dynamic binding then you're effectively giving the language
global state. This will make it very hard to analyse programs and to optimise
them becuase it won't be possible to always replace a word by it's definition
before execution.
For example a program such as:
foo == [ 2 ]
bar == [ foo foo + ]
...could be trivially optimised to
bar == [ 4 ]
...as the program is being read however if you allow redefinition then this
can't be done because foo may not always be [ 2 ].
--
Martin Young working for STMicroelectronics at `(o)_(o)' The fat wise /
1000 Aztec West, Almondsbury, Bristol, BS32 4SQ. ( V ) owl eats only >
+44 1454 462 523 `v'
Martin.Young@... `.___,' clean mice. /
_(_)_ -="==="=============='
John Cowan — 2001-03-29 17:21:36
Martin Young wrote:
> So you're going to allow new words to be defined during program execution?
No, although this capability is already present in Joy thanks to the "include"
word. What is being discussed is 1) whether an unbound word should be
permitted in a definition at all (Forth no, Joy yes), and 2) what the effects
are of executing such a word (standard Joy, no effect; my version of Joy, error).
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Martin Young — 2001-03-29 17:58:05
On Mar 29, 12:21pm,
cowan@... wrote:
> Martin Young wrote:
> > So you're going to allow new words to be defined during program execution?
>
> No, although this capability is already present in Joy thanks to the
"include"
> word.
Hmm. I wouldn't have included "include" in "the language" myself. It's more
of an environment thing.
> What is being discussed is 1) whether an unbound word should be
> permitted in a definition at all (Forth no, Joy yes), and 2) what the effects
> are of executing such a word (standard Joy, no effect; my version of Joy,
> error).
So all you're discussing is whether (a) forward references should be allowed in
programs, and (b) what happens if you try to run them before the reference is
resolved?
Ho-hum.
--
Martin Young working for STMicroelectronics at `(o)_(o)' The fat wise /
1000 Aztec West, Almondsbury, Bristol, BS32 4SQ. ( V ) owl eats only >
+44 1454 462 523 `v'
Martin.Young@... `.___,' clean mice. /
_(_)_ -="==="=============='
Billy Tanksley — 2001-03-29 22:34:54
From: Manfred von Thun [mailto:
phimvt@...]
> 3) In interp.c after line 825 you recommend that
> "If an attempt is made to execute an undefined symbol,
> a runtime error should occur."
> I am not so sure about that. Certainly, in most other
> languages this is the most sensible thing to do. I was
> toying with the idea years ago, but then I rejected it.
I find this shocking :-). I'm VERY glad I found Joy; it's good to see some
different thought from what I've always known.
> My reason was, roughly, this. Consider the definitions
> LIBRA
> square == dup * ;
> nothing == ;
> double == 2 * .
> The most reasonable behaviour for "nothing" should be that
> if it is ever executed it should do what the definition
> says: everyting between the "==" and the ";" and that
> is the empty program which is the identity of concatenation.
Perfectly reasonable.
> OK, so now consider a list,
> [ peter paul mary ]
> which, when first used, cause the three names to be entered
> into the symbol table.
What??? Why? Why should "using" a list cause anything inside the list to
be entered into the symbol table? I think that only a (1) symbol literal or
(2) definition should cause anything to be entered into the symbol table.
So [ `peter `paul `mary ] could cause what you're asking for. Or to borrow
from Scheme, `[peter paul mary] would work very well.
> No runtime behaviour has been defined
> for them if they were executed by, say,
> [ peter paul mary ] i
> Now it seems to me that no runtime behaviour defined should
> mean that the three names behave just like empty programs.
> That was my reasoning.
Even accepting your initial premise on the behavior of identifiers appearing
inside a list-literal, that doesn't make sense to me. Undefined runtime
behavior doesn't mean _no_ runtime behavior. IMO _doing_ something makes
more sense; and an error makes the most sense of all.
> It would be good to hear what other people think,
> especially the Forth people. What do the Forth implementations
> do, and what reason is given for whatever that behaviour is?
> I am willing to be persuaded one way or another.
Forth compilers ALWAYS emit an error on reading an undefined word which
isn't parsable as a number. This allows:
- immediate errors when you make a mistake.
- TONS of optimizations, including the obvious generation of trivial native
code (subrouting-threaded).
- ease of reading: you KNOW everything's defined somewhere above where it's
written.
Now, sometimes (rarely) you need to use a word before it's defined; most
commonly that would happen when defining mutually recursive words, but any
programmer might want to do something like that in order to make the
presentation clearer. This would be trivial in Joy if it were possible to
declare functions before defining them.
Printing no error, and doing nothing at runtime, opens one up to terrible
debugging experiences, and gives no advantages of any kind (I'm going out on
a limb). I would recommend disallowing any undeclared word at compile-time
(in the Forth style), but I could probably be convinced that runtime errors
are okay if someone would come up with an advantage.
> b) generic functions. I toyed with (text-)macros a bit, using
> (contrary to the advice of some members of the group) M4
> for lack of something better and available. It 1) gave the
> ability to inline some functions (and therefore increase
> efficiency a little bit), 2) allowed debugging info to be
> inserted/deleted at the flick of an M4 macro, without
> runtime cost, and 3) was _intended_ to provide some
> genericity - but I never got very far there. And, since
> M4 of course only provides text macros, errors can only
> be caught at macro expansion time. Maybe you should write
> some small generic functions in your imagined extension
> of Joy and let us have a look at them.
I believe he's talking about function overloading, not genericism. I'd like
overloading, as provided in strongForth (q.v.).
I don't care for M4, not because I don't like M4, but rather because a
concatenative language should be able to do everything M4 possibly can.
Simply add two new concepts to the Joy language:
1) immediate words, which execute as soon as they're parsed (even in the
middle of a definition)
and
2) access to the source from a Joy word, together with parsing words.
So, for example:
HIDE
reverse (immediate) == parse-token parse-token insert-into-source
insert-into-source;
IN
test == reverse print "Hello world!";
'reverse', of course, is silly and pointless; however, it illustrates the
point: it parses source which appears in definitions in front of it, and
modifies the definition in which it appears. One could imagine defining a
word which would read an algebraic or k expression and insert the equivalent
RPN one.
> - Manfred
-Billy
Billy Tanksley — 2001-03-29 22:55:48
From: John Cowan [mailto:
cowan@...]
>AFAIK it is not allowed to even mention, in the definition of a Forth
>word, any word whose definition has not yet begun. So Joy has this
>advantage over Forth (from the standpoint of flexibility), that
>you may mention not-yet-defined words and define them later.
Not much of an advantage -- all Forth needs to catch up is a way to declare
words without defining them. In fact, most Forths use DEFER for that
(although it's not in the ANSI standard, it's ancient common use).
>> Anyhow, enumeration types like "TrafficLights"
>> might be a useful addition to Joy, possibly more so that
>> just symbols in set literals.
>True, but right now Joy does not have user-defined first-class
>types. All in good time...
Another chance to plug strongForth: rah! rah! :-)
>> b) generic functions.
>I will post more on this later. My desire is to make it possible
>for people using user-level types such as queue and bigset to
>write functions which are generic across several of them.
>I think this can be done with a single rather strange low-level
>word, but the details are not firm in my head yet.
I'd like to hear more. I suspected that you were talking about function
overloading, and it looks like I'm right.
>> Best wishes, and thank you again for your interest
>I am also thinking about a large extension, about 60 words,
>to add ANSI C programming support, allowing Joy to do about
>anything than C can do (other than link in modules in C,
>to be sure). This would involve three new types: floats,
>FILEs, and something I call "ocseq"s for "octet sequences".
>These last are like strings, but are counted rather than
>null-terminated, and are used for binary file I/O.
>I will start posting patches for parts of this effort
>as I get it done.
Exciting! I especially like how you're replacing C's annoying and
inappropriate use of null-termination with some counted strings.
One comment: Forth used to use bytecounts for all of its strings, but this
was a mistake. It meant that no Forth words could accept strongs longer
than 255 characters, and it meant that in order to use an ordinary C string
Forth had to copy it. Modern Forths, ever since the ANSI standard, now
assume that the counts are stored seperate from the strings; in other words,
any function which accepts a byte pointer also accepts a count. The pair
together make up a string. This allows strings to be stored in the old,
compact format, but also allows you to use very long strings and/or
null-terminated strings.
>That will leave the biggest limitation on practical Joy programming
>to be the fact that there is no garbage collection for strings:
>they are allocated with malloc, but never freed. So a Joy version
>of cat(1) would in effect have to keep the whole input memory-resident
>but garbage, unless it copied using getch and putch alone.
>Anyone feel interested in tackling this problem?
If you manage to implement generic functions, it should be easy to define
special cases for destructive words which, instead of simply discarding the
address of a string, actually delete it.
>BTW, I presume the Joy source is Open Source, but a formal
>license such as the BSD license (available at
>http://www.opensource.org/licenses/bsd-license.html)
>would be appreciated.
That's true. BSD would be best; if you want to guard your work, LGPL would
also be generally acceptable. GPL, on the other hand, would keep your work
in the educational domain (which might not be unacceptable).
>John Cowan cowan@...
-Billy
John Cowan — 2001-03-29 23:08:28
Billy Tanksley wrote:
> I find this shocking :-). I'm VERY glad I found Joy;
And may we all find Joy!
> What??? Why? Why should "using" a list cause anything inside the list to
> be entered into the symbol table?
It doesn't. Merely typing in a word causes it to go on the symbol
table with a null definition, as in Lisp or Scheme.
> I think that only a (1) symbol literal or
> (2) definition should cause anything to be entered into the symbol table.
Except there are no symbol literals in Joy, only list literals. To get
a symbol on the stack, you have to say
[foo] first.
Forth AFAIK has no symbols on its stack in this sense.
> This would be trivial in Joy if it were possible to
> declare functions before defining them.
In fact, Joy allows defining functions in any order, as long as they
are defined before they are executed.
> I believe he's talking about function overloading, not genericism. I'd like
> overloading, as provided in strongForth (q.v.).
We already have overloading in primitive words; for example, "concat"
works equally well with a pair of strings, a pair of lists, or a pair
of sets. I would like user words to have the same power *without*
having to be written with knowledge of all user-level types in advance.
In this context, a user-level type is identified by an arbitrary predicate,
such as "list of size 3" or "list whose first element is 'foo'" or
"string ending in '$'".
> 1) immediate words, which execute as soon as they're parsed (even in the
> middle of a definition)
> and
> 2) access to the source from a Joy word,
This we have: [foo] first body will push the definition of
foo on the stack. But there is a firewall in Joy against allowing words
to define other words (except by way of "include") that I think assists
in reasoning about Joy programs. Arguably "include" should never be used
in "application time" words.
> One could imagine defining a
> word which would read an algebraic or k expression and insert the equivalent
> RPN one.
One shudders. :-)
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Billy Tanksley — 2001-03-29 23:37:57
From: John Cowan [mailto:
cowan@...]
>Billy Tanksley wrote:
>> I think that only a (1) symbol literal or
>> (2) definition should cause anything to be entered into the
>> symbol table.
>Except there are no symbol literals in Joy, only list literals. To get
>a symbol on the stack, you have to say
> [foo] first.
>Forth AFAIK has no symbols on its stack in this sense.
As we've discussed, Joy really has no symbols either. When you say "[foo]
first", as mentioned, you don't get a symbol on the stack; you get a
function which represents the symbol. Forth calls this a 'word'.
I'm suggesting that if Joy wants to pretend to have symbols, it should
_actually_ support them, via literals and so on. It shouldn't require that
every symbol represent a function.
It's notable that Joy also doesn't support functions as such -- "[foo]
first" wasn't something the author had planned for, it just sort of
_happens_ to work. There are no functions to help with it.
>> This would be trivial in Joy if it were possible to
>> declare functions before defining them.
>In fact, Joy allows defining functions in any order, as long as they
>are defined before they are executed.
This is true -- but it does this by means of a HORRIBLE hack, which forever
prohibits Joy from simple optimization. This would be fine if there were
some justification -- but there's not.
>> I believe he's talking about function overloading, not
>> genericism. I'd like overloading, as provided in
>> strongForth (q.v.).
>We already have overloading in primitive words; for example, "concat"
>works equally well with a pair of strings, a pair of lists, or a pair
>of sets.
This is not overloading; it's merely runtime type information.
>I would like user words to have the same power *without*
>having to be written with knowledge of all user-level types in advance.
That's overloading. You can do it staticly, as in strongForth, or
dynamicly, as in any of the object-oriented languages or extensions.
>In this context, a user-level type is identified by an
>arbitrary predicate,
>such as "list of size 3" or "list whose first element is 'foo'" or
>"string ending in '$'".
That's a great idea, but it's uncomputable. It's better to keep types
simple.
>> 1) immediate words, which execute as soon as they're parsed
>> (even in the middle of a definition)
>> and
>> 2) access to the source from a Joy word,
>This we have: [foo] first body will push the definition of
>foo on the stack.
This does absolutely nothing of the sort -- it's not even faintly, obliquely
related. It can only access stuff which has already been parsed _and
compiled_. At that point it's redundant information. If this is to be
useful as a macro language, it has to access the source before the parser
has even had a chance to look at it.
>But there is a firewall in Joy against allowing words
>to define other words (except by way of "include") that I think assists
>in reasoning about Joy programs. Arguably "include" should
>never be used in "application time" words.
Agreed. I'm not yet suggesting adding defining words, though; I'm only
suggesting source manipulation. Now, a full source manipulator could be
used to create defining words, but that's unavoidable, by the nature of
macros. The nice thing about these defining words, though, is that they're
immediate; they CANNOT be used at runtime, because they always execute at
compile-time.
"include" could be converted to an immediate word.
>> One could imagine defining a
>> word which would read an algebraic or k expression and
>> insert the equivalent RPN one.
>One shudders. :-)
Indeed. :-) May Forth programmers before you have shuddered at the thought
-- then, finally, someone implemented such a thing, and hey presto!, it
wasn't as bad as we thought it'd be. Nor was it as neccessary as some
anti-RPN people thought, but that's to be expected.
>There is / one art || John Cowan <jcowan@...>
-Billy
John Cowan — 2001-03-30 03:47:58
Billy Tanksley scripsit:
> As we've discussed, Joy really has no symbols either. When you say "[foo]
> first", as mentioned, you don't get a symbol on the stack; you get a
> function which represents the symbol. Forth calls this a 'word'.
Granted. I must confess I have not read all the archives yet.
> It's notable that Joy also doesn't support functions as such -- "[foo]
> first" wasn't something the author had planned for, it just sort of
> _happens_ to work. There are no functions to help with it.
What functions would you want? Ask now, and they might get implemented!
> This is true -- but it does this by means of a HORRIBLE hack, which forever
> prohibits Joy from simple optimization. This would be fine if there were
> some justification -- but there's not.
It doesn't prohibit it, it just means it can't be applied in every case.
You are free to inline any definition you already know, since there is
no runtime redefinition. (If the programmer redefines things, though,
you will have to decide what to do with inlined code.)
> That's overloading. You can do it staticly, as in strongForth, or
> dynamicly, as in any of the object-oriented languages or extensions.
It is the latter I have in mind.
> >In this context, a user-level type is identified by an
> >arbitrary predicate,
> >such as "list of size 3" or "list whose first element is 'foo'" or
> >"string ending in '$'".
>
> That's a great idea, but it's uncomputable. It's better to keep types
> simple.
What do you mean "uncomputable"? If general types are too slow for you,
use simple ones that can be computed quickly. But if I want to define
a type "prime number", I see no reason why I can't have it.
> >This we have: [foo] first body will push the definition of
> >foo on the stack.
>
> This does absolutely nothing of the sort -- it's not even faintly, obliquely
> related. It can only access stuff which has already been parsed _and
> compiled_. At that point it's redundant information. If this is to be
> useful as a macro language, it has to access the source before the parser
> has even had a chance to look at it.
I have no interest in implementing a macro language for Joy.
--
John Cowan
cowan@...
One art/there is/no less/no more/All things/to do/with sparks/galore
--Douglas Hofstadter
Reuben Thomas — 2001-03-30 10:04:54
> Modern Forths, ever since the ANSI standard, now
> assume that the counts are stored seperate from the strings; in other words,
> any function which accepts a byte pointer also accepts a count.
However, old-style words that accept counted strings (where the count is
stored before the string) still, unfortunately (but understandably) dictate
that the count is one character in size.
--
http://sc3d.org/rrt/ | violence, n. bravery for cowards
John Cowan — 2001-03-30 17:57:38
Billy Tanksley wrote:
> Not much of an advantage -- all Forth needs to catch up is a way to declare
> words without defining them. In fact, most Forths use DEFER for that
> (although it's not in the ANSI standard, it's ancient common use).
So much for instant inlining, though! In fact, no one can do any better
than "inline words whose definitions you know, don't inline if you don't".
> Another chance to plug strongForth: rah! rah! :-)
It's an interesting effort, and I'd like to see some such facility in
Joy eventually, but it's beyond my current scope. Of course, each
Joy datum already carries its (dynamic) type with it; that's how the
Joy overloaded words work.
>> [...] and something I call "ocseq"s for "octet sequences".
>> These last are like strings, but are counted rather than
>> null-terminated, and are used for binary file I/O.
>> I will start posting patches for parts of this effort
>> as I get it done.
>
> Exciting! I especially like how you're replacing C's annoying and
> inappropriate use of null-termination with some counted strings.
Actually, I think null-termination is perfectly appropriate for
strings, which are sequences of characters, because NUL is not
really a useful character. 0x00 *is* a useful octet, though.
Conceptually, an ocseq is a list whose elements are small integers
(range 0-255), whereas a string is a list whose elements are
characters. Separating these concepts, as Joy already separates
characters from integers, is the foundation of the proper treatment
of strings.
> One comment: Forth used to use bytecounts for all of its strings, but this
> was a mistake.
Internally an ocseq is represented as a pointer to raw octets and a 32-bit
length. Allowing ocseqs and floats means that each Joy stack element
gets bigger, but they are already 3 x 32 bits, so going to 4 x 32 is not
that bad.
> If you manage to implement generic functions, it should be easy to define
> special cases for destructive words which, instead of simply discarding the
> address of a string, actually delete it.
Ugh. Joy shares strings: if you say "foo" dup uncons, then the stack
looks like "foo" 'f "oo", but "foo" and "oo" share storage. Allowing
explicit deletion in that environment is the road to Hell, unpaved.
I am now looking into the Boehm-Demers-Weiser conservative garbage collector
in place of Joy's native GC. This would be a C-compile-time option,
since the BDW collector is not quite portable (though in fact portable
to all commercially important platforms, there does not seem to be a
VMS port).
> That's true. BSD would be best; if you want to guard your work, LGPL would
> also be generally acceptable. GPL, on the other hand, would keep your work
> in the educational domain (which might not be unacceptable).
Or the Free Software domain generally: not all Free Software is uncommercial.
(Ask Cygnus.) Joy is currently fairly uncommercial, though.
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Billy Tanksley — 2001-03-30 19:45:00
From: John Cowan [mailto:
cowan@...]
>Billy Tanksley scripsit:
>> It's notable that Joy also doesn't support functions as such
>> -- "[foo]
>> first" wasn't something the author had planned for, it just sort of
>> _happens_ to work. There are no functions to help with it.
>What functions would you want? Ask now, and they might get
>implemented!
The main thing which would help is some standard for what happens when
you're juggling a function. For example, "i" should be documented to be
able to take a function as an input. We also should have a syntax for
literal functions.
>> That's overloading. You can do it staticly, as in strongForth, or
>> dynamicly, as in any of the object-oriented languages or extensions.
>It is the latter I have in mind.
I'd personally like to do both. Either one alone has problems.
>> >In this context, a user-level type is identified by an
>> >arbitrary predicate,
>> >such as "list of size 3" or "list whose first element is 'foo'" or
>> >"string ending in '$'".
>> That's a great idea, but it's uncomputable. It's better to
>> keep types simple.
>What do you mean "uncomputable"? If general types are too
>slow for you, use simple ones that can be computed quickly.
>But if I want to define a type "prime number", I see no reason
>why I can't have it.
I'm sorry, I meant uncomputable at compile-time. I'd definitely like to
support arbitrary type dispatch; the problem is that it adds immensely to
overhead, when such overhead isn't really needed 95% of the time. If you
can compute the type at compile-time, it's a solid win; if you have to do
something like primality tests at runtime, though, you lose performace with
every call.
>> If this is to be
>> useful as a macro language, it has to access the source
>> before the parser has even had a chance to look at it.
>I have no interest in implementing a macro language for Joy.
Okay. I do. Or more accurately, I want Joy to be its own macro language.
>John Cowan cowan@...
-Billy
John Cowan — 2001-03-30 20:15:24
Billy Tanksley wrote:
> The main thing which would help is some standard for what happens when
> you're juggling a function. For example, "i" should be documented to be
> able to take a function as an input. We also should have a syntax for
> literal functions.
Okay, so you want combinators to accept functions. Easily done.
Currently, of course, you can make it happen thus:
DEFINE I == [i] [[] swons i] iflist.
and then use I instead of i.
> I'd definitely like to
> support arbitrary type dispatch; the problem is that it adds immensely to
> overhead, when such overhead isn't really needed 95% of the time.
*shrug* Joy is not Forth. It already has runtime dispatching in
almost every primitive. Static typing is orthogonal to dynamic
typing, I agree; what I want is user-level dynamic typing.
> Okay. I do. Or more accurately, I want Joy to be its own macro language.
Full steam ahead, then.
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Billy Tanksley — 2001-03-30 20:17:09
From: John Cowan [mailto:
cowan@...]
>*shrug* Joy is not Forth.
Something we can agree on :-).
>> Okay. I do. Or more accurately, I want Joy to be its own
>> macro language.
>Full steam ahead, then.
Yup. :-)
>There is / one art || John Cowan <jcowan@...>
-Billy
Manfred von Thun — 2001-04-11 01:24:59
On Thu, 29 Mar 2001, John Cowan wrote:
...
> BTW, I presume the Joy source is Open Source, but a formal
> license such as the BSD license (available at
> http://www.opensource.org/licenses/bsd-license.html)
> would be appreciated.
Yes, you presume correctly. I did look at the page you mention,
and also at the other licenses. I even joined the license discussion
group (of which I note you are a contributor), but I have not
had time to read, and even less to really understand what is going
on.
Do I have to go through that process of discussion ?
Or is it sufficient to edit the BSD license template
and include a link "license" on the Joy home page ?
Since you know these things, could you just tell me
what to do - please.
- Manfred
John Cowan — 2001-04-11 04:22:47
Manfred von Thun scripsit:
> Do I have to go through that process of discussion ?
No, not at all! If you plan to use a pre-existing license such as the
BSD license, you can just *use* it. The only reasons to belong to
license-discuss are these:
1) the subject is intrinsically interesting to you
2) you enjoy reviewing other people's licenses to see if they are Open Source
3) you are trying to get your very own license classified as Open Source compliant.
None of these apply in this case.
> Or is it sufficient to edit the BSD license template
> and include a link "license" on the Joy home page ?
That is sufficient. You should also add it to each of the source code files
so that if they get separated from the home page, the copyright status
and license are clear.
--
John Cowan
cowan@...
One art/there is/no less/no more/All things/to do/with sparks/galore
--Douglas Hofstadter
Billy Tanksley — 2001-04-11 18:31:20
From: Manfred von Thun [mailto:
phimvt@...]
>On Thu, 29 Mar 2001, John Cowan wrote:
>> BTW, I presume the Joy source is Open Source, but a formal
>> license such as the BSD license (available at
>> http://www.opensource.org/licenses/bsd-license.html)
>> would be appreciated.
>Do I have to go through that process of discussion ?
>Or is it sufficient to edit the BSD license template
>and include a link "license" on the Joy home page ?
>Since you know these things, could you just tell me
>what to do - please.
No discussion needed; simply do what you've said, and include a copyright
notice at the head of each .c and .h file, and one in the executable
(probably at startup).
> - Manfred
-Billy