Show HN: Practical programming language with expressive power, in 10K LOC C++11(github.com)
github.com
Show HN: Practical programming language with expressive power, in 10K LOC C++11
https://github.com/rusini/manool/wiki
9 comments
Well, what about this program?:
-- factorial
{ {extern "manool.org.18/std/0.2/all"} in
: let
{ Fact =
{ proc { N } as
: unless N.IsI48[] & (N >= 1 - 1) signal
{if (~)[N.IsI48[]] then TypeMismatch else InvariantViolation}
else
: var { Res = 1 } in
: do Res after
: while N <> 0 do Res = N * Res; N = N + ~1
}
}
in
Out.WriteLine[/* Out; */ "Factorial of 10 is "; Fact[10]$]
}
It has absolutely all syntactic features and even makes sense!I find the nesting of elements hard to follow and would prefer something like:
-- factorial
(extern "manool.org.18/std/0.2/all") in:
let:
Fact =
proc { N } as:
unless N.IsI48[] & (N >= 1 - 1) signal
(if (~)[N.IsI48[]] then TypeMismatch else InvariantViolation)
else:
var { Res = 1 } in
do Res after
while N <> 0 do Res = N * Res; N = N + ~1
in:
Out.WriteLine[/* Out; */ "Factorial of 10 is "; Fact[10]$]Also, all the Wikipedia links are annoying. Assume we know how to use the internet.
I wanted every link to show me relevant content (e.g. benchmarks[0] :-)
[0] https://en.wikipedia.org/wiki/Benchmark_(computing)
I wanted every link to show me relevant content (e.g. benchmarks[0] :-)
[0] https://en.wikipedia.org/wiki/Benchmark_(computing)
Sorry, I did not had time to add that content (I was in hurry to show my work and at least make an intro, after 4 years of silence and hard work :-) BUT thank you for the suggestion! I will include those benchmarks shortly.
Refs to wikipedia help me to focus on using common terminology as much as possible (and I actually wrote the Intro also for some of my friends that do not understand what "programming" means if I do not speak of "computer programming" and add a link to wikipedia :-). BTW personally, I also find hyperrefs annoying aesthetically...
Refs to wikipedia help me to focus on using common terminology as much as possible (and I actually wrote the Intro also for some of my friends that do not understand what "programming" means if I do not speak of "computer programming" and add a link to wikipedia :-). BTW personally, I also find hyperrefs annoying aesthetically...
It would help a lot if the wikipedia links were visually identified by a little 'definition' graphic or something.
Congrats, it looks very complete and is a great achievement.
Congrats, it looks very complete and is a great achievement.
Thank your for commenting!
> This immediately makes me want to read said postcard. Is there something to this effect? [Couldn't find it.]
I actually did not do such exercise, sorry :-) BUT: 1) almost all syntactic features are demonstrated in the first two examples/lessons in the wiki (and could be compressed further); 2) the formal context-free grammar can be found in the large PDF (caution: crude, work in progress!): https://github.com/rusini/manool/releases/download/v0.2-beta... It has only 25 rules. That's comparable with Smalltalk. Besides, Smalltalk was a source of inspiration for the syntax, since it is culturally a cousin of LISP, does not use S-expressions, but its syntax does allow for a kind of DSLs (think ... ifTrue: ...). MANOOL is similar in that respect, but its syntax is closer to S-expressions (allows you to express name bindings).
>I didn't see the advantage...
S-expressions have syntactic sugar to express lists: (A B C) -> (A . (B . (C . ()))) MANOOL has that and slightly more: infix/postfix operators (and one prefix), etc.: A[B; C] -> {A B C}, A + B -> {(+) A B}, {A: B C} -> {A {B C}}, A.B[C] -> {B A C}, etc... (it does not have dotted pair notation, but I hope the idea is clear).
That syntactic sugar is abstract and independent of what actually A[B; C] and A + B mean. The intention, for example, is that the syntax (at the context-free grammar level - surface syntax) does not need to change no matter what features we need in the future. It is said that context-free grammars are not modular: as the language evolves it is easy to introduce ambiguities (think C++). MANOOL approach does not suffer from that; features (like keywords if, while...) can even be made available selectively in a limited scope, if needed. I call it "universal grammar".
On the other hand, I strongly suspect that the resulting syntax is better than S-expressions "psychologically" (sorry LISP'ers :-). It is not a matter of our familiarity with infix notations (from mid school), but our brain has very limited "stack". Anyway, the point of MANOOL is not its syntax or homoiconicity; it was originally just a nice implementation strategy. The point lies deeper in some semantic features...
BTW that's not the first time that someone comes and suggests something to replace S-expressions and... fails. BUT one successful example is Smalltalk (albeit the result is not quite "homoiconic"), so that inspired me too.
As to why {} instead of ()... the main reason is that () had to be reserved for explicit grouping of subexpressions (just like in mid school or Smalltalk): (1 + 2) * 3. BTW that's why I had to use [] for "applications" and that might look ugly to people (but think about failed M-expressions).
As to optional ";", that was precisely one of those "design compromises" I am talking about. Personally, I am not a fan of "semicolon omissions" :-)
> This immediately makes me want to read said postcard. Is there something to this effect? [Couldn't find it.]
I actually did not do such exercise, sorry :-) BUT: 1) almost all syntactic features are demonstrated in the first two examples/lessons in the wiki (and could be compressed further); 2) the formal context-free grammar can be found in the large PDF (caution: crude, work in progress!): https://github.com/rusini/manool/releases/download/v0.2-beta... It has only 25 rules. That's comparable with Smalltalk. Besides, Smalltalk was a source of inspiration for the syntax, since it is culturally a cousin of LISP, does not use S-expressions, but its syntax does allow for a kind of DSLs (think ... ifTrue: ...). MANOOL is similar in that respect, but its syntax is closer to S-expressions (allows you to express name bindings).
>I didn't see the advantage...
S-expressions have syntactic sugar to express lists: (A B C) -> (A . (B . (C . ()))) MANOOL has that and slightly more: infix/postfix operators (and one prefix), etc.: A[B; C] -> {A B C}, A + B -> {(+) A B}, {A: B C} -> {A {B C}}, A.B[C] -> {B A C}, etc... (it does not have dotted pair notation, but I hope the idea is clear).
That syntactic sugar is abstract and independent of what actually A[B; C] and A + B mean. The intention, for example, is that the syntax (at the context-free grammar level - surface syntax) does not need to change no matter what features we need in the future. It is said that context-free grammars are not modular: as the language evolves it is easy to introduce ambiguities (think C++). MANOOL approach does not suffer from that; features (like keywords if, while...) can even be made available selectively in a limited scope, if needed. I call it "universal grammar".
On the other hand, I strongly suspect that the resulting syntax is better than S-expressions "psychologically" (sorry LISP'ers :-). It is not a matter of our familiarity with infix notations (from mid school), but our brain has very limited "stack". Anyway, the point of MANOOL is not its syntax or homoiconicity; it was originally just a nice implementation strategy. The point lies deeper in some semantic features...
BTW that's not the first time that someone comes and suggests something to replace S-expressions and... fails. BUT one successful example is Smalltalk (albeit the result is not quite "homoiconic"), so that inspired me too.
As to why {} instead of ()... the main reason is that () had to be reserved for explicit grouping of subexpressions (just like in mid school or Smalltalk): (1 + 2) * 3. BTW that's why I had to use [] for "applications" and that might look ugly to people (but think about failed M-expressions).
As to optional ";", that was precisely one of those "design compromises" I am talking about. Personally, I am not a fan of "semicolon omissions" :-)
Great explanation. I do see the advantage of universally supported expression equivalence vs case-by-case macros.
The semicolons are fine as there are few, it's all the brace blocks and following colon-prefixed lines that I would prefer worked like Python. Indenting is human readable vs { : } being more machine readable. There could be a 1:1 rule for converting between formats.
The semicolons are fine as there are few, it's all the brace blocks and following colon-prefixed lines that I would prefer worked like Python. Indenting is human readable vs { : } being more machine readable. There could be a 1:1 rule for converting between formats.
I agree with you in that aesthetically and psychologically, the syntax of MANOOL is not the prettiest thing. But as I already commented, it is a result of trade-offs, and the syntax aesthetics is simply not the main point of the language. Any language whose syntax is more semantic-tailored would almost always look better. However, in turn, we gain homoiconicity and syntactic macros, which is not simply a nice-to-have feature but a huge expressiveness boost, as they are already used to introduce useful constructs without clobbering the core implementation written in C++. Now: whether one can afford the advantage and pay the price on syntactic level is up to once's use case.
Of course, we could still support homoiconicity given almost any grammar (think about Dylan or any language that formally has syntactic macro features... Julia? Rust?), but then there is another trade-off: the mapping "plain text -> AST" and the language itself would be much more complex (and the implementation simplicity is the ultimate goal of the MANOOL project that sometimes even goes in parallel with other appealing goals).
As I have commented, personally, I had to struggle with myself once I devised the context-free grammar for MANOOL after a lot of experiments and realized that actually there were no much room for improvement given the constraints. However, surprisingly, I accustomed myself quite quickly (which I would not say it is always the case for authentic S-expression-based languages as LISP advocates suggest). After all, MANOOL is an intermediate point between S-expression-based languages and "normal" languages. Compare:
Scheme:
But here we are gradually approaching the story of ":". Note that ":" is a punctuation sign that does not has the usual meaning, as e.g., in Python, or even natural languages.
Once upon a time, someone suggested me that if you have an "if" with two branches, one short and another much longer, the shorter branch should appear visually first. In practice, that worked well for me. It apparently has to do with a "stack" in our brain. Another observation I had is that the Ada syntax, however "elegant" as it may seem with short examples, may quickly become ugly as the code complexity raises. And the problem is the excess of indentation (well, to mitigate that, some would suggest creating abstractions and name things, but personally, I would prefer to avoid naming things as long as I can, without going into extremes of combinatory logic-based programming ;-).
So, I though, maybe the authors of Algol-60 (and Pascal) were right, maybe I could write better, say:
Of course, we could still support homoiconicity given almost any grammar (think about Dylan or any language that formally has syntactic macro features... Julia? Rust?), but then there is another trade-off: the mapping "plain text -> AST" and the language itself would be much more complex (and the implementation simplicity is the ultimate goal of the MANOOL project that sometimes even goes in parallel with other appealing goals).
As I have commented, personally, I had to struggle with myself once I devised the context-free grammar for MANOOL after a lot of experiments and realized that actually there were no much room for improvement given the constraints. However, surprisingly, I accustomed myself quite quickly (which I would not say it is always the case for authentic S-expression-based languages as LISP advocates suggest). After all, MANOOL is an intermediate point between S-expression-based languages and "normal" languages. Compare:
Scheme:
(define Fact
(lambda (N)
(if (= N 0) 1
(* N (Fact (- N 1))))) ; a lot of closing parentheses here
; use Fact
Python: def Fact(N):
if N == 0:
return 1
else:
return N * Fact(N - 1)
# use Fact
MANOOL: { let rec
{ Fact =
{ proc { N } as
: if N == 0 then 1 else
N * Fact[N - 1]
}
}
in
-- use Fact
}
Note that in the past, personally, I would prefer rather an "absolutely beautiful" Ada/VHDL/PL-SQL syntax: if ... then
...
else
...
end if; -- "very" explicit terminator
and: while ... loop
...
end loop; -- ditto
Note that also, personally, I do not like the Python/Nim/Occam approach to code indentation, but that's a whole new (orthogonal) story, and if you like, I could expose my rationale separately...But here we are gradually approaching the story of ":". Note that ":" is a punctuation sign that does not has the usual meaning, as e.g., in Python, or even natural languages.
Once upon a time, someone suggested me that if you have an "if" with two branches, one short and another much longer, the shorter branch should appear visually first. In practice, that worked well for me. It apparently has to do with a "stack" in our brain. Another observation I had is that the Ada syntax, however "elegant" as it may seem with short examples, may quickly become ugly as the code complexity raises. And the problem is the excess of indentation (well, to mitigate that, some would suggest creating abstractions and name things, but personally, I would prefer to avoid naming things as long as I can, without going into extremes of combinatory logic-based programming ;-).
So, I though, maybe the authors of Algol-60 (and Pascal) were right, maybe I could write better, say:
for I := 0 to 99 do
if A[I] = Value then {note the lack of indentation}
Found := I;
... and that is the point of those colons in MANOOL: instead of writing: { for ... do
{ if ... then ... else
...
}
}
one can write: { for ... do
: if ... then ... else -- note that ":" is aligned with the braces since their syntactic roles are very similar
... -- but anyway MANOOL is a free-form language
}
Note that those colons are actually a means to get some "right-associative" syntax rules in the language (which are useful in the cases mentioned above).
This immediately makes me want to read said postcard. Is there something to this effect? [Couldn't find it.]
I didn't see the advantage in using braces instead of Lisp-parens or functional languages that use neither. The first thought that came to mind was using the semi-colon insertion parsing like Go, but on source text that uses whitespace indentation like Python and insert all the braces needed by the parser.