This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-01
Channels
- # babashka (2)
- # beginners (51)
- # calva (79)
- # cestmeetup (1)
- # chlorine-clover (1)
- # cider (6)
- # clj-kondo (1)
- # cljdoc (4)
- # cljsrn (2)
- # clojure (31)
- # clojure-europe (2)
- # clojurescript (5)
- # conjure (4)
- # cursive (26)
- # datascript (4)
- # datomic (1)
- # figwheel (1)
- # figwheel-main (2)
- # off-topic (25)
- # reagent (2)
- # reveal (4)
- # shadow-cljs (21)
- # xtdb (1)
Hey, everyone! I’m new here, to Clojure, and to functional programming in general. I’m trying to wrap my head around how I should approach control flow in my Ring app in my request handlers and middleware as I’m fetching things from the database. Any tip for how I can improve these examples?
I feel like I’m possibly using these control flow macros in a way that makes the intent unclear or hard to follow
You can definitely simplify wrap-auth-session
and avoid that nesting:
(if-let [user (some-> (get-in request [:cookies "sid" :value])
(get-active-session)
:user_id
(get-user-by-id))]
(handler (assoc request :user user))
(handler request))
You can remove the (do ..)
wrapper in the first function -- you only have one expression in there so it's unnecessary to wrap in do
. I don't think you can do much other simplification -- parameter access / validation in Ring handlers is always a bit verbose.
Not sure what you mean by "control flow macros" tho'...?
Thanks for the tips! I think some->
is perfect for what I was trying to achieve there. By control flow macros, I only meant things like do
, if-let
, if
, and so on. Wasn’t sure what else to call them
They're special forms, technically, but we tend to just refer to them directly by their names. See https://clojure.org/reference/special_forms When you say "macro" it has a very particular meaning in Clojure.
(and, yes, it's a little blurred that a couple of the special forms are actually implemented as macros that expand to lower-level implementations: let
in terms of let*
, fn
in terms of fn*
)
Hello! Is there a way to add dependencies to deps.edn
, get them from their repos and require them in a running clj
repl?
There’s an experimental branch with support for this but it’s not part of clj yet
also I am wondering if core.match
supports matching nested lists. for instance given ('a ('b 1 2 3))
as input I would like to bind the list (1 2 3)
to a pattern variable.
Are you looking for something like this:
user=> (match [['a ['b 1 2 3]]]
[[_ [_ & r]]] r)
[1 2 3]
user=>
Or if you really want sequential matching
user=> (let [x '(a (b 1 2 3))]
(match [x]
[([_ ([_ & r] :seq)] :seq)] r))
(1 2 3)
user=>
(I'm a bit puzzled by your ('a ('b 1 2 3))
example since that is not what you might think:
user=> ('a ('b 1 2 3))
Execution error (ArityException) at user/eval1600 (REPL:1).
Wrong number of args (3) passed to: clojure.lang.Symbol
user=>
^ @U015GL869TQ is that helpful
I want to pass an expression or a name which binds to that expression to my macro. So I'm calling the macro like (m fn-name)
and (m (fn [] ...))
instead of (m 'fn-name)
. First, is this the right way to do it or should I always quote symbols when passing them to macros?
Second, if it is the right way, then I can't figure out how to make the symbol expand in the original context (the code calling the macro) instead of macro definition context. When I try to macroexpand, it gives an error while trying to resolve the symbol in the wrong context, instead of expanding it.
macros receive lists and symbols, unevaluated
whatever the macro returns will be evaluated afterward
lists will become calls, symbols will be looked up - after the macro returns them
the only job of a macro is to take lists, symbols, etc, return a list (or rarely, just a symbol or whatever), so that the compiler can do the rest
'fn-name shows up to a macro as (quote fn-name)
because the args are not evaluated before the macro sees them
the args to the macro don't expand in the context of the macro definition, they always expand in the context of the macro call
but, the macro can't see the run time value of a symbol - it can return the symbol, and the compiler turns that into code that looks up the value at run time
this isn't a good macro, but it establishes a point:
(ins)user=> (defmacro caller-x [] 'x)
#'user/caller-x
(ins)user=> (let [x 0] (caller-x))
0
by returning the symbol x
, it causes the compiler to emit code that looks up x
Hello, is there any book or other reading material on removing state? I seem to be addicted to state like it's crack. I have written and entire app in clojure that ties 6 different apis together, but I have state all over the place. I can't seem to wrap my head around getting rid of it.
@UAB2NMK25 , on that topic, i would recommend https://youtu.be/ROor6_NGIWU
the gist is to replace state with flow between simple machines. the talk had a lot to say about how this looks in the “large” (between multiple programs and servers), but also in the “small” (within programs)
https://www.infoq.com/presentations/clojure-core-async/ is similar, but i usually don’t recommend it since clojure.core.async is usually overkill for most projects
but the principles are still useful even if you don’t use the library
Here is a simple toy I built that I ended up using as the basis of my app so you can see what I mean about addicted to state. https://github.com/michaelwhitford/clojure-swapi
Hi guys, Can someone please explain what is the difference between these two snippets?
The first quotes the vector expression, which prevents evaluating any of its contents
a vector is a form - everything the clojure repl can consume as a standalone value is a form
The second will evaluate the last expression
Evaluating a vector causes each element to be evaluated
Quote can be used to prevent evaluation of any expression. It is not very useful to do so for expressions that evaluate to their own values like numbers and keywords, but it is not illegal