Parinfer and Paredit: embrace or avoid?

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

17 Likes

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.

2 Likes

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.

1 Like

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:

incrementer

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.

3 Likes

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.

2 Likes

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

2 Likes

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.

1 Like

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 ⌘-/

  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
1 Like

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

2 Likes

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.

2 Likes

@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

2 Likes

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.

4 Likes

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:

  1. 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.

  2. 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.

Eric

4 Likes

Well, I must say that for a newcommer to the Clojure and LISP world like me, Parinfer is a game changer! While Clojure felt really natural to me from the start and I kind of fell in love with the language, I found the parentheses, brackets and braces frustrating. Trying to align everything correctly so as to make my code readable and understandable was difficult and I spent too much time thinking about typing rather than programming.

When I discovered Parinfer and installed its plugin in LightTable, it made Clojure much more fun to work with. I write code instead of balancing characters. It makes incremental complexity easier too, since adding a nested function is taken care of very neatly.

I’d be curious to try out frame-based editing though! Clarity is always a good thing!

2 Likes

There’s nothing more frightening than when I open a file in Atom and it says "parinfer needs to make some changes to this file, 100 changes"
But as I’ve gotten better at following the style guide I’ve had less fights with it while I’m writing code.

However it does make copy/pasta code kind of a pain but also a fun learning experience when you are trying to get it to work

1 Like

Embrace!

We use paredit all the time at work though some devs still hold out against it occasionally. It’s far more productive and perfectly intuitive with only a bit of effort at the start.

But I love that Zach Oakes has implemented Parinfer into his fantastic pure browser editor Paren Soup. For newbies or non technical people this is the editor they like as otherwise getting parens right can be really discouraging. I use it too at quick tech discussion sessions to demo clojure stuff :slight_smile:

http://oakes.github.io/paren-soup/

Might try to use Parinfer over paredit soon but there are some edge cases that Parinfer struggles with where Clojure departs from conventional Lisp syntax I believe.

Don’t know if anyone using the emacs package lispy. The emacs parinfer implementation have the functionality to combine lispy, parinfer and evil (vim modal editing) together.

I’m trying to combine vim’s insert normal state with parinfer’s indent and paren modeThen maybe change some vim’s normal state keybindings into lisp’s. The efficiency is promising if we can manage combining these three together.

1 Like

Hi there,
Despite being a long time lisper and emacsian, I resisted paredit as well as many emacs packages… But being pushed by the younger generation I’ve finally managed to adopt smartparens… I have a shortcut to switch to and from strict mode so I can alternate between the old and the new me at will…