Hacker News new | ask | show | jobs
by enugu 466 days ago
From what you write about macros, it hints at something like F-expressions and first class environments, though I am not sure if it actually does have it.

I find the Kernel programming language to be inspiring. It is based on first class environments and tries to go further in the direction of the philosophy of Scheme : "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary."

Your post is also in this spirit.

A language like this would allow a much greater dynamism and a reflective capability, but compiling it is a research project. (There was also a minor scuffle here on HN, a decade ago, regarding the non-inclusion of eval in ClojureScript in order to enable better optimization.)

https://web.cs.wpi.edu/~jshutt/kernel.html

https://axisofeval.blogspot.com/2011/09/kernel-underground.h...

---

Edit: Brief explanation of F-expressions (vau expressions in Kernel)

For a function call, the argument expressions are evaluated and the function only receives the values.

For a macro, the argument expressions are accessible to the macro, but the macro cant access the environment, so it cant evaluate these expression, but rewrites code into some other code.

For a vau expression as in Kernel(analog of lambda), the expression receives not just the argument expressions but also the lexical environment. This means it can genuinely return a result and not just code. Unlike macros, they can be evaluated even at runtime. Lambda and classical macros can be easily built on top of vau expressions.

1 comments

One evolution of (You're probably aware of re:axisofeval) Kernel is Wat (https://github.com/manuel/wat-js), which implements the Vau operator (hygenic F-exprs), full delimited continuations (as opposed to the usual Shift/reset functionality of most lisp-based langs) and dynamic variables (variables which can break out of the usual lexical ie. compile-time scope and take environmental ie. runtime values).

It's quite fast with all of that. The continuations allow you to define promises, threads, channels, exceptions, branching and so on. Thing is, syntatically the continuations are required to carry quite a lot. Algebraic effects layered on top would have a nicer syntax.

Similarly, I would suggest that dynamic variables and continuations are more understandable in a forth-like language where the return and data stacks are first class. What's more, forth-like languages use a concatenative (streaming) syntax which allows streams to be more first class. Forsp (https://xorvoid.com/forsp.html) is such a language, that supports both lisp-like, and forth-like semantics

Furthermore, forth-like languages give you explicit parsing to be able to handle quasiquote and special chars etc. This parsing can be layered, you can have a low-level parser along the lines of able-forth (https://github.com/ablevm/able-forth), and a higher-level (word/function level rather than char level) parser like rebol (https://en.wikipedia.org/wiki/Rebol) /ometa (https://wiki.squeak.org/squeak/3930).

There's a lot more to say about GC, compilation steps, DSL towers, formal verification, meta-compilation and so on, suffice to recommend checking out the afore mentioned languages!