4 ms·
Io was one of the inspirations that first got me interested in programming languages. It's a beautiful little language. For me, the syntax is a sweet spot of be
by munificent 4y ago
Io was one of the inspirations that first got me interested in programming languages. It's a beautiful little language. For me, the syntax is a sweet spot of being extremely simple and elegant but no so simple that it gets awkward and verbose like Smalltalk and Lisp can.
The semantics are equally beautiful and elegant.
It's just a cool language.
The main downside is that the semantics are so dynamic that it's virtually impossible to optimize.
- JonChesterfield 4y agoI think the "dynamic so had to be slow" assumption has been quite badly savaged by luajit and the various javascript engines. "Assume stuff doesn't change all that quickly and recover transparently if it did" goes a long way to statically compiling dynamic languages. Worst case the parts that actually do very dynamic things end up interpreted, but that's stuff you otherwise can't do without writing an interpreter.
- munificent 4y agoIo is way more dynamic than almost any other language you're thinking of. Yes, even Lisp and Smalltalk. Arguments are passed to methods as unevaluated syntax trees and a method can decide at runtime whether or not to evaluate the argument expression, or not, or introspect over it, or mutate it. It's like every function is a macro but macros can also choose at runtime to selectively evaluate some of their arguments.
- JonChesterfield 4y agoTcl has that. Early lisps did too, sometimes called fexpr or fsubr. More recently Kernel had the same. There's another esoteric lisp that does too but the name escapes me. That's a pretty compelling answer to why it doesn't need macros though. It's got the upgraded version built in. I believe that is amenable to the same style of speculative compilation found in jit compilers for dynamic languages. The above reference to graalvm does seem a good idea in that context. I can't point to an existence proof though. edit: someone is going to object to "upgraded macro", but nevertheless lisp macros are exactly the subset of fexpr that can be statically resolved at compile time, i.e. a subset of a more powerful facility.
- kazinator 4y agoEverything you type into your text editor is a subset of "random string of UTF-8".
- JonChesterfield 4y agoYes, but what the interpreter does with that string of bytes varies rather widely.
- deleted 4y ago[deleted]
- kazinator 4y agoThat exact way of being dynamic was identified as a poor idea by around the end of just the first decade of Lisp. This is all documented. Early Lisp was able to bind an operator symbol two four kinds of procedures: EXPR SUBR FEXPR FSUBR The left column is the exprs; the right subrs. The top row means "machine coded / intrinsic"; the F prefix on the bottom ones refers to interpreted mode: the F is of unclear origin. It might refer to "form" or "formula", conveying that those procedures are made of symbolic expressions, not machine code. The subrs are just functions: arguments are evaluated and passed to them. The exprs operate on expressions: they receive expressions unevaluated, like in Io. Roughly speaking EXPRs implement special operators that are built into Lisp, written in assembly language. FEXPRS are defined by the program: they add new kinds of special operators, whose actions are interpreted; they decide at run time what to do with the argument expressions. Loosely speaking, today's mainstream Lisp dialects still have the equivalent of EXPRs (special operators) as well as SUBRs (built-in/compiled functions) as well as possibly FSUBRS (uncompiled functions in some Lisp dialects that support interpretation). The FEXPR has disappeared; it is not found in e.g. Scheme or Common Lisp. About macros, macros can evaluate things in their own runtime. In a compiled setting, the run-time of a macro is compile time. Macros don't make decisions in the run-time of the code they expanded; macros are gone at that point. All decisions have to be expressed as generated code which refers to information available at run-time in that environment.
- pwpwp 4y ago> This is all documented. Things have changed. Fexprs are coming back in a big way. You need to check out John Shutt's Kernel language https://web.cs.wpi.edu/~jshutt/kernel.html https://web.cs.wpi.edu/~jshutt/kernel.html Yes, older Lisps messed fexprs up. Kernel fixes this. The vau calculus used by Kernel is simply a lambda calculus that, unlike CBN and CBV, doesn't implicitly evaluate arguments. The rest of the calculus is the same. What this means is you get powerful hygienic metaprogramming (arguably as powerful or even more powerful than Scheme's most advanced macro systems) at a low low price and with very elegant theoretical properties. In Kernel, hygiene is achieved simply with the usual lexical scope that's already in lambda calculus. So vau calculus is simpler than the CBV lambda calculus used by Lisps. Because it doesn't evaluate arguments, so it does less than those calculi. And by doing less it gains the great power of being able to do hygienic metaprogramming in the same calculus, without second-class contraptions like macros.