Fork me on GitHub
#beginners
<
2018-11-06
>
jayzawrotny00:11:12

Anyone have any experience using an ouath v1 client with clojure? I’m trying to translate an example from Ruby but running into some issues.

johb.maier06:11:45

I find myself using something like (first (filter #(= (foo %) "some-val") xs)) a lot. Before I make it into a first-where/`first-with` function, I bet I'm overlooking a better way to do it. Is there one?

johb.maier06:11:28

More general would be (first (filter pred xs)

lennart.buit06:11:35

(some pred? coll) is that what you are looking for? Edit: Uhh, I am not sure whether I am reading that correctly

lennart.buit06:11:17

yeah no ignore me

seancorfield06:11:01

@johb.maier There are several reasons why you probably shouldn't be doing that...

seancorfield06:11:21

(this came up very recently in one of these channels)

seancorfield06:11:05

In general filter is going to give you a chunked result so first doesn't mean that filtering stops on the first element -- up to 31 more elements might be realized.

seancorfield06:11:34

Also, if you need to do a linear search, you might have the wrong data structure in the first place. Something to think about.

johb.maier06:11:03

@seancorfield Thanks. It's in a testing context (I'm traversing a kind of "DOM") and a "linear" collection is what the library gives me to work with.

johb.maier06:11:20

So it's not a data structure I control sadly.

seancorfield06:11:40

Then, (first (filter ...)) is likely the best you're going to get.

seancorfield06:11:26

I think it was @andy.fingerhut who said, when this came up elsewhere, if it isn't in core, that's not because the core team haven't thought about it 🙂

johb.maier06:11:44

I guess the best I could do is write more utility functions to hide that functionality and ease traversing the "DOM".

johb.maier06:11:58

Ha, that's a good quote 🙂

johb.maier06:11:30

I usually ask because I'm often sure I just don't know some core functionality or interpret it wrong.

didibus06:11:13

Are you on clojure or cljs?

johb.maier06:11:31

This is cljs at the moment.

didibus07:11:35

(.find #js[1 2 3 4] even?)

didibus07:11:18

JavaScript arrays have a find method, that is really like find first

johb.maier07:11:53

That's good to know, thanks! It's not a js array in my case though (pretty sure at least, I will check).

didibus07:11:45

If it isn't, you're better off with (first (filter as converting to a js array using clj->js will probably be much slower

didibus07:11:04

But if it is, it can be simpler

mfikes12:11:53

Oftentimes you can avoid clj->js and js->clj. For shallow conversion of an effectively immutable JavaScript array to ClojureScript, vec is much faster than js->clj. Going in the opposite direction, into-array is much faster than clj->js.

devyjn16:11:45

occurs java.lang.Exception: No namespace: reply.eval-modes.nrepl found

devyjn16:11:06

anyone knows the reason ?

seancorfield16:11:54

It's caused by a version conflict -- a bug in Boot 2.8.2 https://github.com/boot-clj/boot/issues/720

seancorfield16:11:14

If you downgrade to Boot 2.7.2 it will go away.

devyjn17:11:27

thx, i will try it

jstaab21:11:02

Is there any way to decorate protocol methods when defining a record? E.g.:

(defprotocol MyP
  (thing []))

(defrecord MyR
  MyP
  (thing (decorator (fn [_] 1)))

didibus06:11:52

@ You can, but not exactly how you're doing it.

didibus06:11:42

Say you wanted to create a decorator that would time the execution of a function:

(defn do-the-thing [this]
    (dotimes [x 10000]
    (+ 2 200))
    "done")

(defprotocol MyP
    (thing [this]))

(defrecord MyR []
    MyP
    (thing [this] (time (do-the-thing this))))

user=> (thing (->MyR))
"Elapsed time: 1.330381 msecs"
"done"

didibus07:11:01

You can think of time as a decorator. It is implemented as a macro though. So you can write you're own macros to decorate things. You can also do it with a normal function, but the syntax will be a bit more contrived.

(defn time-decorator [func]
  (let [start-time (System/currentTimeMillis)
    ret (func)]
  (println (- (System.currentTimeMillis) start-time)
  ret))

Now you can decorate a function like so: `(time-decorator do-the-thing)`

But, since our `do-the-thing` function takes arguments, we need to wrap it: `(time-decorator #(do-the-thing this))`

didibus07:11:13

Now I assumed Python decorators is what you were talking about.

didibus07:11:21

If you want Java style Decorator Pattern

didibus07:11:25

You can also do it

didibus07:11:13

(defprotocol Coffee
    (get-cost [this])
    (get-ingredients [this]))

(defrecord SimpleCoffee []
    Coffee
    (get-cost [this] 1)
    (get-ingredients [this] "Coffee"))

(defrecord WithMilk [coffee]
    Coffee
    (get-cost [this] (+ 0.5 (get-cost coffee)))
    (get-ingredients [this] (str (get-ingredients coffee) ", Milk")))

user=> (get-cost (->SimpleCoffee))
1
user=> (get-cost (->WithMilk (->SimpleCoffee)))
1.5
user=> (get-ingredients (->SimpleCoffee))
"Coffee"
user=> (get-ingredients (->> (->SimpleCoffee) (->WithMilk)))
"Coffee, Milk"
Hope this helps

noisesmith21:11:22

no, you can use a higher order function inside the implementation of course, but that syntax isn't valid

ben.borders21:11:07

whats the best way to join collections and singles of things?

ben.borders21:11:12

seems concat is bad ?

ben.borders21:11:30

for example i want eveything to be in one vetor.. Out of these args: [1 23] 4 56 [5 8 9]

noisesmith21:11:46

concat is fine in a lazy context, the problems happen when you mix eager evaluation with stacked concat invocations

noisesmith21:11:51

for that specific example #(vec (flatten %&)) would work, I can't think of anything else simple that would handle it

noisesmith21:11:59

but flatten has some gotchas

sundarj21:11:57

apply conj?

sundarj22:11:48

order dependent though

ben.borders22:11:48

theres so many..

ben.borders22:11:49

its very confusing

ben.borders22:11:54

each with so many gotchas.

rcustodio22:11:13

The best way of using socket in clojure is by java interop?

schmee22:11:30

that’s what I usual do at least, I don’t know of any clojure socket libraries and socket interop is pretty painless

mario.cordova.86222:11:35

why does get only work on vector literal but not on a vector that is def?

mario.cordova.86222:11:18

(get [(t/now) (t/now)] 1) => #object[org.joda.time.DateTime 0x1dd01b46 "2018-11-06T22:11:10.695Z"

mario.cordova.86222:11:38

but (get mydates 1) => nil

seancorfield22:11:51

What is mydates?

mario.cordova.86222:11:57

where (def mydates [(t/now) (t/now)])

seancorfield22:11:14

That should work...

mario.cordova.86222:11:07

hmm its not working my repl

seancorfield22:11:47

(! 509)-> clj -Sdeps '{:deps {clj-time {:mvn/version "RELEASE"}}}'
Clojure 1.9.0
user=> (require '[clj-time.core :as t])
nil
user=> (def mydates [(t/now) (t/now)])
#'user/mydates
user=> (get mydates 1)
#object[org.joda.time.DateTime 0x2cd2c8fe "2018-11-06T22:16:35.465Z"]
user=> 

seancorfield22:11:25

Perhaps you have mydates shadowed by a local binding in the context where you call get on it?

mario.cordova.86222:11:54

Just used a different name and still get nil

seancorfield22:11:10

Show code -- or your REPL session...

noisesmith22:11:17

get on anything that isn't associative simply returns nil

noisesmith22:11:32

any chance you turned the vector into a lazy-seq with map, filter, etc??

mario.cordova.86222:11:39

nth returns UnsupportedOperationException nth not supported on this type: Unbound clojure.lang.RT.nthFrom (RT.java:888)

noisesmith22:11:02

that means mydates is a var that hasn't received a value yet

noisesmith22:11:13

is it somehow declared but not defined yet?

mario.cordova.86222:11:26

com.handler/start> (def testt [(t/now) (t/now)])
#'com.handler/start/testt

com.handler/start> testt
[#object[org.joda.time.DateTime 0x21712cdb "2018-11-06T22:23:00.389Z"] #object[org.joda.time.DateTime 0x6867ddbc "2018-11-06T22:23:00.389Z"]]
com.handler/start> (get testt 0)
nil
com.handler/start> 

hiredman22:11:51

your namespace is bogus

hiredman22:11:27

namespaces with "/" in the name are not going to work correctly

mario.cordova.86222:11:28

So the issue is happening because my namespace is busted?

hiredman22:11:22

that would be my guess, I mean, I am not sure what the mechanics going on behind the scenes that are causing that to happen are

hiredman22:11:52

but putting '/' in a namespace name will break a lot of things, so I am not surprised it breaks that

mario.cordova.86222:11:54

Just ran the app and it worked so you were right. The namespace does seem to be busted

hiredman22:11:07

Clojure 1.9.0
user=> (in-ns 'foo/bar)
#object[clojure.lang.Namespace 0x41709512 "foo/bar"]
foo/bar=> (clojure.core/refer-clojure)
nil
foo/bar=> (def a 1)
#'foo/bar/a
foo/bar=> a
1
foo/bar=> (identity a)
#object[clojure.lang.Var$Unbound 0x51972dc7 "Unbound: #'foo/bar/a"]
foo/bar=> 

hiredman22:11:40

I am kind of surprised you were able to create a badly named namespace like that, it takes a fair amount of work to do (the ns macro won't let you)

mario.cordova.86222:11:55

I didn't create it but I dont have a file with a namespace defined as such so not sure whats happening

mario.cordova.86222:11:28

I have a handler namespace with a function start in it though

hiredman22:11:38

you might be using an older clojure version without the checks for the ns macro

andy.fingerhut22:11:22

How did you start that REPL session? Clojure/Java or ClojureScript?

andy.fingerhut22:11:09

I mean, no need to answer those questions if you can start a new REPL and the issue goes away, but if it is a repeating problem you are having, and you are interested in figuring out why, maybe we can figure it out.

mario.cordova.86222:11:24

In my project.clj I have a :clj { . . . :main com.handler/start . . . }

andy.fingerhut22:11:58

The value of the :main keyword in Leiningen's project.clj file should be namespace name, not a function

mario.cordova.86222:11:07

Right above that :main I have :ring { :handler com.handler/app, :init com.handler/init}

andy.fingerhut22:11:08

It is a little surprising to me that nothing blew up before the REPL started up and gave you a prompt, but there are enough functions in Clojure that don't throw exceptions on invalid input, that I am not completely surprised.

andy.fingerhut22:11:35

I don't know ring well enough to answer, but would guess that those values are expected to be function names, not namespace names.

mario.cordova.86222:11:15

what is :main used for? Is that what the REPL is going to fire up as the initial namespace?

andy.fingerhut22:11:28

It is optional.

andy.fingerhut22:11:07

This heavily commented sample Leiningen project.clj file has lots of info on what various parts of a project.clj file are for, but I wouldn't recommend reading it from cover to cover unless you are bored or intensely curious. Use it when you see something unfamiliar, although since project.clj files can also contain library-specific add-ins like the one you showed for Ring, this file cannot document everything you might see: https://github.com/technomancy/leiningen/blob/master/sample.project.clj

mario.cordova.86222:11:23

com.handler> (require '[clj-time.core :as t])
nil
com.handler> (def mydates [(t/now) (t/now)])
#'com.handler/mydates
com.handler> mydates
[#object[org.joda.time.DateTime 0x6b9cf4ad "2018-11-06T22:41:15.525Z"] #object[org.joda.time.DateTime 0x7cce1e84 "2018-11-06T22:41:15.525Z"]]
com.handler> (get mydates 0)
#object[org.joda.time.DateTime 0x6b9cf4ad "2018-11-06T22:41:15.525Z"]
com.handler> 

mario.cordova.86222:11:49

Thanks @andy.fingerhut @hiredman