Fork me on GitHub

how do i set the entry point for the project in deps.edn?


@veix.q5 Using :main-opts or on the command-line: -m entry.point to tell it to run entry.point/-main

✔️ 4

@veix.q5 Did you ask about manifold streams? I was figuring that out for you and when I came back I couldn't find the question...

✔️ 4

The answer seems to be to call (.description s) and you'll get back a hash map describing the stream. That's not all the fields tho'...


There are also .producers, .consumers, .messages, and .capacity which might return useful/interesting values for you.


(took me a while of digging through the source to figure that out 🙂 @veix.q5)

❤️ 8

@seancorfield appreciate it. did it for me


hmmm, seems like gets the consumers. the other methods you mentioned will sure come handy


Hi, people. Is it normal in clojure, to keep global shared state in atom, and each time a part of the structure (for me atom is vector of ongoing game states) changes (individual game state is updated) I have to swap the atom with updated positional association?


For lack of a better answer, I'm taking the chance to chime in. In my understanding, atoms can be useful indeed when you have a shared state like in your use case. I have seen it used like you described so judging from my really short experience it's valid, though rare and should be avoided when possible.


@UBMJ124P6 it’s more common to use a map instead of vector because in many situations maps provide better developer ergonomics. For instance:

user> (def a (atom {}))
user> (swap! a assoc-in [:game1 :players] ["p1" "p2"])
{:game1 {:players ["p1" "p2"]}}

💡 4

hmm, I am using vector exactly coz it's also Associative structure, and one can do same with indexes... but I guess there is merit in your approach, as then each game identity can be it's "key"


@pavlos I came to atoms, coz essentially what I need is to have server (using ring) which runs the game, but game can have 2-4 players, which have to participate, so I can't use :session, so I have to use some structure on the server which is "visible" for all 2-4 players, so I was led to atoms, and currently they look ok, given that my game-server currently will be only in-memory Trying to implement board game - Cave Troll


Ah, I see. Any reason you need it to be in memory? I think I'd use persistence rather than an atom to capture the shared state!


@pavlos reason - me being beginner, so wanted first to operate with simple functions in memory, later will dump them into some file/db whatever, and it's easier to do REPLing when all stuff is in memory, and there is minimal side-effective functions involved


I am not pretending to implement commercial game, I just picked non-trivial task to learn clojure, at the same time - being deterministic and clear rules with limited "actions", so I can comprehand and pack them into simple clojure program


even writing simple function like - calculating which player's turn is next, is big learning for me. It is not easy to unlearn imperative thinking and do functional thinking, given I have build my career on imperative Java and still, being payed to do imperative code


Yeah I get it, one step at a time 😉 Good luck!


Hey all! Currently writing some unit tests for a function and I have a question

(defn inner-fun [arg]
  (throw (ex-info "msg"
                  {:arg arg})))

(defn a-function [arg]
  (map inner-fun arg))
The following doesn't work (is (thrown? Exception (a-function "test")))
FAIL in () (form-init234056825029385.clj:1)
expected: (thrown? Exception (a-function "test"))
  actual: nil
I have to write it like this (is (thrown? Exception (doall (a-function "test"))) Is this the recommended way to do it or is there a better one, possibly without doall?


@pavlos map is ideally meant to be used with functions that dont do side effects like throwing exceptions as it expects a return value. Also its lazy, hence the doall. If your mapping functions has side effects I'd rather use (run! inner-fun arg) which returns nil. That way you should get the exception

💡 4

Ah, that makes sense, thanks a lot! What if inner-fun typically returns a value but throws an exception in some edge cases? In that case what's the recommended way to propagate an exception to a-function as well?


i.e. I want a-function to fail if inner-fun fails at least once


in that case I'd return some invalid value and check it afterwards


Its generally good practice to not mix up code and side effects.


Oh, I see. I'm used to the "throw early, catch late" adage, so this catches me a little bit off-guard to be honest 🙂


yeah in functional programming its just easier to reason about code if you keep these things separate.


in clojure we generally use the convention of having a ! at the end of function names which may do side effects


its okay to throw an exception here just the usage of map is non trivial.


Yeah it is (non trivial). To be honest I'm not yet 100% sold on the best way to do exception handling in clojure (custom error codes kinda seems like a regression but mixing code with side-effects is inherently bad, like you said). However, you've been really helpful. Thanks for your time! 🙂


Happy to help. Throwing exceptions is totally idiomatic in clojure though. Thats how most functions are written. How to call them is what matters most i think.

👍 4

If I try to update a map with a key that doesn't exist, I get a NullPointerException, for example (update {1 100, 2 300} 3 inc). Is there a smart way to insert in the map a k/v that don't exist and apply a function otherwise?


This is what I come up with:

(defn player-scores
  (if (nil? (get players-map player))
    (conj players-map [player points])
    (update players-map player #(+ % points))))


(update {1 100, 2 300} 3 #((if % inc identity) %))


look at fnil


boot.user=> (update {} :a #(if % (inc %) 1))
{:a 1}
boot.user=> (update {:a 2} :a #(if % (inc %) 1))
{:a 3}


Oh interesting, I've not seen fnil before


boot.user=> (update {} :a (fnil inc 0))
{:a 1}
boot.user=> (update {:a 2} :a (fnil inc 0))
{:a 3}


@nikola.kasev I'm confused, in the initial example you gave, why you're conjing when the key doesn't exist, instead of associng?


@carr0t conj will add a new k/v pair, takes it from the vector with two elements


fnil is one of those easy to forget functions that ends up cleaning up a lot of code when not forgotten (I say as someone who has occasionally forgotten about it) 😉


@nikola.kasev Yeah, I know conj will do that. I mean the normal use for conj is for regular lists, not maps. When I see conj, I expect a vector, list or similar. (conj players-map [player points]) could also be expressed as (assoc players-map player points), which makes it more explicit that you're dealing with a map, follows the pattern in your else case more closely etc etc. I don't understand why you'd ever use conj on a map like that instead of using assoc

👍 4

Hi people!! has anyone ever played with cognitect aws-api please ? I have a little issue while exploring the lib through the examples ... When I try to get a var via the aws/client function, the repl just hangs


@kaffein does the var s3 get bound? Can you type s3 into the REPL?


I can't, it's like if the repl had blocked actually


well actually it returned (I had it running in my other terminal so I couldn’t see it)


and I think I may have found the problem : I @ghadi... the supposedly optional value of one of the params to aws/client is not correct


There it is ...


thanks for your help @ghadi


Ah, yes. You don’t have to provide the region if it’s in your ~/.aws/config @kaffein


Ghadis-MacBook-Pro:~ ghadi$ cat ~/.aws/config
region = us-east-1

👍 4

or if you’ve set AWS_PROFILE and that profile within .aws/config has a region set


according to the documentation, there is a default value set by the lib actually ... so that’s weird


anyway, I will set it in the ~/.aws/configas you suggested


yes the provider itself is defaulted, but the default provider can’t guess information that isn’t there

👍 4

oh got it


I'm doing day 9 of Advent of Code, what would be an efficient data-structure for a ring of integer values where you have to take elements out, put elements in on an index, and also go clockwise and counter-clockwise?

Kelly Innes16:12:19 might be viable? Not sure how efficient it is but I suppose that would depend on the implementation.

Kari Marttila16:12:51

I'm using a Java library accessing Azure Table Storage (couldn't find native Clojure library). I made good progress with Clojure/Java interop but I have one difficulty implementing a class in Clojure that I need to supply to the library. I need to create the following class in Clojure public class CustomerEntity extends TableServiceEntity { public CustomerEntity(String lastName, String firstName) { this.partitionKey = lastName; this.rowKey = firstName; } public CustomerEntity() { } public String Email; public String getEmail() { return this.Email; } public void setEmail(String email) { this.Email = email; } } ... so that I'm able in Clojure to make a call like in the Java example: TableQuery.from(CustomerEntity.class).where(partitionFilter); I'm a bit puzzled should I implement the CustomerEntity class using proxy, gen-class or what?

Kari Marttila16:12:54

... a nice exercise to learn how to use Clojure/Java interop in real life if I can make it work. 🙂


I think you need gen-class since you have to pass named class to the java code. It might be better to actually do this in plain Java instead of clojure.

Kari Marttila17:12:52

Thanks for quick reply! I'll first try to create a gen-class, this is my personal exercise to learn Clojure features, so no hurry here. If I'm not able to make progress I downgrade this part to Java. 🙂

Kari Marttila17:12:53

I followed the diagram and it says: "use gen-class" 🙂

Kari Marttila17:12:39

I wonder if I could find a very simple gen-class example which provides a couple of constructors and a getter/setter...

Kari Marttila17:12:43

Unbelievable. I think this is going to work. I made a very simple gen-class that just extends the base class the library requests. Then I made the query using that gen-class and it returns 2 items just as I know it should: (count (into [] (. productgroup-table execute table-query))) => 2 Now I just have to figure out how to provide the member variables and their getters/setters for that class and how to get the values from the items.

Kari Marttila18:12:41

Using Clojure REPL experimenting with a new Java library seems to be easier than using Java to experiment with a new Java library.

Kari Marttila18:12:42

Unbelievable. I did it. I used a Java decompiler to see what kind of Java class actually got created. The base class provided getters for partitionkey and rowkey. Now it is simple to call the getter: (. (first (. productgroup-table execute table-query)) getRowKey) => "Books"

Kari Marttila18:12:09

This is like magic. I have been programming Java for some 20 years. I got used to all these edit-compile-build-test cycles. Now using Clojure REPL I can dynamically call the Java library methods and experiment in a way that was never possible with Java.

Kari Marttila18:12:11

I thought this is going to take at least a couple of days to learn enough Clojure/Java interop so that I'm able to make the first queries - It took a couple of hours. Clojure is so beautiful and the Clojure REPL just rocks.

clj 4

i write my java class


how to use it in clojure


@minhnhat10bk First you import it in your namespace declaration.


(ns my.namespace (:import (my.package.MyClass))


if you import only one class (:import my.package.MyClass)


Then you can use the interop 'sugar' to instantiate objects, call methods, call static methods ..etc. All explained here


my class path is src/pkg/myclass


(import '[pkg myClass])


but I get Syntax error (ClassNotFoundException)


@minhnhat10bk What is the package statement in your Java code?


(also, did you compile it? Clojure needs the .class file, not just the .java file)


after build it to .class


It ok right now


@minhnhat10bk If you're using Leiningen, you can have it compiled automatically when you run Leiningen. See


very beginner lisp macro syntax q: is there a way to return multiple forms out of a block? so something like:

(assoc {} :a 1
          (if condition
            '(:b 2)))


the idea would be that if condition was met, the two forms would be applied. I know there are other syntactical ways to achieve something like this (`apply`, cond->, etc). just wondering if there’s a more concise syntax