This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-11-26
Channels
- # announcements (2)
- # aws (4)
- # babashka (5)
- # beginners (91)
- # calva (4)
- # cider (17)
- # clara (13)
- # clj-kondo (14)
- # cljsrn (11)
- # clojure (159)
- # clojure-europe (2)
- # clojure-nl (14)
- # clojure-norway (2)
- # clojure-taiwan (2)
- # clojure-uk (32)
- # clojurescript (101)
- # clojutre (4)
- # cursive (13)
- # data-science (1)
- # datomic (46)
- # emacs (68)
- # figwheel-main (5)
- # fulcro (48)
- # graalvm (7)
- # graphql (6)
- # instaparse (5)
- # joker (4)
- # lambdaisland (1)
- # leiningen (2)
- # malli (9)
- # off-topic (41)
- # pedestal (15)
- # re-frame (47)
- # reagent (7)
- # reitit (14)
- # shadow-cljs (180)
- # spacemacs (58)
- # specter (1)
- # tools-deps (13)
Isn't part of the issue with the desire that some would like it to work across both clj and cljs? I think the expression Sean gives above works for clj only.
but even using namespaced keywords, I never use alias to create a short way to type them
You type fully namespaced keywords out manually each time, and/or copy/paste, or Emacs dynamic abbrevations, etc?
Certainly I think some devs might not be taking better advantage of plain old copy/paste as often as they might.
but I suspect it is born from the simple observation that they can easily create aliases for vars in other namespaces, so why not keywords?
maybe it is a sort of circular thing, they see aliases in examples, so they use aliases, and because they use aliases they it is annoying that cljs doesn't have them. and instead of walking all the way back and rethinking the decision to use aliases, they just want aliases in cljs?
People use aliases for namespace on vars all over both clj and cljs
Portably, in cljc files, too.
which makes me think, it is a shame the namespaces for keywords and namespaces for code are both called namespaces
yes, we try to use "qualifier" for the first part of keywords/symbols these days. the qualifier may correspond to a namespace, or may not.
I'm happy to get a deeper understanding of the differences, which I haven't thought through deeply, but at least at the level of X works for Y, why doesn't X also work for Z? kind of analogy reasoning, it is a reasonable question to ask, I think.
namespaces for code are a very formal thing, the runtime keeps track of them, and there are rules about them, and they exist independently of the names in them
Maybe it is a shame they are called the same thing, but that name is enshrined by Clojure core docs and functions like namespace
and name
, from folks that are usually pretty careful about what they call things.
but calling them the same thing leads people to thinking they are connected in someway
They are connected in at least one way -- require
with :as
to create an alias for a namespace, you can use the alias both for Vars and for keywords.
Will be AFK for a while -- flight landing soon-ish 🙂
these days we try to prefer the word "qualifier" for the first part of keywords and symbols
as in qualified-symbol?
, qualified-keyword?
etc
the qualifier may correspond to a namespace or an alias, or neither
one option: go with pure clojure land, e.g., buddy, but I am not sure for the maintenance and future support
I'm told that unlike Java where libraries tend to get updated regularly, Clojure libraries on the other hand live much longer
so you can make use of Clojure libraries even if they were made a while back and be sure that it will work just fine
I guess it's a bit more problematic when it comes to support/fixes/patches/etc. especially for a security library
yes. that’s what I worry about. It still feels a little bit unsafe even people claim clojure world doesn’t care about the recent update time of a library.
the other option is: go with java libraries, e.g., spring security, but it seems too bloated, and I worry about the inter-op.
@seancorfield what’s your dev env? intellij+cursive or emacs+cider ?
@UGC0NEP4Y neither. Atom + Chlorine + Cognitect's REBL. No nREPL, no CIDER, no dev dependencies at all.
Just start a socket repl in any process, connect Chlorine, and that's it.
I don't like IntelliJ 🙃
sure, not a huge fan either -- but the debugger in cursive is very helpful on occasion
A while ago someone mentioned Apache shiro(a Java library for all that) and it looked interesting but I haven't actually used it yet, just bookmarked it for the future
I think in theory it is possible to use in non servlet environments as well, people say you can even use it for command line apps. But I think in those cases you have more to manually setup
hi! how can I import two Java classes with the same base name? I've tried this but the compiler complains about Foo being already defined:
(ns my.ns
(:import [my.first.package Foo]
[my.other.package Foo]))
however, if I just add the fully qualified name, like this, the compiler also complains about ns not conforming to its spec:
(ns my.ns
(:import [my.first.package.Foo]
[my.other.package.Foo]))
Oh, I see. From the docs (https://clojure.org/reference/java_interop), I seems that the only way to do it to not import either class and use my.first.package.Foo
or my.other.package.Foo
everywhere in the code
Thanks! in my case, it's not that big of a deal. My main concern was that I thought my code wouldn't work without the import, but apparently that's not the case, as using a fully-qualified-name will get the class even if not improted 👍
Yeah, you have to fq at least one of them
at least for me its morning 😛. Question is there a function that lets me apply a transformation to a stream... meaning i want to consume a stream make an operation and return a stream (unknownFunction myTransformer (slurp myStream))
yeah. so i would like it as a string first. but i would imagine that would be part of my transformation
Don't know how to create ISeq from: clj_http.core.proxy$
so to put you in context the stream is an http response. I would like to apply a transformation and return the transformation
I ended up asking here : https://stackoverflow.com/questions/59051729/apply-map-to-a-filterinputstream
(require '[clj-http.client :as http])
(require '[ :as io]
(->> (http/get "" {:as :stream}) :body io/reader line-seq (map count)) ;; => result is (98822) (single line of 98k characters)
that is, if you want to process your input stream (which is a stream of bytes) as lines of text (which should be first converted to a stream of characters — reader, and then splitted on newlines)
it all depends on what you want to do with that stream. parse it using some different library? it may have a way to consume input streams
so basically i do need to consume it and then re-create the stream with io/reader right?
I don't know implementation details of clj-http, but it probably just sends input stream to json parser, so there is no "hold json as string in memory" step
i think for now what i was actually looking for is io/reader
I do need the json part too but i can kick that for the future for now
so this worked for me:
vlaaad@stoldt1220 ~> clj -Sdeps '{:deps {clj-http {:mvn/version "3.10.0"} cheshire {:mvn/version "5.9.0"}}}'
Clojure 1.10.1
user=> (require '[clj-http.client :as http])
nil
user=> (http/get "" {:as :json})
;; lots of json
Is there a way to programatically obtain the source location for protocol implementations?
Say I have a protocol from a library
(defprotocol Flippable (flip [x))
and then extend that protocol elsewhere in different namespaces
(ns my.app)
(extend-protocol other.lib/Flippable
Pancake
(flip [x] ...))
Then given the function flip
and type Pancake
, I want to somehow get the file/line number of the extend-protocol expression
(clojure.pprint/pprint other.lib/Flippable)
(into {}
(map (comp (juxt identity meta) key))
(:method-builders Flippable))
(let [{:keys [impls]} Flippable]
(into {} (for [[k v] impls
[method obj] v
:let [var (resolve (symbol (first (string/split (str obj)
#"\$"))
(name method)))]]
[k (assoc (meta var)
:var var)])))
Sorry, I don't understand what the above is supposed to achieve - I'm trying to get the location of the method implementation for a particular type, not the protocol definition
The context for this is tooling support - a protocol or multimethod may have its implementations scattered across many namespaces, and it woudl be nice to be able to "jump-to-definition" for a given type for debugging purposes.
I couldn't get what you wanted / needed, but I share my path Var's usually contains file line metadata, but it do not work for protoocls 😞
hi everyone, why global atom isn't shared between deftest functions ?
Does anyone know of a good library for coercing column names and values from SQL results?
e.g. {:foo_id "test"}
to {:foo/id :test}
given some definition like [:foo :foo_id keyword name]
jdbc.next?
The result builders look interesting. Thanks for pointing them out.
Though it looks like converting to next-jdbc might be more work than necessary.
Or maybe not… looks like there’s a get-datasource
function for backward compatibility. I’ll investigate further.
happy to help, btw, there is the new functionality about to be released - middlewares. commits are on master
Thanks
I've used clojure.set for this before: https://clojuredocs.org/clojure.set/rename-keys
https://github.com/riverford/mappings is really interesting in this space if you're not after something sql specific
Thanks @dominicm, that looks interesting.
You could also check out https://github.com/wilkerlucio/spec-coerce
Does anyone remember what dependency combination will fix this exception?
No implementation of method: :has? of protocol: #'clojure.core.cache/CacheProtocol found for class: clojure.core.memoize.PluggableMemoization
@weavejester - saw this a couple of months ago, maybe it can fit your needs? https://github.com/noprompt/meander
Might be a little too generic, but thanks anyway 🙂
I have a collection of email messages as Clojure data called threads
that I'm trying to extract some info from, mostly via string/HTML parsing. Sometimes the messages have an unexpected format and for now I just want to ignore those errors. Something weird is happening when I eval at the repl.
(map #(try (all-info (:body %))
(catch Throwable th
nil))
threads)
gives:
Error printing return value (IllegalArgumentException) at clojure.core/-cache-protocol-fn (core_deftype.clj:583).
No implementation of method: :date of protocol: #'tick.core/IExtraction found for class: nil
The specific error doesn't really matter, what's weird to me is that it shows up at all since I'm catching everythng. Even weirder,
(map #(try (dump (all-info (:body %)))
(catch Throwable th
nil))
threads)
works as expected, returning the results without any error. dump
is just a fn that pretty-prints its arg and returns it. I don't understanding why wrapping in a printing fn would affect the try/catch behavior.
Is all-info returning a lazy-seq? It probably is all-info calls map
No, all-info
just returns a map:
(defn all-info
[thread]
{:confirmation-number (second (re-find SUBJECT_CONFIRMATION_REGEX (subject-1 thread)))
:departures (departures (html-resource (StringReader. (message-1 thread))))})
For a lazy-seq, the values aren't realized until they are requested. In this case they are being realized when the REPL looks at them to print them, which is past the try form
If any of those are lazy, you can get that behavior
Exactly
Wow, that is a tricky little interaction, thanks @jshaffer2112, saved me a while there. Do people generally just sprinkle in into
calls or something to coerce to collections explicitly?
If I want instant realization, I use vec or mapv (mapv is just map that returns a vector instead of a seq)
But it's usually not for that reason. That type of error catching is really hard to debug. I would prefer to filter out things that will cause that type of error
and do any necessary try right around where the error can occur, not in a parent function
Yes, for is lazy. Normally laziness is good to have, so I rarely force realization
instead of (try (for ...) catch Ex e)
you could write (for [i [...]] (let [x (try ... catch )])
, i.e. make the error handling more local
Usually, yes. Those have different behavior though. (try (vec (for ...) catch Ex e)
will return nil if anything inside causes an error, while the second example will have a nil for each value that caused an error
Right, I'm just being lazy (pun intended) at this point since it's early prototyping on a side project. Also, it turns out that any message that doesn't parse for any reason is irrelevant anyway, so I'd rather just express that once at a high level than catch a bunch of specific parse failures, only to wrap and propagate them up for the same effect.
You could put the try inside all-info then, and just call (map #(all-info (:body %)) threads)
You would have to realize departures, so (vec (departures ...))
maybe
True, that might be better. It's interesting to see how laziness interacts with everything here. It feels like a non-local effect. Haven't been bitten by that before.
Laziness interacts in odd ways with lots of things: dynamic binding, side effects of most kinds, and exceptions.
Things go so much smoother if you write as many pure functions as possible
It is also something that you do not always notice in repl tests, due to the forcing of laziness caused by the P
Yes, that's definitely a good rule, but it's still interesting to think about. When you're in pure, data-manipulation code, laziness feels like a good default, but otherwise eager-by-default seems to fit better. I believe at one point Rich said laziness might not be as pervasive in the language if he'd landed on transducers earlier.
@jshaffer2112 Are you talking about pure to the point of using monadic composition for error propagation and avoiding try/catch?
No, I just filter out or just return nil for invalid values. I mean pure as in "when you call it, it does the same thing every time with no side effects". Not that it can't use side effecting operators like try-catch internally, just that they can't escape
I might throw IllegalArgumentException, and you can find ways to crash things, but usually exceptions are from programming errors
I want to give spec a try though. Then it'll be "pure as long as the spec validates"