Parinfer and Paredit: embrace or avoid?


#1

In Effective Programs - 10 Years of Clojure (Oct 12, 2017), Rich Hickey talks about how he never considered Lisp’s syntax to be a problem when designing Clojure. He suggests that attempts to work around the syntax are bad:

I think things like Par—make-it-go-away – whatever that is – is a terrible idea, and it’s not good for beginners to do that – to try to solve a problem that’s a feature.

I’m not clear if he’s referring to Paredit or Parinfer there, but guessing the latter?

As a relative newcomer to Clojure with only limited exposure to Lisp syntax (via Racket), I’ve been using Cursive with Parinfer mode active. To me it feels natural to have the syntax be inferred, since the “guesses” are often what I want anyway. Projects that make Clojure easier to read and write seem healthy to me.

Is using it really as bad an idea as the creator of Clojure suggests?


#2

Just found this on Reddit, which I think answers the question:

Shaun Lebron and I spoke with Rich in the hallway at the Conj and asked him about this.
He was not referring to Parinfer or Paredit (ie: ways of editing Lisp code via text).
He was referring to editor / plugin projects that hide parenthesis. He said it was important to show the full structure.

Thought I’d update the thread in case it helps others who were similarly confused by the comment. Happy that I can continue using Parinfer without feeling like I’m doing something that will hurt me later on.


#3

Would you like to take a look at my opinion on parentheses?


#4

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.


#5

I really like parinfer and think it’s amazing :slight_smile:

Writing clojure with parinfer feels nicer than writing python. Think that’s a big win.


#6

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.


#7

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.


#8

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!

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 defn, 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. :slight_smile: )


[WIP] A visual blocks engine for Clojure -- need your input!
#9

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.


#10

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.


#11

Thank you for this insight, @shaunlebron, and thanks for Parinfer / Lotus / Locus / Embrace / whateverItGetsRebrandedTo! (I supported your Patreon within ten minutes of trying it out.)

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.


#12

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.


#13

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.


#14

I embrace parinfer, even if that’s what Rich meant he can pry it from my cold dead fingers.


#15

Do embrace!

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.


#16

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!)


#17

On that point, here’s a cool trick to comment-out stuff using the comment fn (if you don’t want to just hit ⌘-/

  1. write (comment) above the form you want to comment out.
  2. select the form you want to comment out
  3. tab to move it into the comment form

reversing it entails:

  1. select the lines after the comment line
  2. shift-tab to move them outside the comment form
  3. delete the (comment) line

#18

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:

comment-function

(Follow-up about wrapping top-level forms: Idiomatic Clojure indentation – wide or deep? )


#19

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.


#20

@seancorfield Ah, good to know, thanks. That seems to work great for lists, but it splits vectors (tried Atom and IntelliJ). For example:

comment-split-vectors