Fork me on GitHub

thanks @seancorfield @sova this looks like a handy resource. i like that templates exist for a bunch of libraries so you can quickly get a taste of their apis.

Ryan Haskell-Glatz03:01:54

Hey folks! I've seen way too many Rich Hickey tech talks and now I'm finally getting around to trying out Clojure / ClojureScript 😄

rich 5
Ryan Haskell-Glatz03:01:14

I'm trying to do the Quick Start (at on my Mac, and was wondering if anyone could help me out with an issue with cljs.main


I don't do any cljs but I can try...

Ryan Haskell-Glatz03:01:24

Haha, thanks @seancorfield! I'm just running clj --main cljs.main --compile hello-world.core --repl and I'm getting a stack trace that starts with:

Ryan Haskell-Glatz03:01:26

Exception in thread "main" Could not locate cljs/main__init.class, cljs/main.clj or cljs/main.cljc on classpath.

Ryan Haskell-Glatz03:01:02

And let me know if I should checkout the #clojurescript channel instead. I'm a beginner here in many senses of the word 😂


What's in your deps.edn file? In the folder where you are running that command.

Ryan Haskell-Glatz04:01:03

I put my deps.edn in the wrong folder :man-facepalming:


Rubber duck debugging is real :)

🦆 20

Glad to help 🙂


I was just stepping through the instructions on that page to make sure I'm on the same page as you


Right now I'm on my Windows laptop and using WSL with Ubuntu … and I got the cljs welcome page in MS Edge and was able to run the js/alert in the WSL REPL and, sure enough, it popped up in Edge 🙂

Ryan Haskell-Glatz04:01:58

Things are working great now, thanks again!


As a next step, you might try your hand at sticking Figwheel in there. It's a great tool for interactive programking. I personally tend towards Shadow Cljs, since it excels at a few things, such as making NPM package usage a ton easier.


One day I'll get back into cljs -- I tried it about four years ago and decided to stick to Clojure and backend stuff, but it's improved a lot since then.

Ryan Haskell-Glatz04:01:52

A little background about me: I recently had a pleasant experience learning Elm coming from a Java/C#/JS background, and I'm looking for another mind-expanding thing to learn. Functional programming is really neat, and it simplified the way I think about building stuff!

👍 5

Elm is pretty slick, yes. Evan really cares about how the experience works for folks not coming from an academic/Haskell sort of background and he's done a great job with it.


You'll find folks here are always eager to help. You won't be put off by the JVM and Java ecosystem around Clojure so that's good.


(I gotta go help with dinner but I'll be back later)

👍 5

(back, just in case anyone else is around with questions)

Lennart Buit07:01:27

what, the JVM really rocks, how can that put people off


@lennart.buit There are a lot of people who detest the JVM -- whether their complaints have basis or not is another matter.

Lennart Buit07:01:34

There is always people disliking things for sometimes valid reasons

Lennart Buit07:01:16

What I like about the JVM, is that any improvement of the JVM affects everyone equally without programmer intervension.

Lennart Buit07:01:54

Oh we found a better way to determine that objects don’t escape the stack? Here, have a slightly better optimizing JVM!


Indeed. I've been full-time on the JVM for almost twenty years now. It's such a rock solid platform and so ubiquitous that I can't imagine giving it up. I love that I can be polyglot on the JVM and that so many languages have JVM-compatible versions, even when the original/reference implementation of that language is non-JVM. Sure, there are valid complaints: startup time, stacktraces… but there are workarounds for those and, to be honest, they're not a problem for "most" projects.


But if you're coming to the JVM from a background of other languages, those complaints can seem pretty major.

Lennart Buit07:01:44

Right, as is often with software engineering, everything comes with a decent set of tradeoffs that can make or break something for your particular usecase ^^

Lennart Buit07:01:41

hah, the Graal impl of Python does support 3


if I wanted to call clojure.string/escape to escape a single quote in my text, what’s the proper way to reference a ' in the character map argument?


(str/escape "hello guv'nuh" {\' "*"})


maybe it’s bc I’m on cljs but getting an error that \' is an unsupported escape character


ah. didn't realize that was cljs.


yeah didn’t figure there would be a difference but there seems to be in this case


will try the cljs group, thanks for the help!


this works for me in cljs ?


what is your repl environment?


cljs 1.10.439 via figwheel 0.5.17


in emacs? what's your environment


in CIDER with figwheel this works for me as well as from a terminal

[dan@fedora clojurescript]$ script/repl
Clojure 1.9.0-alpha17
user=> (require '[clojure.string :as str])
user=> (str/escape "hello guv'nuh" {\' "*"})
"hello guv*nuh"


Moving this to OT..


running in cursive/intellij


will try posting in the cursive channel


@mss when its in a string you need two \s. "\\'"


it's annoying but the slash is the escape character, so when you actually want that rather than the sigil you need to use two of them


yep that worked!


makes sense


really appreciate the help


Hi, people. Have qustion. What is Clojure take on different established Java technologies, like all the EE stuff and Spring? Those technologies rely heavy on annotation processing and different convention-over-config deployments etc. How Clojure can tackle into that? When some time ago I tried to figure out how one work with annotations, it doesn't seem to be good interop.


aside from using metadata to create annotations which I already posted below, you can also use a small java class that uses clojure.lang.RT to look up Clojure code for its internal implementation - this is simpler than all-clojure interop sometimes


example here - java code implementing the methods used by jsvc, using DI to find clojure namespaces to invoke via properties

Vincent Cantin19:01:50

Clojure has meta-data, they are similar to annotations with the difference that you can dynamically build new values out of original ones with different meta-data.


you can actually use metadata on forms to create annotations


it's true that metadata can be used like annotations, but this doesn't help Spring, which only knows how to use your object via its annotations

Vincent Cantin19:01:10

You are right, I misread his question.

Ben Grabow19:01:07

I have a testing question. #testing looks a little dead so maybe I can find some help here? I have some test data (input and expected output) in a text file. I would like to parse the examples from this file and somehow get clojure.test to tell me which examples are failing. Should I try to do something like (doseq [...] (deftest ...)) or (deftest ... (are [x y] (= x y) ...)? I am also hoping to get the test runner to print the actual data from the files, rather than printing the code verbatim that I used to pull data from the files. E.g. I want (deftest file-parsing (is (= (parse "input-file.txt") (slurp "output-file.txt")))) to print the output file contents as the expected value rather than to print literally "(slurp \"output-file.txt\")".

Ben Grabow20:01:42

@seancorfield helped me figure out what I was trying to do in #testing if anyone is curious:


I'm writing a library that uses to do date/time management. When I load that library in, I get a bunch of warnings like so:

WARNING: contains? already refers to: #'clojure.core/contains? in namespace: net-promoter-score.nps-dates, being replaced by: #'java-time/contains?
[Other similar warnings]


Is there a way to make java-time play nicely with the standard ns?


@eric.boersma Are you using :use or :require .. :refer :all? That's where you're introduce the conflicts that Clojure is warning you about. Much better to do :require .. :as .. and refer to the library functions through an alias.


Ah, I'm using a use


(:require [java-time :as jt]) and then (jt/contains? ..) etc


The warnings come from use which refers in all the symbols (as does require .. :refer :all) and you should avoid those as much as possible.


Thanks, that's good to know


Is the idiomatic way to use :as when importing a library in pretty much all files?


Thanks, that's a handy resource, I hadn't seen it before


How can I see which parts of a function are taking most of the execution time? for example, which parts are slow and have potential optimizations to be made?

Alex Miller (Clojure team)22:01:18

You’re using boxed math everywhere, which is about 100x slower than primitive math

Alex Miller (Clojure team)22:01:06

I don’t have time to go through the details, but that’s usually a good place to start (assuming there’s not an algorithmic complexity issue)


how can i update a nested value in an atom ? assoc-in?


update-in is nice if it's a more complex operation


(swap! a update-in [:x :y :z] inc)


i don't want to increment it, i just want to set it to a new value i have determined


ignore the atom


figure out how to do it whatever value is in the function


so what does the value look like initially and what would you like it to look like


I'd suggest using update-in, even if your function ends up being (constantly new-value) because with a compound type like a map here, using reset! to set a key is a race condition


when you use update-in, changes to other keys come in automatically, if you use reset! with the whole new value, you can wipe out all concurrent changes


and if there's any possibility of two threads touching the same key for update, use compare-and-set and check that the key doesn't change before assigning the new value


(or swap! using a function that uses the key's contents instead of blindly overwiriting)

Alex Miller (Clojure team)22:01:14

maybe not the place to *start* :)

Alex Miller (Clojure team)22:01:22

surely there is some better writeup of using primitives somewhere but I do not have it at my fingertips


I think it's algorithmic complexity of my naive implementation that is slow 🙂


I'll check it out, thanks


;seek map and update rating on serverside
    (let [seek-tv-state (find-tv-item pid)
          seek-cm-state (find-cm-item pid)]
         (println "seek-tv " seek-tv-state)
         (println "seek-cm " seek-cm-state)
         (if (= nil seek-tv-state)
             (swap! nf-comments update-in [seek-cm-state :number-of-ratings] (constantly num-ratings))
             (swap! nf-comments update-in [seek-cm-state :ratings-total] (constantly total-score)))
             (swap! tv-state update-in [seek-tv-state :number-of-ratings] (constantly num-ratings))
             (swap! tv-state update-in [seek-tv-state :ratings-total] (constantly total-score)))))


... my swap! lines give me the error " Key must be integer "


that means it's a vector and not a hash-map usually


it's a vector of maps


what is seek-cm-state


and i use seek-*-state to determine the array-index so-to-speak


these need to be integers within the range of your vector


also you can replace:

             (swap! nf-comments update-in [seek-cm-state :number-of-ratings] (constantly num-ratings))
             (swap! nf-comments update-in [seek-cm-state :ratings-total] (constantly total-score))
(swap! nf-comments update seek-cm-state assoc :number-of-ratings num-ratings :ratings-total total-score)

mario-star 5

(once you adress the vector vs. map issues we are discussing, of course)


i don't know what the issue is


"Key must be integer" ... it is


works nicely now ^_^


was it an integer?


@sova there’s also (nil? x) instead of (= nil x)


and if you really want to write out the else, then you can alway use cond


Hi! I am trying to extend a protocol for an integer in ClojureScript (browser). What should I use to name the type? I have tried Number, Int, Integer, Num, cljs.core/Integer,... but none of them seem to exist.


I want to be able to call the protocol on numbers defined like this: (def some-number 5) (no decimals)


I tried finding out by doing (type 1), but it returns #object[Number], and I have no idea how to use that information.

Lennart Buit22:01:57

why do you want to extend integer?

Lennart Buit22:01:19

not trying to be a smartass here, but it is generally ill advised to extend such fundamental objects


I want to validate forms, and I use a special constant (`-1`) to indicate a missing value for ids. I want to be able to call the same missing? method on any field, and have the polymorphism help me figure out how to determine whether a real value is missing (e.g. for keywords I use another constant). I do not use nil for missing because it doesn't play nice with the form controls and easily lead to bugs (e.g. using empty string for missing text fields instead of nil avoids null exceptions).


It's for a rapid mockup, so I don't really care about the code being idiomatic; I just need to know the word to type so I can extend js number 🙂

Lennart Buit23:01:11

Don’t have intimate knowledge but this: seems to have your answer


Great, thanks! I was looking for an overview like that, but didn't find it. (I am using extend-protocol). Thanks!


Turns out it's lowercase number

Lennart Buit23:01:34

right, same deal for extend-protocol I guess