Fork me on GitHub
#clojure
<
2019-08-21
>
g02:08:20

@hiredman, i’m using tufte, and just adding p tags around different components of the function

g02:08:02

for example, if i have (defn recursive-kindof [] (p :thing (do-a-thing)) (p :recur (recursive-kindof))), :recur will seem to take the most time

hiredman02:08:43

Because you have a loop and are suming the runtimes of each iteration of the loop geometrically (I think that is right term)

hiredman02:08:18

So imagine the last iteration of your loop runs, takes N seconds, returns t

hiredman02:08:08

To the previous iteration, and N is added to :recurs runtime

hiredman02:08:43

The previous iteration returns, it's runtime 2N is added to recurs runtime (3N), and so on adding 3N to become 6N, then 4N to become 10N as the call stack unwinds

hiredman02:08:13

I mean, that is my guess as to why a naive profiler would end up amplifying the reported runtime of recursive calls

hiredman02:08:00

Arithmetic, not geometric

hiredman02:08:25

No, arithmetic isn't right either, it is Fibonacci like

Silenced Ego04:08:30

I'm confused how type casting works in clojure with abstractions. Is there a lightweight pointer type conversion that happens to achieve polymorphism similar to OOP languages. Or when upcasting happens, does it transform the object itself? Consider (= (list 1 2 3) [1 2 3]) which evaluates to true. I think here the list and the vector are both upcasted to a collection. How does that upcasting work?

hiredman04:08:37

it doesn't do that, = eventually calls the equiv method on either the list or the vector, which both say "if the thing you comparing is a java.util.List or a clojure.lang.Sequential then compare it by taking the seq of it and comparing that"

g00:08:09

yeah, that makes sense. didn’t know if there was some other overhead associated with recursion itself, different from allocating stack space normally. thanks

hiredman04:08:17

where a seq is a functional (immutable persistent) iterator kind of thing

hiredman04:08:54

trying to think about things in statically typed oop terms with casting is just going to confuse you a lot with clojure

hiredman05:08:35

A lot of the Java code in the implementation of clojure is pretty atypical Java and can be thought of as clojure transliterated in Java, lots of methods that just take Object which is the type at the top of the jvms class hierarchy, which makes any casting down casting

pinkfrog08:08:51

is there any library that supports messaging (publish/subscription) (just like what rabbitmq does, but as a library instead of a standalone process)

kirill.salykin08:08:10

or maybe manifold event bus?

helios09:08:56

+1 for core.async

pinkfrog09:08:46

yup. that’s also on my mind.

dominicm09:08:39

Apache have an amqp compatible thing, is this for mocking?

Ben Hammond10:08:29

I would like it if I could declare a defmethod as a simple reference to a function having to write

(defmethod example-multi :ex 
  [& args]
  (apply my-ex-handler args))
feels very jarring when all I really want to write is
(defmethod example-multi :ex my-ex-handler)
or
(defmethod example-multi :ex #'my-ex-handler)
am I the only one who's ever felt like this ?

Ben Hammond10:08:47

is there technical reason why it could not be added to

(defmacro defmethod
  "Creates and installs a new method of multimethod associated with dispatch-value. "
  {:added "1.0"}
  [multifn dispatch-val & fn-tail]
  `(. ~(with-meta multifn {:tag 'clojure.lang.MultiFn}) addMethod ~dispatch-val (fn ~@fn-tail)))

vlaaad10:08:37

I remembered seeing addmethod was requested to be added to clojure.core at least once before. it's trivial to write yourself though, since defmethod is a convenience macro around .addMethod

Ben Hammond11:08:06

I guess I'm asking whether it has been considered and rejected as A Bad Idea

Ben Hammond11:08:05

decomplecting dispatch choice from dispatch invocation seems like an obvious thing

vlaaad11:08:11

I think it was not rejected as a bad idea, @U064X3EF3 was positive about adding it to the core if I remember correctly

Ben Hammond12:08:15

ah yes you mean I can call

(.addMethod ^MultiFn example-multi :ex my-ex-handler)
in my .clj and we're all good

Ben Hammond12:08:53

(and therefore complicating (defmacro defmethod adds little value)

Ben Hammond13:08:24

that's almost exactly what I was looking for Thanks 👍

stathissideris12:08:37

has anyone ever tried to target Python as compilation target for Clojure? (like a clojurescript but for the python runtime)

Las13:08:20

I believe @U07TDTQNL is the author of one of them

mpenet13:08:52

a couple of them 🙂

mpenet13:08:20

and pixie, but that's not really python

Joe Lane13:08:10

Have you looked at Hy-Lang?

stathissideris08:08:52

@U0CJ19XAM @U06QSF3BK afaik Hy makes no attempt to replicate Clojure’s core library, nor its immutable data structure like Clojurescript does. It’s certainly a Lisp, but not a Clojure implementation!

viesti08:08:19

hosted language though :)

stathissideris08:08:45

sure 🙂 but so is cljs and it makes more of an effort!

stathissideris08:08:14

(no offence meant for Hy, it looks awesome)

stathissideris08:08:56

I wonder how hard it would be…

jeroenvandijk09:08:31

@U050AACJB Maybe cnuernber's work is relevant here too https://github.com/cnuernber/libpython-clj . I believe the main goal there is to build a clojure bridge for the (python) data science community

stathissideris09:08:12

Thanks, I’m aware of this (although I couldn’t get it to work!)

viesti14:08:46

I wonder if there's things to learn from Hy's bytecode generation (assuming it does so) for possible clj over python bytecode alternative

stathissideris09:08:59

@U06QSF3BK it would definitely be worth looking into both the cljs and Hy compilers I one was to start such an effort (notice my reluctance to mention my interest 😄 )

mpenet11:08:34

I imagine pyrsistent + hy gets you pretty close

👍 4
mpenet12:08:02

yes there were a few (2 I can recall at least) but both are abandonware.

marciol13:08:46

Hi all, I have a newbie question. I want to play with ClojureScript analyze and emit from a Clojure project. How I import this code in a regular Clojure project?

herald13:08:22

If you add org.clojure/clojurescript as a dependency you can require the libs like normal (`(require '[cljs.compiler.api :refer [emit]])`)

Jakub Holý (HolyJak)14:08:30

Hello, any idea why do I get LispReader$ReaderException: java.lang.RuntimeException: Invalid token: ::kd/sid when trying to use a namespaced key with an alias? The full session:

$ repl.sh
nREPL 0.6.0
Clojure 1.10.1
OpenJDK 64-Bit Server VM 1.8.0_222-b10
user=> (require '[app.domain :as kd])
nil
user=> kd/CATEGORIES ; the ns is required and I can access stuff in it using the kd/... form
#{:additional-services :all-usage}
user=> {::kd/sid 123} ; ... but not in keys?!
Caused by: clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: Invalid token: ::kd/sid
Or:
user=> (alias 'u 'user)
user=> ::u/k ; => RuntimeException: Invalid token: ::u/k
The some code works in another REPL:
$ clj
Clojure 1.10.1
user=> (alias 'u 'user)
nil
user=> ::u/k
:user/k
Stack trace:
Caused by: clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: Invalid token: ::u2/k
	at clojure.lang.LispReader.read(LispReader.java:314)
	at clojure.lang.LispReader.read(LispReader.java:216)
	at clojure.lang.LispReader.read(LispReader.java:210)
	at clojure.core$read.invokeStatic(core.clj:3766)
	at clojure.core$read.invokeStatic(core.clj:3741)
	at clojure.core$read.invoke(core.clj:3741)
	at nrepl.cmdline$run_repl.invokeStatic(cmdline.clj:103)
	at nrepl.cmdline$run_repl.invoke(cmdline.clj:85)
	at clojure.lang.Var.invoke(Var.java:393)
	at nrepl.cmdline$interactive_repl.invokeStatic(cmdline.clj:358)
	...
Caused by: java.lang.RuntimeException: Invalid token: ::u2/k
	at clojure.lang.Util.runtimeException(Util.java:221)
	at clojure.lang.LispReader.interpretToken(LispReader.java:412)
	at clojure.lang.LispReader.read(LispReader.java:305)
	at clojure.lang.LispReader.read(LispReader.java:220)
	at clojure.lang.LispReader.access$200(LispReader.java:41)
	at clojure.lang.LispReader$WrappingReader.invoke(LispReader.java:771)
	at clojure.lang.LispReader.read(LispReader.java:285)
	at clojure.lang.LispReader.readDelimitedList(LispReader.java:1398)
	at clojure.lang.LispReader$ListReader.invoke(LispReader.java:1243)
	at clojure.lang.LispReader.read(LispReader.java:285)

Alex Miller (Clojure team)14:08:02

what is repl.sh? how does it do read?

Jakub Holý (HolyJak)14:08:13

it essentially just connects to a remote NREPL server, with some ugly readline and Spring magic to run the correct class:

env LOADER_MAIN=nrepl.main LOADER_ARGS="--connect --host 127.0.0.1 --port 55555" socat readline exec:"java -cp $(ls myapp*.jar) org.springframework.boot.loader.PropertiesLauncher"

Jakub Holý (HolyJak)14:08:58

This works, BTW:

user=> (read-string "::u/k")
:user/k

Alex Miller (Clojure team)14:08:36

dunno, sounds like an nrepl issue to me

Alex Miller (Clojure team)14:08:05

it looks like the resolver used by the reader doesn't have access to the runtime load state

Alex Miller (Clojure team)14:08:01

if it's reading on the client side somewhere, that would explain it

Alex Miller (Clojure team)14:08:34

the examples you have that work are all doing the resolution on the server side during eval, not read time

👍 4
Lennart Buit16:08:34

In clojure.spec (the first version), is it possible to register(?) a generator for a custom predicate that is just a plain function. Like, such that, (s/gen my-predicate?) gives me a generator in much the same way as (s/gen int?) would.

Lennart Buit16:08:02

I can of course (s/def ::my-predicate (s/with-gen my-predicate? ...)) but I was wondering whether that would work with symbols instead of keywords

Alex Miller (Clojure team)16:08:41

no, that's not an open api atm

Lennart Buit19:08:40

Okay, thanks for the answer :)!

jjttjj16:08:39

Does anyone else prefer the interceptor over middleware pattern for purely aesthetic reasons? I understand that most things (ie pedestal) implementing interceptors do so for other reasons as well, such as easier error/async handling. I have worked with both a little bit on and off for years. But with middleware I find myself having to pause and mentally work out how to order my middleware, and frequently make dumb bugs like forgetting to call a handler, etc. Is this just me? Does it get better with more experience/extensive use of middleware? Would anyone else choose to use interceptors in a library even when a middleware pattern would suffice?

dominicm16:08:20

Interceptors still have ordering, no?

jjttjj16:08:56

yes but they more clearly separate the "enter" and "leave" stage and don't leave it to you to call the next step

Joe Lane17:08:38

They are also dynamic

Joe Lane17:08:38

You can re-order them on the fly. I prefer them over middleware for the reasons you described, as well as finding them easier to reason about.

jjttjj17:08:33

That said, if you were developing a library and had to choose between them, would you depend on a library (pedestal interceptors or sieppari seem to be the main choices) to use interceptors, roll your own, or just use middleware with no dependencies

jjttjj17:08:20

in my case none of the async or fancy re-ordering will be needed

dominicm18:08:48

I don't know that I often find I need to supply the option

tianshu20:08:52

Hi, Is there a algorithm to compress a string to a string? I have some names like demo_combinator-demo__red-child. I want to make it shorter, but still unique. is it possible?

noisesmith20:08:30

the transit lib caches keywords so they can be represented by a short token - or is the goal to end up with something human readable?

tianshu20:08:55

they don't need to be human readable. but I will use this in macro, I want a unique name by compressing a qualified symbol, so I think cache is not good for my case.

noisesmith20:08:51

it's not a stored cache - it's only per unit of encoding for transit, sounds like it isn't the kind of thing you want anyway

tianshu20:08:41

yes, thanks anyway.

tianshu20:08:06

I guess I have an idea, just got one