https://github.com/paulhoule/ferocity
which lets you write extended Java in a lispy syntax. It generates stubs for the standard library and other packages you choose, unerasing types by putting them into method names. It works pretty well with IDEs but there are still problems w/ type erasure such that some kinds of type checking can't be done by the compiler working directly on the lispy Java, probably I wouldn't implement newer features such as pattern matching that are dependent on type inference to work, though lambda definitions are feasible if you give specific types.
The 'extended' bit was almost discovered instead of invented in that it is pretty obvious that you need quote and eval functions such that you can write lispy Java programs that manipulate Java expressions. Said expressions can be evaled at runtime with a primitive interpreter or incorporated into classes that are compiled w/ Javac. The motivation of the thing was to demonstrate Java-embedded-in-Java (an ugly kind of homoiconicity) and implement syntactic macros from Java which I think that prototype proves is possible but there is a lot more to be done on it to be really useful. Enough has been implemented in it right now in that you can use it to write the code generator that builds stubs. It might be good for balls-to-the-walls metaprogramming in Java but I think many will think it combines all the worse features of Java and Lisp.
This may be true in some implementations, but the actual defintion of the `(the)` special operator is that if e is not type τ, the behavior of `(the τ e)` is undefined! Crashing when the type is determined to mismatch is one allowed result, but `the` is also the language's "escape hatch" to permit implementations to improve performance by throwing away runtime type information, at which point abusing types will crash in surprising ways.
Since the article's publication, this is now possible with the industrial-grade Coalton: https://github.com/coalton-lang/coalton/
I'll note that the GitHub README says:
> Coalton has not reached "1.0" yet. This means that, from time to time, you may have a substandard user experience.
For example, you cannot define a type that means "A List of type X" because that requires recursion i.e. this is not allowed:
(deftype typed-list (x) `(cons ,x (or (typed-list ,x) null)))
So one must either declare the type of the loop-local variable(s) (when iterating) or the first N item(s) of a list (when recursing), which is a bit unfortunate. SBCL, in particular, does a great job of inferring types at compile time with just a few annotations, but code that is optimizer-friendly is made significantly more ugly by this. Or, you know, people just end up using arrays for everything.Mind you I feel like over time we are seeing dynamic and static typing converging more and more. Python type annotations are a thing to some degree I know, while c# a while back added the dynamic type.
I have to say I'm glad I started this thread because your reply and others have given me a lot to chew on.
Code as data is, while not simple in a type theoretic context, pretty well researched. I think the most promising method for achieving semantics relatively close to Lisp's `code type` is the modal type theory work from the early 2000's. It starts (according to most accounts) with Pfenning and Davies work from '94-'95 [1], then moves over to Taha,Sheard,et al's work circa 2000 on MetaML[2]. Then I think the work by Kim, et al in 2006[3] which led to Murase's work in 2017[4].
This line of work delves pretty deeply into the proof-theoretic foundations and type-theoretic of macros as a well founded element of programming languages. However, I am a firm believer in the theory of best fit for this sort of problem. A large amount of the work is based on a relatively small amount of primitive concepts, and in a language like Lisp with imperative features and mutable state, a safe implementation that is algorithmically checkable should be possible, without attempting to prove the categorical semantics of the construct.
Long story short, I think that a 'safe' and useable typed syntactic macro construct should not be thought of as intractable, but approached with sensible guide rails to implementation and then used as needed by developers.
[1] - https://dl.acm.org/doi/pdf/10.1145/237721.237788 (A Modal Analysis of Staged Computation [Davies,Pfenning 2001] [2] - https://www.sciencedirect.com/science/article/pii/S030439750... (MetaML and multi-stage programming with explicit annotations [Taha,Sheard 2000] [3] - http://kwangkeunyi.snu.ac.kr/paper/06-popl-kiyicr.pdf (A Polymorphic Modal Type System for Lisp-Like Multi-Staged Languages [Kim,etal 2006]) [4] - https://lfmtp.org/workshops/2017/inc/slides/murase.pdf (slides from a talk)
There should be no holes, but non-determinism.
Typed Lisp, a Primer (2019) - https://news.ycombinator.com/item?id=23878612 - July 2020 (26 comments)
As have excessive apostrophe's.