6 ms·
I've never really got Forth. It's good for sending commands to a printer, but actually programming in it seems like a drag. I get that it's technically the same
by James_K 2y ago
I've never really got Forth. It's good for sending commands to a printer, but actually programming in it seems like a drag. I get that it's technically the same as lisp code, just backwards without the parens, but adding the parens just makes it easier to understand. Adding variables is smart and would make it more tolerable but I would still rather work in lisp.
- gergo_barany 2y agoForths do have local variables. (Cue debates on what makes a stack-based Forth-like language a "Forth".) Here is the description of Gforth's support for its own extended locals and the Standard Forth locals: https://gforth.org/manual/Locals.html https://gforth.org/manual/Locals.html (Cue debates on whether Standard Forth is a Forth and whether it is standard.) When I learned Forth about 15 years ago, we used the { } syntax described here, not the newer(?) {: :} syntax: https://gforth.org/manual/Local-Variables-Tutorial.html https://gforth.org/manual/Local-Variables-Tutorial.html
- anta40 2y agoMe too. For some reason, Lisp is kinda easier for me. And if I need to go low level: assembly. I read Forth was popular among embedded devs during 80/90s. That's not my field, though.
- wolfadex 2y agoThere are Forth like languages, such as Kitten, that have variables and more. https://kittenlang.org/ https://kittenlang.org/
- James_K 2y agoDo they have any compelling reason why "List<T>" isn't just "T List"? That's how they write it in OCaml. Then comma separated lists, are they mad? I much prefer how Uiua does this.
- veltas 2y agoHere's why it's interesting: https://termbin.com/blz3 https://termbin.com/blz3 There you go, now it has parens, just backwards. Can even use parens instead of braces if you want, I just didn't want to overwrite comment syntax.
- Y_Y 2y agoI copy your code below, because it's so terse and marvellous and I don't want to deprive anyone who assumes otherwise and doesn't click on your link: : >BRACES 1 CELLS BRACES +! BRACES @ ! ; : BRACES> BRACES @ @ -1 CELLS BRACES +! ; : { DEPTH >BRACES ; : } DEPTH BRACES> 1+ <> ABORT"unbalanced" ; And the example "backwards lisp" expressions you give as test cases: { 1 2 + } . { 5 { 1 2 + } * }
- James_K 2y agoI don't find that particularly interesting. My entire point was that it has essentially the same semantics as lisp, and this just demonstrates that. Also, I don't know a lot about Forth, but it would seem to be limited to 30 levels of brace nesting, even between functions. Unless I am mistaken, it requires a pointless increment and decrement of a variable before and after every function call. I also don't know if it would work in a threaded context. Aren't those just functions? If so, it wouldn't work in compiled code.
- veltas 2y ago> it would seem to be limited to 30 levels of brace nesting Yes because I declared 30 cells, you can declare more if you want. > Unless I am mistaken, it requires a pointless increment and decrement of a variable before and after every function call. Yes it adds overhead, you can rebuild with : { ; IMMEDIATE : } IMMEDIATE ; and then there's zero overhead on any Forth, when you've demonstrated the braces match. This is meant as an aid for people that struggle without parens. > Aren't those just functions? If so, it wouldn't work in compiled code. It works in compiled and interpreted code, 'just functions' compile automatically without trouble in Forth, it's parsing words and immediate words that need care. No that code wouldn't work with multiple threads, but if you declare the space as USER space it would, similar to just whacking 'thread_local' on something. The example is failing in one regard, that it doesn't provide a way to reset the stack if something goes wrong. You can use something like : RESET{} BRACES BRACES ! ; to accomplish that. But it is just meant to show that Forth is quite succinct and powerful, which it does.
- eschneider 2y agoForth is awesome in situations where you've got a small environment, with crap tools, and you need to do some iterative development. In a pinch, you could hand assemble a Forth kernel and just burn it on an EEPROM and away you go. There are usually nicer alternatives today, but when you had to build your tools up from nothing, it was a very reasonable option.
- dreamcompiler 2y agoCorrect. You can build a Forth compiler from hand-typed hex machine code. It will be a bit easier if you have an assembler handy, but that's not essential. Trying to build a Lisp compiler this way would be madness.
- bunderbunder 2y agoI guess you could say that syntactically it's like lisp, only backwards and without the parens. But the deeper truth is that concatenative programming and procedural programming (or functional, I suppose, depending on your preferred lisp flavor) are very different paradigms that lead to fundamental differences in how you structure your code. I haven't used Forth in anger for over two decades now, but in some ways I do miss how the language felt even more hackable than a good lisp, while simultaneously being easy to reason about at a low level. That said, the RPN and stack manipulation definitely make it a bit of a brain teaser, especially at first. In that sense it reminds me of Prolog and APL and, for that matter, Lisp: they're languages where the greatest joy of learning them is the way they force you to think in very different ways, and how that can promote epiphanies about computation. I would need to spend more time grokking this language to really understand, but it appears that the author has effectively achieved something that's semantically equivalent to Forth, but has a lot of syntactic commonality with Lisp. That's rather compelling to me from a "eliminates the first and most noticeable stumbling block for newcomers" perspective. That said, I'm having to repress a bit of a desire to react the same way parts of the Racket community did when Matthew Flatt announced his infix syntax project. Is a key part of Forth's concatenative nature lost when the syntax itself is no longer concatenative? I don't know, and I'll admit it's very doubtful that I'll spend enough time with Forsp to find out. But it's an interesting thought, all the same.
- qludes 2y agoThe coolest thing about Forth to me wasn't Forth itself but that it was a part of the OpenFirmware standard: https://standards.ieee.org/ieee/1275/1932/ https://standards.ieee.org/ieee/1275/1932/ I never understood why that standard just died and wasn't adopted for something like ARM SBCs where the built in debugging ability would come in useful.
- astrobe_ 2y agoThe comparison between Lisp and Forth that is often made is very shallow. It's more than just prefix vs postfix. Lisp takes garbage collection for granted, Forth is designed to avoid any complication and doesn't even have heap allocation. The lack of local variables and named parameter is also a consequence of this search for ultra-low complexity, in dialects that follow the traditional style (the one of the creator of Forth, Chuck Moore). The readability argument is one that should always be taken 1024 grains of salt. You say Lisp is more readable, yet you'll find some people to say that it's "Lots of Insipid and Stupid Parenthesis" and that prefix notation is unnatural. You could also find positive opinions about APL. It is just a matter of training and habits.
- James_K 2y agoLisp is objectively more readable. Adding parentheses around expressions distinguishes them. Compare the following. a b c d (d (c b) a) The bottom example is objectively more readable. You can determine more about its intended function by looking at the code. In the top case, you can't tell what is a function call or how many arguments each function consumes. In the bottom, you can.
- astrobe_ 2y ago> objectively more readable Certainly not "objectively" in the literal sense, because there's no measure of "readability". But you can define one if you want, so that we can argue about its biases and relevance ;-) But Forth programmers sometimes use double spaces to separate sub-expressions: (d (c b) a) <=> a b c d ... or something like that. But in reality what one writes is (hopefully this is close enough to your abstract example): (square-root (+ (square a) (square b))) <=> a square b square + square-root Or if we stick to real-forthers-do-not-use-local variables: square swap square + square-root Newbies will probably use "training wheels comments": ( a ) square swap ( b ) square + square-root I know the usual objections that one needs to keep the number of inputs/outputs of each word/function. It's actually not as difficult as it seems with good naming and when you keep things simple. Actually, the former is a well-known hard problem and the latter is a perhaps lesser-known hard problem. But I would say that's good problems to solve.
- timonoko 2y agoForth was the sweetest thing in fixed length machines 60 years ago. When everything is one word, you can assign unique symbol for that word and keep those symbols in separate file (aka paper tape). Some Forth primitives were also machine primitives, like INC [SP] or "++", increase the number at top of stack.