This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-12
Channels
- # admin-announcements (1)
- # bangalore-clj (13)
- # beginners (149)
- # boot (123)
- # cider (7)
- # clojure (167)
- # clojure-brasil (3)
- # clojure-greece (1)
- # clojure-korea (2)
- # clojure-new-zealand (2)
- # clojure-russia (70)
- # clojure-sanfrancisco (3)
- # clojure-spec (84)
- # clojure-uk (36)
- # clojurescript (300)
- # code-reviews (242)
- # community-development (34)
- # core-async (4)
- # css (1)
- # cursive (37)
- # datascript (1)
- # datomic (20)
- # defnpodcast (1)
- # dirac (15)
- # events (7)
- # garden (12)
- # hoplon (100)
- # lein-figwheel (11)
- # off-topic (2)
- # om (69)
- # om-next (3)
- # onyx (86)
- # planck (14)
- # proton (4)
- # protorepl (1)
- # quil (2)
- # re-frame (53)
- # rum (3)
- # untangled (1)
- # vim (50)
@quoll I just listened to your interview on the most recent Cognicast - I think it makes the perfect companion to your Conj talk, there was a lot of great information in both that complemented the other. As someone who had no idea what semantic web or rules engines were 2 weeks ago, it was a pretty comprehensive intro and I think I may even have some future work that might benefit from one. Thanks!
i find the lack of good random graph generators in clojure surprising, perhaps i am just not finding it. anyone knows implementations of the Barabasi-Albert or even better the Holme-Kim generator? Or something that can generate scale-free networks at least?
closest i got was this https://compuzzle.wordpress.com/2015/02/03/generating-barabasi-albert-model-graphs-in-clojure/
is the general consensus to prefer namespaces keys in maps?
@alexisvincent yes, this is one of the hot topics, specially since clojure.spec, you should prefer namespaced keywords, unqualified keywords are still good for more local things
@wilkerlucio This seems to be the way spec nudges you. Shot
it's a good thing, global long namespaced names can be shared across applications and libraries, think that on long term you will be able to re-use specs like you do with functions, and even better, imagine just by using the correct keyword as key you get the data validation for free 🙂
it also encourages you to use a single flat map instead of many nested maps. Now :person/name can exist in the same map as :car/name and :pet/name, and :data.importer/name, no longer a reason to have three separate maps.
@alexisvincent what's your concern with namespaced maps?
that is nice 🙂 I feel like it limits refractorability. Unless the clojure refractoring tools are good? Im new to the language
Im concerned that if I overqualify things Im going to give myself a hard time later when I want to better structure my code. Im new so this is an inevitability
@alexisvincent: namespaces of keywords can be independent of namespaces of code
so at worst your code might be a bit more verbose to continue referencing the old keyword-namespaces
except if you’re using ::
everywhere, this would break if you moved things…?
that's what I meant by the code being more verbose -- you'd have to change those
so it doesn't limit refactorability, but it might limit your appetite for refactoring :)
"but it might limit your appetite for refactoring :)” thats what I meant xD
I’m building a system where namespaces look like this shipping.parcel
, should I not use the ::
helper with spec? It’s a pain specifying :shipping/*
everywhere
OH 🙂 ::
can also be used for aliasing
@alexisvincent the support for refactoring is very good on Cursive, it always worked for me when I need to rename keywords
@wilkerlucio I’ve just switched from cursive to trying cider with spacemacs
enjoying the experience so far
nice, just use what feels better for you 🙂
@alexisvincent about the namespaces, I discussed with some people at Conj and this seems to be a common pattern: use fully qualified namespaces for library code (code you intent to share with other people, so long names like company.core.model/name
) and single namespace for domain data (like :shipping/name
:user/name
)
@wilkerlucio this does make sense 🙂 I kinda have the best of both worlds with the current aliasing approach
I would like some better aliasing, you can do on clojure, like: (create-ns 'shipping.parcel)
then (alias 'sp 'shipping.parcel)
, after that you can do ::sp/whatever
, just keep in mind this doens't work on clojurescript
and as mentioned, if you do (:require [foo.bar :as b])
you can then later do ::b/name and that will expand to :foo.bar/name
Thanks guys. Thats helpful
Im keen on the aliasing method. Flexible and doesnt clutter the namespace
@wilkerlucio there's several Clojure tickets asking for that, I think the current status is that they need some hammock time since there's no reason this needs to be tied 1:1 with Clojure namespaces.
But I want that feature too.
@tbaldridge yes, that will make using long namespaces a non brainer, after that I would be happily willing to use long names for domain data 🙂
What is the best way of namespacing an existing map? Using a function, not the reader. Keys are unknown
alqvist: everybody writes a "map-keys" function at some point 🙂
I don't think there's a right answer
I sometimes just do (into {} (for [[k v] m] ...))
and there are plenty of libraries that make transforming maps easier
like specter
jcromartie: I went with
(defn qualify-map [namespace m]
(reduce-kv #(assoc %1 (keyword namespace (name %2)) %3)
{} m))
it looks fine to me
honestly I don't understand the point of reduce-kv over plain old reduce
is it a performance thing?
@jcromartie the existence of clojure.lang.IKVReduce
is a hint that yes
yeah, I'd assume
I looked at the source of reduce-kv quickly but it just calls a protocol function of course
Hey all, the 2016 State of Clojure Community survey is now open! We do this every year as a way to take the pulse of the community and if you can spare 5 minutes to take it, it would be awesome to get input from everyone here. https://www.surveymonkey.com/r/clojure2016
@jcromartie it's definitely faster in many cases than pure reduce
I think your solution is going to have good performance. Maybe just use a full (fn [m k v] ...)
instead of a #(...)
for clarity?
jcromartie: Wooah take it easy now, I don't want to be replaced just because someone could understand my code 😛
BTW with specter, it looks like this
(defn qualify-map
[namespace m]
(transform [ALL FIRST] #(keyword namespace (name %)) m))
I think this is about as fast as you can get: (defn qualify-map [ns mp] (persistent! (reduce-kv (fn [m k v] (assoc! m (keyword (name ns) (name k)) v)) (transient {}) mp)))
@tbaldridge I would assume that the various protocol implementations for reduce-kv use transients
but it might be a bad assumption!
@tbaldridge actually, for small maps (PersistentArrayMap) it's faster not to use transients
@jromine transients are for updating collections reduce-kv doesn't update anything
I may be way off here but I could imagine an implementation of reduce-kv that starts with a transient version of the initial map
or vector
but no, I see what you mean
it's not associng anything
it's entirely up to the fn you pass in...
Does anyone know where I can get more background on org.fressian.impl.InterleavedIndexHopMap
which is used by Clojure Fressian serialization?
I just wanted to get some background one what it’s about. Obviously I can just read the implementations, but not sure that’ll show me the real reasoning behind the choice. (I guess theoretically I could figure it out 😛 )
@mikerod it's a hashmap that uses open-addressing, and the InterleavedIndexHopMap describes how to deal with collisions
I think @stuarthalloway could probably help with rationale/impl
anyone aware of a cfg parser generator a la instaparse, but for parsing clj data instead of strings?
@alandipert rewrite-clj has done the work you want, I think
I was just wondering if it was based on some paper somewhere or something like that to get some quick background
@dominicm thanks, i'll give it a look
Leiningen seems to be remembering which dependencies I have used in the past. I do
$ rm -rf ~/.lein ~/.m2
$ lein repl
and it downloads all the dependencies in my profiles.clj
(which no longer exists). Are there any other caches I need to clear? This behavior does not reproduce on a virtual machine with a fresh install of macOS and Leiningen. I have also tried $ brew uninstall leiningen && brew install leiningen
to no avail. I am not running any of the above from inside a Clojure project.after brew uninstall leiningen
can you check to see if which lein
finds anything?
the simplest explanation for lein downloading deps specified in your profiles.clj is your profiles.clj still exists
and are you running lein repl
in a filesystem subtree that has a project.clj or profiles.clj somewhere above it?
re: namespaced keys, at an old job we once spent like a couple of years first realizing and then untangling the fact that our python webapp had a ton of code that read self.country
and did various things based on it
and a slightly smaller amount but still medium amount of code that set self.country
and performed some side effect
(with great method names like self.set_country_and_maybe_redirect(args)
) - i have learned to be terrified of things with names like foo_and_maybe_perform_side_effect()
but anyway so what i’m getting at is that it took us a while to realize that there were different kinds of country, and to notice that different corners of the codebase were setting self.country
and reading self.country
with their own interpretations
so this third of the codebase treated self.country
as the country of the business that was currently being viewed by a user, and this other third treated it as the country associated with the user’s account, and this other third treated it as the country associated with the web interface’s locale
and so if you were trying to reason about how page X would behave if a logged-in user was viewing a business in france and the user’s home country was set to england and they were viewing it in the en_US locale....
anyway we (mostly) got rid of self.country when we realized how messed up the situation was, and started instead just explicitly passing around things like business[‘country’]
or interface_locale.country
, etc
and all this flashes through my head whenever i think about regular keys vs namespaced keys - a lot of hassle could have been avoided if we’d eg used :business/country from the start rather than :country
namespaced keys are a wonderful thing
@pesterhazy does https://github.com/pesterhazy/boot-fmt have a lein equivalent that you know of? pretty cool!
doh. your readme answers it! https://github.com/pesterhazy/boot-fmt#usage
@robert-stuttaford , yeah boot-fmt works irrespective of the build tool, especially with the --git option
There's also lein-zprint by the original author of zprint
thank you!
Choosing a http server lib. Any suggestions? I’ve seen ring mentioned a lot.
@alexisvincent: Have you got specific requirements, or just anything to get started?
@shaun-mahood Not so bothered about super quick starting. Want something powerful and elegant, that’s generally made good design decisions. So far I’ve been really impressed with the clojure package ecosystem so I have high hopes 🙂
@alexisvincent I would say that http-kit is good. It is evented (NIO). It uses ring underneath. You can quickly add compojure for routing and get running within minutes.
@kadaj So not pure ring?
@alexisvincent Ring is not a server, it's a convention for request and response data
http-kit @alexisvincent . plug and play
Oh interesting. Thats what libs mean by ring-compatible
thanks @kadaj and @robert-stuttaford
yeah, it's similar to the role of Rack in Ruby
Never done Ruby dev
http-kit is a great choice, and another common choice is ring-jetty-adapter
http-kit it is 🙂
and compojure?
yes, compojure for routing Ring requests to your particular handler functions
great 😄
compojure lets you build functions that respond to Ring requests, http-kit or ring-jetty-adapter connect those handler functions to a HTTP server
unless you are using special features of the servers you can swap any Ring-compatible server for another and keep your handler functions the same
Thanks guys. The Clojure community is honestly the best I’ve ever experienced. Always tons of people to help. 🙂 Its really cool.
@jcromartie Awesome thanks
I'm glad you feel welcome
If i’m in cider, is there a quicker way of reloading the repl with new libs then restarting cider?
and i'm assuming project deps in your project.clj file, rather than deps of a particular file that already exist in the project
@alexisvincent: are you using clj-refactor? I always add my new dependencies through it (`C-c RET a p` — cljr-add-project-dependency
) and it magically loads things into the running environment.
@alexisvincent I'll throw Pedestal into the ring (pardon the pun) for you: http://pedestal.io/
It's quite simple to get going and has a ton of features not seen in other Clojure http servers
@dpsutton yeah in project.clj
. @camdez yeah I amm, thanks! @tbaldridge Shot, thanks 🙂
@alexisvincent: Sweet. clj-refactor is like having superpowers.
its great stuff 🙂 Spacemacs also makes discovering stuff you can do really easy
@dpsutton: yep, and you can extend that however you like with your own stuff. But that’s using core / things are that already loaded. But cljr-add-project-dependency
will browse libraries and pull them into your project.
I don't think I understand what declare
really does:
user=> (declare foo)
#'user/foo
user=> (def f foo)
#'user/f
user=> (def foo inc)
#'user/foo
user=> (foo 1)
2
user=> (f 1)
IllegalStateException Attempting to call unbound fn: #'user/foo clojure.lang.Var$Unbound.throwArity (Var.java:43)
Why doesn't that work?@isaac_cambron the second argument to def
is evaluated when you call it
which is generally true of arguments to calls in clojure. in function calls it's always true for all arguments, in macro calls (as def) it's usually true for some
i see, so since its value is unbound-thing
that's now just f
ok, i can see that
any ideas on how to work around this? Specifically, I have a map of keyword
-> fn
and a function -- let's call it foo
-- that looks up functions by keyword and calls them, like (foo :do-a-thing)
. But I'm trying to add a key/fn to that map that composes foo
, so I'm in the awkward position of having my map and foo
have a circular dependency. I could just mutate the map after I define foo
, but it seems like there should be an cleaner way
user=> (declare foo)
#'user/foo
user=> (defn bar [x] (foo x))
#'user/bar
user=> (def foo inc)
#'user/foo
user=> (bar 42)
43
boot.user=> (declare memap)
#'boot.user/memap
boot.user=> (defn foo [kw]
#_=> (kw memap))
#'boot.user/foo
boot.user=> (def memap {:foo foo})
#'boot.user/memap
boot.user=> (foo :foo)
#object[boot.user$foo 0x367f8e91 "boot.user$foo@367f8e91"]
arguments to things are resolved/evaluated, but function bodies are not, so declare works there
@jcromartie @bfaber yup, those both make sense. Thanks!
this is basically what `declare was meant for, function bodies, ie so you don't have to define your functions in a specific order
Yeah, the problem was that the way I thought about it wasn't differentiating the second value of def
from function bodies
Sort of funny that you can spend this much time writing code in a language without really thinking through precisely how it works