Fork me on GitHub

I'm trying to get this example working in Clojure

final LineMessagingClient client = LineMessagingClient
        .builder("<channel access token>")
but I can't seem to get the above working. my first instinct was
(def client (-> (LineMessagingClient.)
                (.builder channel-access-token)
but seems like there is no constructor Should I be using something like proxy etc. (Also I feel that Spring Boot examples tend to make Java interop less direct)

Lennart Buit08:10:19

builder looks like a static method, so perhaps (LineMessagingClient/builder "<channel access token>")


Thanks @lennart.buit you were right! 😄


I was looking into mount example mentioned here , we are not passing any argument to (mount/start) how all state will be initialised here ?


Does start just takes number of states present in namespace? according to

Ben Sless14:10:21

This is an opinion, but if you're just starting I recommend against using mount

Ben Sless14:10:33

Start takes states explicitly or starts them implicitly by the order of require-s


Which one I can use?

Ben Sless14:10:04

In my opinion, start with Component


Next I was planning to learn it

Old account11:10:04

How can I make (.plus (Instant/now) EXPIRY_DAYS ChronoUnit/DAYS) human readable?


Do you need something like ?

(-> ChronoUnit/DAYS

Old account11:10:56

😄I mean when printing out


are they three parameters you are passing? or calling function one by one

Old account11:10:55

(prn (.plus (Instant/now) EXPIRY_DAYS ChronoUnit/DAYS))


NOt sure if it's what you're looking for, but I strongly recommend, which is super easy to use, comes with formatters, easy to use functions and much more. I love it.


Your code would be re-written as:

(plus (instant) (days EXPIRY_DAYS))
And if you want to format it :
(-> (instant)
    (plus (days EXPIRY_DAYS))


I did something pretty hacky a while ago to make Date. more readable:

(defn v-time [timestamp]
  (let [dos (java.util.Date. timestamp)]
    (str (subs dos 0 10) " " (subs dos 24 48) " " (subs dos 10 20))))


You pass in unix time and you get something "human readable" out

Jelle Licht11:10:33

I wrote a library with quite some namespaces; what is the most idiomatic way to offer a (ns mylib.porcelain)that simply re-exports most of the relevant functions and macros? I looked at intern, which doesn’t seem to work for macros, and I looked at simply re-`def`/`defmacro`-ing everything.

Lennart Buit12:10:47

There are tools for this, but personally, I’d say write your ‘api’ in an .api or .core namespace in plain old Clojure. Re-exporting comes with lots of tool caveats (for one, Cursive doesn’t understand re-exported vars).

Jelle Licht12:10:34

The no-magic, no surprises approach sounds appealing indeed, thanks!

Lennart Buit12:10:31

obvious code is best code 🙂


> I looked at simply re-`def`/`defmacro`-ing everything I agree, this is fine. It's your API, it's better to devote some of your time to it and be explicit about how you expect the users to use your library. I'd suggest that you also consider defn instead of def. def might seem like less effort because you don't have to type as much but with defn you can have different docstrings for the users vs for contributors and maybe even (slightly) different signatures, which can be useful.


both def and defn will ignore the original doc string, and require adding a new one


Right, didn't realize that def can also have a docstring, thanks. That makes sense actually.


and with either def or defn you can copy the metadata of the original as part of the declaration


or maybe it's simpler with intern actually

(cmd)noisesmith.gui=> (intern *ns* (with-meta 'my-conj (meta #'conj)) conj)
(cmd)noisesmith.gui=> (doc my-conj)
([coll x] [coll x & xs])
  conj[oin]. Returns a new collection with the xs
    'added'. (conj nil item) returns (item).  The 'addition' may
    happen at different 'places' depending on the concrete type.


Hello all, How do I access

public class GoogleAuthorizationCodeFlow { ....
   public static class Builder extends AuthorizationCodeFlow.Builder
      public Builder(HttpTransport transport, JsonFactory jsonFactory, GoogleClientSecrets clientSecrets, Collection<String> scopes)
      { ....
? (GoogleAuthorizationCodeFlow$Builder/Builder. HTTP_TRANSPORT JSON_FACTORY (generate-secrets) SCOPES) ?


oh, I missed GoogleAuthorizationCodeFlow$Builder declaration


why casting to other class it show source class?

(:import [ JsonFactory]
   [ GsonFactory])

(def JSON_FACTORY (cast (GsonFactory/getDefaultInstance)))

(type JSON_FACTORY) -> 


cast doesn't change anything - it just adds an assertion to the compiled bytecode


if you were to do the same thing in java you'd get the same behavior


(defn type 
  "Returns the :type metadata of x, or its Class if none"
  {:added "1.0"
   :static true}
  (or (get (meta x) :type) (class x)))

(defn class
  "Returns the Class of x"
  {:added "1.0"
   :static true}
  ^Class [^Object x] (if (nil? x) x (. x (getClass))))


JsonFactory JSON_FACTORY = (JsonFactory) GsonFactory.getDefaultInstance();


in the context of clojure cast lets you avoid some reflection calls


clojure.core/cast is pretty much never what you want


the problem is that the Builder won´t recognize the ctor


No matching method Builder. found taking 4 args for class$Builder


@U0YJJPFRA does the ctor have a varargs parameter?


ctor is that Builder does not fit with args


you aren't calling a constructor


you are calling a method named Builder on the class$Builder and passing it 4 arguments


you want something like ($Builder. 1 2 3 4) not whatever you are doing


(you added an extra /Builder in there, which is syntax for calling a static method)


oh, yes, you right


Hey guys/gals. I ran into this discussion't%20a%20return,something%2C%20in%20these%20cases%20nil%20. and the accepted answer says if your algorithm needs a return statement, it's a major code smell. I thought I needed a return statement for what I’m trying to do, and was wondering if someone could point me to a better way of writing this: I’m looping through a vector using doseq to save files from an http request, but if one of those looped objects is themselves a vector and not a map, I wanted to ‘return’ or ‘throw’ a bad-request. But do-seq returns nil so my (if (vector? file) (bad-request "Not a map") doesn’t actually return and make it to the http-response. Any suggestions?


(defn handle-file-upload [params]
  (if (vector? (params :file))
    (doseq [file (params :file)]
      (if (vector? file)
        "Cannot parse request body. Found a vector within the file vector. Expected maps.\n"
        (copy-file-local file))
    (if (map? (params :file))
      (copy-file-local (params :file))
      "Expected file request to be a map.\n"))

(defn upload-route []
   (POST "/upload" {params :params}
         (let [res (handle-file-upload params)]
           (if (nil? res) (response "File uploaded\n")
               (bad-request res)))


so there are a few approaches


the most manual - loop


(if (vector? (params :file))
  (loop [[file & rest] (params :file)]
    (if (vector? file)
      "Cannot parse request body. Found a vector within the file vector. Expected maps.\n"
        (copy-file-local file)
        (recur rest)))


a little less manual - reduce and reduced


  (fn [_ file]
    (if (vector? file)
      (reduced "Cannot parse request body. Found a vector within the file vector. Expected maps.\n")
      (copy-file-local file)))
  (params :file))


both work fine


Sweet, thank you very much for this.


So if you don’t recur a loop it won’t continue?


and recur needs to be in tail position


my code there might be a bit wrong - i think you need to check if file is nil which happens at the end w/ the loop - but i think it still shows you some ways to do what you want


Yes it does, I just read through loop and reduced in the docs, just what I was looking for thank you. A little surprised there isn’t a foreach macro, I guess that’s pretty much just a loop ?

George Silva19:10:28

Hello Friends! I just made my first API with compojure-api and it is very very cool. Just wanted to thank everyone for the support. The Clojurians community is amazing and I always get a lot of cool tips here.

👆 2
🎉 1
George Silva19:10:34

Of course it's super silly and stupid, but I can change an atom from the outside world.

George Silva19:10:48

(ns econ.core
  (:require [compojure.api.sweet :refer :all]
            [ring.util.http-response :refer :all]
            [schema.core :as s]))

(s/defschema Transaction {:amount s/Num
                          :account s/Str
                          :type (s/enum :outbound :inbound)})

(def transactions (atom []))

(defn add-transaction [transaction]
  (swap! transactions conj transaction))

(def app
   {:ui "/"
    :spec "/swagger.json"
    :data {:info {:title "Econ API"
                  :description "Econ API Documentation"}
           :tags [{:name "api" :description "Econ API documentation."}]}}

   (context "/api" []
     :tags ["api"])

   (GET "/transactions" []
     :return [Transaction]
     :summary "Returns all transactions"
     (ok @transactions))
   (POST "/transactions" []
     :return Transaction
     :body [transaction Transaction]
     :summary "Echoes a transaction"
       (add-transaction transaction)
       (ok transaction)))))

Andrei Stan19:10:42

Hello guys, i struggle finding a way to filter the first vector, with the pred: • name_A = name_B, but age_A not= age_B

(let [list-A [{:name "unique_A_name" :age "99"} {:name "joyce" :age "25"} {:name "connor" :age "32"} {:name "brad" :age "21"}]
      list-B [{:name "joyce" :age "77"} {:name "connor" :age "60"} {:name "brad" :age "21"}]]
<filter?! function here>)
the expected result is a list of items that have same :name but different :age  ({:name "joyce" :age "25"} {:name "connor" :age "32"})
Thank you in advance!


Struggling to find a way to filter the items suggests that you might want to structure your data differently, if it's in your control.


Do you explicitly want the returned list be a filtered version of list-B (ie. in the same order)?


One approach would be to (group-by :name list-A) and then check elements of list-B against that.


(let [list-A [{:name "unique_A_name" :age "99"} {:name "joyce" :age "25"} {:name "connor" :age "32"} {:name "brad" :age "21"}]
      list-B [{:name "joyce" :age "77"} {:name "connor" :age "60"} {:name "brad" :age "21"}]]
  (filter (fn [person]
            (some #(and (not= (:age %) (:age person))
                        (= (:name %) (:name person))) list-B))


the above is inefficient/brueforce though


but you can take it as a baseline to make it less wasteful maybe


and yes my instinct is also what @UCYS6T599 said, the datastructure feels wrong. It sounds like you want to deal with relations here (sets of maps) and maybe some of the clojure.set operations, depending on the context surrounding that code.


take a peek here if you didn’t have already, might be useful:


This is a nice tutorial on creating lookup maps which are generally very useful in my day to day job;


(into {} (map (juxt :name identity) list-b)) might be how I'd start if I was solving the above problem

☝️ 1

sorry I couldn’t figure out a better data structure. but I edited my above suggestions to be a bit more efficient. It works but I think there must be something more elegant and efficient.


I second finding a representation of your data more amenable to the kinds of queries you'd like to do. If that's not an option, you can get quite expressive using clojure.set. The following

(set/difference (set/join list-A list-B {:name :name})
                                    (set/join list-A list-B {:name :name :age :age}))
returns a set of the values in list-A you want to keep. You can convert this into a vector, or, to preserve order, use this set as a predicate with filter.

Andrei Stan17:10:39

thank you all for your time and effort,

(let [list-A [{:name "unique_A_name" :age "99"} {:name "joyce" :age "25"} {:name "connor" :age "32"} {:name "brad" :age "21"}]
      list-B [{:name "joyce" :age "77"} {:name "connor" :age "60"} {:name "brad" :age "21"}]]
  (filter (fn [person]
            (some #(and (not= (:age %) (:age person))
                        (= (:name %) (:name person))) list-B))
@U01EFUL1A8M’s solution works for me

Andrei Stan17:10:34

i will try the other solutions also and read the links provided. Thanks


As long as all names are unique,@U01EFUL1A8M's solution will work perfectly. My solution is actually not correct, due to how set/join can pick a key's value from either list.


If a name can appear more than once in list-B, you need to deal with that somehow. I don't know if that's a possible scenario for your code.

(let [n (group-by :name list-B)
      na (group-by (juxt :name :age) list-B)]
  (filter (fn [person]
            (and (get n (:name person))
                 (nil? (get na (juxt :name :age person)))))