This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-08-30
Channels
- # aws (2)
- # beginners (139)
- # boot (9)
- # cider (1)
- # clara (2)
- # cljs-dev (35)
- # cljsrn (3)
- # clojure (112)
- # clojure-dusseldorf (9)
- # clojure-greece (6)
- # clojure-italy (13)
- # clojure-russia (160)
- # clojure-seattle-old (1)
- # clojure-uk (79)
- # clojurescript (85)
- # clojutre (1)
- # community-development (11)
- # core-async (32)
- # cryogen (2)
- # cursive (5)
- # data-science (16)
- # datomic (2)
- # events (1)
- # fulcro (29)
- # funcool (1)
- # graphql (4)
- # immutant (5)
- # instaparse (20)
- # jobs (2)
- # juxt (6)
- # leiningen (11)
- # luminus (21)
- # lumo (1)
- # off-topic (7)
- # onyx (20)
- # parinfer (33)
- # pedestal (4)
- # re-frame (41)
- # reagent (34)
- # ring-swagger (14)
- # rum (5)
- # spacemacs (9)
- # specter (11)
- # sql (14)
- # test-check (3)
- # yada (20)
So I have this sort of statement in an let statement. Is there any better/more idomatic way to conditionally accept an object? I know of if-let
but if I understand it right it wouldn't work in this situation, since I want the img object itself, not the result of .isError
.
(let [url-img (Image. url)
img (if-not (.isError url-img)
url-img
(Image. (.toString (io/resource config/missing-image-location))))]
;;code using img (url-img is not used) here
)
just a semantic nitpick, clojure doesn’t have statements (let and if-not are expressions, they return values)
(let [url-img (Image. url)
img (if (.isError url-img)
(Image. (.toString (io/resource config/missing-image-location))))
url-img)]
;;code using img (url-img is not used) here
)
maybe?wow it’s really a challenge to get the monospace spacing right when you copy/paste into the non-monospace edit box 😬
@donyorm a small function is idiomatic here:
(defn safe-img [url]
(let [img (Image. url)]
(if-not (.isError img)
img
(Image. (.toString (io/resource config/missing-image-location))))))
(let [img (safe-img url)]
;; code using img
)
More newbie time!
I want a function that takes a map, and depending on a integer value n
in that map returns a new map with an appropriate key added.
;; If n =< 1, return {:n 1 :red}
;; If n > 1 AND n =< 2, return {:n 2 :orange}
;; If n > 2, return {:n 3 :green}
How do I construct such a function in a clojure/lispy way?sounds like a job for http://clojuredocs.org/clojure.core/cond or http://clojuredocs.org/clojure.core/cond-%3E
http://clojuredocs.org/clojure.repl/find-doc is handy for answering these types of questions
(defn cond-ret
[{:keys [n] :as in}]
(cond
(<= n 1) (assoc in :color :orange)
(and (> n 1) (<= n 2)) (assoc in :color :red)
(> n 2) (assoc in :color :green)
:else "Something wrong happened"))
(cond-ret {:n 2})
@emilaasa i can recommend Joy of Clojure, though it's quite a bit more in-depth than Brave
I usually have to bash my head against a reference style book for a while before I feel really comfortable!
I really appreciate the support here, my first few days of trying clojure has been great in no small part because of the slack and discord
question: I have list of sequences containing numbers, I want to get one resulting sequence as a sum input sequences by consequtive values
@tsulej (apply map + [[1 2 3] [1 1 1] [9 8 7]])
although this will give you a lazy-seq
I don’t know if there’s a direct way to produce a vector
there is, mapv
instead of map
hello! what's a nice way to get a collection or primitive's type as a string? using clojure.core/type
gives a function, and then I'm not sure how to get the name of that function into a human-readable string
(type []) ;; => cljs.core/PersistentVector
(str (type[])) ;; => "function (meta,cnt,shift,root,tail,__hash){\nthis.meta = meta;\nthis.cnt = cnt;\nthis.shift = shift;\nthis.root = root;\nthis.tail = tail;\nthis.__hash = __hash;\nthis.cljs$lang$protocol_mask$partition0$ = 167668511;\nthis.cljs$lang$protocol_mask$partition1$ = 8196;\n}"
if I use str
on the function returned by type
doesn't give me the kind of human-readable name I'd like to have (':
can someone show me an example where the reduction thats part of a transducer that counts the number of items?
Any chance there is a built-in function to do
[[[:a] [:c]] [[:b]]]
-> [[:a] [:c] [:b]]
apparently flatten1
works:
cljs.user=> (flatten1 [[[:a] [:c]] [[:b]]])
([:a] [:c] [:b])
@stvnmllr2found it after trying flatten
and then searching for any other functions that were similar using (find-doc "flatten")
actually there are a few options here:
https://stackoverflow.com/questions/10723451/whats-the-one-level-sequence-flattening-function-in-clojure
apply concat
seems the most popular
Thanks. I'll look into that. On windows so never got a js repl working. But lumo say it works. so will check it out.
Hi not necessarily clojure question but I’m going over web dev with clojure book (ch 7 database) - the example uses Jdbc4Array (org.postgresql.jdbc4.Jdbc4Array) but it seems that class was deprecated v42 onwards. I can’t seem to find any reference to what to use or even mention of it in changelog (https://jdbc.postgresql.org/documentation/changelog.html#version_42.0.0) Anybody know what happened to it?
https://github.com/pgjdbc/pgjdbc/issues/559
also some discussion on it here:
https://clojurians-log.clojureverse.org/luminus/2016-07-29.html
seems you can just use java.sql.Array
ah cool. I ended up using org.postgresql.jdbc.PgArray as it had similar api. it seemed to work for me. thank you! I didn’t realize I could check pgjdbc (actually, didn’t know that existed) 🙂
Where do you guys draw the line between :require and :use? What should I refer into the current namespace? Is there any rules/good practices to follow?
(:require [clj-http.client :as http]
[cheshire.core :as json]
[buddy.sign.jwt :as jwt]
[buddy.sign.jwe :as jwe]
[buddy.core.keys :as ks]
[clj-time.core :as t]
[clj-time.coerce :as convert])
I liked this blog post that had some opinions on readable clojure: http://tonsky.me/blog/readable-clojure/#dont-use-use
Thanks! I like the idea of always using qualifiers better than trying to figure out where stuff is coming from
For example, aggregate-history
might look like this:
{"1" [{:event :bar, :data {:id "1"}}
{:event :baz, :data {:payload "whatever}}]}
what that means is that you wrote:
(doseq seq ....)
instead of
(doseq [elem seq]
(do something with elem))
What's the best way to make a Clojure binary available on a package registry? Comparing with Node.js, if I want to install a CLI foo
I can just do npm i foo -g
and have it available in $PATH
right away (there's a bin
key on the manifest that can point to a JavaScript file to be compiled as a binary). What is the best practice to achieve the same result in Clojure?
@rinaldi AFAIK, there's no easy way to do this in Clojure, the best way I can think of is to put dependencies in the global lein profile like:
;; ~/.lein/profile.clj
{:user {:dependencies [[your-app "1.0.0"]]}}
then run:
lein run -m your-app.main
lein will run the -main
function inside the your-app.main
namespaceClojure is probably not the best language for writing CLI tools since it takes so long to start up...
You could do it in ClojureScript using the Lumo runtime (based on node.js) but there's no standard way to install stuff from a repo.
But I think what @rinaldi is asking about isn’t how to create a binary in say, Planck or Lumo, but rather whether there’s something akin to NPM that lets you register a Lumo binary
like imagine being able to type cljpm i -g nyancat-repl
at a prompt and pull down from Clojars someone else’s awesome Lumo binary that runs a CLJS repl with Nyancat in it somehow
it’s totally possible to build a pretty darn fast CLI app with Lumo but the registry to publish, discover, download those things doesn’t exist for the Clojure or Clojurescript ecosystem, AFAIK
@chris_johnson Couldn't you just target nodejs with Clojurescript though? I suppose there's also the usual general purpose package managers (pacman, apt, homebrew, chocolatey, etc.) as well.
oh, I see - so build a Lumo thing and put it on npm
I suppose that could work, I haven’t tried it so I offer no guarantee 🙂
right, but the original question was about adding CLI binaries and that’s Lumo’s wheelhouse (or Planck’s)
FWIW, you can also make a literal binary: https://clojurescript.org/guides/native-executables
you can also require users to install lumo via npm: npm i -g lumo my-app
then execute your cljs files using lumo:
#!/usr/bin/env lumo
(ns my-app.core)
(println "Hello World!")
set your package.json
's bin
to core.cljs
Guys, I’m playing around with Ring and Compojure to craft a web service. I’m thinking about how to approach authentication and authorization.
At first, I thought about using middlewares, because I’m used to deal with these topics in Java and JAX-RS using ContainerRequestFilter
s. But now, I realized that those filters in JAX-RS are post match filters, and Ring middlewares are pre match, right?
If I’m not wrong about this, then how should I approach authentication and authorization? Should I invoke a function inside every handler that needs them? Or maybe wrap the handlers themselves inside of the auth functions, like this:
(GET "secret/" request (wrap-auth handler))
@lvbarbosa middlewares are exactly functions that wraps handlers
@akiroz but aren’t they intended to be used like this?
(wrap-auth (GET "secret/" request handler))
instead of this (GET "secret/" request (wrap-auth handler))
?
What if, in the second form, the wrap-auth
function is invoked and the requesting user is not authorized?
Let me reformulate the question
Facts:
1. Let’s say I have two routes, specified to the application exactly in this sequence: secret
and not-secret
;
2. The secret
endpoint is wrapped inside the wrap-auth
middleware, which checks the HTTP headers for a token, whatever, like this:
(wrap-auth (GET "secret/" request handler))
;
3. I am not authorized to access the secret
endpoint.
Usage:
If I issue a request to the not-secret
endpoint, the handler of secret
will be tried first, won’t it? Because of the order I specified them (in defroutes
, let’s say)
Since the wrap-auth
is invoked and I get a big UNAUTHORIZED as a response, Compojure will stop trying to match the routes, since a non-nil value was returned. This is what I am calling a pre match filter. I am assuming that putting the middleware after the route will make it post match and avoid the premature termination, like this:
(GET “secret/” request (wrap-auth handler))
Am I missing something?
Does it make sense at all? Maybe I got everything wrong
@akiroz @chris_johnson @mfikes @driphter Thank you for your input. Distributing a ClojureScrpit binary via npm sound feasible. I've seen people do that. I guess I'm gonna write this CLI in Go then 🙂
@lvbarbosa oh, that's right, your auth middleware returns an unauthroized response instead of nil, you'll need to wrap it after the GET
@akiroz do you think that is a good place to put the auth-dealing code?
If you have a path prefix that needs auth, you can do:
(context "/secret" []
(auth-middleware
(routes
(GET ...)
(POST ...)
)))
I’ve tried to find more information on the Compojure documentation, but I did not find anything. I am also a little bit afraid, because I don’t know how the GET
macro works. Will it return nil
automatically if the route isn’t matched?
I also tried to read the code for the GET
macro in the github repo, but it was too complicated for me since I’m a beginner
Oh, that’s nice.. I didn’t associate the use of contexts and middleware. It will be nice to aggregate secure routes together
perhaps (take-while seq (iterate rest [:a :b :c]))
oh, wrong direction, you want drop-last
drop-last for lazy-seq or list, but pop works for vectors (and is more efficient)
awesome, thanks @noisesmith!
Quick question: is it acceptable to ask for a quick review of some code on gist here?
In that case I would appreciate if anyone can take a look at this (very simple) code: https://gist.github.com/hmaurer/6ae4142be2bb9dc43f20bb80f079de38 🙂
also maybe having the datomic/entity
call inside pull-extra-info
is a bit of a complecting
A few minor suggestions from a very quick read-through, some of which are purely personal preference:
- I would tend to pull a helper fn or two out of init-attributes
so that init-attributes
is more quickly readable.
- A couple of your if
and if-let
would be better as when
and when-let
.
- I’d be tempted to pull out a little helper fn that captures something like (when <something> (throw (Exception. (str <something-else>))))
, possibly with the doseq
as well if it generalizes well to validate-ref-attribute
. Or I might try it & then decide it’s not a big-enough simplifier, and pull it back out. throw-when
maybe?
- Definitely second @sundarj on the destructuring — eg the let
statement in validate-ref-attribute
. You might be able to replace one or two of your if-let
with that, in cases where nil-punning would work OK.
- In general, looks good!
@sundarj @U077BEWNQ thanks to both of you, that was very helpful 🙂
is there an easy way to turn a JS object into a CLJS ordered map such that key order is preserved?
@rgdelato I know this isn’t helping with your question, but why do you need to reply on the order of properties in an object?
it seems a bit brittle; from what I gather even though order is preserved in most browsers the actual order may vary from implementation to implementation
So I wrote a one-off script that took some JSON files and generated a CSV file... and now that a bunch of data has been entered into that CSV document, I'm hoping to write another one-off script to turn it back into a JSON file again So yeah, it doesn't need to be robust, it just needs to work once. 😄