Comments (10)
What if you switched the roles of ()
and []
, so that parentheses are used in most places and []
is for grouping? Or what if {}
was used for grouping and ()
and []
left more like shrubbery notation?
FYI, I changed the parser in the package implementing #163, because I think the pop quiz here pointed to a mismatch between the prose spec and the implementation. The point stands that the result is not obvious.
from rhombus-prototype.
What if you switched the roles of () and [], so that parentheses are used in most places and [] is for grouping? Or what if {} was used for grouping and () and [] left more like shrubbery notation?
Assuming a parsed representation that uses tags, neither of these deeply bothers me but I think they run counter to the most common associations of each delimiter.
from rhombus-prototype.
I think that Mathematica use a similar system, where scare brackets are used for function definition and application, and parenthesis are used only in math expressions.
from rhombus-prototype.
I'm trying to figure out how essential it is to equate a group with one item and that item. It seems like the sort of representation choice that usually goes wrong in subtle ways. For example, suppose a macro f
rewrites f [X, Y]
to X + Y
. If X
in a us turns out to be an identifier that is implemented by a macro, then X + Y
ends up meaning that X
receives +
and Y
. Writing the result template as (X) + (Y)
doesn't do anything if (X)
is the same as X
at the reader level. Something like values [X] + values [Y]
would mean the right thing, but you wouldn't want values [X]
as macro boilterplate. Those problems are resolved if grouping is always reflected in the representation, even for single-item groups, but I'm not sure whether that creates other problems. Is representing a single-item group with a basic goal here, so that extra parentheses can be wrapped around any group whether or not its in an expression position, or is it less important than that overall?
It looks like the area several bugs in the parsing of fib
. Here's an attempt to repair:
(define fib [n]
{(cond
{{(n == 0 {0})}
{(n == 1 {1})}
{(else {(fib [(n - 1)] + fib [(n - 2)])})}})})
from rhombus-prototype.
Thanks for the repair to fib
; I've updated the text.
The problem with dropping parens is interesting. The goal of normalizing parens was to avoid situations where macros break due to extra parens that are used to disambiguate. For example, writing cond
on one line requires parens, and I'd like to make sure all these parse the same:
cond | (x < 5: #t) | (else: #f)
cond
| (x < 5: #t)
| (else: #f)
cond
| x < 5: #t
| else: #f
That way the cond
macro doesn't have to have additional cases for an explicitly-parenthesized alternative body.
The idea of x + y
and (x) + y
both successfully parsing but with different answers bothers me. This gets back to my other comment on enforestation. I would prefer a more structured system in which a macro never consumes a variable amount of syntax, and where parsing an undelimited region can be accomplished using information about operator arities and argument contexts before macros expand. But I'd need to read your enforestation and Rhombus syntax proposals more deeply to understand how compatible that goal is with the rest of the design.
from rhombus-prototype.
Thanks for the clarification.
I can appreciate the goal of allowing parentheses to group without interfering with matching. I expected that kind of interference with shrubbery parentheses, but for what it's worth, it hasn't turned out to be a problem. Implementing parentheses as a specific expression, binding, etc., form has worked well. I also consider it a feature that (fun) (x): x
and fun ((x)): x
are not equivalent to fun (x): x
. The only place where I remember extra parentheses as a problem was in an intermediate ad hoc attempt at propagating static information; the problem was resolved there by an approach that's less ad hoc.
A similar grouping idea might be applied to shrubbery notation by removing the ability of{}
to create blocks, but still allow them as extra wrappers to delimit blocks. The old rules about removing redundant blocks had the same goal, but I can see how splitting the role of {}
from :
and |
might make things simpler and better.
from rhombus-prototype.
for what it's worth, it hasn't turned out to be a problem
In that case, the parenthesis-dropping idea isn't essential. I'm not really sure I like
lambda ([x]): 1 + 2
parsing the same as
lambda [x]: 1 + 2
anyway.
So if we set that aside, as well as the goal of having orthogonal grouping and sequencing forms and its big tradeoffs, I think there are still two ideas in here I'd like to make sure come across:
- There is only one major lexical syntax for a given parsed syntax. I like the idea of removing
{}
as a way to create blocks in Shrubberies. I could see them functioning either in the way you describe as an optional delimiter for the extent of blocks:
cond | x > 5: { #t } | x < 5: { #f }
or as another grouping / sequencing form like ()
and []
, which could be useful for things like dictionary and set literals.
- The notation is described not in terms of individual punctuation syntaxes, but in terms of bigger concepts. I think the Shrubbery proposal could adopt this idea. Right now the headings of the Shrubberies proposal are:
- Grouping by lines
- Grouping by opener-closer, including blocks
- Group separators
;
and,
- Grouping by indentation
- Grouping by
:
- Grouping by
|
- Continuing a line with
\
I think a syntax very similar to Shrubberies (especially if you drop {}
blocks) could be described with this outline:
- Groups
- Whitespace-separated elements.
- Nested groups
- Opener-closer pairs can bracket nested groups.
- Sequences
- Commas within brackets form a sequence of groups contained by the bracketing form.
- Blocks
:
introduces a block.;
or newlines separate groups in blocks\
continues a group across newlines
- Alternatives
|
introduces alternatives.
If you keep {}
blocks, they would be described as a second syntax in the blocks section rather than the sequences section.
I would find that description much easier to follow.
from rhombus-prototype.
I like the idea of completely separating {}
from block notation. The connection between :
and {}
was the main idea in tonyg's racket-something, which was a starting point of shrubbery notation. But maybe because of other parts of shrubbery notation, {}
hasn't been especially useful for blocks in the Rhombus experiment prototype.
The main use of {}
has been for macros that consume or return definition sequences, such as implementations of binding forms. Patterns and templates for those macros used to be written as ?{ .... }
, sometimes in the middle of a group. It works to change each macro protocol to use a layer of parentheses, so block patterns and templates are written as ?(: .... )
. That's not as nice as ?{ .... }
, but it's close, and since contexts that manipulate blocks are relatively rare, it seems like a fine tradeoff. My experiment so far haven't imposed the rule that a block must have something before it, otherwise more would be needed between (
and :
.
I tried going entirely without a delimiting form for shrubbery blocks, but then there's no way to render some shrubberies that are naturally constructed through templates. For example, if t | x | y
might be spliced in place of EXPR
in if a | EXPR | b
. (A template splice would produce the correct shrubbery structure; it's just a question of representing that structure as text.) Delimiting is rarely needed, though, so my current experiment uses « ... »
for delimiting blocks, leaving {}
potentially for sets and maps. A delimiting « ... »
pair is allowed for the three block-creating positions: just after :
, just after |
, and around a sequence of |
s:
x: y:« a; b »; c
if t | «if f | a | b» | y
x: if t «| a | b»; y
from rhombus-prototype.
Hmm. Now that I better understand the situations where {}
is useful I feel more ambivalent. Thanks for the explanation, in any case!
from rhombus-prototype.
These do seem like situations where Square's idea of having extra parentheses be insignificant works well, however. In Square I think the first two examples would be:
x: (y: a; b); c
if t | (if f | a | b) | y
I can see how in expansion it would be useful to manipulate blocks and alts separately from their surrounding group. Perhaps Square should make (: a; b)
parse as {a b}
and (| a | b)
parse as {{a} {b}}
. Then a ?(: ... )
pattern would make sense without needing extra parens in the protocol.
from rhombus-prototype.
Related Issues (20)
- Should multiple-value static infos live under a key? HOT 2
- Is `export` in `meta` supposed to work?
- `super` outside of a class uses wrong syntax object for error
- identifiers with dots in them HOT 4
- Module-path operators confuse Check Syntax
- `values` reducer incorerctly propagates initial-value static info HOT 3
- Improve static error for incorrect arities of subclass constructors HOT 1
- Some use of `Group` leads to “syntax class incompatible with this context”
- Alts after extra-indented blocks
- Not all macro options are allowed in pre-alts block position HOT 1
- Scope pruning in Rhombus blocks
- arity error in annot.macro implementation HOT 2
- Eager expansion of definitions’ right-hand sides can be detected HOT 1
- Unquoted matches are not available in the same pattern
- Use-site binder hygiene bug for `let` HOT 7
- A `let` before another `def` in the same block HOT 2
- Giant green blobs in DrRacket HOT 6
- punning doesn't work in presence of :~ or :: HOT 1
- Fallback option in veneers
- ad used, when "as" was probably better HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rhombus-prototype.