Fork me on GitHub

Regression tests, would be hard to build any complex system without it


docs won't do anything about that type of problem


But in Clojure, I do not write tests to know code works, only tests to make sure public behaviour is never altered after release


And fuzz/generative tests, as a form of deep bug finding exercise


I've also found, component or mount, and the word state is confusing. State can be stored in a global Var/Atom/Ref or passed around from fn to fn. You only need component of mount if you're state needs to be initialized and cleaned up. So if a namespace needs a DB connection, expecting it to be connected already, with mount, you'd put a dependency on that "state", and mount will know to initialize it before giving it to you. But if by state, you mean just like running app state, like say I keep track of users created in a global Atom, the only need for mount/component, is to maybe clear the atom on reload, if I ever want too. But the value proposition is much less in this case.


Hello guys, is there a way how to reference other project files in project.clj? Say I have DB configuration in src/config/db_config.clj and I want to pass it to some lein plugin configuration. Thx for help 🙂


@petr.mensik You can use ~ in project.clj to cause evaluation of forms, so you could read the db_config.clj file that way... but I'm not sure I'd recommend that. You could join #leiningen and ask for more approaches there. We switched to #boot and found that much easier to use as a build tool for anything even vaguely complicated.


Trying boot at the moment and it’s “freaking awesome”


The point is, obviously, to follow DRY principle and don't repeat the same configuration on multiple places 😕 But I can ask there, thanks


We have our config in EDN files. Our Boot script contains tasks that build Components and start them and then run functions. Those Components depend on our Configuration Component, which reads the EDN files. Our applications also use Components. So our config is DRY and both Boot and our application leverage (some of the same) Components, ensuring they are DRY too.


(that's much harder to achieve with Leiningen and plugins, than with Boot and tasks)


@U04V70XH6 on a bit of a sidenote, you mention #boot being much easier to use for “anything vaguely complicated”. I am new to Clojure and initially jumped on the Lein ship but recently switched to boot and I found it simpler to wrap my head around. Maybe I am missing something about lein and/or didn’t read the doc properly, but overall, even for simple projects and as a beginner, boot made more sense to me


Yeah, I think I would probably recommend boot to everyone starting Clojure these days, with the caveat that nearly all the examples you find in books and online still use lein...


...which means you kinda need to know how to convert project.clj to build.boot.


Not that it's hard per se, but it's yet another hurdle to picking up Clojure.


@U04V70XH6 Is it really a hurdle though? It seems to me that you can pick up boot very incrementally. The ability to declare dependencies at the top of a Clojure file seems brilliant for a beginner. You can incrementally teach the bascs of clojure, then tell them to add a few lines at the top of a file to pull a dependency, and later tell them to move that part to a build.boot and drop their code in a src/ folder


True... and the other thing is that you can run a new app project's main without even needing build.boot:

lein new app foo
cd foo
boot -r src -r resources call -f foo.core/-main
=> Hello, World! and then to run the tests:
boot -r src -r resources -s test -d adzerk/boot-test test


(and you don't even need -r resources for the simple case)


@U04V70XH6 oh, that’s pretty neat 😮 One thing I found out about while learning boot (which might be doable with lein, I’ve no idea) was the ability to pull dependencies in the command line. e.g. boot -d some-dep:1.0.0 repl


really useful too


exactly what you did above actually


Can I use functions created with defn as helper functions to craft forms for defmacros. Say I have a list of symbols that I want to have a specific set of symbols output will it work in a reduce function or does it have to be a defmacro helper.


macros can call functions (or other functions) freely


just remember that the macro doesn’t see the actual data passed in at runtime, it only sees the form from the source code


as long as your function can do something useful with that, you are good to go


also, it’s good to distinguish a macro calling a function from a macro emitting a call to a function


right, that's still an exercise to wrap my head around.


I've got most of it but the macro is getting large and hard to follow, so didn't know how I should split it up


the thing that helped me most was focusing on the fact that a macro takes source code (in the form of symbols, lists etc, not a string) and returns the new source code to use in its place


The end part I can wrap my head around, emit symbols and it evaluates after macroexpansion. Actually crafting it is the hard part for me


as a beginner, one way to do that is often to make a function that just takes a form and returns a form (and break that down into more functions as needed) no macro definitions needed at any point there, and finally wrap a call to this function in a macro


breaking it up by writing functions that take code-data and return code-data to the macro is a good approach


@noisesmith that is definitely what I should have done, working to piece the whole is already taxing.


helps with repl testing too as you don't need to macroexpand all the time


switching to that approach is easy though


you can pretty much just take your defmacro, change it to defn, give it a new name, and now pass it quoted args as needed


Also how do I solve this issue. I'm appending to a form that needs to end up as

(do (ns some-ns) (print (escaped-form) ~(escaped-form))
so I first create a `[do] vector and am conj to that since it's append last. Then I convert it to a list and return that from a macro


first off, there’s no vectors there


that first one is after the conversion


oh sorry, now I get it


usually people use ~@ for that


(defmacro repl-step-do
  [time & forms]
   (fn [print-exprs [title & rest-forms]]
     (let [namespace (.toLowerCase (clojure.string/replace title " " "_"))
           form-exprs (conj (for [expr rest-forms]
                              ('print expr))
       (-> print-exprs
           (conj `(ns ~(symbol namespace)))
           (conj form-exprs))))


;;;; Example
   '("Basic Operators"
     (+ 1 1)
     (+ 2 2))

   '("Some Other Stuff"
     (def a 12)
     (str "This number is a " a ".")))

;;;; Output
;;; * Basic Operators
;;;   (ns basic-operators)
;;;   (+ 1 1) => 2
;;;   (+ 2 2) => 4

;;; * "Some Other Stuff"
;;;   (ns some-other-stuf)
;;;   (def a 12) =>#'basic-operators/a
;;;   (str "This number is a " a ".") => "This number is a 12"


so the ~@ version would be ````(do ~@(for [expr rest-forms] `(print ~expr)))```


I'm basically just creating a "slideshow" for repl blocks to easily run through an example for reference


I'm struggling with something really simple, hopefully you guys don't mind being asked a dumb question. I need to generate a game board, let's say a chess board, so I'm trying to create nested vectors like this: [[1 2 3 4][5 6 7 8][9 10 11 12][13 14 15 16]] I can't figure out how to generate something like that in a functional way


play with partition and range


(yeah, what @dpsutton said ^^ -- beat me to it!)


that should be enough to get you going. let us know if you run into anything or get stumped


also be mindful of your types (vector versus lazy lists) if that's important for you


Hint: you can get from a list of lists to a vector of vectors with (mapv vec ...)


That was super easy, thanks. Follow up question, say I didn't want those vectors to be contain numbers but something else (say a map at each location), still with the same structure of vectors though. Is range still the way to go? For example, this is what I have right now:


I don't need those id's in the map, that was just how I created the maps. I'm trying to create the 16 maps in that configuration and put some other stuff in there


That solves it, thanks


@noisesmith how do you use clojurebot?


you don’t need the into calls if lists are OK


@hmaurer /clj (maybe buggy)


it barfs on strings for example