Fork me on GitHub
#beginners
<
2021-11-29
>
kevinc05:11:37

I'm a beginner who's getting familiar with Clojure through the language site, YouTube talks, and koans. I'd like to read the source of a project next. Can someone please make a recommendation?

lsenjov06:11:10

(Polylith is its own thing for dealing with monoliths, so don’t worry too much about that)

lsenjov06:11:25

I link these mainly because if you don’t understand what’s going on, you can look at the equivalent in the language of your choice

seancorfield06:11:51

https://github.com/seancorfield/usermanager-example/ is probably a good place to start if you're interested in building a simple web app with a database behind it.

seancorfield06:11:13

(that links to variants of that app using different libraries and different approaches)

adi07:11:31

I'm going to go the other way from applications. IMHO, single-purpose libraries are good places to start. Personally, I struggled a lot understanding how to apply concepts, when reading application code, until it occurred to me to read library code instead. Library code tends to be complete and small, and is focused on a single well-defined problem, so all complexity is related to one domain only, and not to combination of domains, which is why I struggled with application code. Another reason is there is no one standard way to assemble applications, because people choose different libraries for different technical and design tradeoffs, which are completely not obvious when one is just starting off. Here are my favourites. • I'd say give no more than a day or two to each. • In a standalone project, play with the APIs. Drill down from outer layers to inner layers and back up and sideways to build a sense of how things could fit together. • Allow the sources to throw "oh, I see", "wait, but why?", and "zomg" moments at you to bookmark for later. Ring, to understand one of the most popular HTTP server abstractions in the Clojureverse: https://github.com/ring-clojure/ring Hiccup to understand a natural translation of one domain (HTML) to Clojure data. Writing HTML as Clojure data is what we mean when we say "well, it's just data" or "data DSL": https://github.com/weavejester/hiccup Clojure.test which is the built-in testing framework, in a surprisingly small amount of code. Also, incidentally, to feel OK diving into Clojure's own source code: https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj I also use clojure.repl/source a lot, at the REPL, to pull up source code for functions that are new to me. After that, you may like to look at more advanced code like https://github.com/seancorfield/honeysql, or web applications, or https://github.com/orgs/cmr-exchange/repositories?q=&amp;type=&amp;language=clojure&amp;sort= project just to have one's mind blown 😁

1
👍 2
2
👀 1
thom08:11:14

Jepsen is one of the most impressive Clojure codebases, it's a framework for verifying databases and distributed systems. It solves a hard problem so is big, algorithmically complex, and touches lots of external software. But it's very well documented and tested and touches every nook and cranny of Clojure. It's a lot, especially for a beginner, but definitely worth diving in from time to time: https://github.com/jepsen-io/jepsen

1
kevinc17:11:27

Thanks, all!

2
papachan20:11:37

good references here....

zackteo08:11:37

Does anyone know how to set a different lein path in calva?

zackteo10:11:53

Managed to find the configuration needed for this. But thanks :)

sheluchin14:11:04

Is there something like select-keys that works with nested structures?

(foo {:a {:b 1}
        :c 2
        :d {:e {:f 3 :g 4}}}
       [[:a :b]
        [:d :e :f]])
  => {:a {:b 1}
      :d {:e {:f 3}}}

henrik15:11:24

I'm not aware of anything in precisely that shape, but check out https://github.com/lilactown/pyramid Your maps would be normalized (using an ID), but then you could use pull to select over the entities.

Mno15:11:33

not that I know of, but it's also very odd that you'd need to remove a key in a nested map instead of just ignoring it.

sheluchin15:11:01

@U06B8J0AJ neat! looks like it shares some ideas with https://github.com/wotbrew/relic

sheluchin15:11:53

@UGFL22X0Q Valid point. I'm aware that the Clojure convention is to just pass maps along, but I'm dealing with network requests here, which is one place the convention doesn't hold true.

Mno15:11:02

oh, yeah that's one of those cases! Maybe there's something spec can do to make it conform that I'm not aware of.

Ben Sless15:11:42

Reduce over the sequence, get-in, assoc-in?

Ben Sless15:11:55

Not terribly efficient but concise

Ed16:11:07

I think mali provides a strip-extra-keys-transformer that would let you use an inline schema to define structure you wanted to select. Maybe that would be useful?

Martin Půda16:11:54

(defn deep-select-keys [map1 keyseq]
  (reduce #(assoc-in %1 %2 (get-in map1 %2)) {} keyseq))

☝️ 2
👀 1
clojure-spin 1
pithyless16:11:24

@UPWHQK562 there's a couple of libraries that have attacked this problem. If it's a question of just a couple of maps, it's probably not worth the effort, but these are useful libraries to be aware of if you need to do a lot of declarative data transformation: 1. https://github.com/vvvvalvalval/supdate 2. https://github.com/noprompt/meander 3. https://github.com/redplanetlabs/specter

sheluchin17:11:25

Thanks all. Indeed, I only need it in a few places so a conditional will suffice. I was just wondering if there was a select-keys-in sorta thing I missed along the way.

oly16:11:01

anyone happen to know where cljs files are cached ? I am hoping to cache them in a build step using clj with figwheel to build the project

Adam Haber21:11:15

hi! I’m learning how to use calva + vscode and there’s something that I don’t understand

Adam Haber21:11:26

I’ve opened vscode in the project directory, and evaluated a file called env.cljc - now in the repl window I have clj꞉sicmutils.env꞉>, which is what I want

Adam Haber21:11:16

I now want to jump to a function definition in a different file - derivative.cljc. I go to the new definition, make some changes to the function, and want to evaluate it - but just the function, not the whole derivative.cljc file

Adam Haber21:11:57

when I’m in the function and choose “select current top level form”, I get:

Adam Haber21:11:11

which, again, is what I want

Adam Haber21:11:54

but, when I do evaluate the current top level form - alt+enter - the repl changes from clj꞉sicmutils.env꞉> to clj꞉sicmutils.calculus.derivative꞉>. Is this the desired behavior?

seancorfield21:11:09

Yes, evaluations follow the namespace you're in (so the REPL switches to that ns).

Adam Haber21:11:51

got it. so if I want to edit a function that’s in a different namespace and go back, I simply need to re-evaluated the original namespace?

Sam Ritchie21:11:10

@seancorfield is there a way to prevent this - to do the equivalent of “paste this into the repl”, or cider-eval-defun-at-point?

seancorfield22:11:36

@adamhaber I never type into the REPL so I don't pay any attention to what ns it is in. I always eval code from a file (so the REPL follows that ns but that's irrelevant to me).

seancorfield22:11:30

If you're just experimenting with code, I recommend using a

(comment
  )
form in your file and putting code inside that and evaluating it -- so you have a record of expressions you've tried and that can form the basis of tests etc.

seancorfield22:11:18

(I use Clover with VS Code -- for Socket REPLs -- and you can't type into that REPL at all: it is output-only and I like that a lot since it prevents the "typing into the REPL workflow")

seancorfield22:11:12

(Stu Halloway says he is "baffled" when he sees people typing into a REPL 🙂 )

pez22:11:12

Calva has some ”Send to REPL” commands for this.

Sam Ritchie22:11:38

Haha I don't get why Stuart is baffled…

Sam Ritchie22:11:29

But I have heard this view before. What if you want to take some expression, like a math expression you are trying to simplify, @seancorfield , and you want to maintain a history of your attempts

Sam Ritchie22:11:35

But not necessarily store them all?

Sam Ritchie22:11:08

I often work this way then pull a few choice examples into a comment block

Sam Ritchie22:11:53

(I wouldn't do that working on something like a web app where there is no interactive playfulness, I guess)

Sam Ritchie22:11:41

@jackrusher was also baffled that I do this fyi:)

😂 1
tschady22:11:26

i run (source foo) in a REPL but that’s it. do y’all pull in clojure.repl into your editing buffer somehow? Doesn’t seem worth it for my infrequent usage.

Sam Ritchie22:11:34

Cider has a key command for this; usually I would jump to source and look at it directly

seancorfield22:11:27

I have hot keys (in VS Code) to show docs, source, and a bunch of other stuff.

tschady22:11:30

cool! just found in CIDER, thanks @U017QJZ9M7W

👍 1
Sam Ritchie23:11:31

What is great about M-. @U1Z392WMQ is that you Can keep going into more functions you find

Sam Ritchie23:11:38

Then use M-, to come back up the stack

🖤 1
💯 1
Sam Ritchie22:11:12

comment block would be a weird way to use a calculator, as an example, @seancorfield … right? Or do I need my screws adjusted

hiredman22:11:43

its like using a calculator with a paper tape

Sam Ritchie22:11:25

But so Is the REPL - and it is slightly easier to summon the previous form evaluated with M-p in emacs at the REPL

hiredman22:11:26

at least for me, comment blocks, or even my scratch.clj files become lists of iterations on the same thing

phronmophobic22:11:35

I type into my REPL regularly. Doesn't seem crazy to me 🤷

phronmophobic22:11:15

I also use comment blocks. why not both?

Sam Ritchie22:11:31

I get that you would have to adjust to the comment block thing if your editor is not well integrated with a REPL. Totally agree @smith.adriane both are good

cdeszaq22:11:58

If your REPL is just a buffer where output is appended similar to as if you had typed it, there’s nothing wrong with typing into the REPL. It is just another buffer right?

cdeszaq22:11:19

But it would be for more ephemeral things I suppose

👍 1
Sam Ritchie22:11:46

Yeah and you can promote ones you want to keep to a comment block

cdeszaq22:11:12

Or copy-paste them elsewhere depending on how useful your ephemeral code was

hiredman22:11:08

or just do everything in scratch.clj to start with

seancorfield22:11:14

I will do math in a REPL, but not anything related to the actual code problem I'm working on -- that code always goes into project files. But I know some folks who use a scratch file, even for that sort of thing 🙂

Sam Ritchie22:11:48

My code problem is all math these days so I am in a weird zone

hiredman22:11:53

% wc -l ~/src/scratch.clj
20104 /home/kevin/src/scratch.clj
%

😆 1
cdeszaq22:11:58

If your REPL buffer is a scratch file, and gets saved, etc. like any other file… best of both worlds?

Sam Ritchie22:11:59

Symbolic math etc

practicalli-johnny22:11:17

All my webapp projects have interactive playfullnes, that's why I started learning Clojure. Anything you can do in a Repl buffer/window, you can do in a source file and usually have better editing tools to do it with and comments and history of evaluation. I really only use a repl buffer/window for managing longer running processes

Sam Ritchie22:11:41

Maybe it is just that emacs has awesome REPL tooling, same as normal editor

phronmophobic22:11:18

I am also an emacs user. I wonder if there's a correlation here.

phronmophobic22:11:25

I don't think there's a one size fits all. Different folks can have different workflows and that's a good thing. My workflow changes over time regardless.

❤️ 2
cdeszaq22:11:08

Perhaps Calva’s approach of having the REPL be basically another unversioned file has poisoned my mind 🙂

🤯 1