This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-21
Channels
- # 100-days-of-code (1)
- # announcements (2)
- # beginners (164)
- # cider (23)
- # cljs-dev (30)
- # cljsjs (11)
- # cljsrn (7)
- # clojure (116)
- # clojure-boston (1)
- # clojure-dev (20)
- # clojure-finland (2)
- # clojure-italy (4)
- # clojure-nl (1)
- # clojure-uk (10)
- # clojurescript (39)
- # core-async (19)
- # cursive (43)
- # data-science (2)
- # datomic (24)
- # emacs (10)
- # figwheel-main (20)
- # fulcro (63)
- # hoplon (7)
- # hyperfiddle (7)
- # instaparse (3)
- # kaocha (1)
- # nrepl (3)
- # off-topic (170)
- # onyx (13)
- # other-languages (3)
- # parinfer (13)
- # re-frame (39)
- # reagent (5)
- # reitit (22)
- # ring-swagger (4)
- # shadow-cljs (284)
- # spacemacs (2)
- # sql (27)
- # testing (28)
- # unrepl (2)
defprotocol really can't work any other way for a mix of reasons and if you had to lump them together you might just call "interop"
defprotocol both has compile time effects and interacts with jvm classes, which result in global names
they are bad because naming something is not the same as creating something, and we have both many ways to name things (def, let, fn application) and many different things to create
one thing missing from that spec definition is a generator, and you cannot add a generator because the macro combines s/def and creating the predicate
(defmacro sspec [proto]
`(s/def ~(keyword (str (.getName *ns*)) (str proto))
(s/with-gen
#(satisfies? ~proto %)
#(s/gen #{~(->SomeRecord)}))))
So generating the anonymous function with a macro but not the s/def
from a macro is not a code smell then?
OK, walking through the Guestbook for Luminus, and running into a date filter formatting error with the following code:
(defn save-message! [{:keys [params]}]
(if-let [errors (validate-message params)]
(-> (response/found "/")
(assoc :flash (assoc params :errors errors)))
(do
(db/save-message!
(assoc params :timestamp (java.util.Date.))
(response/found "/")))))
Error is On filter body 'item.timestamp|date:"yyyy-MM-dd HH:mm"' and filter 'date:"yyyy-MM-dd HH:mm"' this error occurred:2018-11-20T00:39:40.733 is not a valid date format.
SQL in resources/sql/queries
is -- :name save-message! :! :n
-- :doc creates a new message
INSERT INTO guestbook
(name, message, timestamp)
VALUES (:name, :message, :timestamp)
I'm sure I could change that to a formatted string before handing it off.
Any ideas on where I can look next to fix this?
user=> (require '[selmer.parser :refer [render]])
nil
user=> (render "{{creation-time|date:\"yyyy-MM-dd_HH:mm:ss\"}}" {:creation-time (java.util.Date.)})
"2018-11-20_16:35:14"
user=> (render "{{creation-time|date:\"yyyy-MM-dd_HH:mm:ss\"}}" {:creation-time "2018-11-20_16:35:14"})
Exception On filter body 'creation-time|date:"yyyy-MM-dd_HH:mm:ss"' and filter 'date:"yyyy-MM-dd_HH:mm:ss"' this error occurred:2018-11-20_16:35:14 is not a valid date format. selmer.filter-parser/apply-filters/fn--1342 (filter_parser.clj:135)
user=>
Hey all, in clojurescript, why does this not work: (into {} '((2 1)))
, but this does: (into {} (into [] (map #(into [] %) '((2 1)))))
? I get No protocol method IMapEntry.-key defined for type number: 2
Oh hey, found it; https://clojuredocs.org/clojure.core/into#example-5858e2eae4b004d3a355e2c8
Still curious though, and is there a better way than (into {} (map #(into [] %) '((1 2)))
?
there's also (apply hash-map '(1 2))
if you control the data structure coming in
Hi all! I have a Java project, and I'd like to invoke some Clojure from it. (Ideally, the Clojure doesn't need to be re-compiled to a jar
each time it changes.)
Following Method 1 here (https://push-language.hampshire.edu/t/calling-clojure-code-from-java/865), I can download a Clojure .jar
file, put some Clojure code in a script, and use require.invoke(Clojure.read("my.namespace.core"));
and Clojure.var
to grab the IFn
I want to execute.
My question is: if I want the Clojure file to be able to pull in dependencies (e.g. from Github, as described in this documentation for deps.edn: https://clojure.org/guides/deps_and_cli#_using_git_libraries), is there a way to do that? Where would I put the deps.edn
? Or would I use a different mechanism?
that’s used to build a classpath (at the shell level)
it does not dynamically add stuff to your java classpath
there are ways to do so using various Clojure libraries, but that is probably overkill for what you’re doing
@alexmiller Thanks! Good to know. Yes, I should be able to avoid dynamically adding to the classpath... I know ahead of time what Git library I'll need my Clojure scripts to rely on.
I'm newish to JVM development and don't have a great mental model of dependencies / the classpath. Do you have a sense of what the best way to accomplish this might be? Maybe I can clone the Github Clojure repo locally, and somehow add it to the classpath for my java project? In that case, will require.invoke(Clojure.read("my.namespace.core"))
succeed (if my.namespace.core
uses (require ...)
to pull in names from the Git library)?
(In that case, how can I handle the dependencies of the Github repo, which are specified in a deps.edn
file of its own?)
@minhnhat10bk No, looks weird. This works fine:
(every? #(= \space %) " ")
;; => true
(defn is-space [ch]
(= \space ch))
(every? is-space " ")
;; => true
(every? #(is-space %) " ")
;; => true
@minhnhat10bk Java static methods are not first-class in Clojure, so you can’t use them in higher-order functions like map
without wrapping them like you did
I have seen somewhere that *name*
notation is used. And it is called "ear muffs" or something. Could someone remind me when to use such convention
how can I create a deftype
that I can apply? Is there a protocol I can extend for that for clojure and clojurescript?
huh, okay, that works for clojurescript only. So I suppose I will need a gen-class implementation for the jvm, or is there a more convenient way to define them?
ah, okay, I am creating (to learn more about clojure) a "vec3" class, which stores 3 floats in an array
You're creating a custom datastructure and you want it to support being called like a function?
so I have solved the clojurescript part, because IFn is a protocol, but in clojure, it's an interface, and I wonder, do I just have to bite it and implement it as a gen-class on the jvm side, or is there a way I can define both versions at the same time?
Oh, hum, well I'm not sure how to make it work for both. In Clojure you have to implement the IFn interface. And in ClojureScript extend the IFn protocol
> Each spec consists of a protocol or interface name followed by zero or more method bodies: protocol-or-interface-or-Object (methodName [args*] body)*
I figured it out, IFn on clojurescript defines -invoke
, but it is invoke
in clojure. confusing 🙂
so now I have my vec3 type, I have declared a VecOpts protocol on it supporting v+
. What I'd like is to redefine +
to invoke v+
on things implementing VecOpts, and fall back to +
in the default case- is there a good way of doing that?
there are some known performance issues with satisfies?
unfortunately: https://dev.clojure.org/jira/browse/CLJ-1814
@schmee it seems that protocols themselves have quite an overhead. ~3.5x that of a standard call on my tests (in cljs)
(reduce
(fn [rela key] (into rela {key ({:composer "J. S. Bach" :country "Germany"} key)}))
{}
'(:composer :country))
{:composer "J. S. Bach", :country "Germany"}
(set (reduce
(fn [rela key] (assoc rela key ({:composer "J. S. Bach" :country "Germany"} key)))
{}
'(:composer :country)))
#{[:composer "J. S. Bach"] [:country "Germany"]}
@minhnhat10bk What do you want in the set? The values from the map?
(doc set)
-------------------------
clojure.core/set
([coll])
Returns a set of the distinct elements of coll.
nil
so set treats its input like a collection. which for a hashmap is a seq of key value pairs
@minhnhat10bk you want hash-set
instead
as @bronsa mentions, there are usually a "collection" function and an "elements" function
Any recommendation on how to connect and fetch data from databases? Is HugSQL the way to go?
depends on what type of database you’re talking about, but if it’s SQL then my tip is https://github.com/clojure/java.jdbc combined with https://github.com/jkk/honeysql
I have two lists, '(:a :b :c)
and '(:x :y :z)
, and I would like to create a third list that intertwines them into couples, like '(:a :x :b :y :c :z)
so I can use it with map
in a X Y coordinate style. I have seen this somewhere but I can't seem to find now.
look into (doc interleave)
and also maybe (map vector col1 col2)
. the former will sequence them, the latter will create tuples for you
Thanks! Perfect.
Hello all: quick question. I am trying to compute a sum of a range of numbers.
I can throw compute-sum into (reduce + (compute-sum 10))
and it will reduce, however, if I try to reduce within the compute-sum function, I get a "IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:542"
for
executes the body form once for each assignment in bindings
(reduce + x)
will be executed once for each value of x
from 1 to n
But what you want is to reduce the range itself
ahhh. okay, that totally makes sense
so (reduce + (range 1 (+ 1 n)))
Also, +
is variadic so you can just apply it to a sequence of numbers.
(apply + (range 1 (+ 1 n)))
You all really cleared that up for me!
in general, the first argument to reduce should be a function that takes two parameters
That should help you understand what for
does
one is the “current” running total (I like to think of it as a memo), and the second is a value from your sequence
so you could write it like so: (reduce (fn [memo, val] (+ memo val)) (range 1 (+ n 1)))
. But since +
can also take two arguments, just like my anonymous function, you can just put it there: (reduce + (range 1 (+ n 1)))
.
Finally, (+ n 1)
can also be written as (inc n)
, with inc standing for increment.
Very nice, @lennart.buit.
Yeah, higher order functions take some mental gymnastics to get your head around, but they are oh so helpful!
I have a collection like this [[1 2] [3 5]]
and I want to generate combinations like [[1 3] [2 5] [2 3] [2 5]]
. The catch is that the original collection can be [[1 2] [3 5]]
or it could contain more than two sub-collections. On the surface for
seems like a good choice, except that the number of sub collection is dynamic. Is there a way to accomodate for this in the for
?
@tkjone check out https://github.com/clojure/math.combinatorics, especially cartesian-product
I have a map like this { ... :subname "//" (env :DB_HOST) ":" (env :DB_PORT) "/" (env :DB_NAME) ... } I am getting "Map literal must contain an even number of forms". I understand what is wrong but how can I fix it?
{:key "value"}
has two forms {:key "value" "extra"}
has three forms and can't form a map of key and value pairs
presumbably you want the key :subname
to point at (str "//" ... all those things you wrote)
call (str on those things)
to get a single string { ... :subname (str "//" (env :DB_HOST) ":" (env :DB_PORT) "/" (env :DB_NAME)) ... }
(#(f %) x)
= (f x)
. so you don't need to invoke range on 5, you can just use the invocation (range 5)
@somedude314 there's also the format
function if a printf-style format string feels more readable. e.g. (format "//%s:%s/%s" (env :DB_HOST) (env :DB_PORT) (env :DB_NAME))
I generated a project using lein new compojure hello-world
and installed [environ "1.1.0"]
. How do I load enviroment variables that would show if I do (require '[environ.core :refer [env]]) ... (env :database-url)
from REPL? I created a profiles.clj with `{:dev {:env {:database-url "jdbc:<postgresql://localhost/dev%22|postgresql://localhost/dev">}}
:test {:env {:database-url "jdbc:<postgresql://localhost/test%22|postgresql://localhost/test">}}}` and it's not working (returning nil). Can someone please tell me what I am missing?
You may want to edit the above, surrounding the multiline code snippet with triple-backticks instead of single-backticks: ie:
Also, if I export a variable from shell. This works (System/getenv "DB_HOST")
but this returns nil (use 'environ.core) (env :DB_HOST)
on the same REPL session!
Try (env :db-host)
-- it picks up UPPERCASE variables as lowercase keywords and converts _
to -
in them.
Thank you @seancorfield. That worked 🙂
No idea about the profiles.clj
question -- it doesn't work for me either, on the first attempt, but I don't use Leiningen so I may be doing something wrong as far as the instructions are concerned.
@somedude314 Keep in mind that if you had your REPL running and changed anything in your profiles.clj
and project.clj
you will have to restart your repl
@mario.cordova.862 yes, cursive. I am trying to restart the entire IDE now.
@mario.cordova.862 probably not - I opened the directory and right clicked on project.clj and clicked Run REPL for ... - however I also tried starting the REPL from the terminal.
In Cursives menu click on Run
then look for Edit Configurations
. Then in the upper left hand side there should be a +
. Click on that and set up a local REPL.
Check Run nREPL with Leiningen
and make sure you have the correct profiles
set up if it applies.
@mario.cordova.862 just tried it with dev,user,system,base,provided,default
same issue.
This is showing the variable (database-url) but still not accessible from Clojure code:
> lein show-profiles dev
{:env {:database-url "jdbc:},
:dependencies (),
:jvm-opts nil,
:eval-in nil}