Fork me on GitHub

Which I think is a safe use of eval, but its unclear


If I have a bunch of futures in a list, is it a good idea to (map deref) on it to wait for everyone? Or is there a better way?


@pablore Perhaps (run! deref futures) to avoid map laziness


@mfikes yeah that look better than composing doall and map


If you just want to wait, and aren't going to consume the future values as a result of the map call, yeah run! is about as succinct as it can get


run! doesn't return the value from the futures though


I'm concatenating them all and then writing the result to a file, but it may be better for each future to write to the file since order doesn't matter...? Or may it cause problems if I do that?


if they are in futures for performance reasons, consider that writing to a file might be the slowest part


So I did it, I scraped the entire MTGMarket website for card names and their price. Each future was meant to deal with one specific page of a giant table.


Is :gen-class’s :methods still the only way to add annotations to methods, as shown here: It’d be nice if the annocations can be added to the functions instead…


@xiongtx functions aren't methods, they are objects that extend IFn (which has an invoke method and applyTo)


@xiongtx you can make an annotated method without a gen-class, but then you need something that defines a method (eg. reify, proxy, defrecord ...)


@noisesmith What I’m wondering is if, by using :gen-class, I have to add the annoations in the :gen-class bit, like:

 :methods [[^{ {:value #"^a withdrawal is in the DB$"}}
            a-withdrawal-is-in-the-db [] void]])
Or whether the annotation can be added to the function instead.


what would you annotate on a function?


if you need an annotated method, you can't use a function for that - you don't have control over how function objects create methods


Hmm, yeah, that makes sense. Then :gen-class doesn’t know anything about the function until it looks it up, so annotations on the function can’t inform :gen-class, I suppose.


the gen-class ends up creating a stub method that just uses the function, and it won't use annotations on the function (even if you figured out how to put it here)


as far as I know at least


I'll go ahead and use the eval, resolve seems harder, since it can't work with locals and non symbols


@xiongtx I've written (Java) annotated functions in Clojure for New Relic agent tracing... let me get the blog post about that...


:thumbsup:, I’ll take a look


I used definterface and deftype to create a framework in which to place annotated methods.


When using :extends in a :gen-class, is there a way to access fields of the extended class?


greetings! is still a thing? is it actually noticeably useful compared to regular try/catch? and when?


@misha it’s more idiomatic to use normal try/catch with ex-info now


I invite everyone, who agrees with this, to click that thumbs-up reaction

Alex Miller (Clojure team)14:03:00

it is most common to use normal try/catch. But additionally, slingshot provides additional functionality that is useful and I’ve gotten a lot of value out of that too.


for instance, with clj-http I found this pattern useful:

  (catch [:status 401] {:keys [request-time headers body]}


does anyone have a repo they can point me to w/ a test suite they love? i want to get a sense for how the clojure community thinks about granularity of tests, organization of tests, etc


What is the CLJ view of ? An idea worth copying, or no fundamental ideas / misguided ?


Reminds me of


Has benefits. The environment becomes a first class thing you can pass around, but then you end up with incompatible environments, as became the case with lisp and smalltalk "images"


@U8ZA3QZTJ: I'm missing somethihng, what does smalltalk/clojure have to do with storing entire documents in an URL ?


Hmm? I was replying to your post - your post is the one that asked opinions of lively-kernel, and I mentioned something closely related


Storing stuff in a URL isn’t the point, it’s that self-contained bots are a possible future


thats.... unpleasant


In Clojure is there a way to do protocol composition? Being able to create new protocols out of other protocols similar to how you can create new Go interfaces using composition?

Alex Miller (Clojure team)18:03:08

protocols are maps. it’s possible to programmatically manipulate them.


@dnaeon: the way it's typically done is to make protocols that represent each aspect of a data type, then implement a group of them, you can look at the protocols / interfaces implemented by built in clojure types with supers


user=> (supers (class {}))
#{clojure.lang.IFn clojure.lang.IObj clojure.lang.IMapIterable java.lang.Runnable clojure.lang.APersistentMap clojure.lang.AFn java.util.concurrent.Callable clojure.lang.ILookup clojure.lang.Seqable java.lang.Iterable clojure.lang.IHashEq clojure.lang.Counted clojure.lang.IPersistentCollection clojure.lang.Associative clojure.lang.IKVReduce clojure.lang.IMeta java.util.Map clojure.lang.MapEquivalence clojure.lang.IPersistentMap clojure.lang.IEditableCollection java.lang.Object}


I'm working on project which would need to abstract things on the storage backend side, so that we can have different storage backend implementations. Currently the storage backend protocol consists of a few functions for getting a particular thing (e.g. get-user, put-user, etc.). While still evolving I suspect other things would show up as well (e.g. more functions like get-foo, put-foo, etc.), so my concern is to keep the whole protocol small and tight and was hoping to use some kind of composition. Another possibility I was thinking of is having a protocol for each type, e.g. defprotocol User with it's functions, another one defprotocol Foo, etc. Which way is better to go? Should I go with one big protocol, or separate protocols for each type and have each backend implementation implement only the protocols it is concerned about? What is considered most idiomatic in Clojure? Or am I going in the wrong direction as a whole? 🙂


separate protocols is definitely better


ancestors dont list all protocols if i recall


Depends when/how a type is extended (inline vs with extend)


right - in this case encestors and supers return the same thing


user=> (= (ancestors (class {})) (supers (class {})))


(on mobile I can't play with a repl, but this should be easy to test)


ancestors appears to be supers + derive


ancestors calls supers, and adds to the results


derive is what creates the global multimethod heirarchy


@noisesmith is having separate protocols for each type something that is considered idiomatic in Clojure? Thanks for all the feedback so far! 🙂


@dnaeon: yes, in idiomatic clojure the only reason to include two methods on one protocol or interface is if they are coupled


clojure.core is made of a large number of very thin interfaces


@noisesmith thanks a lot, I know what to do now. Was having some doubts myself, but your answers made things clear for me on how to move forward. Thanks again!


It seems that the :exposes-methods option of :gen-class requires that the exposed-name be different from the super-method-name; otherwise the generated class will have methods w/ duplicate names / sigs. Is this just the way gen-class works? Don’t really see anything in the documentation about it.


In this specific case, couldn't you just use normal recur?