Hacker News new | ask | show | jobs
by mclehman 3225 days ago
Lisp + Emacs + SLIME: miss no longer.

Picking them all up is a tall order though.

2 comments

Emacs suffers from not being like Lisp machines REPL, meaning lacking graphical display on buffers.

If I remember correctly, XEmacs used to support it (which was my favorite fork), but it seems to have faded away.

For example, try to achieve this demo on Emacs.

https://www.youtube.com/watch?v=o4-YnLpLgtk

I have never used a Lisp Machine so forgive my naivety but I saw the demo and you seem to be referring to the ability of displaying images inline in a buffer. Emacs can definitely do that, I have used Emacs IPython Notebook[1] which is a REPL supporting this. I could fire up a jupyter notebook and use pillow[2] to recreate the image manipulation part of the demo.

[1] -- (https://github.com/millejoh/emacs-ipython-notebook/blob/mast...) [2] -- (https://python-pillow.org/)

That is partially what I was referring to.

The other part, which might not be visible on that video is the integration of debugger into the REPL, and the ability to redo a piece of code after breaking into the debugger and fixing it.

So you can do something like, REPL => error (ask to start debugger) => track down and fix error => restart error expression => finish the execution of the original REPL expression with the respective result.

The only debugging experience I find enjoyable in Emacs is debugging Clojure using cider[1] and I think it comes close to what you are describing but I think you might already be aware of that :)

[1] -- (https://github.com/clojure-emacs/cider/blob/master/doc/debug...)

SLIME doesn't give you this?
I don't know, back when I cared about Lisp development on Emacs, SLIME wasn't a thing, as you might understand from my XEmacs reference.
SLIME does let you redefine functions and restart a stack frame (assuming the Lisp implementation supports that). You can even do it without using Emacs/SLIME, although that's not very convenient of course. A silly example with SBCL,

    ~ $ rlwrap sbcl --noinform
    CL-USER> (defun foobar (x y)
               (if (evenp x)
                   (/ x y)
                   (* x y)))
    
    FOOBAR
    CL-USER> (foobar 10 0)
    
    debugger invoked on a DIVISION-BY-ZERO in thread
    #<THREAD "main thread" RUNNING {1001BB64C3}>:
      arithmetic error DIVISION-BY-ZERO signalled
    Operation was /, operands (10 0).
    
    Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
    
    restarts (invokable by number or by possibly-abbreviated name):
      0: [ABORT] Exit debugger, returning to top level.
    
    (SB-KERNEL::INTEGER-/-INTEGER 10 0)
    0] backtrace 3
    
    Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {1001BB64C3}>
    0: (SB-KERNEL::INTEGER-/-INTEGER 10 0)
    1: (FOOBAR 10 0)
    2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (FOOBAR 10 0) #<NULL-LEXENV>)
    
    0] down
    (FOOBAR 10 0)
    
    1] source 1
    
    (IF (EVENP X)
        (#:***HERE*** (/ X Y))
        (* X Y)) 
    1] (defun foobar (x y)
         (if (and (evenp x) (not (zerop y)))
             (/ x y)
             (* x y)))
    
    WARNING: redefining COMMON-LISP-USER::FOOBAR in DEFUN
    FOOBAR
    1] restart-frame
    
    0
What do you mean with "picking them all up?"
They mean the learning curve is steep.
A "steep learning curve" actually means that the amount learnt grows rapidly over time. It's odd how this basically obvious conceptualization has had its meaning inverted in popular usage.
This is one of my pet peeves, as well. Though I have moved on. Colloquially, it is clear how folks take that saying. Just transpose the chart if it helps you think about it.

That is, it may have originated with that meaning. But it is far from unique in having the general meaning shifted with use.

Ah, fair enough. The nice thing is most repl's have the same bindings as each other. So, some basic drills can get you up to speed.