Fork me on GitHub
#clojure
<
2018-02-09
>
arrdem02:02:08

I have logs of @bronsa's fine rant.... I should get those hosted somewhere. Yet another project. edit: https://www.arrdem.com/logs/Clojurians/%23clojure-dev/%23clojure-dev-2018-02-02.log maybe some file coding issues....

qqq02:02:31

Is there a better way to write this:

(defn foo [& rst]
                              (into (vec (drop-last rst))
                                    (last rst)))

                            (foo 1 2 [:a :b :c])
                            

qqq02:02:51

=> [1 2 :a 😛 :c]

rgorrepati02:02:54

How do we make transit serialize java arrays?

rgorrepati02:02:55

throws Caused by java.lang.Exception Not supported: [Ljava.lang.String;@6117ccdd AbstractEmitter.java: 183 com.cognitect.transit.impl.AbstractEmitter/marshalTop JsonEmitter.java: 28 com.cognitect.transit.impl.JsonEmitter/emit WriterFactory.java: 126 com.cognitect.transit.impl.WriterFactory$1/write transit.clj: 149 cognitect.transit/write transit.clj: 146 cognitect.transit/write transit.clj: 14 jett.argus-compute.transit/data->output-stream

seancorfield03:02:48

(apply vector 1 2 [:a :b :c])

qqq03:02:11

@seancorfield: right, that works great, but becomes messy when I try to refactor it into afunction

qqq03:02:26

how do I refactor (apply vector ...) into a function (foo ...) ?

seancorfield03:02:17

(defn foo [& rst] (apply apply vector rst))

qqq03:02:57

interesting, I've never considered using (apply apply ...) before

seancorfield03:02:41

apply is sort of the inverse of &

qqq03:02:54

@seancorfield: for some reason, I had this incorrect psychological barrier, thinking that apply was a MACRO, when, in reality, it's a function, so yeah, of course (apply apply vector ...) is valid

qqq07:02:30

does clojure (outside of specialized matrix routiens) have a transpose operator? input = vector of M elems, each elem = vector of N elems output = vector of N elems, each elem = vector of M elems

robert-stuttaford08:02:30

@qqq (->> vec-of-vecs (apply map vector))

qqq08:02:46

@robert-stuttaford: 1. I can't believe (apply map vector ...) does transpose 2. even more impressive, after getting over step 1, is that `(apply map vector [(range 10000) (range 10000 20000)])` didn't cause a stack overflow of some sorts (i.e. I expected the 10000 args to apply would screw things up)

qqq08:02:46

actually, I should have tested:

(apply map vector
       (for [i (range 1000)]
         [i (* 2 i)]))
but that works too w/o overflow

robert-stuttaford08:02:13

not much magic in Clojure, but this certainly bloody feels like it 🙂

rauh09:02:45

@qqq You can even pass in an infinite sequence to apply

rauh09:02:21

So this works pretty well:

(defn- unique-id-gen
  "Generates a sequence of unique identifiers seeded with ids sequence"
  [ids]
  (apply concat
         (iterate (fn [xs]
                    (for [x xs, y ids]
                      (str x y)))
                  (map str ids))))
(take 20 (unique-id-gen ["a" "b"]))

kah0ona09:02:08

Hi, I want to read all files directory like: /<myproj>/resources/some_dir/ … from within an uberjar.

kah0ona09:02:26

i can get it working with normal file operations but that doesn’t work when i make my app an uberjar

kah0ona09:02:31

what is the idiomatic way to do this?

kah0ona09:02:43

doh. i just realized how to do it:

(-> "somedir/under/resources/"
      io/resource
      io/file
      file-seq      )

rauh09:02:25

@kah0ona There are no files in a jar only resources IIRC

kah0ona09:02:24

ah yeah you are right that doesn’t work, i need to slurp the resources

borkdude09:02:24

yeah, that’s quite annoying

borkdude09:02:40

you’re basically inside a zip file

juhoteperi09:02:50

@kah0ona It is possible to ask classloader about resources, but it's not very simple: https://github.com/Deraen/ring-cljsjs/blob/master/src/ring/middleware/cljsjs.clj#L22-L31

juhoteperi09:02:07

.getResources returns the list of jar files in classpath which contain the given path, then one needs to go through the jar file contents to check for matching entries

joelsanchez09:02:50

https://github.com/JoelSanchez/ventas/blob/dev/src/clj/ventas/utils/jar.clj list-resources will get you a list of the resources in the current jar, you can just slurp them if you want

kah0ona09:02:03

ah thanks for those pointers, cheers

juhoteperi12:02:42

@kah0ona @joelsanchez Not sure, but I think running-jar probably only works when running from uberjar, ring-cljsjs code should work for both for dev and uberjar

joelsanchez13:02:58

in dev you can just read the files from /resources

qqq14:02:57

@tord: is clj-chess a clojure wrapper of uci? I'm looking for a lib in clojure that can just wrap/interact with stockfish

foxlog16:02:06

100-most-used-clojure-expressions file not found with 404 error. http://lispcast.com/files/clojure-source-files.zip Do you guys have this file which include 100 most used clojure expression? I found this page but it is not available now with 404 error.

reborg16:02:49

@foxlog in case you're after the top-most used functions look here https://gist.github.com/reborg/f7068568ff27d2b6b8f3cb5c439e3839

Arno Rossouw17:02:05

How many programming languages , should a senior programmer know?

chris17:02:30

¯\(ツ)

Arno Rossouw17:02:23

lol. ok. Just curious what is the best way to do functional tests within clojure?

paulspencerwilliams17:02:30

Can anyone provide any suggestions in how to enable clojure.data.xml/emit-str to not raise ExceptionInfo Auto-generating prefixes is not supported for content-qnames. Please declare all URIs used in content qnames. clojure.core/ex-info (core.clj:4617) when specified xml contains namespaces? I've tried specifying them such as

(xml/emit-str the-xml {:xmlns/gh ""
                                                       :xmlns/gs ""
                                                       :xmlns/os ""
                                                       :xmlns/xsi ""
                                                       :xmlns ""})
but that generates a
IllegalArgumentException No value supplied for key: {:xmlns/gh "", :xmlns/gs "", :xmlns/os "", :xmlns/xsi "", :xmlns ""}  clojure.lang.PersistentHashMap.create (PersistentHashMap.java:77)

hiredman18:02:45

that exception is because emit-str expects named arguments after the-xml

hiredman18:02:58

have you looked at the docs for it?

hiredman18:02:23

suggests something like (xml/emit-str the-xml :doctype {...})

paulspencerwilliams18:02:42

I must admit I'd focused on the readme with

(emit-str (element (qname "" "title")
                   {:xmlns/foo ""}
and I'd missed the paren thinking :xmlns was an arg for emit-str, not element. However, as I say, trying with options results in the Auto-generating prefixes is not supported for content-qname

hiredman18:02:51

what do you mean by trying with options?

paulspencerwilliams18:02:26

So, I load an xml document up that has several namespaces. Load it into a zipper, make a simple string change to one element's content. If I keep the zipper pointing to this element, or any parent upto, but not including the root element where the namespaces are applied, I can emit-str on that element. As soon as I point the zipper one element up to include the namespaces, I get the previously mentioned error.

paulspencerwilliams18:02:41

Maybe a simple demo would help!

jeff.terrell21:02:24

Might be worth posting this to #announcements for more exposure and easier finding later.

wiseman21:02:44

> Whilst important and and related, this post won’t cover the following: > > * Setting up logging frameworks Damn! i understand why not, but i’m still disappointed 🙂

noisesmith20:02:34

@danielglauser you might also find this interesting - it’s a library I wrote for capturing data at runtime and instead of putting it in an atom to inspect in a repl immediately, putting it in a transit formatted file so that you can debug from another repl or use it in a unit test https://github.com/noisesmith/poirot

noisesmith20:02:49

also works from cljs

danielglauser20:02:32

Thanks @noisesmith, I’ll check it out.

aaron5121:02:46

In the repl, how do I auto reload and run deftests when files change? I tried requiring the code in lein-test-refresh but it’s in a plugin, so it can’t be required in a repl(?)

tanzoniteblack21:02:27

@aaron51 if you use cider, you can enable cider-auto-test-mode on the test buffer you want to automatically reload; other development environments might have something similar. If you don't want to use a command line feature, you might look into something like https://github.com/weavejester/lein-auto ?

aaron5121:02:38

Thanks @tanzoniteblack I will give this a shot! Is code in a plugin (like lein-auto) accessible from the repl? I couldn’t require a namespace that was in lein-test-refresh (it is listed in :plugins in project.clj)

noisesmith21:02:23

no, plugins are not meant to be accessible from your project repl

tanzoniteblack21:02:56

some plugins are accessable from a repl; but I believe that particular plugin is designed to be use standalone from the command line (i.e. in addition to your repl, you'd kick off lein auto test in another terminal)

noisesmith21:02:12

from a repl you can run (clojure.tools.namespace/refresh) and (clojure.test/run-all-tests), and hypothetically you could reload files automatically on change (but some might find that disruptive)

tanzoniteblack21:02:13

the IDE approach would probably easier and more customizable then a lein plugin

noisesmith21:02:53

@tanzoniteblack some plugins add dependencies to your project, but the plugin itself still isn’t in your project, if it was your project would also have to include leiningen itself

tanzoniteblack21:02:08

@noisesmith you are absolutely correct. But from a user standpoint that difference is just semantics 🙂

aaron5121:02:34

@tanzoniteblack @noisesmith Thank you, this is helpful!

noisesmith21:02:54

@aaron51 the clojure.tools.namespace readme has some good examples of how to hook its refresh into an app that needs some sort of initialized state at runtime (eg. http server, database connections) and I suspect the reason that there’s no easy to find auto-reloader is that most people wouldnt’ want their http server and db etc. restarted every time they touch a file https://github.com/clojure/tools.namespace

jakemcc21:02:08

@aaron51 I’d be careful with automatically refreshing namespaces on file changes with your repl. I think you’ll find yourself blowing away state you might be interacting with. This is pretty much why I haven’t done work to have lein-test-refresh be callable from a repl.

aaron5121:02:11

@jakemcc Understood! So when we use lein-test-refresh it’ll run separate from the repl

qqq21:02:08

Short question: what does (fn [a b] (+ a b)) do under the hood? When I try to dynamically generate a function which coes a :: int, b :: int -> (+ a b) :: int I end up either: 1. creating a static class, so it's (.... some work to generate bytecode ....) (someClass/myPlus ...) 2. or some method of a class, so I have to call it via (.go (.... code taht generates class on the fly) 2 3) Yet, Clojure's fn makes it possible to do: ((fn [a b] (+ a b)) 2 3) what is going o nwith fn ?

noisesmith21:02:40

fn creates a new class

Clojure 1.9.0
(ins)user=> (class (fn [a b] (+ a b)))
user$eval11$fn__146
(ins)user=> (class (fn [a b] (+ a b)))
user$eval149$fn__150

noisesmith22:02:17

in clojure, anything we call a “function” is an object which implements clojure.lang.IFn

noisesmith22:02:41

which implements a few methods, importantly applyTo and invoke

noisesmith22:02:23

@qqq you might find this informative

user=> ((reify clojure.lang.IFn (invoke [this] "HI")))
"HI"

noisesmith22:02:58

when you put something in parens, clojure’s compiler looks for how to apropriately call it, including checking if it implements IFn

noisesmith22:02:29

which might help this error message (which I know you’ve seen before) make more sense

user=> (1)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user/eval157 (NO_SOURCE_FILE:4)

noisesmith22:02:51

@qqq I don’t know if this addresses your question about “static class” but

(ins)user=> (defn foo [x] (fn bar [y] (+ x y)))
#'user/foo
(ins)user=> (class (foo 1))
user$foo$bar__159
(ins)user=> (class (foo 2))
user$foo$bar__159
- each invocation of foo returns an instance of bar - the difference is that each one has its own binding for x

noisesmith22:02:13

(though I forget if x is directly a field on bar, or if bar internally has some env slot that contains x - most of the time this shouldn’t matter)

qqq22:02:34

@noisesmith: this is very helpful, and I think is enough for me to make it work; thanks!

justinlee22:02:05

@noisesmith that’s interesting. can i assume cljs takes an analogous approach?

noisesmith22:02:46

@lee.justin.m iirc in cljs they can directly use the js function type, instead of needing a special type for functions

justinlee22:02:02

oh right, since functions are objects

noisesmith22:02:08

since js actually has first class functions that aren’t properties of objects natively

noisesmith22:02:46

perhaps clojure implementation would look different if java.util.function.Function etc. came out sooner(?)

noisesmith22:02:25

sadly the link to the .java file in that article rotted

hiredman22:02:28

that is a bummer

noisesmith22:02:47

I tried googling but found nothing promising

hiredman22:02:40

you could instead of having an interface for function types make function values method handles

hiredman22:02:11

an interface for function values