Arc Forumnew | comments | leaders | submitlogin :D

Did you build all these dialogue boxes yourself too? Very snazzy. :D

New 2-minute video: support for strings, arrays and file handles that starts to give this the feel of a shell language.

2 points by Mitranim 38 days ago | link | parent | on: Observations on homoiconicity

I might check it out later, but is there a gist in text form somewhere?
1 point by akkartik 38 days ago | link | parent | on: Observations on homoiconicity

You might enjoy this talk which mentions this equation:

    code = AST + formatting/comments
2 points by Mitranim 39 days ago | link | parent | on: Observations on homoiconicity

Should clarify something (follow-up to previous reply, see below or above).

Most macros don't want to deal with whitespace and comments. We also might want to _not let_ them, otherwise people will start using comments as code, like in Ruby. Macros just want expressions. So, we would define a second level of the AST and perform a second pass.

For the same base notation, there may be multiple languages defined in terms of it. If such a language has any form of prefix or infix, or uses the `outside_parens()` calling convention, the second pass would have to group nodes into expressions, in ways specific to that language. Furthermore, it should be addled with metadata about packages, types, and so on. The resulting AST is compiled, fed to macros, etc.

2 points by Mitranim 39 days ago | link | parent | on: Observations on homoiconicity

> Why do you care about emitting exactly the code that was parsed? What new apps does it enable?

Got a `gofmt` addiction, can't go back. Auto-formatting should ship with every language.

Briefly skimmed the Go implementation, and you seem to be right: it seems to lose whitespace and enforce its own formatting.

> Are you aware of any languages that perfectly reproduce input layout?

For now just my own. [1] The language isn't real yet, and might never be realized, but it has a base data notation (very Lisp-like), a parser, and I just started writing a formatter. Because the AST for the data notation preserves whitespace and comments, the formatter can print the code _exactly_ as is. This has interesting repercussions.

For a fully-implemented formatter for a fully-defined language, you wouldn't need whitespace; see Go. However, being able to print everything back means your formatter is usable from the start. It can support one or two simple rules, making only minor modifications, but you can use it on real code right away. Furthermore, this means we'll _always_ be able to choose which rules to enable or disable, which can be handy if the family of languages described in terms of this notation has different formatting preferences. I actually want the formatter shipped with the language, like `gofmt`, to be non-configurable, but this still seems like a useful quality.


1 point by akkartik 39 days ago | link | parent | on: Observations on homoiconicity

Thanks for sharing! It's been a while since I thought about this, but my conclusion a few years ago[1][2] was that homoiconicity was an ill-posed idea. A language only really needs two properties to make macros convenient:

* Everything is an expression, and

* Unambiguous parens.




That said:

* I like symbols. Having symbols and strings in a Lisp doesn't seem any more weird than having variables and string literals in Algol or Java. Even if I _could_ use one in place of the other, it seems useful to separate symbols as part of the program from strings as part of the environment/domain/data model. You could implement one with the other, sure, but I wouldn't question anyone who chose not to. After all, every attempt I've seen to support spaces in symbols has been quite ugly.

* Your other points seem to be in the context of building tools like code formatters where the output will be seen by humans. That's not really the context for Lisp macros. I haven't really thought much about how useful they would be. Since I believe in macros, I can probably be persuaded. So that might be an interesting post to write. Why do you care about emitting exactly the code that was parsed? What new apps does it enable?

Are you aware of any languages that perfectly reproduce input layout? Even Go supports gofmt only by tightly constraining how programs "should" be indented, and only outputting that layout.

2 points by Mitranim 40 days ago | link | parent | on: Observations on homoiconicity

While Lisp-style homoiconicity can simplify the initial implementation of a dynamic language, there are tradeoffs; the post lists a few.

New 2-minute video: defining functions in this postfix language.

Very interesting. This would have made learning Forth easier!

You're right that in general any such example can be refactored to reduce stack operations. That's even a fun game for many Forth programmers to play. (We lispers have our own equivalents.) But it usually makes the code less comprehensible, in my experience.

Yes, that is definitely simpler, although the formula is more esoteric. At least, for me, it triggers the "I was taught this in school and haven't used it since" filter.

Maybe something like:

  total-price cost-per-item number-of-items shipping-cost-per-item rush-cost = cost-per-item number-of-items * shipping-cost-per-item number-of-items * + rush-cost +
This doesn't seem super great; it could be refactored to use each thing once, but it's late and I can't think of any better example.

Yeah, some other polynomial might be a better example. The Pythagorean formula has a clean separation when it comes to which args each term uses. How about the roots of a quadratic equation when you start out with a, b and c on the stack?


Is it that you're trying to reduce stack juggling? That's hard to understand from simple examples (that you need to have to grok the syntax). Maybe compare something like finding the hypotenuse of a right triangle given the two other sides. Without naming arguments, you'd have to do something like:

  hypot = dup * swap dup * + sqrt
But with named arguments:

  hypot x y = x x * y y * + sqrt
That seems a little easier to read, but even the original isn't so complicated. Is there an example that makes it more obvious why it's better? Even your `square` example is more tokens than with stack juggling (without arguments, `square = dup *` is just four tokens, compared to six with named arguments). I'd say the with-arguments one is easier to read, but I've far less familiar with stack-based postfix programming.

That's a great point. As I've built this, the keystone example in my mind has been the `square` function:

    x square = x x *
So it's really funny that I haven't added it yet. Now added.

Super interesting! I like how you can zoom into the system, almost like using a microscope to see how code works.

One thing that isn't quite clear from your examples here (and maybe that wasn't the point, but I am wondering): why have a different stack when a function is called? Your examples would work fine if they used the same stack. That is, if functions used the same stack, `1+` could be defined as `1 +`.

Perhaps it would be more clear if an example used two variables, or used the same variable twice.

Sounds interesting. Sorry about the RSI. Went to using an ergonomic keyboard, which seems to have squelched it for me.

I've been hanging out on the Handmade Network Discord channel recently. Mostly because I've developed RSI so can't work as much on Mu, and because I'm bored staying home for months on end.

The site seems to be some sort of offshoot from a channel where a game developer used to screencast himself developing a game:

From what I can piece together, Handmade Network periodically has some sort of Jam for a few days where a few people hack on projects following some theme.

The most recent theme was Lisp:

Flip was built for the Lisp Jam. You can see a demo about it here: (though you'll need to sign up to that Discord group)

There was a discussion about it, a sort of debrief after the Jam, that you can read at

It's already sparked a bunch of ideas for me: So decent payoff on being bored and finding this community :)

Tell us more
2 points by zck 100 days ago | link | parent | on: Still alive?

I use a static site generator I wrote in Arc to generate two websites. It's more fun to do that in Arc than any other language I know of.
2 points by akkartik 103 days ago | link | parent | on: Still alive?

It's still running HN :)

Previous thread:

Edit: Another thread from 5 years ago:

Thanks! The goal is to make it _way_ easier to reproduce a single test, and investigate what's going wrong.

And it's a testament to the power of Lisp that I didn't have to change much to make it happen.

This is awesome. Particularly the instructions for rerunning a single test in isolation.

"See, most data structures aren't really data structures at all. They're _acceleration_ structures _for_ data."

I just encountered the GraphBLAS project which feels like maybe a more mature approach to this idea:

Well... That's a good question.

I haven't read any more than a few papers on it, and maybe only one of those in depth (which I'll mention below). Mostly I'm going by forum threads, wiki articles, and the design choices certain languages make (like Inform's multimethods and Haskell's type classes).

As far as I understand the history, Philip Wadler's work basically defined the strict parameters of the expression problem and explored solutions for it. Separate compilation and the avoidance of dynamic casts were big deals for Wadler for some reason.

That work was focused on Java, where it's easy to define new classes that implement existing interfaces but impossible to implement new interfaces on existing classes.

The solution I'm most familiar with for Java-style languages is the use of object algebras, as described in Oliveira and Cook's "Extensibility for the Masses: Practical Extensibility with Object Algebras" ( In this approach, when you extend the system with a new type, you define a new interface with a generic type parameter and a factory method for building that type, and you have that interface inherit all the existing factory methods. So you don't have to solve the unsolvable task of implementing a new interface for an existing class, because you're representing your types as type parameters and methods, not simply as classes.

So I think the main subject of research was how best to represent an extensible program's types and functions in a language like Java where the most obvious choices weren't expressive enough. I think it's more of a "how do we allow extensions to be made at all" problem than a "how do we make all the extensions maintainable" problem.

But then, I've really barely scratched the surface of the research, so I could easily be missing stuff like that.

There is already a wiki that isn't getting much use[0].



It sounds like you mean a JSON generator (emitting JSON) rather than parser (ingesting JSON). Is that right?