
Writing a Forth in Haskell - reinvdwoerd
http://reinvanderwoerd.nl/blog/2017/06/08/writing-a-forth/
======
moomin
Surely you just take an existing LISP implementation and call "reverse" at the
correct location in the code? :p

~~~
lacampbell
Even at the most basic level, Forth and lisp are quite different. Lisp has
grouping and evaluates using a tree. forth has no grouping* and evaluates
completely linearly.

* well you can hack it to give it grouping, but usually it doesn't.

~~~
kazinator
Lisp's abstract model doesn't use stacks to pass arguments. Arguments are just
lexical variables and they live in environments like other lexical variables:
completely foreign stuff to Forth. Environments often have to survive the
termination of a lexical scope's execution; it is required when a closure has
escaped. So things can't even be compiled to a stack-based machine, using a
"pop everything when returning" strategy: only in some cases.

(ANSI) Lisp function calls are safe w.r.t. wrong number of arguments, and
support optional and variadic arguments also. This is true of compiled code
without source: when we load someone's compiled file and call a function in it
with the wrong number of arguments, it is diagnosed.

Forth and Lisp are so miles apart, that I have to scratch my head why a
comparison comes up in discussion from time to time.

(It is pretty much _always_ from someone who uses Forth and doesn't know Lisp
(or, worse, anything that isn't Forth). "Hey, I heard Lisp is also interactive
and meta-programmable, so it must just be a Forth with postfix switched to
prefix and parentheses added ...").

~~~
lacampbell
I had this dumb idea of actually evaluating LISP in a forth inspired way. It
would be a stack of subroutine/accumulator pairs. so given

    
    
        (+ 1 2 3)
    

"(" would pop an pair on a stack, + would set its subroutine, and 1 2 3 would
be fed to the subroutine and accumulate a value. when ) is encountered, the
data is fed into the subroutine/accumulator pair lower on the stack, so you
could still have nesting.

Horribly inefficient, but I thought the idea was neat. I'm sure I'm not the
first to think of it though.

~~~
agumonkey
some antique famous lisper (Henry .. forgot last name) did write a linear lisp
that works by stack evaluation. From the few that I grasped, since everything
is mostly duped, it's like a new value each time; free borrowing ?

------
andybak
Can anyone point me to a Forth implementation where the absolute bare minimum
is written in (C/assembly/whatever) and everything possible is then
bootstrapped in Forth itself?

I recall reading what the minimal word set needed to be able to write the rest
of standard Forth (Fig Forth if I recall) but I seem to remember that most
implementations don't push the purity quite that far for performance reasons.

~~~
Marazan
Jonesforth is pretty minimal bootstrap

[https://rwmj.wordpress.com/2010/08/07/jonesforth-git-
reposit...](https://rwmj.wordpress.com/2010/08/07/jonesforth-git-repository/)

------
801699
[https://github.com/anse1/firmforth](https://github.com/anse1/firmforth)

has not been mentioned on hn afaik.

~~~
PeCaN
The very neat part about firmForth is that if you compile the firmForth JIT
with cparser (libfirm compiler), it can inline C functions into the JITted
code.

------
dopu
On an unrelated note, this is a pretty nicely designed website, OP.

------
Tyr42
I think it's also valuable to take a look at how Joy handles quoting program
fragments. I just wish there were better online resources around the language.

~~~
lacampbell
Links? When I tried I just used "[" to construct an empty dynamic array, and
pushed words into it until I found "]". Very inefficient, but simple.

------
sebcat
Doesn't really give Forth the credit it deserves. Totally misses the point of
Forth: the simplicity of the environment and it's relationship to the
underlying hardware, defining primitives like : and VARIABLE with CREATE and
DOES>, threaded code, , (COMMA) , ... Nice promotion of Haskell though

~~~
reinvdwoerd
You're right of course, this is an ongoing exploration. I hope to learn the
deeper truths in the process.

~~~
jacquesm
I would suggest re-doing the exercise on an 8 bit cpu with < 8 K of RAM. That
will open your eyes to what is so special about Forth.

~~~
robert_tweed
I'm curious about Forth, as it's probably the most important language I've
never learned. I've done a fair bit of low-level, micro-optimised coding in C
and assembly, but don't get much time for that kind of thing these days.

How would you describe Forth in relation to those? What makes it stand out and
what are its weaknesses?

~~~
jacquesm
Forth is probably the smallest true high level language there is. It is
entirely self-contained, needs just about nothing in terms of hardware support
and can run in as little as 2K of memory.

It is well suited to things like real-time control, you'll probably have a
hard time getting used to stack manipulation (especially in the beginning) and
it tends to keep you up all night (not sure if that is a strength or a
weakness ;) ).

It will also be the most fun you've had with a computer in a long time and it
will likely make you look at the rest of what we do with computers as clunky
in the extreme.

What Forth is not really suitable for is large projects and things built with
a team. It is more of an artisanal thing, something closer to watchmaking or
jewelery than major construction.

If you want to know more about why Forth is the way it is you could do worse
than to start with studying the life of Chuck Moore for a bit, the language
and its author are roughly equally interesting and for want of a better word
peculiar.

One thing Forth is not: wasteful.

~~~
gerdesj
I remember writing a fairly trivial program in Forth on a ZX81 for a school
open day. You needed the 16K RAM pack thing with the usual lump of Blu Tac to
stop it wobbling.

When I "discovered" Forth, it seemed like science fiction (soo fast!) to me
after BASIC juddering around the screen.

~~~
pedrow
Probably worth mentioning the Jupiter Ace here[0] - a ZX81/Spectrum era
computer which had Forth in ROM, instead of BASIC which was common at the
time. The basic model only had 1K of RAM. I never used one but I remember when
it came out, reviewers commented on its speed and memory efficiency.

[0]:
[https://en.wikipedia.org/wiki/Jupiter_Ace](https://en.wikipedia.org/wiki/Jupiter_Ace)

