Fork me on GitHub

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)
                (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))))
;;code using img (url-img is not used) here


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)
      (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?


Also I'm looking for a resource that answer these types of newbie questions 😃


To clarify, the part I'm struggling with is how do conditionally return data

sundarj11:08:07 is handy for answering these types of questions



(defn cond-ret
  [{:keys [n] :as in}]
    (<= 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})


Lol find doc is awesome


This language feels like cheating


hahah, tbh a language should feel like cheating 😄


Damn I need a comprehensive noob book


maybe I should read the braveclojure one a bit better >D


@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!


no shame in that :~)


Nah you have to be shameless to be an effective newbie! 😃


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


ex. [ [1 2 3] [1 1 1] [9 8 7]] -> [11 11 11]

Lucas Barbosa12:08:16

@tsulej (apply map + [[1 2 3] [1 1 1] [9 8 7]])

Lucas Barbosa12:08:35

although this will give you a lazy-seq

Lucas Barbosa12:08:45

I don’t know if there’s a direct way to produce a vector


omg, obvious... thx!


I don't need vector

Lucas Barbosa12:08:18

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 (':


oh wait I need to ask this in #clojurescript I think


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])


wow! thanks @shan glad I asked


found it after trying flatten and then searching for any other functions that were similar using (find-doc "flatten")


wait. where is flatten1?


oh, might be a cljs thing


well.. that's even better. Because that's were i'm using it 🙂


just tried clojure first


I usually use lumo for a quick repl, which is based on cljs.


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 ( Anybody know what happened to it?


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) 🙂

Lucas Barbosa15:08:17

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?


use require with an alias


(: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:

Lucas Barbosa15:08:16

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}}]}


so line 3 is printing something out but the for is skipping?


The above output is what is printed on line 3.


not sure if for works with maps as I think it’s expecting a seq


for is lazy


you should use doseq for side-effects


I thought for was for side effects.


ah yeah, nice spot


Yess, thanks @sundarj!


no worries


´doseq` requires a vec but dorun works with the lazy list.


doseq does not require a vector


Thanks very much!


otherwise it would be called dovec simple_smile


I get a doseq requires a vector for its binding in


what that means is that you wrote:

(doseq seq ....)
instead of
(doseq [elem seq]
  (do something with elem))


Ah, okay. I wrapped the for in the doseq. Thanks again


(doseq (for [x [:a :b :c]]))


doseq works like for, but for side-effects


right. doseq throws away the results of calling a side effect on each element


Okay, I hope I learned that now 🙂


Much appreciated!


I was stumped.


no problem


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 namespace


Clojure 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.


The most similar solution to using npm would be using Clojurescript with node/npm 😛


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 🙂


It doesn't have to be Lumo specific


right, but the original question was about adding CLI binaries and that’s Lumo’s wheelhouse (or Planck’s)


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

Lucas Barbosa17:08:27

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 ContainerRequestFilters. 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

Lucas Barbosa17:08:47

@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))?


they are the same, GET works like a middleware too


well, the order is not the same, but you get the idea

Lucas Barbosa17:08:06

What if, in the second form, the wrap-auth function is invoked and the requesting user is not authorized?

Lucas Barbosa17:08:15

Let me reformulate the question

Lucas Barbosa18:08:26

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?

Lucas Barbosa18:08:47

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

Lucas Barbosa18:08:04

@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" []
      (GET ...)
      (POST ...)

Lucas Barbosa18:08:06

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

Lucas Barbosa18:08:04

Oh, that’s nice.. I didn’t associate the use of contexts and middleware. It will be nice to aggregate secure routes together


yeah, I think this is one of the weaknesses of compojure. data > functions >>> macros


is there an idiomatic way of achieving [[:a :b :c] [:a :b] [:a]] given [:a :b :c]?


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?


for learning purposes (e.g. am I doing anything silly)


well, i would say so


In that case I would appreciate if anyone can take a look at this (very simple) code: 🙂


looks pretty good to me, though i am by no means an expert


only thing i would say is, i personally would use destructuring more


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?


I don’t think key order is guaranteed in JS objects.


it's not guaranteed in the spec, though it tends to be preserved in practice


@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. 😄


@rgdelato granted that’s not the cleanest option, but you could convert your object to a list of tuples