Fork me on GitHub
#clojure
<
2018-10-12
>
Tiago Dall'Oca00:10:08

Just a quicky here

Tiago Dall'Oca00:10:34

So, I have this piece of code:

((clojure.core/fn
        [n]
        (clojure.core/let
            [__self_rec__
             (clojure.core/fn
               __self_rec__
               [n]
               (clojure.core.async/go
                 (if (< n 2) 1 (*' n
                                   (clojure.core.async/<!
                                    (__self_rec__ (dec n)))))))]
          (clojure.core.async/<!! (__self_rec__ n))))
      100)

Tiago Dall'Oca00:10:11

And it's throwing this:

Tiago Dall'Oca00:10:29

IllegalArgumentException No implementation of method: :exec of protocol: #'clojure.core.async.impl.protocols/Executor found for class: clojure.core.async.impl.exec.threadpool$thread_pool_executor$reify__13318  clojure.core/-cache-protocol-fn (core_deftype.clj:568)

dpsutton00:10:53

Is this from the new recursive library to get around stack limits?

idiomancy00:10:14

is there any way to either do unquote splicing in a quoted (non backtick'd) list, or to specify that symbols in a backtick'd list should be opted out of auto namespace expansion?

andy.fingerhut00:10:20

In a backtick'ed expression, you can opt out of auto namespace expansion by preceding the symbol with ~' but that would require doing that on all symbols you want to opt out for. I don't know of a way to do it globally for most of the expression.

idiomancy00:10:43

gotcha. well, that's not too bad, I guess

andy.fingerhut00:10:05

In a normally quoted expression, there is no way to do splicing built into Clojure. There might be some templating library somewhere that can do something similar to what you want there.

idiomancy00:10:39

cool, well, that little opt out trick should be fine. I'm not in the habit of writing particularly large macros

Tiago Dall'Oca01:10:17

A little clean-up on the code:

Tiago Dall'Oca01:10:25

(require '[clojure.core.async :refer [go <! <!!]])
(def fact (fn [n]
                 (let [__self_rec__
                       (fn __self_rec__ [n]
                         (go
                           (if (< n 2)
                             1
                             (*' n (<! (__self_rec__ (dec n)))))))]
                   (<!! (__self_rec__ n)))))
(fact 100)
> IllegalArgumentException No implementation of method: :exec of protocol: #'clojure.core.async.impl.protocols/Executor found for class: clojure.core.async.impl.exec.threadpool$thread_pool_executor$reify__13318  clojure.core/-cache-protocol-fn (core_deftype.clj:568)

Tiago Dall'Oca01:10:20

Also equivalent:

(def fact (letfn [(__self_rec__ [n]
                         (go
                           (if (< n 2)
                             1
                             (*' n (<! (__self_rec__ (dec n)))))))]
                 (fn [n] (<!! (__self_rec__ n)))))
(fact 100)
;; thows the same exception

enforser01:10:38

it seems to have worked for me! @mrdalloca

enforser01:10:22

=> (fact 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000N

enforser01:10:39

using clojure 1.8 and async 0.4.474

andy.fingerhut01:10:10

Is core.async expected to work with embedded (fn ...) forms? I haven't used it, but know it has some limitations of what it can handle inside of the code in a go form.

bronsa15:10:44

core.async can't cross fn boundaries, lexically, but this is not what's going on this case

enforser01:10:55

I dove into that new library for a bit yesterday, and looked at doing what you're doing here - wrapping the "rec" function in letfn, then realized by doing that you lose the ability to use the mutually recursive functions because they can't access each others "helper fn"

Tiago Dall'Oca01:10:06

Didn't think of the mutually recursive functions

enforser01:10:26

I do think that ideally there'd be some way to avoid defining two functions in the namespace. My only idea for this was to potentially hide the recursive helper in the function metadata, but I feel like that's probably not a great solution.

dominicm07:10:49

I'm struggling with something I thought would be simple. I have a SocketAddress, can I figure out the host IP, even if it's been set to 0.0.0.0 in the socket address? My current thought is to handle that specific case, but I'm not sure that's a great solution.

john13:10:50

Well, in case you want to know the public ip

dominicm14:10:20

Nope. I just want to know whether this is on localhost:3080 or something else.

stijn09:10:32

how do I know where clj puts its downloaded artifacts from maven? Does it use some environment variable or maven config?

tristefigure10:10:19

~/.m2/repository/ ?

mgrbyte10:10:55

think you can inspect the .cp and .lib files in .cpcache to see

noisesmith15:10:42

@mrdalloca that specific error can be caused by reloading the core.async code - you end up with parts of core.async running using the old versions of protocols, which breaks as soon as you try to invoke their methods

8
Tiago Dall'Oca16:10:35

@noisesmith Updated clojure version, restarted the repl and ta da, it worked!

Tiago Dall'Oca16:10:36

Here's the code for factorial:

user> (def fact (recfn
                 [n]
                 (if (< n 2)
                   1
                   (*' n (rec-self (dec n))))))
#'user/fact
user> (fact 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000N

Tiago Dall'Oca16:10:04

Where recfn is the equivalent to fn but it's made to be able to use with rec-self

hiredman16:10:46

fn already does that

hiredman16:10:10

(fn f [n] do-whatever-with-f)

Tiago Dall'Oca16:10:27

Another example:

user> 
(declarec EVEN?)

(def ODD? (recfn [n]
                 (if (zero? n)
                   false
                   (rec-self (dec n)))))

(def EVEN? (recfn [n]
                  (if (zero? n)
                    true
                    (rec-self (dec n)))))
#'user/__rec__:EVEN?
#'user/ODD?
#'user/EVEN?
user> (ODD? 10)
false
user> (ODD? 10001)
false
user> (ODD? 1000001)
false

hiredman16:10:26

(you didn't use EVEN? in ODD?)

taylor16:10:55

like (def ODD? (complement EVEN?))?

Tiago Dall'Oca16:10:32

I'll fix this and test

Tiago Dall'Oca16:10:07

@hiredman > fn already does that > (fn f [n] do-whatever-with-f)

Tiago Dall'Oca16:10:06

user> (def fact (fn fact [n]
                  (if (< n 2)
                    1 (*' n (fact (dec n))))))
#'user/fact
user> (fact 10000)
Evaluation error (StackOverflowError) at  (Numbers.java:3909).
null
user> (def fact (recfn [n] (if (< n 2)
                             1 (*' n (rec-self (dec n))))))
#'user/fact
user> (fact 10000)
;; enormous number 

hiredman16:10:42

sure, that is how a call stack works when you don't have tco

hiredman16:10:21

fact with recfn is like a million times slower

Tiago Dall'Oca16:10:48

@hiredman yeah it is. But the point here is not blowing the stack

hiredman16:10:14

use trampoline

Tiago Dall'Oca16:10:43

Have you seen the new recursion library?

Tiago Dall'Oca16:10:57

It's worth checking out its rationale

hiredman16:10:10

I haven't, but if it is based on using core.async, I doubt it is useful

Tiago Dall'Oca16:10:57

Well, that's another discussion but you got a point

hiredman16:10:32

I mean, it is a cute toy, but I use core.async all the time, and I definitely don't want to be calling async/go for everything single function call

noisesmith16:10:43

core.async needed to invent some form of continuation, and now this other library tries to use those continuations more generally?

hiredman16:10:38

but core.async doesn't expose the general form of continuation, so this library that builds on it sticks every function call in a threadpool queue

hoynk20:10:08

What is the correct function if I need Java's modulus (%) operator? Is it mod or rem or neither?

seancorfield20:10:25

@boccato Ask doc in the REPL

user=> (doc rem)
-------------------------
clojure.core/rem
([num div])
  remainder of dividing numerator by denominator.
nil
user=> (doc mod)
-------------------------
clojure.core/mod
([num div])
  Modulus of num and div. Truncates toward negative infinity.

seancorfield20:10:02

There's also

user=> (doc quot)
-------------------------
clojure.core/quot
([num div])
  quot[ient] of dividing numerator by denominator.
nil

seancorfield20:10:19

@boccato It looks like Java's % operator is technically a remainder, not a modulus? And looking at (source mod) I see it's defined in terms of rem but then adjusts a negative remainder to be positive. I saw a SO post that defined a mod function in Java in a similar way on top of the %...

hoynk20:10:57

I was in doubt about that, but in my case I can be sure that only positi

hoynk20:10:14

ve numbers will be mod'ed

hoynk21:10:35

Another question, what libraries / framework would you suggest to me to port a small python/django app that implements a http API. I need file upload, to return some JSON, authentication and serve a simple js/html page that access the API (with a login page).

dadair21:10:06

What have you looked at so far?

hoynk21:10:09

I used luminous in a past life... lol. Like 5 years ago for a toy project.

hoynk21:10:39

I am more concerned with the security part. If there is something mature for the authentication / JWT part.

dadair23:10:07

Buddy is a common set of libraries for that

lilactown21:10:55

has anyone created a clj incantation to start an HTTP server in a dir?

seancorfield22:10:40

@lilactown It's just going to be whatever web server library you choose and a couple of -e options...

seancorfield22:10:29

I seem to recall doing something similar with lein-try back in the day... let me see if I can find that...

hiredman22:10:50

python -m SimpleHTTPServer 7777 is hard to beat

🙂 4
seancorfield22:10:44

@lilactown Because I couldn't resist...

clj -Sdeps '{:paths ["."] :deps {ring {:mvn/version "RELEASE"}}}' -e "(require '[ring.adapter.jetty :refer [run-jetty]] '[ring.middleware.resource :refer [wrap-resource]])" -e '(run-jetty (wrap-resource (constantly nil) ".") {:port 3333})'
That will serve files as static assets in the current folder.

🙏 4
aisamu16:10:43

Oh, I thought "RELEASE" wasn't supported!

seancorfield18:10:08

And "LATEST".

seancorfield22:10:45

(I found an old blog post where I did something similar with lein-try -- and someone commented on the post with the python command too as I recall :rolling_on_the_floor_laughing: )

lilactown22:10:03

it is pretty much the standard

lilactown22:10:29

might be fun to create a "runner" that would detect if ring/jetty/http-kit is on the classpath and automatically start it

lilactown22:10:30

and do things like auto reload CSS. maybe even come with nREPL to dive in and muck about

lilactown22:10:19

I just thought if it because I had to edit actual HTML/CSS for the first time in forever and missed the comfort of having a REPL around 😛

ag23:10:43

anyone uses deps.edn and lein-tools-deps.plugin with private dependencies? I can’t make it work in a docker container… it can’t find clojure executable, when I install it manually, it can’t find clojure deps files…

aisamu16:10:59

It does work with s3-wagon-private, as long as you have the repositories correctly configured. I also use docker, but I do have :lein-tools-deps/config { :clojure-executables ["/usr/bin/clojure" "/usr/local/bin/clojure"]} on the project.clj, though.