6 ms·
Why the superfluous syntax? I think remembering syntax like this is orthogonal to the goal of being easy to learn. The syntax is basically Ruby + Python + Hask
by tinco 13y ago
Why the superfluous syntax? I think remembering syntax like this is orthogonal to the goal of being easy to learn.
The syntax is basically Ruby + Python + Haskell. Each of those languages has a lighter, more intuitive and memorable syntax.
Why would the syntax be:
data BinTree:
| leaf
| node(value, left, right)
end
Instead of just
data BinTree = leaf | node(value, left, right)
The whole colon thing in Python is a mistake, it should have never been in Python, and it definitely not be repeated in other languages..
- clarkevans 13y agoI think the colon isn't a mistake, it clearly delineates an indented block; I think it's a great marker that indented languages might want to standardize on. Perhaps syntax issue is that it has both a colon and an "end" marker? The former indicates indentation-based syntax, the latter is often used in white-space agnostic contexts. The result of using both is confusion.
- sirclueless 13y agoPyret doesn't actually have an indentation-based format (so far as I know) it just happens to look like python.
- dbpatterson 13y agoThat's correct. There is a preferred indentation (enforced by the emacs mode and our online editor built on CodeMirror), but whitespace is only needed to separate things - the actual amount of whitespace never matters. So, for example, you can move chunks of code from one place to another and select it all and re-indent - something that you can't do (in general) in Python. It also makes it easier to programatically generate code.
- ptx 13y agoWhen you have both braces/keywords and whitespace, it seems to me that you're essentially storing the same information about the program structure in two places, of which one is read by the machine and the other is read by humans. The "re-indent" operation reads the master copy and updates the other one. (And if you forget to re-indent, your human readers will be interpreting an outdated copy and be very confused.) In Python, on the other hand, the information only exists in one place: the indentation. This is read both my machines and humans. There is no "re-indent" operation as the indentation is the only place the information exists, so there is nothing to sync. I have heard people bring up programatically generated code before, but as another commenter put it "where Ruby usually denotes code blocks with a `do` and an `end`, Python denotes code blocks with a `:` and an outdent" – so is that really a problem? Isn't it just a slightly different way of encoding the same information? (As to moving chunks of code in the editor: If the editor has a command to re-indent a selected block, it probably also has a command to shift it left or right.)
- acjohnson55 13y agoBut if indentation matters, and it's pressent, then why do you need the colon?
- ptx 13y agoWell, the colon can be used without indentation if the block that follows is just a single line: def embiggen(x): return x * 2 for i in range(10): print(embiggen(x)) Also, it just makes things read more naturally to us humans, I think.
- ek 13y agoI would encourage you to view the syntax as "Python, but repaired", for the following reasons: 1. Pyret comes out of Shriram's group's expertise with pinning down exactly what Python and other dynamic scripting languages do right, and (mostly) do wrong. Check out their recent paper Python: The Full Monty: A Tested Semantics for the Python Programming Language http://cs.brown.edu/~sk/Publications/Papers/Published/pmmwplck-python-full-monty/ http://cs.brown.edu/~sk/Publications/Papers/Published/pmmwpl... for more context. 2. Ruby is far and away not the originator of 'end' to end blocks -- this comes from Pascal and is in other languages that have nothing to do with Ruby, like Lua. 3. Languages that aren't Haskell have ADTs too; it happens that they've lifted an ML-style syntax for defining them. 4. Python is widely used pedagogically, so for better or for worse, students are already being familiarized with the colon, which I agree is a bit anomalous.
- cwzwarich 13y ago> Ruby is far and away not the originator of 'end' to end blocks -- this comes from Pascal and is in other languages that have nothing to do with Ruby, like Lua. The use of 'end' comes from Algol, not Pascal.
- timtadh 13y agoThanks for the link to that paper. Super interesting to see actual semantics for python come out. It would be nice if this leads to better tooling for analysis of the language. Currently, it is pretty hard to bootstrap anything for the language in comparison with what you can do for the JVM.
- skrishnamurthi 13y agoYou'd first have to fix Python's broken notion of scope. If you want to read only one, simple, page, read the last page (appendix 2 on variable renaming). Pyret was created to not have such problems by design.
- clhodapp 13y agoI think you mean that it's in opposition to their goal of being easy to learn, not that it's orthogonal, as that would mean "it doesn't interfere". Anyway, it seems to me that the only real difference between your code examples is that the second one lacks an ending designator and uses an equals-sign instead of a colon. However, in order to make the lack of an ending designator work, you need a more complex parser (it needs to infer block-ends from indention or some other context). Leaving off ending designators also increases mental overhead for the user, as they must keep block-end inference rules in mind in writing code. Using colons versus using equals-signs is simply a matter of taste (not weight, as you seem to claim). That said, I do see some waste in their datatype definition syntax. First, I'd prefer curly braces over the colon/end pairs that they went with, as that saves a few characters. Second, newlines are a fine separator, so why also require pipes? This requires the user to type three characters (newline, pipe, space after pipe) when just one would have done fine.
- ek 13y agoNewlines are not a fine separator; what if you have a definition that you intend to span multiple lines? In any case, the pipes go all the way back to EBNF, since what you are really doing when you specify an ADT is specifying a grammar of types. I admit to also being a brace weenie; I would very much prefer if all the languages I had to use had them. However, Pyret exists in a tradition of many successful, braceless languages like Python, ML, and Lua.
- clhodapp 13y agoI feel that the argument for the need for multiline definitions here is a bit weak. You are already putting each definition on its own line, so the definitions are actually fairly close to how their actual usage will look. I feel that if you really need them to be all that long, you are already in weird-style territory, so it isn't such a bad idea to just say "deal with wide files". Overall, it improves ergonomics for the vast majority of use cases, with the only cost being a possible aesthetic annoyance for users who are already writing aesthetically-annoying code.
- 13y ago
- jpolitz 13y agoYou can actually use ";" as an alias for "end" in Pyret, so you could write: data BinTree: | leaf | node(value, left, right); We use "end" or ";" in order to have unambiguous delimiters for the ends of syntactic forms and avoid needing to depend on whitespace (we added some discussion on pyret.org about our philosophy on indentation and why we don't want to depend on whitespace). Making that leading pipe optional is a good idea. I made an issue for it, we'll think about if it'll break or confuse anything and add it if it doesn't: https://github.com/brownplt/pyret-lang/issues/106
- e12e 13y agoI realize it's a trade-off -- but I think having ";" as an alias for "end" (or vice-versa) is a pretty bad idea. I personally prefers python's indentation-for-blocks syntax, but I understand why you want semantics to be decoupled from indentation. But when using explicit end-markers, I'd prefer to match them to the start, maybe even introducing some verboseness, like: end-case, end-if etc -- maybe taking it further and allow/demand naming of blocks: check: 4 + 5 is 9 1 / 3 is 2 / 6 9 - 3 is 6 5 > 4 is true end Then becomes, not wrapped in end-check, but: check(arithmethic-test): 4 + 5 is 9 1 / 3 is 2 / 6 9 - 3 is 6 5 > 4 is true end(arithmethic-test) Or something similiar. This makes mis-matching "end"s (either typos or artifacts from cut'n'paste coding) explicit errors that are easy to spot, and identify. It would add a lot of verbosity, of course. As for ";"/"end", consider (the presumably valid): check: 4 + 5 is 9 1 / 3 is 2 / 6 9 - 3 is 6 5 > 4 is true ; That trailing ";" is going to trip someone up. Also consider (cut'n'paste-with-quick-edit): check: 4 + 5 is 9 1 / 3 is 2 / 6; 9 - 3 is 6 5 > 4 is true; end Is this valid?
- fgoodman 13y agoHaving ; on a new line is valid, but having both ; and end on a block is invalid.
- skrishnamurthi 13y agoI have wrestled with "uniform closing" vs "non-uniform closing" designs for ages. For those not clear on what I mean here's an example: Lispy syntaxes have a uniform close (it's always ")"), whereas XML syntaxes don't (you have to put the name of the opening tag in the closing token). So e12e is making an argument for XML-y over Lispy. However, choosing good words is really, really hard. If you pick a different word for each construct, there's a needless mental burden; if you pick a uniform strategy ("end-<kwd>") you potentially get less readable code. And either way it's far more verbose, as you point out. Some of our target audiences are middle- and high-school students, some of whom have weak typing skills (we know from numerous workshops we run). Increasing even the raw number of characters is a real problem for them. My preference is to use ; for one-liners, but end where you have a multi-clause entity and you want to be able to clearly tell where it ends. If we find that there is general agreement on this, we can make it a context-sensitive check, à la indentation. Then, a program generated by a tool can do something consistent and ignore all these checks, whereas human-facing environments would enforce them (by checking or correcting). As for your examples, to my Pyretical eye, the third of your examples (with the dangling ";") looks just wrong. However, your fourth example is syntactically incorrect.