Fork me on GitHub
#beginners
<
2016-06-04
>
mtorres00:06:37

I've been looking for good practices when it comes to error handling in clojure/clojurescript, and it seems like the try catch pattern is standard. Am I missing a better way? Thanks.

renan01:06:14

hi guys, i am developing a websocket server with clojure, but i have a problem i can not do a 'broadcast' between users connected in websocket. Anyone already done it?

seancorfield01:06:18

@renan: What’s the front end? ClojureScript?

seancorfield01:06:39

If so, have you looked at Sente? That supports broadcasting, as far as I remember.

renan02:06:52

@seancorfield: In back end, I was using the Immutant, because this not work the 'broadcast', i'll see the Sente, thanks 😁

seancorfield05:06:12

I'd probably start with something small and lightweight like http-kit -- unless you need all of the features Immutant and JBoss bring? @renan

seancorfield05:06:00

I'm really liking the freedom that moving away from big Java style containers brings.

renan05:06:55

@seancorfield: Not, In my case just test, but I have other problem now is running JAR's files of Lucene with Clojure 😅

seancorfield05:06:33

Hmm, Lucene and Solr are on my list. I hope they work okay with Clojure!

renan05:06:47

@seancorfield: I found little dependencies... and not support the latest version of Lucene.. and my experience with Solr not very good, i don't like Solr 😅

val_waeselynck07:06:55

@mtorres yes try catch with ExceptionInfo for conveying data with the errors

val_waeselynck07:06:26

and some macro helpers to make it work with core.async

dmbennett16:06:13

hey folks, in terms of practical conventions when is it appropriate to use def vs defn is there a case where using def over defn or vice versa is an antipattern?

bronsa16:06:36

what do you mean? defn is sugar over def for defining functions, you should always use defn over def when defining functions, unless you cannot for very specific reasons.

donaldball17:06:08

Essentially the only reason I will not use defn when defining a fn in a var is if I want the fn to close over some other values that I don’t want to be vars, or don’t want to pay the var lookup tax to access

dmbennett17:06:40

What I’m trying to understand is the difference between passing the outcome of a function to a function and calling a function on a function directly.

donaldball17:06:43

I’m afraid I don’t follow that, do you have a pair of examples?

donaldball17:06:44

Well, sum is a fn of two vars, so neither example should work

dmbennett17:06:59

right, my bad

donaldball17:06:28

In the latter example, square-of-sum is a var whose value is 16

dmbennett17:06:36

alright, so I corrected that, but my question is: def vs defn?

donaldball17:06:51

def defines a var of arbitrary value

donaldball17:06:01

defn defines a var that is a fn, which is the most common kind of var

donaldball17:06:19

(defn [x] …) is essentially equivalent to (def (fn [x] …))

bronsa17:06:08

@dmbennett: are you familiar with other programming languages other than clojure? your question doesn't make much sense, in java what you're asking would be the difference between e.g.

public static long squareOfSums(long x) { return x * x; }
public static long val = squareOfSums(2+2);
and
public static long squareOfSums = (2+2)*(2+2);

dmbennett17:06:30

I’m new to programming in general, but have some experience with ruby

bronsa17:06:48

one is a method you can apply to different values, the other is just a value

dmbennett17:06:19

Alright, so in trying to clarify my question, so that its more sensible: is it preferred to call a function on a function, or set a var to the outcome of a function and then call a function on that variable?

dmbennett17:06:11

or does it depend on the context

dmbennett17:06:35

I’ve ammended the snippet

bronsa17:06:18

alright so "call a function on a function" does not mean what you think it means -- in clojure functions are values themselves so that phrase would mean "passing a function as an argument to a function"

dmbennett17:06:21

all the examples are supposed to output the same value.

bronsa17:06:41

what I seem to understand you asking is "should I def intermediate values or should I inline the expression" to which the answer is: it depends. def is for values that you need globally and you will reuse. intermediate values are not that. if you want to name an intermediate value to avoid nesting too many calls, look at let

dmbennett17:06:33

ok, I think that addresses my question, thanks for being patient and teaching me through my own opaqueness.

Drew Verlee19:06:29

In cases where side effects are necessary, how do you indicate that their occurring? Take the case where you create a postgres database. I can think of 2 approaches to draw attention to the side effective. 1. Comment the code — WARNING SIDE EFFECT: db create 2. return a handle/connection to the database. I think these might be the only option regardless of the side effect. As I think of necessary side only being necessary when your changing something that you need to persist past the programs execution (though I would be interested to hear counter examples).

donaldball19:06:19

When I have var fns that have side effects, I usually use the trailing ! convention

donaldball19:06:49

Though almost always when I have code that has side effects, I’ll look to encapsulate it behind a protocol

Drew Verlee19:06:12

@donaldball: > Though almost always when I have code that has side effects, I’ll look to encapsulate it behind a protocol could you explain a bit what that means? or what the benefit is?

donaldball21:06:14

Sure thing. Clojure protocols are coherent groups of fns that operate on one or more things. An example might be:

donaldball21:06:46

(defprotocol UserStore
  (load [_ id])
  (save! [_ id user])
  (delete! [_ id]))

(defrecord Database [db]
  UserStore
  (load [_ id]
    (first (jdbc/query db ["select * from users where id = ?" id])))
  ...)

(defn build-memory-user-store
  []
  (let [state (atom {})]
    (reify UserStore
      (load [_ id] (get @state id))
      ...)))

donaldball21:06:20

The advantages are that it decouples the callers from the implementation details, and in particular for protocols with side effects, allows you to reify local implementations for use in tests or in development.

donaldball21:06:00

The disadvantages are the same as with anything that adds a layer of abstraction: it hides implementation details from the call sites, making it potentially more difficult to understand and debug, particularly if the abstraction is awkward or poorly conceived.

donaldball21:06:15

I generally extract protocols from spike or legacy code, but tastes differ. I’m given to understand core.async was initially presented by Rich as two or three protocols with no impls.

donaldball21:06:50

(Immutable data structures are my favorite part of clojure, but protocols are a close second.)

seancorfield23:06:03

(map (partial select-keys [:created]) histories) I think

seancorfield23:06:54

Ah, no. select-keys takes the arguments the other way round

seancorfield23:06:06

(map #(select-keys % [:created]) histories)

seancorfield23:06:48

mapv if you really want a vector back instead of a sequence @dmbennett

dmbennett23:06:46

worked like a charm