This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-21
Channels
- # arachne (21)
- # beginners (22)
- # boot (58)
- # cider (27)
- # cljs-dev (67)
- # cljsjs (10)
- # cljsrn (13)
- # clojure (91)
- # clojure-greece (6)
- # clojure-russia (1)
- # clojure-uk (6)
- # clojurescript (6)
- # core-async (3)
- # cursive (6)
- # datomic (3)
- # events (2)
- # hoplon (152)
- # off-topic (44)
- # om (8)
- # om-next (7)
- # onyx (16)
- # protorepl (10)
- # re-frame (10)
- # reagent (22)
- # untangled (5)
do you know if there’s going to be any discount for the ClojureWest hotel? or should I just go ahead and book a room directly with the hotel
nvm, thanks @mkeathley 🙂
use a sorted set?
that came out really fast. I have no idea what that will do 😜
@ag Two ways I can think of -- in addition to the vector, also maintain a set of the vector's elements, using the set for the check whether an element is new, adding to both set and vector only if it is new.
@ag Second way is to use an ordered-set from flatland library: https://github.com/amalloy/ordered
Oh, and of course if the O(n) search time through the vector doesn't bother you, you can always search the vector for an element before adding yourself
eeish… I thought maybe there’s simple elegant solution. so often after writing “something very smart” I realize there’s an implementation in .core
thanks @mkaschenko!
ugh wait. with-out-str
outputs a string whereas i was using printf
to convert hex strings to numbers
i'm getting a strange error when i try to use https://github.com/cch1/http.async.client
(ns discord.core
(:require
[clojure.data.json :as json]
[http.async.client :as http]))
(defn request
"Perform an http request through discord's official api. "
[token-kind token method path query body]
{:pre [(or (nil? token-kind) (keyword? token-kind))
(if (nil? token-kind) true (token-kind #{:bot :bearer}))
(or (nil? token) (string? token))
(keyword? method)
(method #{:get :put :patch :delete :post})
(string? path)
(or (nil? query) (map? query))
(or (nil? body) (map? body) (vector? body))]}
(with-open [client (http/create-client :user-agent "DiscordBot (, 0.0.0)")]
(apply
(method {:get http/GET :put http/PUT :patch http/PATCH :delete http/DELETE :post http/POST})
(str "" path)
(concat
(if (nil? body) [] [:body (json/write-str body)])
(if (nil? query) [] [:query query])
(if (or (nil? token-kind) (nil? token)) [] [:headers {"Authorization" (str (clojure.string/capitalize (name token-kind)) " " token)}])))))
The error says
java.lang.IllegalArgumentException: No value supplied for key: {"Authorization" "Bot DISCORD_API_KEY"}, compiling:(discord/core.clj:560:1)
I'm invoking it from here:
(defn get-channel
"Get a channel by ID. "
[token-kind token channel-id]
{:pre [(string? channel-id)]}
(request token-kind token :get (str "/channels/" channel-id) nil nil))
(get-channel :bot "DISCORD_API_KEY" "269507447671095298")
If I require
org.httpkit.client
and use this definition of request, it operates succesfully:
(defn request
"Perform an http request through discord's official api. "
[token-kind token method path query body]
{:pre [(or (nil? token-kind) (keyword? token-kind))
(if (nil? token-kind) true (token-kind #{:bot :bearer}))
(or (nil? token) (string? token))
(keyword? method)
(method #{:get :put :patch :delete :post})
(string? path)
(or (nil? query) (map? query))
(or (nil? body) (map? body) (vector? body))]}
(get
(update
@((method {:get client/get :put client/put :patch client/patch :delete client/delete :post client/post})
(str "" path)
(merge
{:user-agent "DiscordBot (, 0.0.0)" :as :text}
(if (nil? body) {} {:body (json/write-str body)})
(if (nil? query) {} {:query-params query})
(if (or (nil? token-kind) (nil? token)) {} {:headers {"Authorization" (str (clojure.string/capitalize (name token-kind)) " " token)}})))
:body
json/read-str
:key-fn
(comp
keyword
clojure.string/lower-case
#(clojure.string/replace % \_ \-)))
:body))
The logic is virtually the same, the only difference is the second implementation of request does some extra stuff. I can't see how the second implementation can work, while the first one doesn't.
@bcbradley That error indicates illegal syntax on line 560 of discord/core.clj — is the code on GitHub where we can see the source?
No. Put it up on GitHub where anyone can see it and help you.
clojure.spec question here… from the docs:
(s/keys :req [::x ::y (or ::secret (and ::user ::pwd))] :opt [::z])
However, would you expect the generator to generate ::secret, ::user, and ::pwd?
(gen/generate (s/gen (s/keys :req [::x ::y (or ::secret (and ::user ::pwd))] :opt [::z])))
#:spec-game.core{:x 2447, :y 0, :secret -25791379, :user 190093, :pwd -3668447, :z -36153036}
It only states what is required — additional keys are always acceptable.
Sure, however it never generates anything with any unspecified key. It seems like it would never generate a map that’s missing a secret, or pair of user/pwd, which seems like it’s likely to cause issues
further, it means you have to use a custom generator if the rule is: secret or user/pwd, but never both.
But a map with both still conforms to the spec.
In your case {:x 1 :y 1 :user “fred”}
would fail conformance but {:x 1 :y 1 :user “fred” :secret “hush”}
would pass I believe.
I agree it conforms to the spec, however I think the problem is that there is information provided that is disregarded in generating sample data. I realize this is an extreme example, but it’s as if the implementation of the int? generator was (constantly 0). Technically conforms, yes, but not really in the spirit of “generating” data
There's actually a ticket with a patch that overhauls all this stuff
David Chelimsky worked on it with Rich
I can find it
It will definitely be nicer if the generator for s/keys
respects or
in the intuitive way.
You still need to bear in mind that something could pass you {:x 1 :y 1 :user "fred" :secret “hush”}
and that does conform.
The same as {:x 1 :y 1 :username "fred" :secret “hush”}
would conform.
@seancorfield absolutely yes. Both the case I’m presenting, and yours, are relevant in the spirit of generating sample data that might hit edge cases you didn’t consider
Those changes better handle or options in the gen but won't add nonexistent keys
If you want that, then create a spec that merges your spec with another one and override with that generator
@seancorfield looks like that ticket is written as you’d like: >(s/keys :req [(or ::x ::y)]) always generates maps with both ::x and ::y but it should also generate maps with either ::x or ::y.
@bcbradley args to http.async.client fns are keyword args, not a map, IIRC. (apply ,,, (mapcat identity options))
The header option is one of the options. Here’s an example with one option, @bcbradley :
(with-open [c (http.async.client/create-client)]
(apply http.async.client/GET
c
""
(mapcat identity {:timeout 1000})))
Seems like (apply ... (concat ...))
would be correct there?
The error message suggestions a syntax error in the source file, not a runtime failure to destructure arguments.
Does anyone now what the +site template does on luminus?
@max-tweddell According to the github page, +site
seems to be a combination of +h2
and +cljs
. Strange name for such an option, though.
https://github.com/luminus-framework/luminus-template
yeah, I saw that but I wasn't sure if that was all of it, or if there was something else to it
Also, @cch1 your advice about flattening the headers map isn't right. It expects a :headers argument key followed by a map that represents the contents of the header
That’s what I was trying to demonstrate with another key (:timeout). the GET method wants flattened arg pairs. In the case of header, the val is a map and of course should not be recursively flattened.
@seancorfield @hiredman I think I solved my issue from yesterday: definterface
expects type hints to be fully qualified (unless they are primitive or from the java.lang package). Too bad this is not documented for definterface
, only for gen-interface
.
how can make a promise in clojure that depends on another promise? I basically want a promise that is delivered as soon as the promise it depends on is delivered, and the value it returns when derefenced should be the output of a function applied to the value of dereferencing the original promise.
Has anyone heard of Clojure(Script) codebases that are significantly larger than 100k lines? Like 500k or something?
the largest I've read about is a bit over 34K http://magazine.aerospacemanufacturinganddesign.com/article/october-2016/updating-diagnostics-for-boeings-737-max.aspx
OMF began with more than 1,700 requirements from Boeing and took two and a half years to develop. Built using more than 34,000 lines of Clojure code, it is one of the largest Clojure code bases to date
Yeah. I've heard several reports of codebases of 100-150k lines and have personally worked on one, but I'm wondering if there's anything bigger out there.
while I have worked on 1MLOC Java code bases, it seems hard for me to believe that many projects would ever require 1MLOC Clojure code bases
Clojure allows you to create abstractions that reduce code size (unlike Java where abstractions typically increase code size), so my experience has been largely that size is dependent on the amount of time you dedicate to refactoring
and if you can spend more time refactoring, your code can almost always be smaller
but it’s not always worth doing so
“I didn't have time to write a short letter, so I wrote a long one instead.” ― Mark Twain
@miikka IMO, once you get close to 100k lines of CLJ code, projects tend to look for more leverage to keep the LOC down. For example, you could encode your business logic as CLJ code, or you could write a rules engine and store your rules in a database of some sort.
So once you figure in macros, rules systems, logic engines (datalog, etc.), I find it hard to believe that someone would need a project of 1mil lines of CLJ.
sometimes, I get a feeling that almost everything can be built in less than 100kLOC of app code in clj
actually, chunkiest parts of code in my company are usually queries or parts related to GUI
@miikka: @tolitius World Singles just passed 50kloc, including about 13kloc tests.
@seancorfield can you break this number down roughly?
@seancorfield thanks for the numbers, I thought you mentioned you have quite a large codebase some months ago, but I was not sure what it was.
do you use https://github.com/clojure-expectations/expectations for all 13kloc
of tests? Is there a particular way you tend to structure your tests to minimize the time to refactor?
I also heard that circleci codebase is quite large in lines. Boeing is the only large one I actually saw the numbers for. Most of the Clojure codebases I work(ed) with tend to split into smaller libs or different projects once they reach something that is hard to load into one's brain in the morning