This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-28
Channels
- # announcements (6)
- # beginners (89)
- # boot (1)
- # calva (1)
- # cider (24)
- # cljsrn (19)
- # clojars (2)
- # clojure (102)
- # clojure-europe (2)
- # clojure-italy (9)
- # clojure-nl (1)
- # clojure-spec (6)
- # clojure-uk (56)
- # clojurescript (29)
- # code-reviews (14)
- # cursive (5)
- # data-science (1)
- # datomic (44)
- # duct (1)
- # emacs (10)
- # figwheel-main (5)
- # fulcro (8)
- # graphql (10)
- # hoplon (1)
- # leiningen (7)
- # overtone (17)
- # pathom (8)
- # re-frame (13)
- # slack-help (3)
- # spacemacs (22)
- # sql (2)
- # vim (3)
@veix.q5 Using :main-opts
or on the command-line: -m entry.point
to tell it to run entry.point/-main
@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...
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)
@seancorfield appreciate it. manifold.stream/description did it for me
hmmm, seems like manifold.stream/downstream 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/a
user> (swap! a assoc-in [:game1 :players] ["p1" "p2"])
{:game1 {:players ["p1" "p2"]}}
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
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.
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
[player
points
players-map]
(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) %))
boot.user=> (update {} :a #(if % (inc %) 1))
{:a 1}
boot.user=> (update {:a 2} :a #(if % (inc %) 1))
{:a 3}
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 conj
ing when the key doesn't exist, instead of assoc
ing?
@delaguardo, @rakyi thanks
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
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
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
according to the documentation, there is a default value set by the lib actually ... so that’s weird
yes the provider itself is defaulted, but the default provider can’t guess information that isn’t there
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?
https://en.wikipedia.org/wiki/Doubly_linked_list might be viable? Not sure how efficient it is but I suppose that would depend on the implementation.
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?
... 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.
This can be useful: https://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
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. 🙂
I followed the diagram and it says: "use gen-class" 🙂
I wonder if I could find a very simple gen-class example which provides a couple of constructors and a getter/setter...
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.
Using Clojure REPL experimenting with a new Java library seems to be easier than using Java to experiment with a new Java library.
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"
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.
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.
@minhnhat10bk First you import it in your namespace declaration.
Then you can use the interop 'sugar' to instantiate objects, call methods, call static methods ..etc. All explained here https://clojure.org/reference/java_interop
@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)
@minhnhat10bk If you're using Leiningen, you can have it compiled automatically when you run Leiningen. See https://github.com/technomancy/leiningen/blob/master/doc/MIXED_PROJECTS.md