99% was spot on with me, and articulated far better than I would have.
dlenmn wrote:
All data is effectively passed between functions (like plus) with two stacks which you are very intimate with.
Once you get used to this concept, you'll find other languages kind of limiting because you're constantly having to name things, even when they really don't need a name.
Quote:
commands are kept very short, making them quite cryptic.
No, you just don't know the language yet (by which I mean you're not "fluent" with the language yet).
The recommended Forth word is no longer than two lines. Moreover, you should strive hard to have fewer than 3 items on the stack for a word (this does
not mean that your stacks cannot exceed this depth to be useful; it just says that, as a rule of thumb, any one word shouldn't need more than 3 parameters. Obviously, rules of thumbs can have exceptions if well founded). For example:
Code:
: paint initialize begin event-loop done? until ;
That's not hard to read, and is amazingly English like. Let's see how this goes as we get deeper:
Code:
variable done
create handler-table
' mouse-movement-handler ,
' mouse-button-handler ,
' keyboard-handler ,
: off 0 swap ! ;
: done? done @ ;
: initialize graphics-mode reset-mouse done off ;
: event-type current-event @ @ ;
: to-handler cells handler-table + @ ;
: handle-event event-type to-handler execute ;
: event-loop begin event? until handle-event ;
Note that "!" and "@" mean "store" and "fetch" respectively. They're assigned single-character names because they're used so often. By the way, for those interested in the history of those names, it's because back then ! was used to indicate "destructive updates" in Lisp, which means the value written destroyed another value in the same memory location (e.g., as STA overwrites memory with the current accumulator contents). Hence, ! became store, while @ became fetch. For BASIC users, ! is POKE, @ is PEEK.
Other than what I described, I'd like to see if the reader has any difficulty in understanding the above code. If not, then let that stand as proof that self-documenting and highly readable and maintainable Forth is possible. Don't be fooled by the claims of Forth being write-only. I've seen even Pascal programs that were extremely difficult to read and maintain too, and Pascal is
the benchmark in readable code (or, at least, was, until Python came around, but even Python is a descendent of Modula-2).
Quote:
I should also point out that the language is not interpreted (although it didn't quite fit my idea of compiled, mainly because, in hindsight, I didn't have much of an idea of what complied means).
It's both. Forth is interpreted at the outer interpreter level (e.g., what you type interactively
is interpreted in the BASIC sense of the term). Inside colon definitions, however, the code is typically compiled into what's called
threaded code. Threaded code (not to be confused with multi-threaded code!) is a highly compact representation of a program where most of the overhead of normal interpretation is performed at compile time. This representation can be either interpreted with what's called an
inner interpreter, or can be natively executed by the CPU. It all depends on the type of Forth you're using. There are also native-code compiling Forth environments that produce code rivaling or exceeding those of modern C compilers as well, but they're usually commercial Forth environments, and tend to be expensive.
To illustrate how these different methods differ, look at the following example:
Code:
\ in Forth, this is what you see...
: to-handler cells handler-table + @ ;
\ in a direct-threaded Forth environment, this is what the CPU sees:
to_handler:
jsr colon_definition
dc.w cells, handler_table, plus, fetch, exit
\ in an indirect threaded Forth environment, this is its memory layout:
to_handler:
dc.w cells, handler_table, plus, fetch, exit
\ in a subroutine-threaded Forth environment:
to_handler:
jsr cells
jsr handler_table
jsr plus
jmp fetch
Quote:
Also, many (most? certainly most for older processors) implementations of forth do not have built in support for floating point numbers, so you have to put some thought in to using integers as fixed point numbers.
This is true only for those systems that lack a hardware FPU. Those which offer a FPU will typically have floating point words defined for them.
Quote:
I can't imagine writing complicated pieces of software in forth, but probably because I'm not in the right mind set.
It's all about the mindset. Several quite significant projects have been written in Forth. See
http://forth.gsfc.nasa.gov/ . The Canon Cat word processing system was written entirely in Forth. Nearly every one of Atari's stand-up arcade games were written in Forth back in the early to mid 80s. The Soviet Union even used Forth for its military and academic projects (while we concentrated on C and Lisp) because they couldn't afford the computing resources we enjoy. Now that the iron curtain has fallen, we're seeing a sharp decline in the use of Forth in Russia.
Quote:
Because you have to write many small functions, it's really ideally suite for breaking a problem down into (very many) bite sized pieces, and hence is good for top down design.
But, you'll want to do
bottom-up implementation. Test the foundation code as you go, interactively. This leads directly to lower time to market and with fewer bugs.
Quote:
Moore has said some stuff along the lines of "All forth programers are jubilant, but I've never met a happy C programer," I beg to differ
While that is quite a stretch, I do know for a fact that I haven't met a single former-C-now-Forth programmer who wasn't ecstatic about the language. I've converted quite a few people myself, and not once did I do any proselytizing. I won the programmer over with documentation, actual working code, and observed programming productivity performance.
I hate the proselytizing myself -- my other all-time favorite language is Oberon, which is a refinement of Modula-2 -- about as wholesale opposite of the Forth philosophy as you can get.
As someone knowledgable in BASIC, BCPL, C, Forth, Io, Java, Lisp, Modula-2, Oberon, Pascal, Perl, Python, Tcl (vaguely), and more I probably forgot, I think I have a right to say that Forth really is the all-time most misunderstood language, perhaps with Lisp in 2nd place. Lord knows that, next to BASIC, it's easily one of my most productive programming languages, and like BASIC, it is highly conversational.