Paul Rubin wrote:
> Bernd Paysan <
bernd....@gmx.de> writes:
>> In Forth, you write a program which draws the robot, you don't write
>> an
>> interpreter for complex nested robot data structures. The program is
>> nested.
>
> So what do you do if you want to describe a few different robots in
> the program? Write separate programs for each?
Why not? What would you do when you describe robots in a data
structure? Write a separate data structure for each? Of course. You
can factor complex data structures, and you can factor complex programs.
If you think there is a substantial difference between a program and a
sufficiently complex data structure, you just don't get it.
You can have a robot with
4 red arms
green cylinder body
4 black wheels
Is this a data structure or a program? I don't know, I don't care. To
draw the robot, you have to interpret the data structure or to execute
the program.
> But all the features in Unity3D are there because somebody wanted
> them. And if you're making a toolkit for other people to use, I think
> you really do have to anticipate their requirements.
Hm, again, Forth philosophy is slightly different.
a) you don't anticipate future needs (you only take current needs into
account) and
b) you don't bury your tools
This b) is actually done to anticipate future needs *the right way*. If
I make a toolkit, and make sure you can't access *my* tools, I have to
anticipate what you will need, and implement all of that. If I give you
my toolkit-building tools, you can implement your stuff, even though I
didn't anticipate it. I wrote something which allows to easily draw
robots and let them move through a maze, and you use the tools to draw
robots to instead draw plants and flowers, and let the user manage his
or her garden.
>> No, you just write your program piecemeal, and debug a few additional
>> word at a time.
>
> But then you end up modifying the code and that usually introduces
> errors, so you're back to debugging.
I try to make these modifications one little piece at a time, and then
test it, as well. If I don't, if I do a big lump of changes, chances
are high that it doesn't work, and that getting out of that mess takes
more time than unrolling all the changes, and doing them one little step
at a time.
git bisect even automates this sort of debugging - when you have an
automated test for it. It's clearly not unique to Forth. Having
automated tests for the features that already work is a good idea.
I think someone like you, with a good grasp for formal methods, should
look at John Hayes ttester (in Gforth under test/ttester.fs; the
examples in the test directory are of more value than the source code
itself). You complained that Forth doesn't check stack effects. Well,
just add a check yourself:
require test/ttester.fs
: bounds ( addr len -- last first ) over + swap ;
t{ 3 5 bounds -> 8 3 }t
For words with no side-effect, you can simply leave these tests in the
code. When you introduce an error, you see it when you compile next
time.
>> Furthermore, we don't really have that many types in
>> Forth, so the most likely confusion is between integers and floats.
>
> Don't forget addresses and xt's, which are easy to get confused with
> data.
Addresses and xts *are* integers. And they do point to some other data,
which you can inspect - in an ITC Forth, even portably among different
ITC systems (Gforth's stepping debugger works only on Gforth-ITC,
because it uses this fact).
> And I don't think Forth's lack of strings, arrays, associative
> tables, closures, etc. help its attractiveness to programmers used to
> such newfangled conveniences.
Most desktop Forth systems will provide you with most of those features.
There's even a package for closures based on mini-oof, which passes
Knuth boy-or-men test.
If you haven't found Forth strings, arrays, hash tables, etc., by now,
it's because you were looking at an embedded Forth, where all these
features just don't fit.
>> I probably would use string.fs from Gforth; it's not really difficult
>> to add reasonable string handling to Forth.
>
> I'd think reasonable string handling absolutely has to use garbage
> collection (or at least, C++-style finalization on exit from a scope)
> to clean up the intermediate results of complex string manipulation.
> If strings.fs does that then it's interesting.
string.fs uses a transformation model rather than a creation model.
I.e. all you have are global string variables. Most string
manipulations aren't complex, they usually are either adding things to
the end of a string, or search/replace passes through the string, which
transform the string.
Other people have suggested and implemented string stacks. That works
even for cases where you need to create string objects dynamically, but
with a limited scope (like this C++-style finalization). You finally
have to drop it off the string stack when you leave the scope.
>> As I said, it's probably a skill issue. Just look for people who
>> have experience in incrementally and quickly compiling code at
>> run-time, and you end up finding Forth implementers.
>
> Oh come on, there just aren't that many Forth programmers. Lisp
> systems have done on-the-fly compilation since the dawn of time, Java
> probably uses the best-known JIT, etc.
Java's VM has a direct ancestral line to Forth, because Goslin worked on
Postscript before (and Postscript is highly influenced by Forth).
In any case: JavaScript *is* a Lisp, apart of the syntax. It would be
far more natural that the JavaScript engines would use Lisp compilation
techniques, which have been there since the dawn of time. It doesn't,
for whatever reason. Two out of four state-of-the-art JS engines use
Forth. None uses Lisp (ok, we don't know about Microsoft's, this is the
one closed source state-of-the-art JS engine). And there are probably
more Lisp programmers around. But for them, the on-the-fly compiler is
an "others people problem". For a Forth programmer, the compiler isn't.
This is a consequence of "don't bury your tools" philosophy. Therefore,
while you find less Forth programmers than Lisp programmers, you will
find more Forth programmers who can help you to implement a JIT.
Or Forth-influenced programmers who did work on other JITs like JVM.
They are Forth-influenced, because JVM is Forth-influenced.
>>> Rust is really a more advanced language than Java or C++.
>> Somewhat, yes. But it's still an ahead-of-time compiled language. I
>> don't consider ahead-of-time compiled languages (as only option) as
>> "advanced". Less retarded, maybe, is the right word.
>
> Meh, once you've got a fast build system (maybe not possible for
> certain styles of C++ but quite reasonable for other languages),
> ahead-of-time is fine.
Well, most of what you write in Forth is compiled ahead-of-time, too.
However, the good thing is that you aren't limited to that, and you can
do on-the-fly stuff whenever necessary. Like when running simple test
cases as part of the ahead-of-time compilation (shown above), or when
trying out new functions interactively on the terminal. And when
extending the system with features you think are lacking.
>> I'm usually not trying to reinvent wheels which are actually good.
>> So maybe I will just use Lua as the high level scripting language for
>> net2o.
>
> Probably a reasonable choice. Lua has some traction, has a very nice
> embeddable implementation, and is lightweight and efficient. I'm not
> that crazy about the Lua language itself but I think alternatives
> (mostly Lisp-based, like Guile) will probably stay unpopular.
Though Lua does away with most of the curly braces and the semicolons,
and even has multiple return values.