Difference between revision 34 and current revision
No diff available.want LL(1) at the high-level parsed via recursive descent, plus Pratt parsing (or shunting yard, but i've heard Pratt parsing is supposed to fit together nicer with recursive descent?)
https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html https://matklad.github.io/2020/04/15/from-pratt-to-dijkstra.html https://matklad.github.io/2023/05/21/resilient-ll-parsing-tutorial.html
https://www.reddit.com/r/rust/comments/g0eusf/blog_post_simple_but_powerful_pratt_parsing/ https://www.reddit.com/r/rust/comments/g1p1mn/blog_post_from_pratt_to_dijkstra/ https://lobste.rs/s/o1jwxo/from_pratt_dijkstra https://internals.rust-lang.org/t/proposal-grammar-working-group/8442/46
---
unlike Haskell, we don't want to allow arbitrary operator precedence, because then you have to look up (or have memorized) every function in code that you read just in order to parse it.
like Haskell and Lisp and unlike Python, we separate fn arguments by spaces, not commas, and we don't require them to be surrounded by parens
like Haskell and unlike lisp, we dont require outer fns invocation to be surrounded by parens;
like haskell unlike lisp, we have function composition syntax (e.g. haskell's $)
like python and unlike haskell and lisp, we have syntax for list/array/dict access and mutation
like haskell, we have optional whitespace
like lisp and octave and unlike python, we allow space-separated list literals
like javascript, we have a type of map literal that implicitly quotes the key names
like ruby and perl (supposedly; see http://news.ycombinator.com/item?id=3068819 ), good options for quoting within literals
like octave, we have a way to quickly print out the result of each step (but ours is opt-in, not opt-out; e.g. mb if there IS a semicolon, then print)
like python and unlike haskell and lisp, our fundamental data structure is dict-like, not list-like
pattern matching partial functions? seems messier than a pattern-matching switch statment to me; that way it's all in one place. is there any benefit to doing it the partial way? also, look at simon's advanced guards thingee -- is there some corecursion thing going on there that makes partial functions look more appropriate?
--- i just wrote:
"
That is to say, in Oot you write "x = 1++(f y)", not "3++(y f) = x". "3++(y f) = x" (the nonstandard way that we didn't adopt) would be clearer, because when you read it from left to right, that follows the order that data actually flows thru the expression.
However, programming text is usually left-aligned, which makes it easy to scan down the screen with your eye and look at the leftmost words.. and hard to scan down looking at the rightmost words. A common use of scanning is to look for where some variable is defined. So, the lhs of the assignment operator should indeed be on the left hand side.
todo: mb mix and match? x = 3++(y f) ? "
hmm, mb should do:
anything with a side-effect, including assignment, goes on the leftmost side. So, there can only be one side-effect per line. The side-effectful thing is executed last. Everything else is 'backwards', e.g. x f instead of f x, i.e. the left-er stuff is executed earlier.
hmmm but now where/how do we put parens now that everything is backwards?
instead of:
defun (map f xs if (unit? xs unit cons f car xs,, map f, cdr xs
we have
defun ( unit xs cdr, f map,, xs car ..
no no no, the whole idea of doing it backwards is for the order of evaluation to be followed. so you can't put something after a conditional first. so i guess the order of arguments should not be reversed
defun unit? xs unit cons xs car f ,, xs cdr, f map ) map xs f
no, too irregular. since we want the side-effect to go on the left, and the side-effect is usually the last thing, we either have to put the first stuff on the right, as usual, or we do it backwards but then we have an irregularity because we switch directions between the first thing on the left and the second.
so let's stick with the usual direction.
---
i do like the rule that a side-effectful command/function may only be leftmost on each line (and hence there can be at most one per line). But this means that when you change something from pure to side-effectful, callers all the way up the call chain must rewrite the way they call you.
right associative, but left associative with , (which only changes parsing to the right of the comma), newline with parens open is left associative w/r/t the parens opening through the line boundary. In other words its like http://chrisdone.com/z/ except using opening parens instead of indentation, and with commas to indicate multiple arguments.
If there is a newline without unbalanced opening parens on that line, then the line is implicitly surrounded with parens.
empty lines are sugar for {}s which are like 'big parens' that define 'blocks'. Blocks are like big parens which auto-close parens as needed at the end of the block. They also provide scope for block-scoped macros.
since we are using {} and () now for grouping, and we are using [] for data literals, we need another bracket grouping symbol for annotations and/or type system directives. How about <>. Use 1 for comparison.
---
todo read http://en.wikipedia.org/wiki/Bracket#Uses_of_.22.28.22_and_.22.29.22 and subsequent 'uses of' sections.
---
for punctuation used as operators and also as normal symbols, you want the languagey things for single uses and the normal symbols as repetitions, because the languagey uses are much more common, e.g. - is inverse, -- is subtraction. But for punctuation used as grouping, you want the single uses as symbols and repetitions as grouping, because once you think you see a grouping symbol you dont want to have to lookahead to see if its not really one, and also you want weird grouping stuff to stand out when you are skimming code
--
mb start with right associative, and switch into left association mode when you enter parens, or start with left associative, and switch into right association mode when you enter parens
dont alternate/switch again with nested parens; thats too confusing
--
in the context of wondering if "a , b , c = 1 , 2 , 3" should work, and if it would that would seem to imply that a, b, c == [a b c], what is really gained from Haskell-ish currying, e.g. always having f(x)(y)(z) instead of f([x,y,z]) ?
http://www.haskell.org/haskellwiki/Currying says "The major advantage of considering all functions as curried is theoretical: formal proofs are easier when all functions are treated uniformly (one argument in, one result out). Having said that, there are Haskell idioms and techniques for which you need to understand currying."
http://www.haskell.org/haskellwiki/Composing_functions_with_multiple_values notes the imbalance between curried inputs and tuple outputs
oh i remember one thing it lets you do; it lets you not distinguish between:
can this be easily mimiced with tuples and partial application? partial application can take the second and turn it into the first, but is there a situation where you need to go the other way somehow?
i think that's it. the benifit of currying instead of having tuple arguments is that it lets an arbitrary multiargument function be implemented as a function that takes some of its arguments and returns a function that takes the rest. i guess that's important.
--
remember that big blocks are also scopes for things like macros and transactions (should we allow transactions with 'dynamic boundaries' too? probably)
-- ppl seem to dislike function scope, and prefer block scope but with closures (e.g. something defined in an ancestor block is available in all descendents)
http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
"
Don’t tell me it’s got lexical scope, because JavaScript’s? scoping is an abomination in the face of God. Guy Steele isn’t even dead and JS scope makes him pre-emptively roll in his not-yet-occupied grave.
...
At the same time, we’re ignoring the things about JavaScript? that make it not Scheme. It’s got a much richer syntax including a great notation for data. I’m not a huge fan of prototypes (anymore), but it’s an interesting dispatch model that Scheme doesn’t have. "
-- http://journal.stuffwithstuff.com/2013/07/18/javascript-isnt-scheme/
"JavaScript's C-like syntax, including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens." -- http://www.crockford.com/javascript/javascript.html
"
Avatar danielparks • 4 days ago
Could you expand on your contention that JavaScript?