Fork me on GitHub
#clojure
<
2017-04-18
>
wottis00:04:48

someone familiar with boot and can please explain me how to make use of java imports within a task?

noisesmith00:04:26

those calls are weird and interop forms don't work that way

noisesmith00:04:12

get rid of the binding of drv-mgr and use DriverManager everywhere where you currently have drv-mgr

noisesmith00:04:52

the import form ensures that DriverManager will work without needing anything like resolve or the full package name

noisesmith00:04:52

same thing with initializer - use SQLAccessControlSystemInitializer instead

noisesmith00:04:00

@wottis see this example

+user=> (. Character isUpperCase \A)
true
+user=> (def c Character)
#'user/c
+user=> (. c isUpperCase \A)
IllegalArgumentException No matching method found: isUpperCase for class java.lang.Class  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)

noisesmith00:04:34

the . form breaks if you don't use the class itself to get the static field - you'd need a different syntax (maybe even reflection?)

wottis01:04:45

@noisesmith unfortunately just using DriverManager doesn't work. It complains that there's no such thing 😕

wottis01:04:41

don't know if that also affects imports

wottis01:04:52

but i certainly can't just do an import 😕

noisesmith01:04:08

if DriverManager is not on the classpath, none of that code works

noisesmith01:04:24

the issue is that you need the right classes on your classpath when that code runs

noisesmith01:04:43

yes - resolve works for vars, but not for classes (as far as I know at least...)

noisesmith01:04:20

maybe you want (Class/forName "java.sql.DriverManager") - that's the equivalent of what resolve does for vars

noisesmith01:04:01

oh - the same error for no matching method happens with Class/forName

noisesmith01:04:52

I can't find in the docs any way to call a static method on a class not available until runtime, except using clojure.reflect which is not exactly a simple or pleasant way to do things

wottis01:04:52

thanks alot

noisesmith01:04:02

sorry I couldn't be more helpful - there are various libs for reflection if you look, but I bet there is a smarter way to do this in boot, for example ensuring that your code is loaded, compiled, and run in a context where the classpath has all your deps on it already

noisesmith01:04:17

but I don't know boot, I'll let someone else chime in on that

wottis01:04:51

learned something knew and gained a better picture. that is very helpful ^^

joefromct02:04:23

general question about everyones workflow... sometimes i'm working in a new project in core.clj, and get interrupted... and then at some point come back to my repl and attempt to restart. My repl won't restart, because i didn't find a good stopping point. Should i be doing my development always in core_test.clj, or is there some wayto have a worksheet or something? I'm using emacs + cider. any tips appreciated.

joefromct02:04:09

just wondering how folks do this sort of thing with a repl driven workflow. It's fun, but when my phone rings and i lose track of thought, i find i have to trace my steps back for a while to figure out what i was doing.

noisesmith02:04:57

that's why I don't like the :init-ns option actually - if you don't use that, you can always get a repl in user and then fix your file until (require 'my.ns :reload) succeeds (then switch to that namespace)

noisesmith02:04:50

a workaround is to (comment ...) the whole body of the ns, then start a repl, then take things out of the comment bit by bit, fixing as you go

joefromct02:04:30

ok, let me read up on :init-ns, thanks. I'm sure it's somehting in project.clj i overlooked.

noisesmith02:04:43

it's usually in there by default, yeah

qqq03:04:31

I want to learn Alan Kay style OO programming, without using smalltalk. Are there any good books/tutorials on doing Alan Kay style OO programming in Clojure ?

joefromct03:04:45

not to be pesky, but i just googled this, and am curious why you're interested in this? It sounds like the opposite of all the great things i like about fp.

joefromct03:04:20

i was just reading part of that and in my brain doing a s/object/list/g but what do i know

qqq03:04:22

Hmm, Rich Hickey in https://clojure.org/about/state#actors explicitly states why he decided against the Actor Model 😞

qqq03:04:06

@joefromct : the original "OO programming" is much closer to Erlang than to Ruby/C++

qqq03:04:11

in that regards, it's "very pure"

joefromct03:04:21

heh, interesting stuff. hadn't thought of this. I think this was funny: > [actor model] is a world in which everyone sits in a windowless room and communicates only by mail

qqq03:04:54

I kinda like that.

qqq03:04:04

It enforces encapsulation / API.

qqq03:04:08

And separation of concerns.

joefromct03:04:25

enforces or forces? I guess if you know beforehand an api is maybe needed then you have the option, but i guess not-having-an-api is sometimes a worthy trade off

noisesmith03:04:31

it also means you can't separate data from the stateful protocols of message transfer

qqq03:04:51

I don't now what these words mean, but I do feel like erlang workswell in practice.

noisesmith03:04:39

One of the benefits of fp is transparent access to data. Forcing data hiding means adding a layer of complexity to anything that needs the data.

qqq03:04:25

yeah, but the real world doesn't mirror FP -- i.e. I can't read your emails / bank balance

qqq03:04:49

"within each actor, I like the idea of FP" -- bue between objects, I like this idea of well desinged messaging

roberto03:04:56

I don’t see why you need objects. I find types are more useful than objects.

qqq03:04:26

let's move this to #off-topic 🙂

qqq03:04:35

however, if anyone has a nice way of doing actors in clojure/cljs, please let me know 🙂

didibus04:04:31

There's also a few other Java based ones that you could just interop with.

didibus04:04:17

Now, actors are heavier weight I believe than smalltalk objects. I think you could easily build yourself a smalltalk like model in Clojure

didibus04:04:07

Maybe have one namespace per object, make everything private except a single function like (msg action data). In that function have a case on action.

tbaldridge05:04:17

When it comes to actors I like to ask, "why?"

tbaldridge05:04:10

Most things I've seen modeled with actors can be done much cleaner with a more functional style.

mpenet08:04:31

on the jvm it's quite difficult indeed

didibus08:04:49

I doubt there's any reason to use Actors unless you are building a highly distributed system. In that case, the actor model helps because of the supervisor pattern, actors can easily fail and restart independently, and their messaging fits easily into any kind of network communication protocol. They're probably annoying for everything else, though I know lots of people find simplicity in the constraint they enforce.

didibus08:04:48

And I mean very highly distributed, where you expect hundreds of nodes with lots of inter node communication.

tbaldridge12:04:21

Sure, but as someone pointed out to me once: what do those systems look like? These highly distributed ones? 90% (or more) of the time you're building a message queue or a data store. Why not use a message queue or a data store in those cases? But even then, I don't see anything about these models that mandates actors. So what we're saying is that the answer to hard distributed problems is: hiding mutability inside opaque processes that communicate with -non-deterministic unreliable message passing. Framed in that way actor systems don't sound simple.

leonoel12:04:38

@tbaldridge leaving apart the distributed aspects, don't you think actors and go blocks have many similarities ?

leonoel12:04:33

a mutable thing, that can react to messages by changing internal state, perform side-effects, or emit other messages

tbaldridge12:04:44

Sure, there's similarities, but there's also differences, I cover a few of them here: https://youtu.be/096pIlA3GDo?t=30m19s

didibus23:04:20

@tbaldridge No, systems that have data stores and message queues are not not highly distributed normally. I

didibus23:04:30

I'm talking about something like mass phone relay

didibus23:04:11

Very large infrastructure services of that sort

tbaldridge23:04:22

Sure, but how many people are building those when they reach for actors?

didibus23:04:23

It probably makes a lot of sense for Whats App for example

didibus23:04:49

Ya, I agree with you

didibus23:04:23

When I meant I don't think there's reasons to use actor except if building highly distributed, I was really talking about the 1% use case

tbaldridge23:04:36

That's my problem, reaching for actors when building HTTP servers and retail order pipelines is nonsense.

didibus23:04:41

People jumping on the Erlang bandwagon are doing so because they are hipsters

tbaldridge23:04:46

I agree there

didibus23:04:20

Nobody needs actor for building a RAILS app, and everyone doing RAILS is moving to Pheonix, its just the next cool kid on the block

tbaldridge23:04:36

(With the highly distributed bit, they aren't all hipsters I'm sure :) )

didibus23:04:58

I think folks building those are the anti-thesis of hipsters 😛

didibus00:04:09

The Beam VM is like the most boring piece of technology built since the JVM. I think it was made cool because of Scala and Akka.

didibus00:04:10

Like, people wanted to get into FP, learning Scala, doing Akka, they're not sur what they're doing yet, but all along they wanted ruby, so they google Actors Ruby and find Elixir

didibus00:04:08

Elixir is actually pretty great, so in the end, I think this is for the best. More people learning FP paradigms, but for a while it will lead to over-engineered software.

didibus00:04:30

Like Actors everywhere

noisesmith03:04:08

Copying the real world is overrated. Modeling it well is another concern, but making data less accessible is often just a crutch to make mutation less problematic.

noisesmith03:04:27

I'd rather global mutable state than hidden mutable state even.

roberto03:04:42

I saw a library somewhere but never used it. TBH, if I wanted to use actors, I would use Akka for that instead of trying to do it in clojure.

qqq03:04:54

Actor model is like a capitalistic market. Clojure's top down control is like a totaltarian government.

gv11:04:28

This breaks on reloading via tools.namespace - I get a ClassCastException for callsites to calculate that whatever implementing class I pass cannot be cast to IObjective

gv11:04:43

Without the :inline function the reloading works as expected. What is the reason that it does not when inlining. Note: all code is in the same namespace.

gv12:04:18

ok, it's not the :inline implementation but the type hint on the first argument....

mbjarland12:04:25

a tangential question here, where would I find documentation for the :inline metadata in the above?

Alex Miller (Clojure team)12:04:52

I dont think there is any. It's not really considered a public feature

andrzejsliwa12:04:59

Hi folks, can you share (via gist) your profiles.clj, I'm looking for examples of using "pimp my repl" tools like inject, debug-repl, push, try etc

andrzejsliwa12:04:18

I know that vinsaya was moved to lucid

gv13:04:26

@alexmiller the ClassCastException still arises without :inline implementation if the first argument has the interface type hint. do you know why that is?

mbjarland13:04:32

high level question, in a previous life I used to write some groovy code and one really nice feature of the language (and yes, feel free to bash good old groovy) was power assertions:

assert [[1,2,3,3,3,3,4]].first().unique() == [1,2,3]

// Output:
//
// Assertion failed:
// assert [[1,2,3,3,3,3,4]].first().unique() == [1,2,3]
//                          |       |        |
//                          |       |        false
//                          |       [1, 2, 3, 4]
//                          [1, 2, 3, 4]           
now I'm a clojure newbie, but in my innocense I would assume that clojure being dynamic and with access to the AST, this kind of visually easy on the eyes output would be possible in clojure (could be applicable to things like clojure.spec, midje, etc). So reaching out to the community for a reality check. Do you see any fundamental reason why this would be difficult in clojure?

jimberlage14:04:51

I don't think so - the clojure equivalent should be

(assert (= (distinct (first [[1 2 3 3 3 3 4]])) [1 2 3]))

jimberlage14:04:11

You could also do (assert (= (-> [[1 2 3 3 3 3 4]] first distinct) [1 2 3])), to order the function calls a bit more like your groovy example

jimberlage14:04:13

Oops, looks like I didn't realize you were talking about the niceness of the output. That's pretty cool.

mbjarland14:04:54

right, I'm a sucker for visualizing data. If nobody sees a reason this would be difficult in clojure, maybe I'll start a little project and see how far I get

mbjarland14:04:40

it would be nice if a library like this could decorate the output of say clojure.spec runs or midje fact executions

dominicm15:04:24

Could be done with a custom macro I think 🙂

dominicm15:04:57

You'd need to rewrite the code in your macro, such that each function call stored it's output somehow. An atom would work, but statey & slow. I think it would be better to do it functionally, doing an assoc onto a map somehow as you go (or conj). But my brain won't quite context switch to figure that part out.

dominicm15:04:13

Then your version of the is macro would flag up a new message type to clojure.test (see the api on clojure.test). And you could implement a printer for that type of message, which prints it however you like 🙂

noisesmith16:04:38

there might be a way to use plumatic’s graph functions (part of plumatic/plumbing) to represent this - but it might be awkward and miss the point also https://github.com/plumatic/plumbing#graph-the-functional-swiss-army-knife

mbjarland16:04:57

thanks, got side tracked looking into specter for solving a nested navigation problem. Will put this on my to-investigate list

mbjarland13:04:49

for complex expressions I found the explicit visualization extremely helpful. I know Peter Niederwieser implemented this for scala as https://github.com/pniederw/expecty

gv13:04:37

What libraries would you use to implement video streaming in a Clojure web project?

wamaral14:04:12

@mbjarland that's pretty nice, I'll try to bash groovy a little less now because of that 🙂

devth14:04:08

@mpenet I haven't been able to get basic auth working in spandex client usage. is it necessary to set :request {:authentication? true}? (i tried)

mpenet14:04:49

you're using`:basic-auth {:user "..." :password "..."}` ?

devth15:04:25

confirmed it works if i bake in an Authorization header (base64 encoded) instead

devth15:04:25

(es/request
    (es/client
      {:hosts hosts
       :http-client {:basic-auth {:user user :password password}}})
    {:url (es-utils/url [index-name])
     :method :head})

devth15:04:30

(does not work)

devth15:04:41

response 403 nil body

qqq15:04:00

to use spark + clojure; do I have to install spark separately, or can I pull in spark as a boot/lein dependency ?

noisesmith16:04:06

I think the slick approach for this would be to use flambo as a dep https://github.com/yieldbot/flambo

mpenet15:04:23

Can you create a ticket for this?

ashishnegi15:04:47

where can i get javadocs for clojure ? and how can i set it up with cider emacs ? thanks for any help

mbjarland15:04:25

clojure question, is there a shorter way of adding a value to a vector in a map optionally adding an empty vector if there was no vector there, i.e.:

(defn shorten-this [data new-entry]
  (let [entries (get-in data [:consultant :entries] [])]
    (assoc-in data [:consultant :entries] (conj entries new-entry))))

-- repl
(shorten-this {:consultant {:entries [1]}} 2)
=> {:consultant {:entries [1 2]}}

ashishnegi15:04:48

@lsenjov i want to use to jump from emacs to source code locally..

donaldball15:04:16

(partial update m (fnil conj []))

lsenjov15:04:16

I can't help you I'm afraid, I'm using vim-fireplace

lsenjov15:04:50

But there should be a shortcut for viewing source with the emacs repl

mbjarland15:04:54

@donaldball : ) ok, that is indeed shorter, will look into it

donaldball15:04:56

(update-in m path (fnil conj []) value)

donaldball15:04:11

something like that 🙂

dominicm15:04:22

Well, there is with CIDER.

ashishnegi15:04:24

@lsenjov so, can you tell from where you got java source code ? did you just git clone clojure.git ?

lsenjov15:04:13

I don't think you're wanting the java source code unless you're doing clojure development (tell me if you are)

lsenjov15:04:25

Otherwise you want the docstrings of functions

lsenjov15:04:51

Is there a particular reason you're wanting the java source itself?

ashishnegi15:04:18

@dominicm my eamcs is setup with cider and it works good for clojure code.. but everytime i am at : ThreadPoolExecutor i can't find the java code file.

jumar10:04:34

@ashishnegi for me (I use spacemacs), the navigation to JDK sources works out of the box. For the clojure core java classes I had to add clojure sources explicitly - already discussed here: https://clojurians-log.clojureverse.org/cider/2017-04-10.html#inst-2017-04-10T19:25:21.453923Z

ashishnegi11:04:40

@U06BE1L6T thanks this is really helpful.. i finally downloaded the source code from http://download.java.net/openjdk/jdk8/ and changed export PATH=$PATH:~/Documents/clojure/openjdk/jdk/src/share/classes but still can't jump to java source code..

ashishnegi11:04:55

might have to switch to spaceemacs .. 😞

jumar11:04:29

As much as I recommend spacemacs I think it should also work in vanilla emacs + cider (as far as I can remember)

jumar11:04:36

I certainly didn't have to modify PATH

jumar11:04:04

btw. this is my classpath from within the REPL:

jumar11:04:11

(.split (System/getProperty "java.class.path") ":")
 "/Users/jumar/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar",
 "/Users/jumar/.m2/repository/org/flatland/classlojure/0.7.0/classlojure-0.7.0.jar",
 "/Users/jumar/.m2/repository/lein-as-resource/lein-as-resource/2.5.0/lein-as-resource-2.5.0.jar",
 "/Users/jumar/.m2/repository/cider/cider-nrepl/0.14.0/cider-nrepl-0.14.0.jar",
 "/Users/jumar/.m2/repository/slamhound/slamhound/1.5.5/slamhound-1.5.5.jar",
 "/Users/jumar/.m2/repository/org/clojure/tools.nrepl/0.2.12/tools.nrepl-0.2.12.jar",
 "/Users/jumar/.m2/repository/clojure-complete/clojure-complete/0.2.4/clojure-complete-0.2.4.jar",
 "/Users/jumar/.m2/repository/org/clojure/tools.trace/0.7.9/tools.trace-0.7.9.jar",
 "/Users/jumar/.m2/repository/com/billpiel/sayid/0.0.14/sayid-0.0.14.jar",
 "/Users/jumar/.m2/repository/io/aviso/pretty/0.1.30/pretty-0.1.30.jar",
 "/Users/jumar/.m2/repository/alembic/alembic/0.3.2/alembic-0.3.2.jar",
 "/Users/jumar/.m2/repository/org/clojure/tools.reader/1.0.0-alpha3/tools.reader-1.0.0-alpha3.jar",
 "/Users/jumar/.m2/repository/org/tcrawley/dynapath/0.2.4/dynapath-0.2.4.jar",
 "/Users/jumar/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0-sources.jar",
 "/Users/jumar/.m2/repository/refactor-nrepl/refactor-nrepl/2.2.0/refactor-nrepl-2.2.0.jar",
 "/Users/jumar/.m2/repository/org/clojure/tools.namespace/0.2.11/tools.namespace-0.2.11.jar",
 "/Users/jumar/.m2/repository/rhizome/rhizome/0.2.5/rhizome-0.2.5.jar",
 "/Users/jumar/.m2/repository/tamarin/tamarin/0.1.2/tamarin-0.1.2.jar",
 "/Users/jumar/.m2/repository/walmartlabs/datascope/0.1.1/datascope-0.1.1.jar",
 "/Users/jumar/.m2/repository/pjstadig/humane-test-output/0.8.1/humane-test-output-0.8.1.jar"]

jumar11:04:57

lots of noise, but I don't think there's something special

ashishnegi11:04:46

"/Users/jumar/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0-sources.jar", this makes it work for clojure code ; but i want to look into jdk java classes like Thread, ArrayBlockedQueue etc..

ashishnegi11:04:09

i think i might have to create -source jar for jdk classes..

jumar11:04:41

Yeah, I know. But as I said, it works for me for JDK classes out of the box -> no need to generate/add sources manually

jumar11:04:42

not sure if my or your JDK installation is somewhat different - I use Mac OS X and have (pretty old) 1.8.0 JDK with src.zip in JDK home

ashishnegi11:04:50

oh.. my src.zip is

ls -l /usr/lib/jvm/default-java/src.zip
lrwxrwxrwx 1 root root 20 Jan 23 22:35 /usr/lib/jvm/default-java/src.zip -> ../openjdk-8/src.zip
where there is no openjdk-8 in above dir 😞

ashishnegi11:04:32

Yeah, I know. But as I said, it works for me for JDK classes out of the box -> no need to generate/add sources manually you are talking about spaceemacs.. right.. just want to confirm..

jumar11:04:13

yes, talking about spacemacs, but I think this is the CIDER stuff - I believe it worked for me in the past when I was using plain Emacs

ashishnegi11:04:45

thanks for all the help

ashishnegi12:04:54

working ... 🙂 needed to run a command : sudo apt-get install openjdk-8-source http://whatcoolwelearnedtoday.blogspot.in/2017/04/clojure-cider-and-emacs-set-up-java.html

ashishnegi15:04:40

@lsenjov just want to go down rabbit hole..

dominicm15:04:17

@ashishnegi it doesn't work for java code.

lsenjov15:04:48

You'll need to look at the source externally

mbjarland15:04:55

@donaldball ahhh...fnil, I have a new friend

lsenjov15:04:01

Dammit, how did I never find fnil before now?

donaldball15:04:45

clojure.core is a treasure trove

lsenjov15:04:26

I know, but there's so many functions in there...

clojureman16:04:04

Probably because the name is a bit unaesthetic and not very suggestive of what it does

clojureman16:04:19

But I agree, it’s nice 🙂

dominicm15:04:09

Or look at other emacs plugins which might offer this functionality

nathanmarz15:04:59

@mbjarland with specter (setval [:consultant :entries END] [2] {:consultant {:entries [1]}})

lsenjov15:04:01

Dammit, how did I never find fnil before now?

josh.freckleton18:04:25

Is there a quick way to refactor out a block of utility fns into their own ns? (using cider, clj-refactor, emacs... the usual 😉 )

dominicm18:04:28

@josh.freckleton You mean move a function to another ns or do you mean extract out some code into a fn?

josh.freckleton18:04:50

sorry, move a function to another ns (or preferably a whole block of fns)

josh.freckleton18:04:24

(ie highlight a few functions in my-ns, and move them to my-ns.utils, but referenced appropriately still in my-ns)

mobileink18:04:41

do they need to be in a separate ns or just a separate file?

josh.freckleton18:04:37

@mobileink well, both, right? is it possible to have a separate file with the same ns? I never even thought of that... @dominicm I think that's it, thanks!

dominicm18:04:23

@josh.freckleton it is actually, clojure.core uses this to split up core.

dominicm18:04:27

I was surprised too!

mobileink18:04:37

you can use load (if i recall). see the clojure.core source for example.

tbaldridge18:04:00

@josh.freckleton it's possible to do that, not sure that I recommend it.

josh.freckleton18:04:08

interesting, huh, I'll have to keep an eye out for when that might come in handy!

tbaldridge18:04:22

Without the "separate files" thing clojure.core would be much larger than the 10k lines it already is.

josh.freckleton18:04:31

I'd think that in most cases you could find some abstraction to divide things along, and come up with a fitting ns name

tbaldridge18:04:38

It also has the nasty habit of breaking a fair amount of tools.

mobileink18:04:29

works great if you need to generate clojure source from config files and add it to an ns.

josh.freckleton18:04:46

so, can you have multiple ns's in the same file?

dpsutton18:04:00

what are you trying to solve?

josh.freckleton18:04:14

nothing with that, the question just follows from the previous discussion

josh.freckleton18:04:21

just my curioisity!

tbaldridge18:04:11

@josh.freckleton yes, multiple ns'es in the same file can be done, but the ones that don't match the filename won't work properly with require

tbaldridge18:04:37

and as always, will break tooling, confuse users, etc.

josh.freckleton18:04:04

well you learn something new everyday with clojure!

dpsutton18:04:14

yeah, i think CIDER makes the assumption of ns = file

tbaldridge18:04:35

as does tools.namespace, and Clojurescript as well (IIRC)

dominicm18:04:36

@tbaldridge I suppose there's no particularly good solution to the code organization vs api exposure problem then? I know you're not a fan of potemkin also.

tbaldridge18:04:27

Personally I'm in favor of the model used by core.async and a few other libs:

tbaldridge18:04:56

public API in one namespace, which are mostly wrapper functions around functions in other namespaces

josh.freckleton18:04:31

@tbaldridge that's a good architecture I've found. Often, there are mini apis within one api that can be broken down similarly within a project too.

mobileink18:04:44

you might find core.matrix instructive. one api ns, with the ability to switch to different implementations dynamically.

jeremyraines19:04:02

is there a better way than top to determine if jvm-opts memory settings are being respected?

ghadi19:04:37

lots of flags there... -gc -gcutil

wei20:04:19

is there a good way to map across a seq but with the function calls rate-limited?

tanzoniteblack20:04:05

Generally I'll just use https://github.com/brunoV/throttler (you could use a similar library as an alternative if you wanted) to create a rate limited function, and then use that in the call to map. I.e. rate limit within the function being called, and be blind to it everywhere else

wei23:04:05

makes sense, thanks @U236LQYB0

wei20:04:56

for example, let’s say a the map function contains an http request

wei20:04:08

thinking something related to transducers but I’m having trouble formulating it

plins20:04:48

hello everyone I'm fairly new to clojure and reading the .spec docs ive encountered double colon keywords like ::wtf-is-going-on are they special in some way?

wei20:04:49

@plins yes, it’s a shortcut for the current namespace

tbaldridge20:04:05

@plins and ::foo/bar will resolve foo in the current namespace. So:

(ns user
  (:require [some.lib.foo :as foo]))

::foo/bar
; => :some.lib.foo/bar

plins20:04:52

thank you folks

lxsameer21:04:09

how can i check to see if a record implement a specific protocol or not ?

mbjarland21:04:57

any compact way to group-by a vector of vectors on nth element while also removing the grouping element from the result?

notid21:04:07

@mbjarland can you give an example of input and output desired?

tbaldridge21:04:10

@lxsameer try clojure.core/satisfies?

mbjarland21:04:18

@brycecovert

(group-by first [[:a 1] [:b 2] [:a 3]])
=> {:a [[:a 1] [:a 3]], :b [[:b 2]]}
any compact way to just get {:a [1 3] :b [2]}

mbjarland21:04:04

seeing as how I am already using specter I can get this done using that, but figured there might be a pure clojure way

notid21:04:57

@mbjarland Others might have more ideas, but in cases like this, I prefer to simply use reduce.

notid21:04:39

(reduce (fn [m t] (update m (first t) conj (second t))) {} [[:a 1] [:b 2] [:a 3]])

madstap22:04:45

@mbjarland I think it's fairly compact even without specter

;; With a (badly named) function
  (defn group-by-by [f g coll]
    (reduce (fn [acc x]
              (update acc (f x) (fnil conj []) (g x)))
            {} coll))

  (group-by-by first second [[:a 1] [:b 2] [:a 3]])

  ;;Inline (brycecovert forgot the fnil to make vectors instead of lists)
  (reduce (fn [acc x]
            (update acc (first x) (fnil conj []) (second x)))
          {} [[:a 1] [:b 2] [:a 3]])

noisesmith22:04:28

oh wait, it’s wrong

notid22:04:56

Personally I like my first approach better, but here’s an idea:

(apply merge-with into (map (fn [[k v]] {k [v]})  [[:a 1] [:b 2] [:a 3]]))