Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Here's why it's interesting: 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.



I 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 + } * }


I 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.


> 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.


> you can rebuild with : { ; IMMEDIATE : } IMMEDIATE ;

Does the call to DEPTH still work in that case?

> But it is just meant to show that Forth is quite succinct and powerful, which it does.

How does it show that? You could write a similar function in almost any programming language, with the only difference being the call to DEPTH which I don't see as being generally that useful. As an example in common lisp:

  (defvar depth nil)
  (defun { () (push (depth) depth))
  (defun } () (unless (and depth (= (depth) (pop depth))) (error "Unbalanced expression")))
And this example doesn't stop working after a certain number of open braces. It's simultaneously more readable and more terse than the Forth code. Saying that Forth is powerful just because you can use it to write a compiler for a more powerful language is silly. By the virtue of Turing-completeness, you can do this for any language.


> Does the call to DEPTH still work in that case?

Code using the braces can use those definitions when you want to remove the overhead, and it disables the feature. This lets you use it as a programming aid, and then remove the overhead completely when it's not necessary or for a 'release build'.

> It's simultaneously more readable and more terse than the Forth code.

Does it still look neater when you use the syntax you've defined?

> And this example doesn't stop working after a certain number of open braces.

If you really want to remove the limit you can, Forth is just explicit about memory management. This is like C vs JavaScript. I'm quite happy playing with memory management myself, but if you don't like that or think declaring a fixed size stack is hacky then I can see why Forth wouldn't be appealing.

Here is one way to remove the limit, it has drawbacks (but so do all dynamic memory approaches, they're just hidden by managed languages).

  : POP   HERE -1 CELLS + @  -1 CELLS ALLOT ;
  : {     DEPTH , ;
  : }     DEPTH  POP 1+  <> ABORT" Unbalanced" ;
> Saying that Forth is powerful just because you can use it to write a compiler for a more powerful language is silly.

Yes but in a few lines of simple code, and the result is actually a syntax that looks nice to use.


> This is like C vs JavaScript.

And you'll notice that C isn't a very powerful language.

> Does it still look neater when you use the syntax you've defined?

No because in CL you would define a with- macro that syntactic enforces equal nesting. So the CL version is:

  (defmacro {} (&rest args) `(progn ,@args))
I thought that would be too trivial demonstrate though. If you really don't like how it looks, you can fix it with two more lines of reader macros. The result would be a nicer syntax as you wouldn't have to put spaces around the braces.

> Yes but in a few lines of simple code, and the result is actually a syntax that looks nice to use.

Those are a few lines of highly complicated code that does something very simple and just happens to use the short function names { and }. The actual implementation of those functions is easier to write in almost any other language, which is what I was demonstrating with the CL example. If you want to make the case that Forth is powerful, you need to do more to prove it than show you can hack together a half-solution for a problem Forth created. Forth simply isn't a powerful language when counting matching braces is a difficult problem.


> C isn't a very powerful language.

Okay.

> I thought that would be too trivial demonstrate though. If you really don't like how it looks, you can fix it with two more lines of reader macros. The result would be a nicer syntax as you wouldn't have to put spaces around the braces.

The example is 'trivial' though. Also compare how big Forth is against CL, I mean Forths are often well under 10KB. I've written a Forth like this. I've never written a CL. Have you?

> Those are a few lines of highly complicated code that does something very simple and just happens to use the short function names

Just because you're incredulous doesn't mean that's not a feature.

> easier to write in almost any other language, which is what I was demonstrating with the CL example

CL isn't 'any other language' though, lisps specifically have quite powerful reflection.

> hack together a half-solution for a problem Forth created

Hacky half-solutions are charming, and Forth didn't create the 'problem' of structured syntax, it just didn't provide a solution out-of-box. That's one of the very explicit tradeoffs of the language.


> Also compare how big Forth is against CL

I would say a lot of this is because CL has a large standard library, but not much of that is primitive. Even then, I would say the CL standard lacks many things, so it is too small for general use rather than too large. From a perspective of implementation, I would almost always choose a small Scheme over Forth or something Forth-like.

> CL isn't 'any other language' though, lisps specifically have quite powerful reflection.

Those functions don't use reflection.

> Forth didn't create the 'problem' of structured syntax, it just didn't provide a solution out-of-box. That's one of the very explicit tradeoffs of the language.

It created the problem of not having structured syntax and that's a trade-off that you lose as soon as you write more than a maybe a hundred lines of code.


> Those functions don't use reflection.

Sorry I mean macros / or whatever. You know what I mean(?).

> that's a trade-off that you lose as soon as you write more than a maybe a hundred lines of code

And yet you can have braces with e.g. 2-3 lines of code. Anyway this is beyond tedious now, sorry for provoking you with my code, or my opinion that Forth is interesting, or with the praise I received, or that Forth kicked your dog or something; I'm not really sure what did it. I have talked with you in good faith to try and help you understand why it's interesting to me, I don't claim it's an absolute good or even necessarily practical in most situations.


You misrepresent me here. I never claimed that Forth is uninteresting, just that your code was. The statement I take issue with is that Forth is powerful. In reality, it is useful only because it is not powerful and hence is easier to implement.

> yet you can have braces with e.g. 2-3 lines of code

You can't really. You'd be better off treating braces as whitespace than having them check the stack depth before and after each function call. They wouldn't even be correct then because you could make multiple calls within the same set of them. If you want to implement braces properly, you'd need a way to introspect how many arguments a function takes, but Forth is not powerful enough to do this.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: