Thoughts
Ooooohhhh cursed language idea. Okay so you know how JS has Instantaneously Evaluated Function Expressions? I like them because they offer a
nice mix of encapsulation without having to create a dedicated value. What if you had "blocks" as one of the only first-class language constructs.
Okay I'm thinking about it more and I think what I'm describing is just a function with scope. But let's re-invent it anyways.
So a block defines any variables it needs at the top, and then runs a bunch of code after that. Like counting to 5 would look like
```
{int i; //other variable declarations up here somewhere
while (i < 5) {
i ++;
}
}
```
No C-style for loops. Obviously this is weird because what is the {} brackets after the while if not a block? Maybe that is a block with scope?
I think we need to be weirder, more fundamental, I don't think the while loop works as-is. But we need some fundamental constructs. How do we call a function? There are no functions, only blocks. Blocks can be nested. Blocks can be nested by name. Oh this gets good. Blocks have a return value. The only 2 types of expressions in the language. Creating blocks and inserting blocks. Blocks can be inserted literally (ie nested) or by name (think, calling a function, but merely referencing a block's name executes its code and returns its value). Blocks have a return value. Variables are nothing but blocks that only return their value.
Wait a minute, all variables are functions? Functions are called without parentheses? This is just Haskell.
Wait! Ok so the question at this point is just, are blocks values? That is, can I pass a block by value to be executed later in time? Well, that's assuming that blocks are actually functions and that they can take values. Uh. The alternative is saying that there are special `macro` blocks. And what this would do, is that, for example,
```
//option 1, blocks are a 1st-class type:
while {x < 5} {
console.log x;
x = (x + 1);
}
```
```
//option 2, there are special macro blocks
while {x < 5} {
console.log {x}
x = {x + 1};
}
```
So to clarify, in option 2, `{}` are used just like grouping. You can nest them without any consequences. `x = x + {1}` creates a block that returns 1, executes it, takes the value, and adds it to x. For something `while {x < 5}`, `while` is defined as a macro, so the language knows not to execute `x < 5`.
In option 1, `{x + 1}` creates a block, always, and only executes it if it is the first thing on the line. So for example `x = {x + 1}` would break, since it would create a block, and then assign x to the block. That is to say, it would be equivalent to the JS `x = (_ => x + 1);`
This sounds like LISP. Hm. Hmmmmmm.
So the question, really, is when are blocks evaluated. Because in normal languages (JS), functions are values, and they're evaluated when you parens after them. And what I'm trying to do here is hand-wave something, to make these blocks sound like they're not functions, and a lot of that is that you don't put parens after them. So we have to decide when to evaluate a function based on other things. I think option 1 is the way to go. So that a given snippet is unambiguous. Because in option 2, you have to know whether `while` is defined as a macro or not to know how it will evaluate.
So to "implement" an example, let's write a Fibonacci generator.
(Oh yeah, this should go without saying. If not mentioned (e.g. no functions), assume JS. So we have native lists, objects, strings, booleans, etc.)
```
while = block (conditionBlock, execBlock) {…native code...}
if = block (conditionBlock, execBlock) {…native code...}
console.log = block (value) {…native code...}
etc.
values = [0, 1];
while {true} {
// Could values.push (values[-1] + values[-2]) in a single line
{ //Define variables as the first thing in the block
lastValue = values[values.length-1];
secondLastValue = values[values.length-2];
values.push lastValue + secondLastValue
}
console.log values[values.length-1]
}
```
This is kind of a boring example because everything just works.
The key thing to recognize, that makes this radically different from JS, is that the first block on each line in implicitly executed. And that's the only way to execute blocks. Which makes this language literally unusable because there's no way to get the return value of a block. (e.g. `.push {add a b}` would push an unevaluated block on to the end of the list.). So I'll need to go back to the drawing board, but not tonight.