Beni Cherniavsky-Paskin: > Summary: I only buy the first of the use cases; I think this construct will > be rarely used and want the sematics to be as simple as possible; I propose > some alternative ideas below.
First of all, thanks SO MUCH for posting!! I'm a big believer in feedback, so I really appreciate your time. I agree that the first use case (multi-line libraries) is more important, which is why I put it first. I do think the other use case is relevant, though, especially if we can resolve both at once. I completely agree that the final semantics need to be "as simple as possible". In general, I try to do a lot of experimentation and out-of-the-box thinking before deciding on something specific, so please don't assume that some more complicated draft structure is the "final word". > If we separate the 2 issues, I feel the no-blank-lines is the more > problematic of them. In Python, I'm fine with most of my defs being > indented because they're class methods, but couldn't live without new lines. > Do you agree? I don't *exactly* agree, though you may be missing an element of sweet-expressions that makes end-on-blank-lines work. But first, my priorities. My current view is that the more important requirement is that the REPL and file format need to be exactly the *same* in a Lisp-based system. In Python you often cannot cut-and-paste from files into the command line ("REPL"), because Python files and the REPL have different blank-line semantics. (Technically, the Python spec only covers files, but that's a useless nuance.) That's actually a problem in Python today, and annoys me sometimes. In a Lisp such a difference would be crazy, because Lisps are programmable programming languages where experimentation is common. Now for blank lines. Blank lines ending an expression actually isn't bad, even in a larger program, because of the rule that comment-only lines (possibly indented) are completely ignored, and do NOT end an expression. I agree that without that rule it'd be hideous to use, but using comment-only lines to vertically separate material actually works very cleanly. It's not insane to use some marker to mean "end of expression", several languages do that. Indeed, sweet-expressions could be modified to that easily enough. But then users have to remember to do that after every expression. If REPL use is rare, that'd be fine. But I expect lots of people to use the REPL, often, and I want the REPL to be very pleasant to use. It's hard to beat "enter a blank line to evaluate". But this approach does have a downside with long library declarations (and similar structures). In these cases, the endless indentation *and* the blank lines ending expressions both start to get annoying. Thus, the <* ... *> proposal. > > Now let's look at the second use case. > > The sweet-expression notation cleanly handles cases where let-expression > > variables have complex values (e.g., using \\), but for simple cases > > (1-2 variables having short initial values) ... > I completely don't get it. > What's wrong about ((x 5) (y 7)) or (x{5} y{7}), > and why is <* x 5 *> or <* (x 5) *)> any better? > When compressing nested lists on one line, parens are the - clearest way to > represent structure. > Specifically, I dislike the usage where <* x y *> implies a double list by > restarting the multiple-items-on-a-"line" rule. While I see the consistent > logic of this semantics, it's IMHO way too hard to scan this visually as a > double list - a problem ((...)) doesn't have. Well, the current notation is obviously not a disaster, since we've written programs without it. But when the variables involve modest amounts of calculation, it gets harder to see what you're doing than I'd prefer, because it's easy to suddenly require more paren-nesting than is typical in other languages. Contrast: let ((x cos(f(c)))) ! dostuff x with: let <* x cos(f(c)) *> ! dostuff x or: let <* x $ cos $ f c *> ! dostuff x In one-variable lets, a common mistake is to forget to embed the variable in double-parens. Since the parens are also usually used for the expression calculation, it can be easy to miss. Making it possible to visually distinguish the outer "parens" that create the variable list, from the internal parens used for the expression, makes it clearer which parens are more structural vs. the ones involved in the variable calculation. That, in turn, makes it easier to notice the omission of doubled parens for one variable. > As I see it, we need some solution for the very-long-form problem, while > one-liner-let is a solved problem. > If restricting <* .. *> to EOL - or even requiring them to stand alone on a > line - makes for a simpler spec, I'd much rather see that rather than fine > tuning the inline semantics. An excellent point. Yes, I agree that simplicity (of spec and implementation) is really important. The older experimental rulesets for <* ... *> were probably a good case-in-point of complications that, if we *had* to do them, were a good argument against them. As it turns out, the new ruleset for <*...*> that I just posted is quite simple, and it basically only requires one extra line in the spec to handle the on-the-same-line case. > I agree that "two-liner-let" is not a solved problem. We can either cram > it on 1 line, or nicely spread on 1+N lines using \\, but not on N lines. It turns out the new ruleset handles this case as a byproduct, and doesn't require any new code or productions to make it work. Which in my mind is evidence that it's the right direction... ideally a grammar should have a few powerful productions that keep getting reused. > IMO this goes deeper than just let but I don't think abusing <*..*> is an > improvement. Fair enough. > I'll try to post thoughts on this in the z language thread. Okay! > IMHO, it's very ugly that "example grid ..." are indented when the body of > the library isn't. Indentation should be (at least) non-decreasing! Hmm, I view this as a *solution*. There's only so much horizontal and vertical space. If nearly the entire file is indented to several levels, that means there's less (horizontal) room to express actual content. I completely agree that indentation should *NORMALLY* be non-decreasing, but the point of this structure is to "restart" indentation so you're not stuck writing all content on the right edge. > If I were to use a construct like this, I'd either have "define ..." > indented deeper (only using <*..*> for blank line freedom), or flatten the > containing lists at indent zero (on the theory it should actually be > negative): > > <* > define-library > example grid > export make rows cols ref each rename(put! set!) > import scheme(base) > <* > begin > > define make(n m) > let (grid(make-vector(n))) > ... > *> > *> I wouldn't format the first define-library...import that way, but that's certainly consistent with the current draft semantics. Perhaps more importantly, the second "<*" is definitely the way I'd expect to see it used. > I'm deliberately restricting <* to the head of the list. I see it as an > esoteric construct, and this is the simplest least-surprise version. Okay. I actually agree with you that multi-line "<*" should be used relatively sparingly, as it's a powerful tool that can confuse if misused. But we're noticing its LACK as we write bigger programs, so that's why we're addressing it. > Which is also a weakness IMHO. Visually, < and > don't feel like a list > start/end, at least not to lisp eyes. ([{ / }]) have a history as list > delimiters, < / > not so much. Fair enough. But no other character pairs, other than <..>, are available in least-common-denominator ASCII. Also, while I think <*...*> is important, I do not think many lines of code will directly *use* these symbols (especially in the multi-line case). So even if I COULD find another character pair (and ), I don't think I would want to use up valuable single-character pairs on this functionality; it's perfectly fine to use multi-character markers. That said, if there are multi-character symbols that you think would better "feel" like list start/end, let us know! I thought about using "<<" and ">>", which look like guillemets and probably "feel" more like list start/end. But Scheme systems like scsh already use these symbols (e.g., use >> for append-to-file). Suggestions? The actual marker sequence would be trivial to change now... and impractical to change later. The rest of your post has interesting ideas I need to think about, but I have to run right now. --- David A. Wheeler ------------------------------------------------------------------------------ Master Java SE, Java EE, Eclipse, Spring, Hibernate, JavaScript, jQuery and much more. Keep your Java skills current with LearnJavaNow - 200+ hours of step-by-step video tutorials by Java experts. SALE $49.99 this month only -- learn more at: http://p.sf.net/sfu/learnmore_122612 _______________________________________________ Readable-discuss mailing list Readable-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/readable-discuss