Earlier quoted context omitted.
This feels a little too strong to me. DrRacket has as its fundamental UI flow a combination of whole-reloaded-file and a REPL, and obviously the creators of Racket are intimately familiar with Lisp REPLs. One problem being addressed is the discrepancy between REPL-based development and non-image-based languages: you have to get your code back out into a source file somehow, without forgetting anything. In image-based…
> In image-based languages like Smalltalk and APL, you just save your environment after modifying it interactively; there are no separate source files and the problem does not exist. My experience with APL was not based on using the image (longterm), but with Smalltalk, there is a source file paired with the image (you can see this with both Squeak and Pharo). And Iceberg has been around for years allowing you to sel…
Why your REPL experience sucks
21–30 of 58 posts
Re: Why your REPL experience sucks
#22Leaving wrong explanation for posterity and to keep thread understandable. See everything after [edit] for corrected explantion This is an important distinction between (funcall #'foo ...) and (funcall 'foo ...) in Common Lisp as well. #'foo evaluates to the function named by the symbol foo, while 'foo evaluates to the symbol foo itself. So if you redefine the function named by the symbol foo any already compiled for…
Re: Why your REPL experience sucks
#23Earlier quoted context omitted.
This feels a little too strong to me. DrRacket has as its fundamental UI flow a combination of whole-reloaded-file and a REPL, and obviously the creators of Racket are intimately familiar with Lisp REPLs. One problem being addressed is the discrepancy between REPL-based development and non-image-based languages: you have to get your code back out into a source file somehow, without forgetting anything. In image-based…
> In image-based languages like Smalltalk and APL, you just save your environment after modifying it interactively; there are no separate source files and the problem does not exist. My experience with APL was not based on using the image (longterm), but with Smalltalk, there is a source file paired with the image (you can see this with both Squeak and Pharo). And Iceberg has been around for years allowing you to sel…
Re: Why your REPL experience sucks
#24Leaving wrong explanation for posterity and to keep thread understandable. See everything after [edit] for corrected explantion This is an important distinction between (funcall #'foo ...) and (funcall 'foo ...) in Common Lisp as well. #'foo evaluates to the function named by the symbol foo, while 'foo evaluates to the symbol foo itself. So if you redefine the function named by the symbol foo any already compiled for…
In sbcl those two work the same.
Re: Why your REPL experience sucks
#25We keep on making fun of php, but it had this problem solved in the 90s. Hit F5 in the browser, get the latest version of your software. No waiting 30s for a rebuild, no stale versions in caches, no headaches.
Re: Why your REPL experience sucks
#26Leaving wrong explanation for posterity and to keep thread understandable. See everything after [edit] for corrected explantion This is an important distinction between (funcall #'foo ...) and (funcall 'foo ...) in Common Lisp as well. #'foo evaluates to the function named by the symbol foo, while 'foo evaluates to the symbol foo itself. So if you redefine the function named by the symbol foo any already compiled for…
In sbcl those two work the same.
(defun bar () 3)
(defvar *the-fn* #'bar)
(defvar *the-sym* 'bar)
(defun foo ()
(funcall *the-fn*))
(defun baz ()
(funcall *the-sym*))
Then at the REPL: CL-USER> (values (baz) (foo))
3
3
CL-USER> (defun bar () 2)
WARNING: redefining COMMON-LISP-USER::BAR in DEFUN
BAR
CL-USER> (values (baz) (foo))
2
3Re: Why your REPL experience sucks
#27We keep on making fun of php, but it had this problem solved in the 90s. Hit F5 in the browser, get the latest version of your software. No waiting 30s for a rebuild, no stale versions in caches, no headaches.
Doesn't have the sophisticated halting and rewinding and redefining that Common Lisp and other image based REPL:s do, but it allows for very rapid development in a similar way.
Re: Why your REPL experience sucks
#28A related question is why would you want to reload the entire file/namespace every time you make a change? Coming from a Common Lisp background, I am used to evaluating single forms/functions. I would sometimes re-evaluate the entire namespace, but that would be relatively rare. I switched to Clojure many years ago and followed the same workflow. Then ClojureScript and tools like figwheel came along and I was somewha…
This way I can be in any file, modify any `def` of `defn` and see its effect on the expression I'm working on.
After modified something, I might jump to its unit test or jump to some definition of some adjacent vars, where i see a point which I want to probe (with a function like this: `(defn ? [x] (pprint x) x)`).
Then I have 2 modified files, and my cursor is in a 3rd file and the expression I'm iterating on is in a 4th; doesn't matter, I can just keep hitting the same shortcut (Cmd-Ctrl-Enter) to see the effects of my changes on the "expression-under-test".
It's an extremely convenient workflow, which is also easy to teach to ppl!
Downside is that you can't have namespaces, which have side-effects WHEN they are loaded.
To deal with that problem, I'm using `redelay`, `rmap`, `meta-merge` & `defonce`, eg:
(ns service
(:require
[meta-merge.core :refer [meta-merge]]
[gini.rmap :as rmap :refer [rmap ref] :rename {ref $}]
[redelay.core :as redelay])
(def kit
(merge {:cfg {:db/uri "..."}}
(rmap {:db (connect (:db/uri ($ :cfg)))})))
(defonce service-ref
(redelay/state
:start (rmap/valuate!
(meta-merge service/kit
{:cfg {:param 'override}
:some 'special-component}))))
(defn service [] (deref service-ref))
(comment
(.close service-ref)
(-> (service) (some-operation x y z))
)
More info on this topic is here:
https://functionalbytes.nl/clojure/rmap/2020/07/04/rmap-2-up...Re: Why your REPL experience sucks
#29Re: Why your REPL experience sucks
#30I've only used a few REPLs so far but Ruby and Elixir are great (and I assume inspired by Lisp). I cut my teeth developing with REPLs and actually struggle a lot with trying to use language environments without them. Like, how can I just experiment and run a little one-of bit of code and data before starting the actual implementation? Or call and play around with the function I just wrote?
* https://www.youtube.com/watch?v=St0_jsPnGAw - analyze some SO HTTP API responses * https://www.youtube.com/watch?v=TaazvSJvBaw - transducers from the ground up
I think they are great, crystal-clear examples of REPL-based development.