Would you like to take a look at my opinion on parentheses?
Thanks for sharing that – an interesting approach. It seems as if Rich Hickey was suggesting that Lisp’s syntax didn’t need fixing; that it becomes a benefit after time. But I certainly see the appeal of a DOM-based editor for complex nested data structures, and I like your implementation of it.
I really like parinfer and think it’s amazing
Writing clojure with parinfer feels nicer than writing python. Think that’s a big win.
My editor does not render macros. So I still write some of my code in plain text, which suggested Lisp-syntax is powerful too. I think my editor makes a small set of Lisp syntax really shiny.
My first experience with lisp pre paredit was a nightmare. It was at least partially why I was against the nested parenthesis at the start.
I was in the audience when Rich said that, and I admittedly jolted into a nervous laughter because I was just about to go after him to give a talk about Parinfer. Chris and I caught him in the hall the following day and asked him if he could clarify what he meant—he did not mean paredit/parinfer.
It was just a confusing choice of the “par-” prefix to describe paren-less syntax. Understandable though—Parinfer’s indentation rules are very similar to what the traditional alt-syntaxes for lisps do. The slight difference being that they use the same rules to remove parens rather than infer them in-place as Parinfer does.
But what was most interesting about our conversation is that Rich then excitedly asked us if we were familiar with “Frame-based editing”. Having studied the shit out of paren stuff this summer, I was like yeah, Greenfoot!
He then proceeds to describe how something like Greenfoot could work with Clojure. It would need to have an extensible way to define UI elements for different types of forms—say
for, and other user-defined macros/functions. His idea was that Spec could be used for describing the properties necessary for something like Greenfoot to create a UI element for a form, and clojure core and third party libraries alike could publish these Specs alongside their source if developers wanted to edit their code using this kind of UI.
What a fun idea! Even Rich is thinking about the possibilities in this space, to empower us to edit and display these parens through augmentation rather than occlusion.
(Rich is not currently working on this idea, and wants someone to do it. )
I am also excited about @jiyinyiyong’s editor research. He started with an alternative syntax, and later decided that we just need better editors to manipulate the structure outside normal text-editing behavior. I think this will eventually be something we want if the UX can be good enough. I particularly like Cirru’s horizontal and vertical bars as structural cues.
I think it’s also telling that Rich was thinking about Greenfoot, but I also vaguely remember hearing that he was working on a way to store code in non-textual format (rdfm?), which might’ve been related to building better UIs for code-editing? I’m not sure, but he alluded to ideas that this would enable.
A big part of the problem in representing code in a piece of data is how to handle macros,
syntax-quote is not represented in pure Clojure data. Not possible for me to generate Macro from a tree editor.
Block editors are a fun idea to help with reading, writing, and teaching, and Greenfoot’s approach seems more practical and accessible than Scratch’s.
Eve has some interesting research ideas in this area too, with a block-based editor and live visual feedback. Although it abstracts away the code more than Greenfoot and @jiyinyiyong’s approach, the tabular layout, model of interaction, and hot updating are all interesting:
An environment that combined block-based editing with live feedback in a package like Zach Oakes’ Lightmod could go a long way to making Clojure(Script) more accessible to beginners.
Demos of Eve are interesting. But I think Eve is different since it’s not general-purpose language. We need more flexibilities for more general problems, which make it harder for the environment to provide more features. I’m still amazed that Eve could achieve so much with such tables.
Wow, that’s a great idea… in fact, I thought it was such a good idea when I saw it yesterday that I spent a couple hours and coded up a prototype: [WIP] A visual blocks engine for Clojure -- need your input!
I think Clojure’s the perfect language for this kind of thing too! Minimal syntax makes it easy, although the extensibility may be a big challenge.
I embrace parinfer, even if that’s what Rich meant he can pry it from my cold dead fingers.
I use parinfer and rainbow parens in Cursive/IntelliJ. For me, the great part about this combination, is that with very few concepts in mind, I can move quickly and fluidly enough and the results are easy for me to predict.
I’ve embraced the indention-means-sub-expression constraint and I’ve simply stopped fussing about any other indentation or horizontal alignment. If an s-expression gets too wide, I vertically stack the top-level forms.
I use tab/shift-tab to move line(s) into/out-of the s-expression directly above it. Sometimes I use opt-up-arrow/opt-down-arrow to widen/narrow a selection a level at a time s-expression. Often though, I can just cut whole lines and paste-and-tab them into place because parinfer is taking care of trailing parens transparently.
Thanks for this, Bill – I just discovered the rainbow parens support in Cursive and it’s made a big difference to checking alignment.
I also like how IntelliJ/Cursive maintains indention level when duplicating a line. Good tips about shift-tab and stacking the top-level forms – that’s not something I’d considered before. (I have a follow-up question about this but will start a new thread!)
On that point, here’s a cool trick to comment-out stuff using the
comment fn (if you don’t want to just hit ⌘-/
(comment)above the form you want to comment out.
- select the form you want to comment out
- tab to move it into the comment form
reversing it entails:
- select the lines after the
- shift-tab to move them outside the comment form
- delete the
Oh, that’s really neat! Thanks for the tip. This is starting to feel fun.
I made a quick screencast in case others want to see:
(Follow-up about wrapping top-level forms: Idiomatic Clojure indentation – wide or deep? )
In general with Parinfer I think you only need put the cursor at the start of the next form and press space and it will auto-indent the whole form into the
(comment). Same with reversing it: cursor on the first form inside the
(comment ...) and just press backspace. At least, that’s how it behaves for me in Atom/ProtoREPL.
@seancorfield Ah, good to know, thanks. That seems to work great for lists, but it splits vectors (tried Atom and IntelliJ). For example:
FWIW I’m on the “avoid” side of this, for myself (a long-time lisper) and for my students (who are often new programmers).
While I think it’s swell for others to use paredit or parinfer if they like them, some of the reasons that I don’t want them in my teaching or development editing environments are:
I often cut/paste and/or edit code in non-linear ways as I’m thinking through a problem, with my code being in syntactically invalid states at many points along the way. Paredit/parinfer makes this frustrating or impossible.
My students already know how to type and manipulate text, and requiring that they learn new ways to do this on top of everything else (basic programming concepts, functional programming, Clojure, AI, etc.) seems cruel and counterproductive. I’ve witnessed considerable exasperation stemming even from some of the less invasive “helpful” interventions in some editors, e.g. auto-typing of closing brackets, or wrapping rather than replacement of a selection when typing an open bracket. Having paredit prevent character insertions in some situations, or having parinfer add/delete brackets that may be distant from the insertion point, are much worse.
Clojure cares about brackets, not about whitespace. So it seems to me that programmers should also care primarily about brackets, not whitespace, or at least have brackets, not whitespace, foremost in their minds. Whitespace is a terrific visual guide to structure, and IMNSHO every Lisp editor must have an auto-reindentation feature that can be manually triggered by the programmer to make the whitespace conform to the programmer-typed brackets. And programmers should routinely invoke this feature on everything they write. But my preference is for the programmer to specify the brackets, and use auto-reindentation to clean up indentation and spot problems.
Again, I can see why people like paredit and parinfer, which I definitely agree are clever, and if people find them helpful then I think it’s great for them to use them. But I think there are good reasons to avoid them too, and I hope that tool developers will keep these in mind, providing ways to avoid them in their editors while nonetheless supporting auto-reindentation and bracket matching.
Hey! I’ll chime in.
If I were going to start over today with what exists now, I’d go with Parinfer. It is really nice that you don’t have to learn a whole bunch of commands. I’ve used Parinfer in a Clojure workshop and it was great. The experienced programmers grumbled a bit as they got used to it, but it worked super well for beginners. I noticed two things:
Beginners were having trouble finding the braces keys, even for those who could touch type. Honestly, how often do you type curly braces when you’re not coding? They couldn’t find them. Having half the number of braces to type really helped. And not having to count the closing things and get them in the right order saved a lot of headaches.
Beginners don’t know how spacing, indentation, etc work. Having a system where an instructor could easily help them nest using only the space bar or tab key was really helpful. If the instructors had had to sit down with them to count closing parens, it may have been a “good, character-building exercise”, but the broader purpose of the workshop would have been lost.
I use Paredit and I’m comfortable with it, but it took a lot of time on my part and a lot of evolution on the part of the implementors to iron out some wrinkles. For instance, now Paredit will detect if you’re unbalanced and let you type in closing parens. It didn’t do that when I started. It would not let you do anything! You had to know how to bypass it.
Parinfer is on more solid foundation, with separate indentation and braces modes.