This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-08
Channels
- # aws (21)
- # beginners (62)
- # boot (29)
- # chestnut (1)
- # cider (110)
- # cljs-dev (37)
- # clojure (93)
- # clojure-berlin (1)
- # clojure-dev (10)
- # clojure-greece (4)
- # clojure-italy (5)
- # clojure-new-zealand (1)
- # clojure-spec (6)
- # clojure-uk (46)
- # clojurebridge (1)
- # clojurescript (54)
- # cryogen (1)
- # cursive (22)
- # datomic (72)
- # emacs (2)
- # events (3)
- # flambo (1)
- # hoplon (88)
- # jobs (6)
- # juxt (51)
- # lein-figwheel (1)
- # leiningen (3)
- # lumo (12)
- # mount (4)
- # off-topic (3)
- # onyx (3)
- # pedestal (4)
- # portkey (27)
- # re-frame (13)
- # reagent (1)
- # ring (4)
- # rum (2)
- # uncomplicate (1)
- # unrepl (3)
But in Clojure, I do not write tests to know code works, only tests to make sure public behaviour is never altered after release
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.
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
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.
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 macrofirst 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]
(reduce
(fn [print-exprs [title & rest-forms]]
(let [namespace (.toLowerCase (clojure.string/replace title " " "_"))
form-exprs (conj (for [expr rest-forms]
('print expr))
'do)]
(-> print-exprs
(conj `(ns ~(symbol namespace)))
(conj form-exprs))))
`[do]
forms))
;;;; Example
#_(repl-step-do
500
'("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"
messy I know
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
(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
repeat!
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