
REPL-Driven Development (2017) - kimi
https://github.com/matthiasn/talk-transcripts/blob/master/Halloway_Stuart/REPLDrivenDevelopment.md
======
pharo70
In Smalltalk, the class browser (editor) has always been the REPL. You can
highlight any snippet of code you browse, including code you're currently
editing, and evaluate it in the context of whatever class you're browsing.

For example, if you're editing a method called "fooBar", you can just type (in
the same input field) "self new fooBar" ("self" is bound to the class being
browsed) or, if it's a class method, "self fooBar", highlight it, and then
type the appropriate shortcut (like Cmd+d in Pharo) to evaluate it.

This is useful for documentation. You can have a method begin with a comment
that shows examples, which a person browsing can highlight and evaluate, and
also experiment with.

~~~
lispm
But that's not really a REPL. It lacks the 'L' and often also the 'P'. Running
code from a text buffer in an editor is one way to interact (many Lisp tools
do that), but a REPL is usually a tool and its purpose is to read expressions,
evaluate them and print the results. I would be surprised, if Smalltalk did
not have that somewhere, too. The REPL has a visible I/O history and is not
conflated with other text input fields (like a function being edited).

~~~
pharo70
> But that's not really a REPL. It lacks the 'L' and often also the 'P'.

This objection is subtle. The "P" in REPL of course does not simply mean to
emit some printed representation of the result of the last evaluation, but to
emit a _specific_ representation that a corresponding operation, (read), can
comprehend.

In that sense, _no non-Lisp_ , including Pharo, has a true "P" and a true
REPL. (Though many objects in Pharo do have such printed representations).

> Running code from a text buffer in an editor is one way to interact (many
> Lisp tools do that),

Like Emacs and SLIME. But having used both, I prefer the Smalltalk browser-
based IDE approach. The browser makes code navigation much easier, and it
saves you from having to type out a lot of class and method creation
boilerplate code like the kind you end up writing when using Emacs and CLOS.
Maybe LispWorks (which I've never used) is that kind of IDE, but for CL?

> I would be surprised, if Smalltalk did not have that somewhere, too. The
> REPL has a visible I/O history and is not conflated with other text input
> fields (like a function being edited).

Repeatedly print-evaluating (Cmd+P in Pharo) code in a workspace/playground is
actually the closest I think most Smalltalks come. A command prompt-style REPL
isn't as useful in a fully graphical environment. You could easily create one
if you wanted, though, and text-based Smalltalks like Gnu and Amber have one.

However, the inspector in Pharo can function as a nice graphical REPL. You can
enter code in an inspector pane, evaluate it with Cmd+G, and the result will
appear in a new inspector pane to the right of the current, and you can cycle
back and forth through evaluation panes.

~~~
lispm
> but to emit a specific representation that a corresponding operation,
> (read), can comprehend.

On the Symbolics Lisp Machine they then added a facility where READ can read
arbitrary things, since each thing you PRINT has a printed
representation/view, which stays connected with the original object. Thus you
can enter non-text things or non-printable things in a REPL.

> Maybe LispWorks (which I've never used) is that kind of IDE, but for CL?

Not really, it is not browser based in the sense of Smalltalk. It has browsers
for things like classes, but you do no in-place editing.

Apple Dylan or Interlisp-D were that way. Interlisp-D is a similar managed
source system like Smalltalk, but with Lisp representations and structure
editing.

> However, the inspector in Pharo can function as a nice graphical REPL. You
> can enter code in an inspector pane, evaluate it with Cmd+G, and the result
> will appear in a new inspector pane to the right of the current, and you can
> cycle back and forth through evaluation panes.

LispWorks has something where you have a REPL and an inspector in a window.
Each evaluation result in the REPL goes into the inspector and you can cycle
between inspected values back and forth.

One can also link windows in LispWorks, for example a REPL with an inspector.

------
mbil
Programming Clojure applications with CIDER[0] is a really slick experience.
By connecting through an nREPL port to a running environment you can capture
variable values like function inputs, change and re-evaluate function
definitions on the fly, and test hypotheses by calling funcs directly with
whatever input you want. Not to mention the speed of prototype iteration. This
has been invaluable when trying to quickly track down production bugs.

I've lately been working in Python, and even with IPython/Juptyer the workflow
isn't quite as magical as Clojure's.

[0]: [https://github.com/clojure-emacs/cider](https://github.com/clojure-
emacs/cider)

~~~
dolzenko
Just a reminder to younger crowd Visual Studio had all this before (packaged
in single app hence well-integrated and easy to install) probably for 15 years
or longer.

~~~
hashkb
Are you trying to say the "younger crowd" is on Emacs and doesn't know about
Visual Studio?

~~~
eatonphil
Anecdata: Am in my twenties, use Emacs, haven't used VS. :p

------
bjourne
For a language with a very good REPL environment, try Factor. :)

But there are a lot of kinks with REPL:s that the talk doesn't detail. Most of
them have to do with code reloading and all the corner cases that can lead you
into. For example, suppose you have started a thread which calls the function
"foo" from within a while loop. Then you recompile "foo." Now, what should
happen with the thread? Should it switch to the new foo or keep calling the
old one? What if you remove the foo function from the module in which it was
defined? What if you have a class and you change its definition. What happens
with old instances? What if you recompile the REPL? Recompile the compiler?

Solving issues like the above is really, really hard. Especially if the
solution has to be both efficient and also work as the user would expect.

~~~
escherize
Clojure has dealt with this problem actually. If you are curious check out
mount, component, and this blog post:
[http://thinkrelevance.com/blog/2013/06/04/clojure-
workflow-r...](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-
reloaded)

------
simonw
As a Python and JavaScript developer I live in Jupyter and the Firefox/Chrome
devtools (and I'm starting to get into Observable). I genuinely don't know how
to be productive in languages that don't have a great REPL.

I think REPLs might be why I've never really got excited about IDEs. When
you're working in a REPL you can answer questions about your code instantly
without needing smart autocomplete or context-sensitive help.

~~~
jdonaldson
I do a good combination of data science and development.

REPLs are nice, don't get me wrong, but they are by nature single entrance,
single exit. You are basically riding shotgun on a single unit test. You get a
great view along the way, but the problem solving doesn't scale, nor can it
handle situations where you need to consider multiple paths through the code.
Writing a good test suite, and knowing just where and how to place debug trace
statements are two of my best problem solving skills.

~~~
wwweston
A good REPL keeps a history. It happens frequently enough that dumping that
history will give you a reasonable basis for a unit test. :)

~~~
ACow_Adonis
Indeed, that's partly what my own testing framework (that I wrote and use on
my own private projects) takes advantage of, except in interactive use.

The Common Lisp REPL automatically binds the last expression evaluated to the
variable "+". It also automatically binds the value returned from the
evaluation of the last expression to the variable "*".

I write code and develop interactively at the REPL with the package under
development loaded/running. When the value I expect gets returned from the
function or form I'm developing at the REPL, i just evaluate the "test"
function (or a variant thereof if extra specificity or features are wanted
such as names, doc-strings or tags, etc.), and the forms and expected values
are packaged into a test and added to the projects' test repository.

Pretty much all the benefits of TDD, without writing tests up-front or wanting
to do red/green (i did allow for the option, but i practically never do in
practice), because they're an almost costless artifact of just developing
now...

------
eadmund
> So Clojure has dynamic classloaders, but it does not have a replacement for
> classloaders. And so classloader confusion is something that cannot be
> solved at this level.

> But I could imagine if you were coming from Common Lisp, or something like
> that, and saying "that seems like a wart." And it is a wart that we lovingly
> embrace, for the mighty power of having access to the whole JVM ecosystem.

There's Armed Bear Common Lisp[0], which is a Common Lisp on Java, which gives
access to the whole JVM ecosystem. Dunno how it handles classloaders though.

[0] [https://common-lisp.net/project/armedbear/](https://common-
lisp.net/project/armedbear/)

~~~
bitwize
Clojure is a Lisp designed from the ground up for the modern era. For new
applications, it's a better fit than Common Lisp.

------
camtarn
Since I've mainly used REPLs in a text-only environment, I never thought about
the idea of creating little GUI 'sidecars' from the REPL, potentially with the
aid of a little utility lib to simplify things such as "make a window
containing the value of this var", "graph this var over time", or "make a
button that executes this snippet of code". Very cool idea.

------
hprotagonist
anecdotally, i tried adding up how many ipython sessions I currently have open
for various reasons on my workstation.

I stopped at about 15. REPLs are incredibly useful.

------
marmaduke
A while ago I wrote a Vim plugin to send Python code to a running interpreter,
redefining and debugging on the fly. Unfortunately that’s not a good fit for
Python. Code reloading on classes , data descriptors etc requires adhoc
semantics. All in all, hard to reason about.

I even find Jupyter notebooks get this a bit, when people eval cells out of
order..

------
hartator
I was hoping for an article advocating REPL-driven development versus test
driven development, I was a bit disappointed!

------
snambi
The alternative to REPL is a DEBUGGER with a great IDE. Don't get me wrong,
REPL is nice, but IDEs are even better.

~~~
hartator
A "debugger" is a REPL.

~~~
slaman
It's a REPL with the ability to arbitrarily jump to chosen points in your
application's execution, as opposed to attempting to populate the scope with
copy-paste or dummy variables.

