Fork me on GitHub
#clojure
<
2017-08-05
>
qqq00:08:19

googling for "debrujin indices clojure" brings up surprisingly few results; is there a library for this in clojure, or for some reason, does debruijn indices not match well with clojure ?

dpsutton01:08:29

Ztellman uses them in one of the numeric libraries

dpsutton01:08:11

Or one of the collection libraries I think. Int-map or something along those lines

qqq02:08:48

1. clojure vectors has efficient "lookup n-th element" does it have either: (a) efficient insert @ front + delete from front OR (b) efficient insert @ end + delete from end ? [I'm basically looking for something like a stack -- push/pop from the same end -- but I also want efficient indexing (otherwise, I would just use a list) ]

noisesmith02:08:00

@qqq lists and vectors both implement IPersistentStack and peek / pop efficiently

noisesmith02:08:12

vectors conj and pop from end, lists from head

qqq02:08:39

https://clojuredocs.org/clojure.core/pop -- was not aware you could pop a vector; thanks!

noisesmith02:08:42

there's also PersistentQueue, which has no literal but peek / pop is from the opposite end of conj

noisesmith02:08:39

one gotcha with PersistentQueue - don't use list ops or it turns into a seq and doesn't behave right any more

noisesmith02:08:06

(I dealt with a bug where someone used swap! rest on a queue, it became a list, and thus went from fifo to lifo)

qqq02:08:08

I'm not touching queue; this is implementing eval with debruijn, which requires only stack + indexing

qqq02:08:33

s/lol/I'm sorry for your pains in debugging the vec <-> list bug, I've dealt with a few of those myself.

noisesmith02:08:31

the worst thing is that I'd literally told the author of the code "don't use rest on a queue", but neglected to tell him why it was a bad idea

noisesmith02:08:54

so he just put it on his long list of things I have an opinion about but he's never going to change, lol

qqq02:08:40

@noisesmith : you should have made him find the bug himself; then he'd realize "noisesmith is a genius; I need to buy him beer for the next month"

henrik05:08:48

Is it possible to find a list of all types somewhere? (i.e. clojure.lang.\ and java.lang.\)

noisesmith05:08:26

you could walk the class path and iterate all classes you find

noisesmith05:08:15

but then you have to decide if eg. (class +) counts as a "type" distinct from (class -) - the jvm doesn't have types in a way that makes much sense to me at least

noisesmith05:08:34

and in clojure each of those is its own class

noisesmith05:08:43

*instance of its own class

henrik05:08:18

Walking the class path sounds like something my editor should do for me 🙂

noisesmith05:08:50

oh, I thought your code wanted the list

noisesmith05:08:59

if any editor did that it would be Cursive

henrik05:08:39

To be honest, I’m just trying to optimize a thing that switches on types into a protocol:

(defn- recombobulate [item]
  (cond
    (string? item) (clojure.string/trim item)
    (map? item)    (recombobulate-map item)
    (coll? item) (recombobulate-vector item)
    :default item))

henrik05:08:22

I ought to try out Cursive one of these days.

henrik05:08:55

It’s mostly me going “wait, strings are Java types, right? Or are they Clojure types?” I.e., should I use java.lang or clojure.lang

noisesmith05:08:36

the repl makes answering all this easy

noisesmith05:08:47

"" is a java.lang.String

henrik05:08:16

I didn’t know that I could just (class "ff") and get the answer. Thanks for that!

noisesmith05:08:48

for coll? I'd use java.util.Collection

noisesmith05:08:23

for many classes (supers (class foo)) is more informative than (class foo) - and all the collections we typically care about extend java.util.Collection

noisesmith05:08:00

for map? java.util.Map probably

henrik05:08:17

Ah, interesting. So that would be everything that foo inherits from?

noisesmith05:08:57

though now that I check (source coll?) it actually is checking if the arg is a clojure.lang.IPersistentCollection

henrik05:08:05

And protocols can switch on any of them?

noisesmith05:08:17

but every clojure.lang.IPersistentCollection is also a java.util.Collection iirc

noisesmith05:08:30

yeah - you can extend any of them for your protocol

noisesmith05:08:39

the trick is picking the right ones of course

henrik06:08:06

Would clojure.lang.ISeq be lists, vectors and sets, but not maps?

noisesmith06:08:19

vectors are not ISeq

noisesmith06:08:23

nor are sets

noisesmith06:08:24

perhaps you want clojure.lang.Sequential (though that leaves out sets...)

henrik06:08:51

A kingdom for a venn diagram of the type system.

noisesmith06:08:19

heh - well supers outputs sets, so you could do it in clojure with the right graphing bindings 😄

henrik06:08:52

Of course, and Proto REPL probably already comes with the graphics libraries to do it 🙂

henrik06:08:15

Anyway, thank you for pointing me in the right direction. Time to hit the REPL.

noisesmith06:08:38

+user=> (set/difference (set/intersection (supers (class [])) (supers (class #{}))) (supers (class {}))) ; it's shared by [] and #{} but not {}
#{java.util.Collection}

noisesmith06:08:40

oh, wow, TIL

noisesmith06:08:53

{} isn't java.util.Collection - so I misinformed you earlier

henrik06:08:32

Oh, cool use of set operations! That’s one way of doing it, for sure.

henrik06:08:30

(defn find-common-ancestors [& things]
  (apply set/intersection (map #(-> % class supers) things)))

henrik06:08:31

It’s unfortunate that java.lang.Object and nil have no common ancestors.

henrik06:08:53

It leaves me with two “catch all” clauses instead of one:

(extend-type nil
  Recombobulate
  (recombobulate
   [thing]
   thing))


(extend-type java.lang.Object
  Recombobulate
  (recombobulate
   [thing]
   thing))

genmeblog13:08:28

@henrik I see small optimization here, use extend to provide common map of functions. This way you define them once.

genmeblog13:08:55

(def recombobulate-common {:recombobulate identity})
(extend Object Recombobulate recombobulate-common)
(extend nil Recombobulate recombobulate-common)

donyorm16:08:29

does the threading macro work with swap!? Ex:

(swap! app-state (->
                                 (assoc :idx 1)
                                 (assoc-in [:a :b] 3))

noisesmith16:08:41

@donyorm it works if you put the threading macro inside a function

noisesmith16:08:56

the arg to swap after the atom needs to be a function

donyorm16:08:57

like would the above example work?

noisesmith16:08:30

you need (swap! app-state #(-> % (assoc :idx 1) (assoc-in [:a :b] 3))))

donyorm16:08:53

right, thanks

noisesmith16:08:54

since (-> ...) doesn't return the function you want to call, but describes the function you would want

joshkh17:08:08

can someone help me with Java interop? i'm trying to convert the following example Neo4j plugin file to Clojure, but i'm struggling with the Java annotations.

joshkh17:08:02

is this off to the right start?

(ns example.core
  (:import [org.neo4j.procedure.Description]
           [org.neo4j.procedure.Name]
           [org.neo4j.procedure.UserFunction])
  (:gen-class {:name ^{org.neo4j.procedure.UserFunction []
                       org.neo4j.procedure.Description  ["This is the description"]}
                     example.core}))

(defn join [value]
  (str "Echo: " value))

noisesmith17:08:43

@joshkh a small thing - you can pick between import and fully qualifying the class names - either works alone and you never need both

noisesmith17:08:12

import doesn't make classes load, referring to them does (it's a jvm thing) - import is for renaming

joshkh17:08:06

ah yes, thanks for that

noisesmith17:08:34

if join is supposted to be a method, it should be -join

noisesmith17:08:21

you can change the prefix, it defaults to -

joshkh17:08:23

got it! updated:

(ns neoxj.core
  (:import [org.neo4j.procedure.Description]
           [org.neo4j.procedure.Name]
           [org.neo4j.procedure.UserFunction])
  (:gen-class {:name ^{UserFunction []
                       Description  ["This is the description"]}
                     neoxj.core}))

(defn -join [value]
  (str "Echo: " value))
any idea how i would use the @Name annotation within the join method arguments?
public String join(
            @Name("strings") List<String> strings,
            @Name(value = "delimiter", defaultValue = ",") String delimiter) {

noisesmith17:08:36

hmm - the docs don't indicate being able to annotate args https://clojure.org/reference/datatypes#_java_annotation_support

noisesmith17:08:28

but by extension, I would assume it would look like (defn -join [^{Name "strings"} strings, ^{Name "delimiter"} delimiter] ...) if it worked at all

joshkh17:08:08

hmmm, yeah

joshkh17:08:35

is there any difference between using the :gen-class key in ns vs. say calling gen-class at the bottom?

noisesmith17:08:36

right, OK, so you annotate the method declaration in gen-class

noisesmith17:08:16

I can't think of any reason to not use the :gen-class key if your file has an ns form (yes there are rare uses for files without ns forms)

joshkh17:08:47

the problem with the key version is that you need to reference the methods by name and they haven't been defined yet

noisesmith17:08:31

why does that matter?

noisesmith17:08:51

you are giving their names and not passing the vars, afaik

joshkh17:08:30

i think in this example foo cannot be resolved in the ns function:

(ns example.core
  (:gen-class {:methods [
                         [^{Deprecated {} Override {}}
                         foo [^{java.lang.annotation.Retention java.lang.annotation.RetentionPolicy/SOURCE
                                java.lang.annotation.Target    [java.lang.annotation.ElementType/TYPE
                                                                java.lang.annotation.ElementType/PARAMETER]}
                         String] void]]}))

(defn foo [])

noisesmith17:08:17

that needs to be -foo

joshkh17:08:27

where as calling (gen-class) after foo is defined can see -foo

joshkh17:08:35

ah yes sorry, -foo 🙂

noisesmith17:08:58

I find it surprising that this doesn't work...

joshkh17:08:32

my code probably isn't exactly right

noisesmith17:08:17

also this is a part of clojure where you could easily reach a point where just writing a small java class that uses clojure via interop is a lot less work

joshkh17:08:28

that's a very fair point. this was more of a brain exercise than anything.

joshkh18:08:29

by the way, you're right - cursive complains that -echo cannot be resolved, but it compiles just fine:

(ns neoxj.core
  (:import [org.neo4j.procedure.Description]
           [org.neo4j.procedure.Name]
           [org.neo4j.procedure.UserFunction])
  (:gen-class {:name ^{UserFunction []
                       Description  ["This is the class description"]} neoxj.core
               :methods [
                         [^{UserFunction []
                            Description "This is the join description"}
                         -echo [String] ]]}))

(defn -echo [^{Name "strings"} value]
  (str "Echo: " value))

joshkh18:08:56

anyway thanks for the input!

noisesmith18:08:23

oh, so it's a cursive bug?

noisesmith18:08:54

and I would have expected echo in :methods (you are describing the method that is visible) and -echo in the defn (you are supplying a thing to call for that method)

joshkh18:08:52

oh good point

kwladyka18:08:39

🍻 Hey guys, just thinking about online meeting 1 on 1 or in small group where we can look at some code, discuss about some issues and solutions. I would like to meet more Clojure people working remotely like me, so i can meet them only remotely 🙂 What do you think about it? Somebody would like to? 🙂

qqq18:08:23

@kwladyka : a while back, we had a debate about the behaviour of reagent in #off-topic; someone fired up a http://livecoding.edu session, we tested it out for about 30-mins, and everyone found it highly instuctive

qqq19:08:07

the important part is that one person live streams their dev env, and everyone else watches / comments

kwladyka19:08:00

How can i know when are Clojure meetings?

kwladyka19:08:46

i mean it is something what you are doing more often or it happened only once

gelsojunior19:08:25

some senior devs could take a day to make a dojo in a "how to do this thing" way, we can use tmate as a tool for everybody has a chance to change the code...

qqq18:08:38

we've never been able to duplicate such live-coding sessions since