
Parinfer – Simpler Lisp Editing - espeed
https://shaunlebron.github.io/parinfer/
======
noctuid
I've argued that parinfer complicates lisp editing. Some notes critiquing
parinfer: [https://github.com/noctuid/parinfer-
notes](https://github.com/noctuid/parinfer-notes)

~~~
dragandj
That's why few people are using things like parinfer. This demo might look
cool to non-lisp programmers, but in lisp-land, everyone is using semantic
editing (in Emacs or otherwise), and _not_ line-based editing.

~~~
lemming
_That 's why few people are using things like parinfer._

I don't think this is true. I develop Cursive and _I_ use it, despite being
competent at paredit. A ton of my users do too, even experienced ones. It's
just easier, and it turns out that a lot of editing is actually line based,
even in a lisp. And when it's not, I can still use the paredit commands in
parinfer mode, at least with Cursive.

It's referenced in an edit to noctuid's document, but many of those criticisms
are no longer valid since smart mode became the de-facto default for parinfer.
It's now really intuitive. Parinfer's worst problem now is its difficulty
inferring parens when there are multiple expressions on a line (i.e. when
there's no indentation to infer from), but it's surprising how infrequently
that's actually a problem.

~~~
dragandj
What percentage of users is that, assuming that you don't make parinfer the
default choice in your IDE? What percentage of Cursive users knowingly say:
I'm a bit confused by how these parens work (my guess: all lisp newcomers),
what percentage goes to preferences to see what they can do about it (my
educated guess: a lot, but less than, say, a third), and what percentage of
those conciously look for parinfer (I don't know - I'm asking)?

Now, Cursive is used by something like a third of Clojure users. Half of them
use Emacs, and in Emacs land there are rather few Clojurians who seek
something like parinfer. Even when they do, it's a usual "how we can make this
more palatable to outsiders" type of quest rather than "I'm really frustrated
by how Emacs does Lisp editing. I'd like something like parinfer"...

~~~
lemming
I don't know exact numbers, since I don't do any user tracking. But I know of
numerous users _who are already experienced with Clojure_ who have switched,
myself included. Cursive currently has paredit on by default, but I'm going to
switch that to parinfer.

FWIW Emacs users do ask about parinfer in #parinfer on Clojurians because they
actually want to use it. There currently isn't a smart mode for Emacs though,
and that's what I consider the game changer. I suspect that uptake will be
good once that's available.

~~~
dragandj
If so many people find parinfer valuable, maybe they should consider donating
some money to Shaun.

------
modernerd
I loved using Parinfer when I was writing ClojureScript, but it also made me
question the value of Lisp syntax.

If brackets can be inferred from indentation, doesn't this imply that they're
extraneous — that indentation only would be sufficient to write many Lisp
structures?

~~~
lispm
One can do that, but most Lisp programmers value the direct "source code is
data" nature of Lisp - using s-expressions.

Alternative notations were originally planned for Lisp when it was designed -
some books were published using it, but for actual programming it wasn't used
too much - especially since most implementations actually a) didn't support it
or b) had s-expressions as a default/internally.

Then several attempts to modernize Lisp with a different syntax mostly failed
to get traction or failed big (like the Lisp 2 effort).

Then some efforts failed to provide more than one syntax and also failed to
appeal to people (Dylan).

What we saw is a bunch of languages derived from Lisp with different syntax
(ML, Logo, ...) and a bunch of Lisps for mathematics with different syntax
(Reduce, Macsyma, ...).

But the core Lisp programmers were never willing to give up the s-expression-
based syntax. It has some clear advantages when manipulating code, especially
in interactive programming.

~~~
modernerd
Thanks for these comments. I didn't realise alternative notations were planned
and never took off. (Dylan in particular looks really interesting.)

I can see the value of homoiconicity / code as data from the perspective of
someone writing a parser.

I've asked what writing code as s-expressions gets you as the end-user of a
language before. People usually say, “macros” or “it's easier to manipulate
code”. But macros exist in non-homoiconic languages, like Nim and Elixir. And
in my short time using ClojureScript I'm not sure what manipulations Lisp
syntax gave me that I don't already have with other languages in a modern text
editor.

I'd love to see examples of accomplished Lisp users on YouTube or elsewhere,
to see what those code manipulations look like.

~~~
lispm
> I didn't realise alternative notations were planned and never took off.

See for example this program from McCarthy, 1960. On top is my Common Lisp
translation and below you find the original code. The original had to be hand-
translated into s-expression syntax to run it in Lisp - in 1960.

[https://gist.github.com/lispm/e44d81c3bb9b86d4313763647e058a...](https://gist.github.com/lispm/e44d81c3bb9b86d4313763647e058a59)

For a Lisp 2 (Lisp 2 as the successor to the original Lisp language - with the
long promised notation) example see:
[http://www.softwarepreservation.org/projects/LISP/lisp2/SP-2...](http://www.softwarepreservation.org/projects/LISP/lisp2/SP-2450-SUMSQUARE_LCS.pdf)

> But macros exist in non-homoiconic languages, like Nim and Elixir.

Lots of languages have some kind of macros: C has textual transformations and
Elixir has AST transformations.

Lisp macros are different, since they are not AST transformations but token
tree transformations. That means Lisp accepts arbitrary token trees (give that
the first item is a macro identifier) and one can write programs to transform
them.

Languages which support macros for AST transformations, need to have the code
parsed into an AST first. That means the expressions it can transform need to
be already parsed into an AST - and the language accepted by the parser limits
the expressions - unless one can add syntax changes to the parser, too.

ASTs are special purpose data structures, while s-expressions are general
purpose data structures and thus are not limited to expressing programs in a
particular syntax and are not limited to express something which looks like a
program.

Lisp offers a bunch of macros: macros for transforming Lisp code, macros for
transforming symbols, compiler macros for optimizing code, macros for
transforming s-expressions, ... Additionally the macro has access to a full
Lisp - which means it can do arbitrary computations: primitive
transformations, complex language transpiling, full parsing&transformation,
doing side-effects in the development environment, running at runtime in
interpreters, ...

That means for me as a programmer I can automate all kinds of code
manipulation. There are many simple and many complex examples.

Another advantage is that the language core can be reduced to a minimum set of
syntactic forms and every other syntax can be built on top of it - and the
developer uses the same mechanism as the language core: macros. This makes
macros very pervasive - a programmer will use a lot of macros and may also
program macros.

One of the disadvantages is that macros also cost us: the code we see can be
very different from the code which executes and there is an additional
programming paradigm to understand: using syntactic abstractions with macros.
One can learn some Lisp without touching macros (see for example SICP, which
does not use macros), but in real world programs one might see a lot of
macros.

Paul Graham wrote a book, which explained use of macros in Lisp: On Lisp. Free
download at:
[http://www.paulgraham.com/onlisp.html](http://www.paulgraham.com/onlisp.html)

There are more disadvantages and also attempts to improve macros. See for
example:
[http://library.readscheme.org/page3.html](http://library.readscheme.org/page3.html)

An example for a typical use of macros is CLOS, the Common Lisp Object System.
It has a three or four - layer architecture:

    
    
       layer 0 : meta object layer for CLOS - here CLOS is implemented in itself
       layer 1 : object layer for CLOS - here CLOS deals with simple representations of itself
       layer 2 : functional layer for CLOS - here have functions operating on CLOS objects
       layer 3 : macro layer for the CLOS programmer - here we have macros providing ways to configure CLOS programs
    

Take for example defining a CLOS class:

0) on layer 0 CLOS has CLOS functionality to represent and create instances of
classes and metaclasses, he were can also write extensions to new kinds of
metaclasses

1) on layer 1 CLOS classes are objects: which have slots which are objects and
which have superclasses which are objects

2) on layer 2 CLOS provides functions to create all that stuff: classes, slot
objects, ...

3) on layer 3 CLOS provides the DEFCLASS macro which at macro expansion time -
which typically will be triggered by compilation - can do all the
transformations and can interface to the development environment at
compilation time.

The programmer will typically use layer 3 to define a class using the macro
DEFCLASS. For more advanced use one could use the function ENSURE-CLASS

Common Lisp originally in 1984 did not have any syntax for defining classes.
The first CLOS implementation was a Lisp program which implemented all the
layers above and provided the necessary syntax to define the new language
objects: generic functions, methods, classes and some others. So it was mostly
a user-level program which added a full complex object system - with only
little code for implementation specific stuff.

Thus the DEFCLASS macro could introduce any syntax it wanted as a user level
program - since it is not constrained by a fronted parser. So the CLOS
developers came up with something that was convenient for them to define
classes. This could mean that it does something trivial by providing a
different order to define things, make things shorter to write or that it does
something more complex by actually checking the provided class configuration
and doing some code transformations.

The whole story of CLOS in CLOS itself is written in AMOP:
[https://en.wikipedia.org/wiki/The_Art_of_the_Metaobject_Prot...](https://en.wikipedia.org/wiki/The_Art_of_the_Metaobject_Protocol)

See also the pointer there to the first and portable implementation of CLOS:
PCL.

~~~
modernerd
Thank you so much for this thoughtful reply — I enjoyed the code samples and
the details on Lisp's macro system, and I can see how its approach gives you
more control to invent on top of the language. It's given me more to read and
think about.

------
sbjs
This is really amazing and it's too bad the author is getting so little from
his Patreon for making it! But at the same time I understand why. People can't
contribute to every open source project that increases their productivity,
there's just too many of them. But what other options do innovative geniuses
like Shaun have to keep making things like this? Make a kickstarter for a
product? Nobody would bite for small but invaluable utilities like Parinfer.
Commercialize it and keep it closed source as an IntelliJ plugin? Would be
incredibly hard to market. Keep it open source but charge for support? It's
not complicated enough, he'd have to add a gazillion configuration options and
intentionally bloat it just to justify it. I would really hate to see things
like Parinfer die out because most people wouldn't justify spending the time
making it, or would make it but wouldn't open source it.

~~~
pmoriarty
_" People can't contribute to every open source project that increases their
productivity, there's just too many of them."_

I'm sure there are people on HN who can do just that, and much, much more.
Some of them may even use parinfer. But whether they can and whether they want
to contribute are two different things.

For me the more interesting question is how the tiny minority of people who
have gotten their hands on the overwhelming majority of money, power, and
resources in this country and around the world can be persuaded to use what
they have in socially constructive ways rather than for the benefit of the
tiny, exclusive minority they are part of.

~~~
sbjs
This gives me an idea for a platform that:

\- looks at your Github repos

\- looks through all your dependencies

\- lists all the projects you depend on that support donations

\- shows you how much (or rather little!) they're making now

\- shows you the (Patreon) rewards you can get for supporting them

\- allows you to support them right there and then!

I honestly think this is a legitimate idea and kind of want to pitch it to Y
Combinator right now. It would be like something that ties Patreon and Github
together.

\---

Okay I just posted this idea to Hacker News, find it in my submissions if
you're interested :)

~~~
lubonay
Sounds like a cool idea for a free open-source project. Too bad your Patreon
for it would be somewhat underfunded...

~~~
sbjs
Chicken v Egg! Haha, did not think of that :D Actually I think a Kickstarter
would be more appropriate for this, but even then it seems unlikely to get any
funding. I think going straight to a VC would be my best bet.

~~~
bostonvaulter2
Nah, just build it. A VC would cause the resulting service to end up very poor
due to money pressure.

~~~
sbjs
I don't think so? The product is too simple to get destroyed from money
pressure and bloat. All it needs to do to make it worth their while is skim a
little off the top, maybe 1%.

------
mackeprm
I'm using the atom parinfer plugin for my clojurescript projects and it makes
development so much easier! The "it feels like writing python" analogy really
fits. Now, if only there was a jump to function definition by ctrl+lmb for
clj/atom it would be the perfect environment!

~~~
simongray
Also coming from Python and now using Parinfer for Clojure/ClojureScript, but
I use the implementation in Cursive (intellij Clojure plugin). Love it. The
only problem is working on a shared code base where people don't bother to
indent code properly.

~~~
chrisoakman
I'm glad you like Parinfer!

 _The only problem is working on a shared code base where people don 't bother
to indent code properly._

Parlinter was designed for this purpose. Maybe you could suggest it to your
team?
[https://github.com/shaunlebron/parlinter](https://github.com/shaunlebron/parlinter)

~~~
simongray
Thanks, that's a great suggestion, although I think this I'm probably not
going to get it through. This is a team of probably around 50 Clojure
developers using different editors and AFAIK I'm the only one using parinfer.

------
jamesrcole
I've sadly never gotten around to using Lisp, but even still, this kind of
thing excites me. I think there's a lot of untapped promise in supporting
structure within free-flowing text editing, like this does.

~~~
hashkb
You don't realize how terrible things like JS are until you experience the
power and freedom.

~~~
always_good
That was the first phase.

But ultimately Lisp taught me not to overvalue technical superiority, so I
eventually stopped using it.

------
EricRiese
The lego analogy is something I've thought about before. Inspired by Firefox's
Tilt 3D[1], I've wondered if it makes sense to code in VR with indentation, or
even level of the AST projected onto the z-axis. Wobbling the perspective
around would probably be annoying and unnecessary, but hopefully a fixed
angle, or one varying slightly with zoom could work.

[1] [https://addons.mozilla.org/en-
US/firefox/addon/tilt/](https://addons.mozilla.org/en-US/firefox/addon/tilt/)

~~~
chrisoakman
I did a quick project around this idea a while ago:

[http://oakmac.com/lisp-3d-1.gif](http://oakmac.com/lisp-3d-1.gif)

[http://oakmac.com/lisp-3d-2.gif](http://oakmac.com/lisp-3d-2.gif)

------
dang
Discussed in 2015:
[https://news.ycombinator.com/item?id=10547772](https://news.ycombinator.com/item?id=10547772)

------
dustingetz
I badly need something like this in
[http://www.hyperfiddle.net/](http://www.hyperfiddle.net/) \- is this a bug in
smart mode or am i doing it wrong ... ?

edit: better video
[https://i.imgur.com/4BsYQ3e.gif](https://i.imgur.com/4BsYQ3e.gif)

Exposing newbie end users to modal editing would seem to be a non-starter, i
think smart mode needs to work

~~~
dustingetz
update: I hacked up parinfer-codemirror to be modal and indicate mode
visually, here is the result:
[https://i.imgur.com/xPDc4Wy.gif](https://i.imgur.com/xPDc4Wy.gif)

I'm wondering if paren mode might be what newbies actually want, and they can
go and learn about indent mode later?

------
agumonkey
who else tried but got back to paredit because of too many years of habits ?

------
dustingetz
Is there a place with a one slide, single demo, "type this, observe this, now
type this, so you understand ZZZ"?

------
nojvek
When I think about LISP and parens it just feels redundant if you’re gonna use
indentation anyway.

Parens are only useful if everything is on a single line. With new lines and
indentation, things can become a lot cleaner like python style.

I strongly believe python got so popular because of its very simple to read,
almost pseudo-code like syntax that anyone could learn.

List had great ideas, everything is a list, but dealing with parens hell makes
me think it could be a lot more elegant.

~~~
nabla9
>More than anything else, I think it is the ability of Lisp programs to
manipulate Lisp expressions that sets Lisp apart. And so no one who has not
written a lot of macros is really in a position to compare Lisp to other
languages. When I hear people complain about Lisp's parentheses, it sounds to
my ears like someone saying: "I tried one of those bananas, which you say are
so delicious. The white part was ok, but the yellow part was very tough and
tasted awful." – Paul Graham

Lisp programmers don't deal with "parens hell". That's one of the
misconceptions that come from outsider looking in. Parens are for the editor.
Lisp indeed uses indentation and not parens as you said. It's very python-like
that way."You have reached Lisp enlightenment when parens disappear"

I think it would be real helpful to have editor for beginners that shows
parents as transparent and low contrast, separately from the rest of the code.
It would help people to understand they should not be trying to match them
visually.

~~~
egypturnash
If Lisp uses indentation and not parenthesis, then why is my mental caricature
of Lisp just ((())))(()))((())))()()()(())))((())))?

~~~
kazinator
Educated guess: because you have zero experience developing an application or
utility program in a language in the Lisp family. Because then if you still
harbored a caricature, it would probably be more sophisticated.

