Fork me on GitHub
#beginners
<
2016-03-08
>
lmergen10:03:10

ok, so, how evil are dynamic vars in clojure?

lmergen10:03:43

it feels a bit like singletons to me

lmergen10:03:49

and they feel like an anti-pattern

lmergen10:03:32

my concrete issue at hand is that i need to have something similar to a connection pool

lmergen10:03:45

and how i should share that between the different ring handlers

tjg10:03:48

FWIW, I used it pretty often when I used Common Lisp, but never yet in Clojure... except when experimenting with error-handling. (Not that this is evidence one way or the other, since you may have a use-case I haven't had.)

lmergen10:03:08

yes, but the problem is... that doesn't always work in practice

lmergen10:03:12

> By all means, provide the functions to acquire and dispose of resources, but then let the application programmer decide what to do with them. Define API functions to take the resource as an argument.

lmergen10:03:42

in my case, that would mean exposing the connection pool explicitly to all ring handlers that use the database? is that correct.. ?

lmergen10:03:50

ehr, rather, exposing a specific connection

lmergen10:03:04

or i would have to write a ring middleware that automatically acquires and releases a connection

jonahbenton11:03:53

hey @lmergen the first one- db functions, called from handlers, should take a pool as an argument and get and release connections around query execution through the pool. So handlers should be able to "see" the pool. How do they do that- Stuart's piece is part of the story of a pattern for managing this tree of state- server -> handlers -> db pool- that also enables a fluid repl workflow: http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

lmergen12:03:12

hey that's the people behind datomic

jonahbenton12:03:46

The company is now called Cognitect, and they are behind Clojure and Datomic

lmergen13:03:21

that's pretty awesome... i really want to use Datomic, but it seems like a really big risk

roberto14:03:26

you don’t need dynamic vars to have a connection pool. I personally use component for that.

chris14:03:56

new(?) clojure faq on their site. going through it now, it’s interesting

krchia14:03:51

is there a sort of printline that i can see in the browser for .clj files/ the backend/

jonahbenton14:03:34

@lmergen bkamphaus from the Datomic team at Cognitect is active on the #C03RZMDSH channel

jonahbenton14:03:33

@krchia: it depends on the web framework, but usually you return a string in the :body of a response object. Using println or similar will write to your application logs or to a similar file on your server- not visible to users

lmergen15:03:21

so, in languages such as Erlang and Haskell, pattern matching is a big thing... in Erlang/Elixir, it's even used for "error propagation" -- what you see a lot, for example, is this pattern:

{:ok, value} = doStuff()
which will raise an error if the the result is not :ok ... is there something as simple and pragmatic for Clojure?

lmergen15:03:26

so the key here is that assignment of value, and the check for :ok is both happening at the same time

lmergen15:03:25

i'm almost tempted to make my own macro for this...

lmergen15:03:31

maybe i can do this with map destructuring... let me see

polymeris15:03:16

By raising an error, you mean throwing an exception, @lmergen ? I am under the impression in Clojure exceptions tend to be avoided, since they break function purity.

lmergen15:03:14

yes, I'm not sure what the best approach is in Clojure.. it feels like it suffers from the same problem as Haskell, that is: there are too many ways to do it

polymeris15:03:16

Often, nil is returned on error. I am not sure nil punning is the best solution (stuff might fail silently if you don't check), but it seems to be most common solution.

lmergen15:03:28

no, i also need to pass an error message

lmergen15:03:39

so nil is similar to Haskell's Maybe

donaldball15:03:04

There’s a pretty good library you might find interesting: http://docs.caudate.me/hara/hara-event.html

jonahbenton15:03:09

@lmergen the mindset is a little different, and there is something of a paradox of choice. pattern matching is a specific instance of a protocol- not a clojure protocol but the manner of callers engaging with callees. in other languages, support for specific protocols is part of the language. the language is opinionated about protocols to use. As a lisp, clojure is somewhat less opinionated. Within the constraints of syntax, you can build that protocol if you're interested- for matching, see an old example called matchure: https://github.com/dcolthorp/matchure

lmergen15:03:58

hmmm both look interesting

lmergen15:03:25

but I'm not really looking for a when-match, I'm looking for a assign-when-matcher-or-raise-error or something simple_smile

lmergen15:03:31

as in, programming by contract style

lmergen15:03:03

it's all a bit... complex

lmergen15:03:33

this might be a good place for a macro, but i think that's just my Clojure noobiness that thinks "oh yes, let's use a macro to solve this!"

jonahbenton15:03:53

right- in jvm-hosted languages, the callee can throw an exception; if you're returning a tuple/Maybe-style you're doing so to avoid the exception handling machinery

lmergen15:03:56

hara looks really good btw, but... maybe even too good

donaldball15:03:02

Curious what you mean?

lmergen15:03:30

well, hara looks like it's really solid, but also a really big project

donaldball15:03:57

That’s fair. It’s certainly not idiomatic clojure.

lmergen15:03:58

anyway, guess I should just get it out of my head i can do erlang-style pattern/error matching

lmergen15:03:22

or maybe i should just do a full-blown core.match

jonahbenton15:03:27

the error model is what's most different, you do have to think about error handling differently

lmergen15:03:12

which means just manually adding a lot of is-valid? checks, right?

jonahbenton15:03:55

well, there are lots of ways of doing it; in Haskell you can rely on the type system; in Erlang you can rely on the runtime

lmergen15:03:18

yes, I like the Erlang approach myself

jonahbenton15:03:53

you do need to be more mechanical in Clojure, which can then yield insights around data flow

lmergen15:03:27

what do you mean, be more mechanical?

d-side16:03:47

It really depends on how you want to handle that error (i. e. some errors aren't meant to be handled and should be spotted by the developer ASAP). If you're expecting an error somewhere you either have to explicitly indicate what to do; you could wrap that into a higher-order function probably for more reusability. I haven't seen many use cases for exceptions in Clojure except for Java interop. But maybe I just haven't seen too much of it yet %)

lmergen16:03:31

well, this for example is from our email provider, in what i consider to be very rare cases, sending an email might fail

lmergen16:03:46

so, throwing an exception would be appropriate

polymeris16:03:04

Use pre- and/or post-conditions, maybe?

lmergen16:03:16

hmmm, that's actually not too bad an idea

d-side16:03:58

Probably, so how do you intend to handle it? Retry? Log and forget?

jonahbenton16:03:02

well- wrt sending an email, it depends on whether that failure impacts the rest of the system, it depends on who cares

lmergen16:03:18

well, in this specific case, i eventually need to hook it into our monitoring system

d-side16:03:23

Then I'd probably stick with a higher-order function that wraps the action and either returns its result only (assuming :ok) or logs the error into the monitoring system and just carries on. Without any feedback to the caller.

d-side16:03:18

The last part about no feedback may not exactly be the best idea... depends.

Tim16:03:28

is there a function that tests if a symbol is a function? like fn? or something?

donaldball17:03:26

The fn? fn tests if a value is a Fn