This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-18
Channels
- # adventofcode (326)
- # aws (1)
- # beginners (67)
- # cider (52)
- # cljs-dev (5)
- # cljsrn (5)
- # clojure (104)
- # clojure-art (2)
- # clojure-austin (34)
- # clojure-france (12)
- # clojure-greece (38)
- # clojure-india (2)
- # clojure-italy (6)
- # clojure-spec (11)
- # clojure-uk (32)
- # clojurescript (51)
- # core-async (5)
- # cursive (11)
- # data-science (5)
- # datascript (3)
- # datomic (3)
- # defnpodcast (7)
- # fulcro (26)
- # graphql (10)
- # hoplon (1)
- # instaparse (2)
- # jobs (1)
- # klipse (3)
- # lumo (13)
- # off-topic (50)
- # om (2)
- # onyx (19)
- # parinfer (1)
- # pedestal (4)
- # re-frame (18)
- # ring-swagger (1)
- # spacemacs (1)
- # specter (42)
- # sql (9)
- # uncomplicate (18)
- # unrepl (13)
`(#(reverse (apply vector %&)) :a :b :c)` is there a way to rewrite the function? (the part before the :a 😛 :c)
(comp reverse vector)
(defmacro def-alias [lst]
`(do ~(for [[k v] lst] `(def ~k ~v))))
(macroexpand-1
'(def-alias [[rev reverse] [ki keep-indexed] [pi persistent!] [ti transient] [gi get-in]]))
(comment
(do
((def rev reverse)
(def ki keep-indexed)
(def pi persistent!)
(def ti transient)
(def gi get-in))))
what am I doing wrong in this macro?Did you guys checked https://github.com/EntilZha/PyFunctional ? I'm wondering if I could create a similar project with clojurescript.
Hi, I use
(defn gen-handler
[k]
(eval
`(defn ^::blocking ~(symbol (str (name k) "-handler"))
[state#]
(try
(handlers/do-handler state#)
initial-state
(finally (run *agent*))))))
to define function at runtime, but it appears the new xxx-handler
function was defined at clojure.core
namespace, not the namespace which gen-handler
was called or defined. How to define a function at runtime at the current namespace? Thanks!Because *ns*
is a dynamic var, the “current namespace” is not the one in which the function was defined, it’s the one in which the code is running. If the defn needs to happen in a specific namespace, use in-ns
to make sure that’s the context. You can also use intern
which explicitly takes a namespace as an argument.
Clojure 1.9.0
(ins)user=> (create-ns 'foo.bar)
#object[clojure.lang.Namespace 0x5443d039 "foo.bar"]
(ins)user=> foo.bar/baz
CompilerException java.lang.RuntimeException: No such var: foo.bar/baz, compiling:(NO_SOURCE_PATH:0:0)
(ins)user=> (intern 'foo.bar 'baz "hello")
#'foo.bar/baz
(ins)user=> foo.bar/baz
"hello"
(def □ 20 )
□
(comment
20)
so it clearly works
however, according to https://clojure.org/reference/reader#_symbols is this guaranteed to work? in particular, it states:
Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, ', and ? (other characters may be allowed eventually).
and I do not know how unicode is defined wrt to alphanumericat every thread the agent
runs in, I use (gen-handler k)
to generate a handler to do a specific job.
this handler is generated using the keyword k
so I can later using keyword k
to get the function's name and call this function.
do you have a specific reason to define top-level function with defn ? It might be more appropriate to create anonymous function with lambda
like in this case, where I define two handler functions
(defn pipe "Create a parallel pipeline."
[xf in out err]
(let [n ncpu
close? true
to (async/chan n)
from (-> in line-seq async/to-chan)
ln-handler (fn [x] (writeln out x))
ex-handler (fn [x] (writeln err x))]
(async/go-loop []
(when-let [ln (async/<! to)] (ln-handler ln) (recur)))
(async/pipeline-blocking n to xf from close? ex-handler)))
@qqq Not sure what you mean by "is it guaranteed to work"? Do you mean, will it ever change in a future version of Clojure? It is unlikely that it will change, as the Clojure core team likes to maintain backwards compatibility, but I don't think they or anyone else can make you some kind of binding promise about it.
I believe the Eclipse Public License is pretty much a guarantee that you can use all versions of Clojure released under that as long as you want to, but that may not be what you are asking about.
@andy.fingerhut: re "unicode in clojure", my current understanding is: 1. unicode var names works in 1.9.0 2. unicode var names is NOT promised to work according to clojure docs 3. I'm curious whether I can rely on unicode var names working in the future
Is there a way in Pedestal
to automatically reject http requests that is not accepted by the application depending on `Content-type´? I tried the above code but I think I didn’t undestand what pedestal does
(ns job-queue.service
(:require [io.pedestal.http :as http]
[io.pedestal.http.route.definition :refer [defroutes]]
[io.pedestal.http.body-params :as body-params]
[ring.util.response :as ring-resp]
[io.pedestal.http.content-negotiation :as conneg]
[io.pedestal.http.route :as route]
[job-queue.api.agent-api :refer [add-agent]]
[job-queue.api.job-api :refer [get-jobs]]))
(def supported-types ["application/json"])
(def content-neg-intc (conneg/negotiate-content supported-types))
(defn home-page
[request]
(ring-resp/response {:message "pong"}))
(defroutes routes
[[["/" {:get home-page}
^:interceptors [(body-params/body-params) http/json-body]
;;agent api
["/v1/agents" ^:interceptors [content-neg-intc] {:post add-agent}]
(def service {:env :prod
::http/routes routes
::http/resource-path "/public"
::http/type :jetty
::http/port 8080
::http/container-options {:h2c? true
:h2? false
:ssl? false}})
and my add-agent
always return HTTP 200
`
(defn get-jobs
[r]
{:status 200
:headers {"content-type" "application/json;charset=utf-8"}})
Anyone know of any library wrapping an external queue (rabbitmq, Kafka, etc) as clojure.async channels?
@luchini I’ve done it several times, but getting the semantics right can be tricky
Esp once alt! gets involved
Be wary of claiming to have processed a message that you have merely dumped into a channel
Kafka is probably the easiest since it’s immutable
@tbaldridge any open source library that already does it or did you implement it yourself?
@luchini funny just opened the slack now as i was just doing some coding on this. Spent few hrs today reading through the code, but in terms of alt i still cant figure out how the handler fn callback on take! is NOT called (or is kinda rolled back) for the channels that do not end up first (in the race condition). I have done this kinda implementation few times in past, but alt i always coded myself because of this. I originally thought the mutex between channels is shared, but it does not seem so; the alt-flag locking also does not seem to do the job.... @tbaldridge if there is no available library but you still could point me to the right namespace and line of code that addresses this that would be very much appreciated ... i should be (edit: hopefully) able to figure out the rest....
@miro I would recommend thinking about the relationship between the queue and the channels. What do you want to happen if a message is 3 channels deep into your app and the service dies?
What I recommend is instead passing an ack funtion with the message, and then the last thread In your channel chain calls that to tell the queue that the message ha been processed
In short, it’s a mistake to ack the message when it goes onto a channel. Queues are durable, channels are not.
@tbaldridge yes, acking i do once the message is processed, keep that as a function of a message or a session. But what i struggle with is how to leverage existing implementation of alt!!.. I always implemented that myself (usually multiple threads polling/waiting on queues with a use of locking and nacking messages that arrived second) because i couldnt figure out how the take! callback would have to look like so as it would work with the core async alt implementation. So my question is what method in clojure.core.async.impl.protocols.Handler is in charge of the "rollback" in case the alt's take! from a channel finishes second?
That’s the problem I think you can avoid. Just keep messages as data and use the default implementations of alt!
Don’t try to do ack as part of an alt!
Not only is it hard to implement, I’m not sure it’s possible to do correctly with a mutable queue.
hey folks, I want to create a series of videos in order to tech clojure in my local language to those who are interested.
or do you know a good presentation or a course in English which i get inspiration from ?
@lxsameer https://www.braveclojure.com/clojure-for-the-brave-and-true/ Might want to check out #beginners and ask around there too
datomic vs postgres for a simple-ish ecommerce site, what are your opinions? I like the temporal nature of datomic, in that if I update facts older transactions remain valid. Vs changing things in a regular rdbms where it can also change prior transactions if not done right. Also the datalog integration with clojure is really nice. But $5000/yr/system ;(
sql through clojure doesn’t seem great, but maybe I’m missing a critical library that helps out a bit (Is HugSQL any good?)
@jgh HugSQL is great! I’ve been incorporating it into my projects more often lately and I love it! I’m a fan of free so I usually go Postgres but that’s just me
is using sut
as name of the system under test when creating test namespaces a bad practice?
that's what cider does by default when creating a new test file, but could not really see anywhere if it's a good practice or not
I do not prefer it, I end up changing it to whatever the pattern is for that ns in the rest of the program
e.g. myapp.thing :as sut
-> myapp.thing :as thing
so I can more easily grep for usages of thing/foo
and other reasons
yeah I also prefer not to use it for that reason
cool, thanks for the suggestion. I’ll be doing most stuff in stored procs (if I go with postgres) but this looks like a great option for executing those.
er well i guess postgres is a bit different from the last time i did a sql database lol, i see they dont really do stored procs. So nevermind that then!
hello everyone, im trying to generate a fat jar of a main application (its not a webserver it just starts some jobs and then dies), but i keep getting errors
lein with-profile dev uberjar
produces:
java.lang.IllegalArgumentException: env variable ‘:db-host’ is not set, compiling:(cfg.clj:17:1)
I have a profiles.clj populated with the right env variables, it does work while working inside the repl
;; foo.cljc
(ns foo (:require [clojure.spec.alpha :as s]))
(defmacro tm [& lst] `(s/def ~@lst))
;; bar.cljc
(ns bar (:require [foo])) ;; notice, we don't alias spec.alpha
(macroexpand-1 '(foo/tm 1 2 3)) ==> (clojure.spec.alpha/def 1 2 3)
so it appears the s/def
is being expanded at DEF MACRO time, not at USE MACRO time. I find this counter intuitive. Can someone explain the machanics by which this is happening ?
[ I was expecintg an error saying there is no such namespace in ns bar ]In order to avoid capturing and re-using some symbol in bar
, ordinary symbols are expanded before you leave foo
. You would need
(defmacro tm2 [& lst] `(~'s/def ~@lst))
to quote the use of s/def
to carry that over and pick up whatever that meant in the environment you are expanding in (here, bar
)oh, except the time of expansion is not your issue here. like lukswater said you're just expecting ` to work differently to how it does
@luskwater: I see the
`(~'s/def
trick now, thanks!I'm sure there is, but it's the type of dry stuff that I don't expect to understand until I run into issues of "I expect FOO, but I got BAR"
I believe this is it: https://8thlight.com/blog/colin-jones/2012/05/22/quoting-without-confusion.html
@dnolen: Great Codemesh talk - I'm loving all of your recent Datomic outreach efforts.
Here's a link to the talk for anyone interested: https://www.youtube.com/watch?v=nbMMywfBXic
the first example has a one item collection and the second has two items
the first example will never use the function to combine elements
because there is only one element
whereas the second example will
I understand that boot/lein uses JVM. I understand that Macro system uses JVM. Right now, in Clojure dev, I use cider to talk to a JVM repl -- is there anyway to make it practical to talk to a node.js repl instead ?
CIDER is basically nREPL middleware so it's JVM only. Can you explain what you think you want to connect to a Node.js REPL?
Socket repls are completely possible.
lumo and planck both support socket repls. As does the CLR.
@U04V70XH6: my current setup is client side = cljs; server side = clj via jvm ;; I am considering changing server side to cljs via nodejs
@tbaldridge: are those meant as dev environments, or a way to write shell scripts in cljs ?
@qqq I think you'll be in relatively uncharted territory. Have you asked folks in #clojurescript ?
For Expectations, which -- notionally -- supports ClojureScript as well as Clojure, the cljs tests are run using a cljs REPL but it's bootstrapped from a Clojure REPL (on the JVM).
Both, planck runs on JS core (self hosted) so you're a bit limited, but lumo runs on Node.JS and can use node modules
not really sure what you mean by "used as a dev env" though
a REPL is a dev environment
and you can use planck and lumo with inf-clojure
so emacs can work with them similar to CIDER but without the huge jvm deps
Good to know! Just installed npm on my Windows 10 WSL Ubuntu bash and then installed Lumo via npm and, sure enough, I can start a Socket Server REPL and connect to it from telnet or similar... Not sure whether that helps @qqq (and I see Lumo advertises its cljs compilation as experimental) but it's impressive.
And it looks like Lumo's cljs compilation is a lot more solid now (just reading the mid-September blog post about it).