Hacker News new | past | comments | ask | show | jobs | submit login
Retro: A Modern, Pragmatic Forth (forthworks.com)
80 points by Supermighty 24 days ago | hide | past | web | favorite | 50 comments



The link http://forth.works/book.html is broken. Maybe the correct link is: http://forthworks.com/retro/book.html


Another modern Forth that has a cross-compiler to make Windows, Linux, Mac, Android, Raspberry Pi, and iPhone executables is 8th.

https://8th-dev.com/

It comes bundled with the C++ based JUCE GUI framework, SQLite, ODBC, encrypted binaries, JSON support, and a lot of support for other things that you typically don't see in a tool written by one person. The more expensive licenses come with AWS and automotive Linux support, so nifty for this area.

Sadly, it is closed source and commercial (although you can get source with an enterprise license I think). On the plus side, it is really cheap (there is a free version too I believe) and the main developer seems to add user requested features and fix bug reports very quickly.

I obviously wouldn't write a production system in it (although I'm sure you could), but I wouldn't mind having a fun REPL based language to write simple and easy to distribute cross-platform desktop apps.


It's interesting (at least to me) because it's different from anything else out there. The way it runs, the way it is compiled and the language itself are nearly unique. It's also easy to bootstrap on very small machines and fairly easy to implement. It's the light saber of programming languages, "a more elegant language for a more elegant time". But then, that could just be the nostalgia talking...


What is the culture here on correcting wrong star wars quotes?

"An elegant weapon for a more _civilized_ age"

https://www.youtube.com/watch?v=0aRtupiY9Dw


Polite pedantry is generally okay here. If done well and including a source, it may even get a bunch of upvotes (a somewhat objective, though imperfect, metric of cultural acceptance).


Thank you, it didn't sound quite right, but wasn't sure why...


Retro has been in development for 2 decades and has gone through quite a few changes in that time. It is inspired by Chuck Moore's forth and avoids the mistakes of the ANSI standard.

It is the forth of choice for any serious forth developer.


> avoids the mistakes of the ANSI standard

I'm unlikely ever to learn forth, but if there are general lessons to be learnt from the mistakes made, I'll learn from them. So, what are those mistakes? (thanks)


> It is inspired by Chuck Moore's forth

Which one? Because Retro and ColorForth seem light-years apart to me.


ColorForth is light-years apart from everything.


I’m not too familiar with Forth, but I see posts about it and variants like this on HN from time to time.

High-level, what makes Forth interesting? What are it’s major strengths and weaknesses?


A long time ago I wrote a tutorial for FORTH. It's in two parts, a part written in i386 assembly: https://github.com/nornagon/jonesforth/blob/master/jonesfort...

followed by a part written in FORTH: https://github.com/nornagon/jonesforth/blob/master/jonesfort...

It builds gradually from asm primitives into a somewhat sophisticated language with features like exceptions, function inlining and a decompiler.

The major strength, probably unique amongst programming languages, is that you can keep the entire system in your head (by "system", I mean both language and the simple operating system that it implements). The downside is that the code is write-only.


I just wanted to say "Thank You!" For jonesforth. I don't know how many times i've read it. It's probably what made everything "click" for me, so "thanx"


I'd like to say thank you too. I've studied your code many times, and it helps me understand forth finally. I was attracted by colorforth first, which is harder.


I wanna thank you fourth! Such a great tutorial, and I used it to build a little Forth for the GBA. It was such a great experience.


Another big thank you.

I've used that to build a FORTH interpreter on an AVR micro.


You can bring it up quickly on a new platform, be it exotic hardware or a self-styled VM.

Small Forths can be totally understood by the programmer (perhaps just a few pages of code for their kernel), but still be expressive enough to actually use. Applications written in Forth are typically deeply entangled with the interpreter. You can't separate a "program" from the environment.

It's more like a collection of ideas and design principles than one singular language. Most Forth programmers write their own implementation, or several. You can decide what indulgences you want. (I like having "quotations"- inline anonymous word definitions like Retro has- and special-cased string literals. I also have my own style of looping words that aren't quite like ANS Forth.) This also means Forth code can never be dropped into another project and directly re-used: you can only take ideas.

Starting from a blank page every time, carrying with you ideas and writing code afresh is a good way to travel light. Self-reliance. Building human-scale programs. No one would write a web browser, or an Oracle-compatible SQL engine, in Forth, because a Forth programmer wouldn't have much of a use for those things. Solve only the problems you really have, with as little code as you can manage.


Forth is like lisp in that there are lots of implementations, but this effect is multiplied. In fact, most folks that learn forth roll their own which is what the inventor Charles "Chuck" Moore does for every project.

Forth is unique as it is probably the only serious language that you can write production systems in and understand the entire compiler/interpreter, parsers, data structures, and functions (called words).

Everything is pretty simple. You could use C as the base, but traditionally you would write a few dozen assembly routines and link them together and form some core words to manage a stack (there are 2 stacks and that is it) and make more complex words.

It gets a lot more deep, but Forths aren't really for me. If I'm going to use something weird, I'll write some APL.


As someone who has written a considerable amount of Forth as a hobbyist, studied APL, and been paid to write K, it's fascinating to me how aesthetically similar the Forth and APL communities are, despite their languages approaching minimalism from completely different sides of the spectrum. I definitely credit learning to read Forth as helping to open my mind to the unconventionality of APLs. Spend enough time out there on the edge and you don't get as hung up on whether syntax resembles C or is "unreadable".


Forth and APLs both have a really strong data flow aesthetic.


Exactly! They're both concatenative languages, or at least languages which have a concatenative subset. Juxtaposition is composition.

APL/K and Forth also have very concise syntax for declaring functions.

    // JS
    const foo = (x,y) => 1 + x * y

    // K, lambda with implicit arguments
    foo: {1+x*y}

    // K, points-free
    foo: 1+*

    // Forth
    : foo * 1+ ;
It's subtle, but I think making function declarations "lightweight" in this manner is important for encouraging factoring. In APLs the scale of the semantic units you give names to is a little different, but that's its own separate discussion.


It would be interesting to have a forth where, if you try to pop from an empty stack, you get a function object that consumes the next things pushed onto the stack (i.e. functions are curried)


Interesting points. Thanks for pointing this out.

I'm nowhere near your level of comprehension in either language, but agree that spending some time outside of curly brace land gets you more comfortable with other languages.


we are quite similar except I am paid to write q. In fact, I am writing a forth in q now.


> I am writing a forth in q now.

For some practical reason or just as an exercise?


I don't know. It's for fun, but I believe I will have trouble to make others to use.


So there's this talk https://fsharpforfunandprofit.com/posts/recipe-part2/ that pops up here every now and then. In it he builds these monads to allow for functions that may or may not throw errors or care about thrown errors etc. Similarly IO monads in Haskell and Mercury are often described as secretly threading the entire world through the monad and returning an entirely new world thus allowing for side effects in purely functional code.

In a stack based language those aren't interesting ideas, they're just naturally emergent.

The other thing is that it makes it utterly trivial to pull out or insert code in a function. allowing for some radical refactoring.


>High-level, what makes Forth interesting? What are it’s major strengths and weaknesses?

Strengths: Lisp-level metaprogramming facilities while also being extremely fast and close to the metal. Weakness: the Perl problem (write-only) but worse.


Write-only, because only the functions (‘WORDS’) are named - no parameter names. There are also no local variables in standard Forth, you have to push (and pop!) them from the separate return stack. Accessing parameters is done by manipulating the stack, which makes the code opaque after a year or so. Named constants and variables are all global. So, it is very difficult for a team to use, since most of the legibility of software comes from insightfully selected names. Two thirds of those names, at least, are missing in Forth.

Like assembler, Forth is untyped.

These failings could be at least partly forgiven if Forth was fast. But it isn’t, because most words are short and all the stack manipulations are done with subroutine calls. It’s possible to write an inlining, optimizing compiler, but then the simple layout of code in memory is lost, and quick introspection using a memory dump becomes nearly impossible.

But, it is a neat tool to bootstrap a working system quickly on new, embedded hardware with limited resources. Definitely a black belt tool for lightweight systems written by a single person. Hard on maintenance programmers.

See Jonesforth for a tutorial example.

I wrote a Forth a few decades ago. The insight gained reminds me of Nand2tetris, but the latter is far more mainstream.


all the stack manipulations are done with subroutine calls

This can have an advantage: one can stuff much more code (and functionality) in a very memory limited system (e.g. smart cards), especially with WORDS compression:

"Huffman threaded code is one of the most compact representations known for a computer program"

https://en.wikipedia.org/wiki/Threaded_code#Huffman_threadin...


> Write-only, because only the functions (‘WORDS’) are named - no parameter names.

Depends on who is the writer...

> There are also no local variables in standard Forth

Named locals variables are in the standard, as an optional extension. Because not everyone want them.

> you have to push (and pop!) them from the separate return stack

That's the main reason why the return stack is exposed to the programmer, yes, but there are other techniques like putting some of the data that are used throughout the program in (global) variables. you generally choose depending on how much simplification you gain and how much modularity you lose etc.

> Accessing parameters is done by manipulating the stack, which makes the code opaque after a year or so

Depends on how you write and comment.

> Named constants and variables are all global. So, it is very difficult for a team to use

Standard Forth as vocabularies to isolate functions, constants, and variables that is supposed to help with name clashes. Many variants like Retro have some sort of namespace mechanism.

Did you actually use Forth in a team context?

> These failings could be at least partly forgiven if Forth was fast. But it isn’t, because most words are short and all the stack manipulations are done with subroutine calls

Not a problem, because you design your programs to minimize stack juggling. Less overhead, more readable, one stone, two birds.

My dialect which uses very naive subroutine threading (it just executes lists of function pointers) can rival with Lua (non JIT) on certain tasks because my Forth doesn't spend its time doing useless stuff like looking up an hash table.

The speed of Forth is not in its bytecode interpreter. It's in the simplifications it encourages.

> It’s possible to write an inlining, optimizing compiler, but then the simple layout of code in memory is lost, and quick introspection using a memory dump becomes nearly impossible

I have written a few decades such a thing for the 8086, and I would say the lack of introspection was never a problem. When you write such a system, the hex machine codes sticks quickly in your head. I think I wrote a disassembler for the lulz, but an hex dump was probably my main "introspection" tool.

> I wrote a Forth a few decades ago

I wrote several Forth systems in the last few decades. The latest one I wrote is my goto-tool and serves me almost daily.


> Depends on how you write and comment.

Unless working in assembly or something of that sort, tend to I comment only on noteworthy matters pertaining to specific logic, not recurring units of basic program structure and their routine connections.


The only "extraneous" comments related to the point-free style of Forth are the "stack diagrams" showing the inputs and outputs of a definition/function, when it's not obvious from the code (it very often is when you write one-line definitions).

This is no different from what people do with Doxygen. Nobody prevents anyone from using a Doxygen-like tool with Forth. Or even literate programming if that's your thing.

Inside definitions, if you have to insert a comment to remind yourself what the state of the stack is at that point, very often it means you have failed in some way. Some refactoring or rethinking is needed.


> Nobody prevents anyone from using a Doxygen-like tool with Forth.

Nobody prevents anyone from writing a perfect solo project from scratch in which their idea of best practices is assiduously adhered to. Then there are projects where other people don't follow one's favorite practices, and projects one inherits that had previous maintainers which didn't follow those practices.


Yes, sure. That's why you have VBA, Java, Perl, C, Newlisp, Fortran, Python projects that are maintenance nightmare. Forth is nothing special with regard to this concern. Code quality has a lot more to do with the skills of the writer than the peculiarities of the language.

Except perhaps that you are more concerned with code quality when you know that it will be hard to read a couple of months later if you are sloppy.

Forth is unforgiving in many ways like an old master. There are people who call him a bad teacher, and there are people who listen to him. This is the difference between good students and bad students.

Anyway, the fact that Forth, Inc., has been in business for forty years and is still taking new commercial projects [1] is enough of a proof that Forth is more than just the code written by hobbyists you see on GitHub.

[1] https://wiki.forth-ev.de/doku.php/events:ef2018:forth-in-tha...


> Forth is nothing special with regard to this concern

When we look at a clump of Forth code that's supposed to be a function, unless there is commentary, we don't know how many arguments it takes or how many values it leaves on the stack.

We don't have this problem with VBA, Java, Perl, C, Newlisp, Fortran or Python.

Forth is an assembly language for a pretty low level stack-based virtual machine. (And such machines are very popular, though rarely programmed by hand.)

It's not a good VM for compiling dynamic languages; it provides no run-time check on mismatched function arguments, and generating code to do that would be inefficient and incompatible with regular Forth function calls. (E.g. we can have a calling convention whereby we push the argument count that the callee will pop and check.)

Forth could be a good target for a static language where function calls are checked at compile time against declarations.

> Forth is unforgiving in many ways like an old master.

Forth is completely forgiving, like an old buffoon. Pass four arguments to a three-argument function? All is forgiven.


> Forth is an assembly language for a pretty low level stack-based virtual machine. (And such machines are very popular, though rarely programmed by hand.)

Forth is indeed an assembly language for Forth processors, but Forth was never intended as some sort of intermediate language. It is a programming language for humans since 1970.

It's interesting to note that, unlike Lisp machines and other language-X-processors who are now rusting in museums, "Forth processors" are still being launched in space [1].

So, to anticipated about what you say later, it must be a cosmic buffoon. Better than dying from a slightly cold winter I guess.

> It's not a good VM for compiling dynamic languages

Off topic, but why would you do that anyway? At some point, register-based VMs outperformed stack-based VMs due to the evolution of processors (cache, branch prediction, large register banks) and progresses in compilation techniques.

Forth doesn't need to be "recycled" as a target language. It is useful enough for those who've practiced it long enough to understand its value proposition.

> Forth is completely forgiving, like an old buffoon. Pass four arguments to a three-argument function? All is forgiven.

Lua and Newlisp (and probably other Lisp variants) let you pass more arguments or less arguments to a function; you won't get any warning while the compiler/interpreter silently ignores the extra parameters or fills the missing parameters with nil.

In Forth there are some ways to detect argument mismatches, but really nobody cares about those training wheels. The problem is solved in a different way.

Also, many dynamic languages had to add a "strict mode" because letting people not declare identifiers is not so "user-friendly" after all...

I'll trade any day a language that breaks on stupid typos for a language that breaks because I forgot to push a result. Actually, that's why I did.

[1] https://en.wikipedia.org/wiki/RTX2010


Using NewLisp as representative of Lisps is a strawman argument. It's a garbage project that is despised by anyone who is serious about Lisp.

ANSI Common Lisp and Scheme do not allow too many or too few arguments to be passed to a function.

Let's try CLISP:

  [1]> (defun test () (cons 1 2 3))
  TEST
  [2]> (compile 'test)
  WARNING: in TEST : CONS was called with 3 arguments, but it requires 2
           arguments.
Or:

  [3]> (defun test (x))
  TEST
  [4]> (compile 'test)
  WARNING: in TEST : variable X is not used.
           Misspelled or missing IGNORE declaration
Unbound vars:

  [5]> (defun test (x) (+ x y))
  TEST
  [6]> (compile 'test)
  WARNING: in TEST : Y is neither declared nor bound,
           it will be treated as if it were declared SPECIAL.
> nobody cares about those training wheels.

Error checking is for lesser programmers: very effective advocacy!

> The problem is solved in a different way

Exhaustive testing? The problem is that there isn't even a reliable dynamic check. A misuse of the data stack in one place can affect code elsewhere. Just because you step on the bug doesn't mean that the machine will halt with a diagnostic, let alone one that pinpoints the cause.


> Using NewLisp as representative of Lisps is a strawman argument. It's a garbage project that is despised by anyone who is serious about Lisp.

Well, your opinion about it has changed quite a bit... I still like it probably because I am less interested in "serious about Lisp" than in pragmatic solutions. The other day I shipped a small networking utility as two files: the standard newlisp.exe and a newlisp script. I used Newlisp instead of my equivalent written in Forth because the user may have needed to hack it a little bit. The instruction I had to give was "just copy that on your desktop and drag the script file to the exe file". Job: done. I count it as Lisp being useful in 2019.

Anyway, there's still dozens of scripting languages that won't move an eyebrow about bad arity.

>> nobody cares about those training wheels.

> Error checking is for lesser programmers: very effective advocacy!

Beginners are not lesser programmers, they are less skilled programmers. It's a temporary condition.

Also, I'm not advocating Forth. It hasn't caught in 40 years, so it is obviously not for everyone. I'm just clearing what I think is misunderstandings. Just like I would defend a show when I think some reviewer totally misunderstood it.

> Exhaustive testing?

Yes, this is one of the ways. Whether you use static, dynamic, or no type-checking that's something you do anyway when things get serious. Because none of them catch all bugs.

> The problem is that there isn't even a reliable dynamic check

Stack imbalances in practice catch half of the programming errors. It's a bit like in Haskell: if it compiles, it has good chances to be right. In Forth, it translates into: if the depth of the stack doesn't change in your main loop, the program is probably right.

> A misuse of the data stack in one place can affect code elsewhere.

Most often the program just segfaults right away, because you're manipulating pointers quite often. That's another 25% of errors caught.

> doesn't mean that the machine will halt with a diagnostic, let alone one that pinpoints the cause

Relying on stack dumps and debuggers is a terrible habit. Looking for the simplest way to solve a problem is far more effective globally.

I know this sounds insane. I was there decades ago. I built a Forth that couldn't possibly crash and was disappointed by the result. I built Forth debuggers and was also disappointed. I built support debugging primitives in VMs and I was disappointed. That's because I was trying to cure the symptoms instead of the illness. Then I started to throw away and rewrite when a piece of code was buggy. That helped a lot.

For one thing you get rid quickly of the "lets try this to see if it works" mentality, which is a recipe for bugs and half-baked code. "Do. Or do not. There is no try".

If debugging is the process of removing software bugs, then programming must be the process of putting them in. -- Edsger Dijkstra

This guy was right. Studies have shown that the amount of bugs is proportional to the LOC count. The message is "Program less, think more", and this is also what Forth says:

You factor. You factor, you factor, you factor and you throw away everything that isn't being used, that isn't justified. -- Chuck Moore, 1x Forth [1]

Basically that's "The simplest thing that can possibly work" [2] approach taken to the extreme. The thing is, being extreme is not easy. You can pick a low-hanging fruit or two by being audacious sometimes, but being extreme means climbing the tree to the top.

[1] http://www.ultratechnology.com/1xforth.htm [2] http://www.agilenutshell.com/simplest_thing


> Well, your opinion about it has changed quite a bit.

I'm not aware that I have held any other opinion about NewLisp at any time in the past.

The language described by ANS Forth not only doesn't have arity checking, it has no type checking. That is to say, the items on the data stack have no type: not run-time, not static. Two addresses could be pushed onto the stack, and then operated on as a double integer.

There is nothing wrong with that, just like there is nothing wrong with machine language instruction sets. We can write a compiler for a higher level language which compiles to ANS Forth, one that is considerably safe. There is value in that because we still have the benefit of portability, small run-time footprint and low resource use, depending on our application size.

Type, arity and other checking is not analogous to training wheels for beginners. Nobody believes nonsense like this once they are out of their programming puberty. I suspect you wouldn't say that in an interview, if you actually wanted the job.

> Most often the program just segfaults right away

If you're getting a "segfault" it's because you're running on a virtual memory system (likely written for you in a considerable amount of C).

Things don't always segfault right away. The problem can be in a conditional code that depends on particular kinds of inputs.

If you're having to trivial function arity mismatches with segfaults (when you have the luxury segfaults) is ridiculous, you can't simultaneously believe that you're working in a higher level language on par with Common Lisp or Scheme, or even ANSI C.

> Anyway, there's still dozens of scripting languages that won't move an eyebrow about bad arity.

And they are all garbage; so what? Many of these languages, however, will at least behave somewhat safely in the face of bad arity. That is to say, if there are insufficient arguments, those parameters get some default values, and excess arguments are ignored, without lingering around to cause a problem elsewhere.


> We can write a compiler for a higher level language which compiles to ANS Forth, one that is considerably safe

You are better off targeting some bytecode VM rather than targeting the Forth language itself. You can target for instance Lua Bytecode and still have all of the benefits.

> Type, arity and other checking is not analogous to training wheels for beginners. Nobody believes nonsense like this once they are out of their programming puberty. I suspect you wouldn't say that in an interview, if you actually wanted the job.

Well I used to believe it was nonsense too. Maybe I'm older that you. Or maybe I was more curious.

I would definitely mention the fact I can program in a point-free, type-less language. That's an additional skill, not a hindrance. I didn't have the chance to test this because I already have a programming job (where I use Forth for personal supporting tools that help dealing with the peculiarities of embedded systems or with the shortcomings of our official software - but don't tell anyone). What I wouldn't do is trying to sell something like Forth to an unknown team for an unknown project.

> If you're getting a "segfault" it's because you're running on a virtual memory system (likely written for you in a considerable amount of C).

Actually yes, it assumes the processor has at least a MMU (virtual memory technically is an additional feature that's often built on MMU). If the CPU doesn't have a MMU, the virtual machine can perform some checks on the pointers (e.g. memory alignment if the CPU requires it). At my current level of sloppiness that's something that could be helpful if really I can't fix my bad habits.

> If you're having [segfaults because of] trivial function arity mismatch, you can't simultaneously believe that you're working in a higher level language on par with Common Lisp or Scheme, or even ANSI C.

I think I did say that Forth is indeed a low-level language. I have no problem with that, because "low-level language" doesn't mean "lesser language" to me.


> Write-only, because only the functions (‘WORDS’) are named - no parameter names

You could use lambda notation to name the parameters of a function, while still preserving postfix function application as in FORTH. This would effectively give you De Bruijn notation, in which named lambda was often denoted `[var] expr`. Though, ironically, De Bruijn is also known for his "nameless" De Bruijn indexes, which dispense with the very naming of function parameters, replacing these names with what are in effect references to positions on some abstract argument stack.


It's also important to observe that Forth's approach to metaprogramming is very powerful, but completely different from Lisp's approach. It's not just another retread of the same ideas. CREATE...DOES>, immediate words, parsing words, fancy tricks with the rstack and other fun Forth stuff has at best very loose analogs in Lisp macros.


Where could I get a good tutorial on Forth metaprogramming?


I think the late J.V. Noble's "A Beginner's Guide to Forth" does a good job introducing the language and touching on some metaprogramming features. Near the end he demonstrates a library which extends the language to support infix math expressions (a "FORTRAN") to make scientific computing more convenient.

https://www.taygeta.com/fsl/docs/551.jvn.fall01/primer.htm#c...


> Lisp-level metaprogramming facilities

Not even close. Rather more like macro-assembler-level metaprogramming facilities.


FORTH is less a programming language and more a religion or philosophy on how programs should be written. The philosophy basically suggests that one should make programs as simple as possible... way, way simpler than a modern programmer might think "as simple as possible" means. This philosophy clicked for me when I saw the segment in the colorforth manual saying "if the cursor doesn't appear on screen, hold up and left until it does." Why bounds check if it isn't necessary?

Ultimately a language is there to make programming a CPU easier. If you believe in just absolute minimal complexity, FORTH is what you get when you find this intersection of leverage vs. minimal tolerable complexity. A FORTHer generally doesn't believe in writing device drivers so much as writing maybe 20 lines of code yourself that twiddle the registers to get done what you want. You're basically told to ask yourself over and over again "do you really need that?" The answer is usually "well I might need it tomorrow... maybe..." but in software, requirements change so fast that the abstractions we design for what we think we might need tomorrow don't actually match what's actually needed. The FORTHer solution isn't to just continue generalizing until you have a fully galaxy brain interface that could accommodate anything the future could throw at you-- it's just to not generalize at all, and to put the weight of working in a system with less abstraction on the programmer. The bet is that the weight of dealing with less abstraction is less weight than dealing with a tower of abstractions that were built for the wrong requirements.

I don't know if I fully buy it, but it's worth trying to think like a FORTHer as an intellectual exercise to make you a better programmer.


A lot of language VMs use a Forth-like bytecode. Python, WebAssembly, even the JVM languages (sort of) use a stack-based bytecode. So it's a useful paradigm to understand if you're interested in working on the internals of a language like that.


I think this is a bit of a misconception. A critical element of Forth is that there are two stacks: a data stack for operands, and a return stack for keeping track of what word to return to after each call completes (and other fun stuff). These stacks grow and shrink independently. Unused operands on the data stack quietly flow along to the next word that takes a peek with no overhead. There's no difference between how the stacks are used within an "expression" and between "function calls"- these concepts don't exist at all like they do in curly-brace languages!

In a typical non-Forth "stack VM", there is a single stack which behaves like the C stack: allocate an activation record with locals on a function call, pop the whole thing off at the end. Intermediate calculations go on top of all this, avoiding the need to explicitly register allocate in bytecode, but operands don't naturally flow between function definitions; they're copied around explicitly as the stack grows and shrinks.


I think they meant that the bytecode itself reads like a forth. The data stack works just like it does in forth within a single Python function.




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

Search: