Fork me on GitHub

Is there some convention for constant naming? BOT-NAME ? or maybe +bot-name+ ?


all top level definitions should be constant / immutable, so having a "constant" isn't useful


that's the typical style guide answer at least


if anything we use names like *bot-name* for things that aren't constant


I've seen +bot-name+ used by people who came from common lisp, but it's not a clojure idiom


Thanks those are good hints


I reached a major milestone .. my bot worked for the first time 🙂

upside_down_parrot 3
Thomas Tay05:11:22

Ngl the juxt function is pretty cool I read a blog post that used it in conjunction with sort-by, and it totally blew my mind as a beginner 🤯


Any suggestions for stack (or even some template) if I'd like to start a new API project?


should I just pick compojure? Or maybe reitit which is mentioned in compojure github page?


Well I picked reitit and try to figure out that

Ben Sless09:11:32

The complete stack would be reitit, jsonista, muuntaja and malli


thanks! will check those as well


Back to the topic of naming, is there a specific reason why style guides don't advocate naming reference types differently? Just adding a * to atoms seem very useful to me, so you don't have to backtrack their bindings to verify whether they've been deref'ed at a previous point (especially when passed across multiple functions).

Jim Newton12:11:05

I'm trying to implement parts of the clojure.reflect/type-reflect function in a Scala program, to do similar (but more limited) kinds of class reflection. I see that from a Class there is a method isInterface() which gives me the :flags :interface part. Does anyone know how the refl/type-reflect function figure out if the class is :public, :final, or :abstract. I don't see that in the code. Maybe it's hidden in a java function.

Jim Newton12:11:14

it looks like there is an integer (Long?) called the access bits. And I can and that integer with certain bit-masks to determine such information. But I don't see how to get the access bits integer.

(def ^{:doc "The Java access bitflags, along with their friendly names and
the kinds of objects to which they can apply."}
   (map access-flag
        [[:public 0x0001 :class :field :method]
         [:private 0x002 :class :field :method]
         [:protected 0x0004  :class :field :method]
         [:static 0x0008  :field :method]
         [:final 0x0010  :class :field :method]
         ;; :super is ancient history and is unfindable (?) by
         ;; reflection. skip it
         #_[:super 0x0020  :class]        
         [:synchronized 0x0020  :method]
         [:volatile 0x0040  :field]
         [:bridge 0x0040  :method]
         [:varargs 0x0080  :method]
         [:transient 0x0080  :field]
         [:native 0x0100  :method]
         [:interface 0x0200  :class]
         [:abstract 0x0400  :class :method]
         [:strict 0x0800  :method]
         [:synthetic 0x1000  :class :field :method]
         [:annotation 0x2000  :class]
         [:enum 0x4000  :class :field :inner]])))

Jim Newton13:11:09

I think I found it. looks like class.getModifiers() gives me the integer.


for some reason lein cljsbuild once compiles the code in core.js but not in main.js as I specified in project.clj .

cljs/core.js:3359: ERROR - Parse error. primary expression expected


I had to downgrade from versions

:dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/clojurescript "1.9.521"]
                 [compojure "1.6.1"]
                 [ring/ring-defaults "0.3.2"]
                 [ring/ring-json "0.5.0"]]
to versions
:dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/clojurescript "0.0-2371"]
                 [compojure "1.3.1"]
                 [ring/ring-defaults "0.1.2"]
                 [ring/ring-json "0.3.1"]]
to make it work


Now using clojure.core.cache.wrapped to cache OAuth access tokens ..

(defn cached-authenticate [app event]
  (let [cache-key [(:name app) (get-in event [:installation :id])]]
     installation-access-token-cache cache-key
     (fn [_] (authenticate app event)))))


Can anyone recommend something that would allow me to delay incoming messages? I’m working with a webhook, but I do not immediately want to process those messages. Ideally I queue them and process them N seconds later. In the Go version of this GitHub app I am putting them in Redis queue and then poll them … I guess I could do the same, but maybe there is something simpler that doesn’t need an external store?


assuming you only want to work on memory

Louis Kottmann19:11:54

how can I treat a string as a file without writing it out? my google-fu failed me..

Ben Sless19:11:24

You mean writing to a Writable object in memory and not to disk?

Louis Kottmann20:11:42

I guess, something I could slurp for example

Louis Kottmann20:11:24

but yes, in memory

Ben Sless20:11:56

You need to create something like a ByteArrayOutputStream then wrap it in a writer

Ben Sless20:11:11

to which you can just .write normally

Ben Sless20:11:28

then just call str on the output stream to get the string

Louis Kottmann20:11:07

thanks, I managed to make it work

Louis Kottmann20:11:29

with (io/input-stream (.getBytes "text"))


Oh nice that is like Python’s StringIO


if you need text rather than binary IO, stringreader is simpler

(cmd)user=> ( "Hello")
#object[ 0x7a34b7b8 ""]
(ins)user=> (slurp *1)


if you need binary io, add the extra arg to getBytes that specifies the encoding


usually you want "UTF-8"


Is there a variant of clojure's read that will match parens for a partial read?


Basically, if I have the file:

(let [x 5
I'd like it to still be able to read the text so far, so it'd read to something like:
(let [x 5])


If, for example, clojurescript used only parens, I could just keep adding parens to the end until it successfully read, but since it doesn't, that wouldn't really work. (Or rather, it'd be much slower...)


(Because I'd have to permute all types of parens)


@leif so the file stops at 5?


@leif clj-kondo will give you this output:

$ echo "(let [x 5" > partial.clj
$ clj-kondo --lint partial.clj
partial.clj:1:6: error: Found an opening [ with no matching ]
partial.clj:2:1: error: Expected a ] to match [ from line 1


Potentially you could use that output to gradually fix the expression and then read it using a normal parser


@leif edamame (my Clojure parser) also has something similar:

user=> (require '[edamame.core :as e])
user=> (e/parse-string "(+ 1 2 3")
Execution error (ExceptionInfo) at edamame.impl.parser/throw-reader (parser.cljc:92).
EOF while reading, expected ) to match ( at [1,1]


you could parse the exception, append the expected thing and try again


possibly we could also add the expected thing to the exception data


@borkdude Yup, as if the file stopped at 5.


So it looks like I'll have to catch the exception, try to parse the exception to get the correct ), ], or }, and then append that to the stream, and try again?


Would it be possible for edamame.core to attach some sort of data to the exception so that I wouldn't have to parse a string?


(parse the exception string)


That's what I suggested: > possibly we could also add the expected thing to the exception data It doesn't do that currently, but a PR for that is welcome


Ahhhh, okay, that makes a lot more sense.


(I missed that)


Oh cool, and it looks like this works with clojure and clojurescript, ya?


(At least based on the .cljc extension


Okay cool. I'll put together a PR later today.


Thanks for the suggestion.


@leif so throw-reader also can receive an optional data argument. So we could fill in {:edamame/expected-delimiter ...} there and that'll fix it.


That + a unit test