Fork me on GitHub

Most Clojure REPLs do not by default clear existing state


also GHCi is different from haskell itself, while the code driving clojure's repl eval is literally the same code that runs when running your app


Getting an editor/IDE setup where you can eval code from a source or test file with just a hotkey into a connected REPL is a much nicer workflow than trying to type directly into a REPL -- but it does take a bit more effort to get it up and running and some practice to get into that new flow.


Then you can get into the habit of starting a REPL once and leaving it running (for days or even weeks) and just interact with it via your editor. Make a small change, eval, see the results immediately, rinse & repeat. But it's a very different workflow to how the "REPL" works in most other languages -- it's a bit more like Smalltalk (or the Lisp systems of old).

👍 8

That way you can "run your application" inside the REPL and interact with it while it is running -- as opposed to "run" being some external operation.


@alper I didn't mean to be harsh, but it does take a while to learn the tooling and the REPL driven workflow of Clojure. Most of your issues with it for the first few hundred hours are going to be due to your lack of understanding and practice, and most of them will disappear as you progress. Not saying everything is perfect, but definitly your current concerns are things you'll just outgrow (like a beginner piano player complaining their fingers can't reach far enough to play a given chord). Like Sean said, in a typical workflow, I use lein run a grand total of 0 times a day, I just never need it. And I am in my REPL constantly, only restarting it at most once a day, often less then that.

Alper Cugun20:12:26

I’m reading a book (brave) where long running REPLs I believe are totally de-emphasized and most code is run using lein run. I’m setting up the stuff now and I get why a tutorial would try to ignore all of this (and be fairly successful with that approach if it weren’t for these kind of confusing edge cases). In your analogy, I’m not trying to play wild chords, just some basic scales.

Alper Cugun20:12:31

But hundreds of hours?

😋 4

Ya, I wish I could say a few hours. But I'm thinking about how long it took me, and it was probably more in line with 100 hours


That could be that the tools are rough around the edges, I mean, most tooling is maintained by one person on their free time. It could be there that things could be made more intuitive and better UX and all, which would reduce that time a lot.

Alper Cugun20:12:17

I may not be around for a 100 hours. I’m learning and evaluating.

Alper Cugun20:12:46

Yeah, I’m getting the niche language experience very heavily now that I’m trying FP.


But also, part of it is building the knowledge of how the read/eval cycle works in Clojure and how evaluation is handled


Ya, Clojure will always feel a bit like that. I tell people its that same feeling you get from using Linux


Like, everything is nice and simple, but there's no one adding the polish that say OSX has


And I think that's a reason why it isn't super beginner friendly, and why its mostly used by very senior devs

Alper Cugun20:12:28

I am a very senior dev.

Alper Cugun20:12:39

I also am very sensitive to developer experience.


I meant senior like prior experience with Lisps and JVM


Like if your an Emacs user for 30 years

Alper Cugun20:12:56

I mean I’ve done a LISP tutorial at some point but this seems to be the only current one left?


The Clojure tooling and repl would be super natural

Alper Cugun20:12:09

And I got as far away as I could of the JVM after university.


Ya. That for sure means there's more to learn


I know people who tried Clojure years ago for a bit. Stopped. Tried it again a few years after. Stopped. And now trying it again the 3rd is when it finally start to click


I think the best dev experience would be to use Cursive in IntelliJ


You should try it. It is free for non commercial use I believe.


And I do recommend getting familiar with the repl driven workflow as soon as possible

Alper Cugun20:12:03

That’s nice. I try not to touch IntelliJ and write everything I do in Code.


Ya, I'm not a fan of intellij either, too bloated. I use Emacs, but In wouldn't recommend that to someone starting out


But it does have the most out of the box just works Clojure experience I believe and is unbeatable for java

Alper Cugun20:12:20

I’m getting familiar with it, but it’s a bit hard to figure out what “REPL driven” means. The main difference is that I can set it up so that it cleanly reimports the file that I’m working on and does not leave all kinds of garbage there as well?

Alper Cugun20:12:52

This seems to work well right now, just holy shortcuts…


Well, so. Repl driven is that you basically start a blank Clojure program (with the libraries you expect to make use of setup on your classpath). And from that blank slate, you inject at runtime additional functionality to piece together a full program


Now you have to understand that Clojure is not file based. So the source files arn't known to Clojure. They're just where you put code and save it to retrieve it later.

Alper Cugun20:12:46

And what’s the source code file for then?

Alper Cugun20:12:22

This sounds like really weird situation, weirder even than the entire GOPATH thing.


yes, the weird thing is that in Clojure parsing and compilation is a runtime event

Alper Cugun20:12:09

But what does “load current file” mean then?


In your IDE, that means the editor will copy the code in the editor file and send it to the REPL

Alper Cugun20:12:55

And that will hopefully overwrite any old garbage that was there with the same names?


It will overwrite things with the same name yes

Alper Cugun20:12:30

But don’t people program collaboratively and distribute code?

Alper Cugun20:12:38

Like run programs?


With one or two caveats due to the underlying JVM, but those are rare and you are probably not using things that have those quite yet


What it won't do is unload what has already been sent to the REPL


For example

Alper Cugun20:12:13

And for that you would occasionally clear the REPL I guess?


(def a 10)
(println a)
Now load into repl it will print 10. Now delete (def a 10) from your file and load it again, it will still print 10. Because the repl still has a, even though you deleted it from your file it does not get deleted from the REPL


Yes. And I was told calva has a function for that should be called refresh


Not sure of the shortcut

Alper Cugun20:12:58

OK. But in short it comes down to that this is more of a lifestyle than a tool?


But refresh will delete everything from the repl and load it a fresh


Eh, I guess that's one way to put it. It is a different approach to programming entirely

Alper Cugun20:12:23

I mean to be fully productive I’ll have to inhabit this stuff, go deep on a bunch more tools than I would like and memorize a bunch of shortcuts.


Think of the difference between a classical music composer write music on sheets of paper. Where as a rock band would jam along and write down things after once what they have is good


Yea, pretty much


That's why it has a steep learning curve

Alper Cugun20:12:29

But people use source files for projects and collaboration though?

Alper Cugun20:12:40

But maybe I’ll just finish the book first.

Alper Cugun20:12:48

And my day3 of the Advent of Code.


And you either hate it or love it. I find it pure fun and a joy, and so I enjoy that way of programming a lot more. That's why I put in the effort to learn

Alper Cugun20:12:26

I’m considering this because I find Haskell to be offputting.


Ya, you use source files and git


Its more the way it comes together is different


Clojure has features to load code from a file, as convenience, because that's the most common way to do it


But its more of a convention based approach


For example, lein requires clojure.set for you automatically when launching the repl.

Alper Cugun20:12:34

And I hate type systems in general. It looks like Clojure doesn’t really have one?


Why? Because sometimes you just want to open the repl, mess around and not have to type a require for something so common


But if you start the program without lein repl, that won't be there. That's what I mean by there's conventions around.


It is a dynamic language, without a static type system. Though there is a a unofficial library called core.typed that adds optional typing, but it isn't very popular


But it is still a compiled language. Unlike python, ruby and JS. That last part is a bit confusing, but for the most part you can ignore it as an implementation detail


When you do lein run... What happens is a blank Clojure program is launched, your project.clj dependencies are added to the classpath, and your main namespace is loaded

Alper Cugun20:12:52

I still haven’t read these parts of the book yet. I read half of it and thought I could with a bit of violence slam myself through the #adventofcode assignment.


That means every top level form is read, compiled, loaded and evaled one by one from top to bottom in your main namespace


But... As it encounters calls to 'require' it will pause and go load that namespace (the one defined by require) first. This happend recursively until everything is loaded in dependency (or required) order, where each namespace is evaluated from top to bottom

thanks 4
Alper Cugun20:12:37

I think what’s nice about this is that it is off-putting enough to other programmers. My main is Python but that is so mainstream by now…


And what you should understand is that's just a convention. You could write a different launcher and a require-weird function that loads things on a different order.


And at the REPL, you choose the order by choosing what to send to repl and when to send it


Ya, so.. For example, most Clojure devs find jupyter notebook a bit dumb

Alper Cugun20:12:23

I don’t get it either.


Because its just a more restrictive form of REPL. Where as Calva is like a more powerful jupyter notebook


Where you get a full VSCode to edit the code and run it at the same time, and you can split the code accross multiple files, etc.


Anyways. I recognize there's a lot to learn here.


Thats another thing. Things in Clojure are well thought out. There's almost always a great reason why everything is as it is, even if it could be non obvious. But Clojure is super powerful!!


Its the opposite of Python's one and only one way

Alper Cugun20:12:24

Yeah, I hate that a bit especially in the tooling space.


Clojure has all the features of all of the other languages combined (almost)


Ya, it can be easy to lose yourself. At the same time, it means you can learn about and get exposed to a lot as well


And the thing is, they're all pretty good. Like, people are always looking for what's the best X. Generally in Clojure all options are good, and just have different tradeoffs.


For example, Boot, Lein, tools.deps are all good package manager!


And people use each one successfully and happily


But its not very beginner friendly. If someone asks which one to learn, its like... Any of them will be good enough


Even for editors. Calva, Chlorine, Cursive, Cider, clojure-lsp, spiral, vim-fireplace, vim-iced, etc. They all have pros/cons


Anyways 😛, I could go on and on... (I really like Clojure haha).


I hope you end up enjoying it as well.

Alper Cugun21:12:08

Haha. Let’s see how it goes.

Alper Cugun21:12:20

It’s easier to get into than Haskell or Rust, that’s for sure.


Ah! Well that's a start

Alper Cugun21:12:58

And weirdly enough a bunch of people I know already seem to have made this jump.

charlie engelhard21:12:15

I'm also new to REPL development and I'm kind of confused. I'm in Cursive/IntelliJ and although it starts in my core namespace, the REPL doesn't automatically run my code by default. I have to copy-paste in all my def's and defn's into the REPL. Is that the intended workflow? Or is there some option I have to set?


Well, I quite like Rust as well. My second favourite language after Clojure 😉


@US1243555 That's not the intended workflow no

Alper Cugun21:12:14

There should be a command that does the copy pasting for you?


If you right click anywhere inside the file there should be a Closure Repl menu, and inside you should see Send to repl and Load file with the shortcut displayed

charlie engelhard21:12:29

oh i see it! thanks!


Ya. So Load file in repl is the same as copy pasting the whole file to the repl


And Sync files in REPL will load all out-of-date files from the editor to the REPL in the correct order


I think based on the project setting, so starting from the specified main namespace


And definitely learn to use: "Run form before cursor"


Learn that shortcut and use it like every 30 seconds


Normally I use Load file from repl and Run form before cursor the most


And I almost never type in the repl itself


When I change a function, add a function or add a def I do Load file from repl after


Or if I changed many files I do Sync


And then to test my code I write code to call my functions or test things directly in the file, sometimes prefixed with a #_ or inside a (comment) and run it with Run form before cursor


I call that REPL only code, and that's why it is commented out. So it doesn't run on load, but the editors are smart enough to send the code inside the comment to the repl when doing Run form before cursor

charlie engelhard21:12:48

very cool. I see it can also run tests.


Ya. Oh also using Switch repl ns is useful


Because when you Run form before cursor, it runs it inside namespace the repl is currently in


Not the namespace of the file you are in


most often you'll want to switch the repl to the ns your are in before, so that shortcut is useful as well


any idea on how to make SMS / 2FA ?


@sova I remember seeing this recently:

😲 4

Stumbled upon this error: Can't embed object in code, maybe print-dup not defined. What does it mean? It goes away when I split reify into defrecord and instantiation.


It likely means you have a bad macro somewhere usually

👍 4

Expanding into some weird object the compiler can't handle instead of into code that produces that object when run

Ihor Horobets10:12:22

Hello How to disable this folding in Cursive?


I do not know the answer, but wanted to point out that there is a #cursive channel that might be more likely to find someone who knows.

Vasilii Avdiuhskin10:12:18

Hi everyone! Had a small tool at work for querying different data-sources on staging environment and recently ported it to next-jdbc ( Since it's the very first time I tried to use next.jdbc, deps.edn and used macro, would really like to hear your feedback before getting any further with development. Also had a bit more specific question: is there an efficient way to feed IReducibleInc returned by next-jdbc into write-csv from The latter works ok with lazy-sequences and previously I used java.jdbc and {:result-set-fn ...} which worked quite well even on large datasets returned by Presto engine in my case.


Good morning! Is there an alternative for enfocus? There haven't been any commits in a while, and there has been an open issue for a long time. I am trying to follow the exercises in Living Clojure but get errors in the cheshire cat example that uses enfocus.

Bobbi Towers15:12:45

Selmer is really nice for HTML templating

🎯 4
Alper Cugun20:12:02

So in Calva do I have to have three windows open all the time? Code + REPL + Calva output?

Alper Cugun20:12:22

(I got the more popular clojure integration before which seems to have been a mistake?)

Alper Cugun20:12:18

Is there a way to make the Calva REPL word wrap? I couldn’t find a setting for this.


> So in Calva do I have to have three windows open all the time? Code + REPL + Calva output? I most often have only the editor open. Calva shows the result of your evaluation inline and also has a richer display of the results in the the hover of the evaluated text, from where you also can copy the results.


> Is there a way to make the Calva REPL word wrap? I couldn’t find a setting for this. There is no setting. I welcome a feature request about it. It makes sense that it would follow whatever setting you have in the editor, me thinks.

👍 4
Alper Cugun20:12:17

This is what I see now wrt to the wrap in the REPL. Things are getting cramped.


I would keep the REPL window closed and evaluate things inline in the editor instead.

Alper Cugun20:12:36

Evaluate does not execute functions? I just ran it on my -main.

Alper Cugun20:12:53

What is this saying to me other than that there is no syntax error in this def?


Yeah. Sorry. I’m assuming too much. What I do instead of evaluating in the REPL window, is that I put the things I want to evaluate inside a (comment…) form, often at the bottom of the file, but also often just below the the function I want to test. Calva has a command that evaluates the top level form inline, and the command treats comment forms as creating a new top level. You can see it in action here:


I’m heading for bed. Please feel welcome to ask for help in #calva-dev. Hopefully others can step in while I catch up on lost sleep. 😃

Alper Cugun20:12:57

No thank you! I fixed the bug in my code and can at a basic level work with this.


Glad you have progress! The offer still stands if you run into more questions.

Alper Cugun13:12:47

Let’s say I’m overjoyed that I do not have to learn Emacs to get into this. 😅

calva 4
Dave Madden20:12:27

I'm also trying to work through the Clojure for the Brave and True tutorial, but having a hard time getting the Emacs REPL even up and running. I get this error: "Symbol’s function definition is void: sesman-current-sessions" I found multiple answers to this on Stack Overflow and Reddit, but none of the answers work for me. I've tried this: but haven't gotten any results. I'm just getting back into coding after 15 years away, so it's 100% possible I'm making some really silly error here. But I'm following the tutorial word-for-word and failing. Any help would be massively appreciated. I'm thinking I should ditch Emacs for the time being and just use something simpler/more intuitive?


if you want to keep up with emacs i can help you but it might be better to go with vs code and Calva

Dave Madden22:12:01

@U11BV7MTK is that because of the learning curve? If so, I'll definitely opt for something simpler. Clojure Twitter recommended Cursive + IntelliJ.


I think clojure community is largely 50% CIDER 50% cursive. You’ll be well served by cursive

Dave Madden23:12:48

thanks. much appreciated.


is there "clojerl" related channel on this slack ?

Alper Cugun21:12:44

Is there a beginner friendly way to profile a bit of code?


The most beginner friendly is just to use time


But its the most limited in features too

Alper Cugun21:12:48

Tufte seems to require sprinkling (p) everywhere. I just want all calls from a call and their durations profiled.


I actually have that one always in my REPL ready to go

Alper Cugun22:12:50

Thanks, that paid off. I know where the time is going, but not why yet.

Eric Ihli21:12:14

What would I search for to figure out how ClojureScript finds dependencies? I want to troubleshoot the behavior of a dependency. My plan was to clone the git repo and point my project to use the local version. Searching for things like "shadow-cljs classpath lookup" and '"clojurescript" dependency lookup' and I haven't found a link to a description.

Eric Ihli21:12:01

Ah I think this is what I'm looking for. It's probably specific to the build tool (at least at the level I'm caring about). So it just defers to NPM for looking up dependencies.


Ya its specific to the build tool you use


Hello, I have a question regarding regex. I'm trying to convert a python program in which I'm using a regex with named capture group (eg. "(?P<Y>[a-z]).(?P=Y)" to capture things like "aXa" or "a0a" inside a string) but apparently there is no named capture group with Clojure/Java. I had a look at javadoc for regex that confirms it does not exists. Any idea how I can achieve this ?


You can use numbered capture groups with Java regexes. They don't have names. They are numbered by the order that their left parens appear in the regex, if I recall correctly.