Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> With paredit, you get meta level direct AST manipulation support in emacs that is still light years ahead of any programming IDE out there.

Do you happen to know of a video or article with visual examples that demonstrates this? I always hear about these things with Common Lisp, but I have personally never seen it. I’d love to understand how this works or enables people.



There's the Animated Guide to Paredit:

http://danmidwood.com/content/2014/11/21/animated-paredit.ht...

It really feels more like you're working on a tree of code than just editing text.


That’s helpful. I’ll read it more in depth when I’m off mobile as that site is hard to read on mobile.

Although, I think there’s still something missing between those demonstrations and the quoted claims.

I have never used Paredit when doing Scheme or Racket, so maybe I should just hunker down with it at some point (I have looked into it before). I don’t use Emacs (tried it a few times), but there are several Paredit-based VSCode extensions.


Paredit is the editor part, but then there is also SLIME REPL. In lisp, unlike in other programming languages, you don't start writing your code with a blank slate and an empty source file.

A common approach is to start with an initial core. The idea is that all programs start the same, with an initial core, that contains runtime and standard library. You can test things out in a REPL, that you run side by side with a text editor. As you work things out in REPL, you can start moving them to the text file and the program starts taking form and shape. It's a much more exploration driven design and with fast structure editing of paredit you can really transplant or reorganize pieces of code really quickly. The idea is to grow the program from the initial core into something else inside-out style. It's akin to being dropped into a running program, and modifying it as it is running but that is not possible with most languages easily and as interactively as in Common Lisp for example.

With SLIME the REPL and text editor integration, you can for example write a buggy function, test it in REPL and find out about the error. Modify it in the text editor, press Ctrl-c twice, and the function is hot reloaded on the fly. No reloads, no re-imports, no-caching, no program restarts. Next time the function is called, it is replaced with a new stuff you just wrote. It really is pretty magical. It just works, and works for classes, objects, meta classes, functions, variables, etc.

The language is unlike other languages, because it offers object introspection (often mistakenly referred to as reflection) and object intercession; introspection and intercession combined give you a true reflection. It is the latter technique that supports all of the above, for an imho superior development experience. It really just works, and it works marvelously well. No yak shaving for hours on end trying to get some dependency chain to work, compiler errors, package version mismatches, etc. No need for build team, no need for testing/qa team, no need for most of your usual dev overhead we are so used to these days :)


Is there any source to learn this way of development?


You could start with a copy of the book „the land of Lisp” or „practical common Lisp”

People seem to recommend portacle https://portacle.github.io/ for a first dev environment but I usually set everything up myself. Portacle seems to have all the essentials. You can follow SLIME installation instructions from the quicklisp page of portacle doesn’t come with it.

Then I recommend slime manual at https://slime.common-lisp.dev/doc/slime.pdf if you’re going to be using Emacs.

I’m not familiar with other tools.


Next Advent of Code, grab yourself a download of Portacle and see how far you can get with Lisp.

By day 7 you should have a feel for what people mean when they say you are directly editing the AST.

Basically: there is the same amount of friction to moving constructs around at a high level as there is at a low level, and this is due to Lisp’s uniform syntax, and paredit leverages this a lot.

Contrast this to a language like Java, where the friction between modifying a single expression and modifying class-level interactions are totally different, syntactically. Now you find yourself leaning on highly specific IDE-level support or Lombok for things like setting up Builders for every POJO, to get around these constraints.

From a Lisper’s perspective, these syntactic constraints are unnecessary, and should at most require a library that you can trivially port to any editor. Which is exactly what paredit achieves.


I have used Scheme and Racket a fair amount and know bits of Common Lisp.

What I don’t understand is what I stated and what I quoted.

Without seeing it demonstrated, I just don’t understand the quoted claims. When I’ve done Scheme and Racket, I never really needed to be copying and moving ASTs (i.e., parenthetic groups) all over the place. Maybe that’s just me and my style, for better or worse.


I think "structural editing" is a better way to talk about it. You manipulate code as units of S-expressions. You don't type parentheses so much as you create and modify (trees of) S-expressions. So things like unbalanced parentheses or improperly indented forms are not possible since there's no way to create them in the first place.

In a somewhat vague sense, the "units of editing" are not characters.

There are some videos on YouTube demonstrating ParEdit and SLIME.


That’s fine, but I don’t see where one gets "light years ahead of any programming IDE out there" from that.

I like Lisps/Schemes as much as the next person, but other languages don’t have parentheses to deal with, so by that same token, you’re getting that for free, such as an ML like F#.


There isn’t a single language IDE that I know of outside of Lisp that allows you to hoist a sub block of a loop (a sub tree in the AST) and remove the parent of that code and paste the hoisted expression while simultaneously removing the loop construction with a single key. Please show me an IDE like that and I will buy it immediately. Paredit is not about parenthesis editing and matching despite its name.


Okay, but my original question remains.


with lisp structural edditing you are editing blocks of code, as opposed to characters. in fact it is the use of s-expressions that makes this possible. here is a simple example. immagine you have a list, two elements just outside it, and your cursor is just after the second element:

  Python: [x,y,z] 1,2
  Lisp: '(x y z) 1 2
and lets say you want everything in the list st

  Python: [x,y,z,1,2]
  Lisp: '(x y z 1 2)
in python it would take me about 5 keystrokes to achieve that, while with paredit in lisp it takes 2. this is just a very simple example of the most basic paredit operation. extending this approach to your whole source file and treating whole blocks of code similarly to the above examlle i find really handy


I think the paredit stuff is a bit overblown but apart from managing parens for you, another simple example is editing single expressions. e.g. in Java you might have a line: "int a = blah.bar(something, thing, whatever);" If you realize you need to actually pass "whatever" first, not last, unless you know an IDE shortcut that can make the edit for you, you're going to have to type stuff. I would probably just move my cursor to the start, type "whatever, ", move my cursor to the comma after "thing" and highlight to the end then delete. If "whatever" was a longer variable, or even more interestingly an entire sub-function call like "whatever(x, y, z)", I might instead highlight it all, cut, backspace the comma, move cursor to the start, paste, type a comma. Moving the cursor to the start might be character by character, or using the operating system wide ctrl+left/right to move in 'word' chunks, or possibly it's faster to use the 'home' key first or god forbid the mouse. Oh no, I might miss a comma or somehow mess up a paren/semicolon or typo a name?! Whatever, it's rare for me, and for most mistakes I'd get a red squiggly alerting me to it immediately. I like typing, and prefer most 'helpful' plugins get out of my way for most things, so such a process isn't that annoying to me.

But I do at least see there's a nicer process if you have something like paredit: you just move you cursor to the "whatever" (even if it's instead "whatever(a,b,c)") and a command will move it to the left/right/etc. and fix up anything that needs fixing up. In Lisp though the base syntax is so simple and uniform that there's not usually much needing "fixing up" -- there's no pesky commas to deal with for instance, and having the opening paren come in front of the function name instead of after simplifies a lot of things. The worst is adding/removing/moving a form that's at the end of a let binding, or sometimes introducing a let binding, or sometimes adding something to the end of a function that previously ended with ))).

I like to use vim (which does have paredit though I have it disabled) and just having the ability to jump between open/close parens by pressing "%" and to cut jumps as a whole, or the insides, without having to move my cursor character by character, is good enough for me. I still use some paredit-like commands in some instances like moving forms around or in those "worst case issues" I mentioned but I use them with these mappings: https://github.com/tpope/vim-sexp-mappings-for-regular-peopl...

There are more advanced things but how much I care about them varies; I don't tend to need them for Lisp, though every so often I'll miss something from Eclipse that I suspect not even emacs does (or does well). e.g. I know emacs can do a "templateized" completion just like a Java IDE where you type a function name and it completes it and inserts its required arguments as placeholder variables to later define/type over, I don't know though whether emacs can then let you place the cursor over each one in turn and with something as easy as 'ctrl+1' hoist that var to an assignment form just above (I did this all the time in Eclipse to avoid having to choose a name, type it, and type its correct type). (In Lisp it's complicated by needing to introduce a let binding if it doesn't exist or append to one if it does. It wouldn't surprise me if paredit can do this, it's just that I'm aware of some refactoring tools in Slime but they don't tend to approach what Eclipse or IntelliJ users expect even if in theory they could.)


you could take a look at this in action here:

https://www.youtube.com/watch?v=D6h5dFyyUX0




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: