#clojure log - Dec 22 2015

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:29 allhailcaesar: Is there a way to make lein check already downloaded dependencies? I'm on a bad connection, and am worried I might be seeing some errors in a project due to connection instability.

1:07 chomwitt: good morning.

1:08 a newbie question. where is ring.core ?

1:13 allhailcaesar: @chomwitt are you getting an error that you don't have it?

1:15 chomwitt: no. i'm trying to understand some basic things. http://ring-clojure.github.io/ring/ i dont see any ring.core in tha API

1:15 allhailcaesar: adding [ring/ring-core "1.4.0] to your dependencies will pull it to your classpath

1:16 hiredman: the docs show namespaces, and there is no ring.core namespace, so it is not in the docs

1:17 but there is a maven artifact (a jar) with the group-id `ring` and the artifact-id `ring-core`

1:18 namespaces and maven coordinates are orthogonal, and can be completely different, but many projects have maven coordinates that are similar to their namespaces

1:19 chomwitt: what the diff of including in my project.clj [ring "1.4.0"]] and [[ring/ring-core "..."]]

1:19 ?

1:19 hiredman: the ring artifact will bring in ring-core and some other stuff as dependencies

1:19 chomwitt: hiredman: your explanation i think is some levels above me :-)

1:20 i dont have an idea what a maven artifact is

1:20 hiredman: what goes in your project.clj are maven coordinates for dependencies (lein grabs stuff from maven repos)

1:20 chomwitt: basically a jar

1:20 chomwitt: better :-)

1:20 a jar brings some bells :-)

1:21 hiredman: a zip file full of code

1:21 when you see `foo/bar` in project.clj `foo` is what maven calls the group id and `bar` is what maven calls the artifact id

1:22 chomwitt: so why some tutorials use ring/ring.core and others just ring ?

1:22 hiredman: if you have something like `ring` lein assumes the group id and the artifact id are the same, so `ring` is the same as `ring/ring`

1:22 chomwitt: hiredman: i see. makes sense nwo

1:22 now

1:23 allhailcaesar: chomwitt: This might help you with the practical side of your question, http://kendru.github.io/restful-clojure/2014/02/19/getting-a-web-server-up-and-running-with-compojure-restful-clojure-part-2/

1:24 hiredman: the ring project used to be published as a single ring artifact, but it is now published as a finer grained set of libraries, you can still get everything by depending on `ring`, but you can also depend on smaller parts of ring, like `ring/ring-core`

1:24 so for tutorials they are likely interchangable

1:29 * chomwitt will have to scratch his head again on this

2:54 keep_learning: Hello everyone

2:54 I am trying to extract the information https://www.refheap.com/112992

2:55 when I am using (map (comp :href :attrs) (list-of-element)) then it return all the links

2:55 but I want to extract the :content also

2:56 so I have written (map :content (list-of-element)) gives me list of list of one element

2:56 I tried to combined it together

2:57 (map (fn [x] ( (comp :href :attrs) x, :content x)) (list-of-element))

2:57 but getting error

3:04 Kneiva: keep_learning: (Without looking at the paste): That last anonymous function could be something like (juxt (comp :href :attrs) :context)

3:06 keep_learning: Kneiva, Thank you

3:09 Kneiva: uh, :content instead of :context

5:29 keep_learning: https://www.refheap.com/112993

5:29 Hello everyone.

5:29 I have list of url links

5:30 and I want to navigate through all these links sequentially

5:30 so I can't write (map fetch-page-from-link url-links)

5:30 I want to do it sequential manner

5:34 kungi: keep_learning: does fetch-page-from-link have sideeffects? If yes then `doseq` is right for you.

5:35 keep_learning: (defn fetch-page-from-url

5:35 "fetch page source/html page from given url"

5:35 [url]

5:35 (do

5:35 (t/set-driver! {:browser :firefox}) ;set this for moment

5:35 (t/get-url url)

5:35 (t/page-source)))

5:35 kungi, Yes but it returns page of url

5:35 kungi: returning something is not a sideeffect. But set-driver! probably is.

5:35 keep_learning: I have to process that html page

5:36 kungi: keep_learning: why are you using `do` here?

5:36 keep_learning: and (t/get-url url) is also a side effect

5:36 kungi: probably yes

5:36 keep_learning: kungi, For sequential execution

5:36 kungi: keep_learning: defn and fn also do an "implicit do"

5:37 keep_learning: kungi, Thank you

5:37 so I can write (map fetch-page-from-url url-link) ?

5:38 kungi: keep_learning: as far as I see it yes.

5:38 keep_learning: Thank you

5:38 kungi: keep_learning: hmm ok wait. Maybe lazyness will screw you there

5:38 keep_learning: I would use `doseq`

5:51 owlbird: how to generate q SQL according different parameter pairs. for example, parameters name and department both are optional, (department maybe used to join another table), what the best way to handle this? Do I have to write a long long (cond ..) ?

6:03 Kneiva: owlbird: I'm not sure I understood the question right. But how about giving parameters in a map and render the SQL from its entries?

6:03 ,(clojure.string/join " AND " (map (fn [[k v]] (str (name k) "=" v)) {:id 12 :name "aa"}))

6:03 clojurebot: "id=12 AND name=aa"

6:05 Kneiva: And I would think there is some library that can do this kind of thing for you.

6:10 owlbird: select * from user u (if department != "") join dept d on u.dept = d.dept and d.name=? (if name != "") where u.name=?

6:11 department/name both are optional parameter, which would be treated like a SQL segment switch, to open/close a logical.

6:20 Kneiva: owlbird: search for sql abstraction here: http://www.clojure-toolbox.com/

6:25 ridcully: banging strings together has a good chance to introduce sql injections - so watch out here

6:26 keep_learning: Hello everyone

6:26 I have clojure file and want to covert it to jar file

6:27 https://www.refheap.com/112994

6:42 Do I need to add main in clojure file

6:44 Kneiva: If you want it to be runnable jar.

6:48 keep_learning: Kneiva, I want to call go-to-tripadv from other java file

6:49 powered: if you want to use the jar as a library then you don't need a main

6:50 keep_learning: powered, Thank you

6:51 I have run lein uberjar

6:51 and it generated the jar in target directory

6:53 powered: you can also run lein jar if you don't want to include dependencies

6:58 keep_learning: I am getting two jar files

6:58 tripadvisor-0.1.0-SNAPSHOT.jar

6:58 tripadvisor-0.1.0-SNAPSHOT-standalone.jar

6:59 Which one I should add to java project to fetch go-to-tripadv function

6:59 ?

7:06 Kneiva: keep_learning: standalone has all the dependencies like Clojure, selenium and other things you use in your clojure code. If you do not have them on the classpath otherwise you should use the standalone jar.

7:08 keep_learning: Kneiva, I have added both the jar file

7:09 but having problem in calling the function go-to-tripadv

7:14 Kneiva: keep_learning: Maybe this helps: http://stackoverflow.com/a/23555959

8:57 vy: Hi all! I am looking at TechEmpower web framework benchmarks: https://www.techempower.com/benchmarks/ Can somebody enlighten me how on earth Compojure can beat Java servlets in the very same benchmarks, given the fact that Compojure depends on Ring, which depends on Java servlets. What am I missing?

9:05 hiredman: ring and servlets are both interfaces, not implementations, so neither of those things can actually be benchmarked

9:06 the servlet api specifies how http can be represented as java method calls, ring specifies how http can be represented as clojure data structures

9:07 vy: hiredman: I agree, but I would expect Compojure to come after vanilla Java Sevlets, assuming that they are compared using identical servlet container configurations.

9:07 hiredman: an adapter exists that allows you to turn serlvet apis in to ring apis, but ring is a spec that doesn't depend on servlets

9:10 the ring spec can be implemented (and has been) on other things besides servlets

9:10 and compojure is built on top of ring

9:12 ridcully: since #1 and #3 seems to differ in db, i'd like to see, how compojure there would do with postgres

9:12 hiredman: so to benchmark "compojure" as a thing, without specificy compojure + what implementation of the ring spec, doesn't make sense

9:13 vy: hiredman: The code is available: https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Clojure/compojure/hello

9:17 hiredman: vy: if you are comparing it to the servlet-raw numbers of techempower, (which is such a meaningless name, there is no such thing, the servlet api is an interface) then it looks like `servelet raw` is using some other servlet implementation, and whatever servlet implementation the compojure benchmark is using happens to be faster

9:17 vy: hiredman: Hrm... Thanks for the explanations.

9:19 hiredman: the techempower numbers are really neat, but non-trivial to interpret, and some of the ways the results are presented don't make much sense

9:20 vy: I think it is just yet another page for comparing apples and oranges. But that's my idea...

9:20 hiredman: alioth for http

9:21 vy: Alioth is measuring/benchmarking more comparable things.

9:23 hiredman: alioth is measuring performance of c ffi to libgmp

10:57 jcrossley3: little_lamb: cool nick, bro

10:58 little_lamb: jcrossley3: I did it JUST FOR YOU

10:58 jcrossley3: :)

12:20 aurelian: hello

12:20 what's a nicer way of doing this: https://www.refheap.com/113004 ?

12:21 I tend to solve most of this kind of problems with reduce/map/filter, but I feel there must be a better way

12:23 yenda: with specter maybe

12:23 (select [ALL :sources ALL] lolz)

12:23 ridcully: is the order important?

12:23 aurelian: nope, order is not important

12:24 yenda -- will check that out thanks

12:25 ridcully: (into #{} (mapcat :sources lolz))

12:26 aurelian: oh, wow

12:27 thanks

12:32 and to keep it unique and as a vector is it better to apply distinct and use into [] or convert the result to vec?

12:33 justin_smith: I'd use ((comp vec distinct mapcat) :sources lolz)

12:34 aurelian: I'm very comfortable using reduce but somehow in clojure there's always a better / nicer way

12:36 mavbozo: ,(doc mapcat)

12:36 clojurebot: "([f] [f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection. Returns a transducer when no collections are provided"

12:36 mavbozo: ,(doc distinct)

12:36 clojurebot: "([] [coll]); Returns a lazy sequence of the elements of coll with duplicates removed. Returns a stateful transducer when no collection is provided."

12:36 aurelian: yup, is exactly what I doing in that reduce

12:36 mapcat I mean

12:36 mavbozo: ah, justin_smith's version uses transducers

12:37 ,(doc vec)

12:37 clojurebot: "([coll]); Creates a new vector containing the contents of coll. Java arrays will be aliased and should not be modified."

12:38 justin_smith: mavbozo: it doesn't actually, but it could probably be converted to do so

12:39 mavbozo: justin_smith, oh, my mistake

12:39 aurelian: ,(doc comp)

12:39 clojurebot: "([] [f] [f g] [f g & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

12:40 justin_smith: ,((comp vec distinct mapcat) :foo [{:foo [1 2 3]} {:foo [2 3 4]} {:foo [3 4 5]} {:bar [42]}])

12:40 clojurebot: [1 2 3 4 5]

12:41 aurelian: sweet, thanks

12:56 justin_smith: ,(into [] (comp (mapcat :foo) (distinct)) [{:foo [1 2 3]} {:foo [2 3 4]} {:foo [3 4 5]} {:bar [42]}]) ; mavbozo - this is the transducing version

12:56 clojurebot: [1 2 3 4 5]

12:56 mavbozo: ,(into [] (comp (mapcat :foo) (distinct)) [{:foo [1 2 3]} {:foo [2 3 4]} {:foo [3 4 5]} {:bar [42]}])

12:56 clojurebot: [1 2 3 4 5]

12:56 WorldsEndless: What is the syntax for :require :only in an ns statement? I don't seem to be having luck with (:require [ring.util.io :only [piped-input-stream]])

12:57 justin_smith: haha, mavbozo did you just come up with the same thing right when I did?

12:57 mavbozo: justin_smith, zing isn't it? LOL

12:57 justin_smith: WorldsEndless: I thought it was use / only and require / refer

12:58 WorldsEndless: justin_smith: I'm not managing to parse that sentence...

12:58 justin_smith: mavbozo: especially because I had to help a coworker with a couple of things before coming back and figuring that out, haha

12:58 WorldsEndless: (:use [foo :only [bar]]) (:require [foo :refer [bar]])

12:59 mavbozo: justin_smith, jinx

12:59 WorldsEndless: Ok; so no :only for refer in ns? (unlike refer http://clojuredocs.org/clojure.core/refer)

12:59 justin_smith: WorldsEndless: (doc use) mentions :only, (doc require) mentions :refer

13:00 WorldsEndless: Guess I'm confused by the first example from the refer clojuredoc page

13:00 mavbozo: justin_smith, hahaha, took me quite some time to realize that the (comp ...) order is reversed

13:00 justin_smith: OK, but the args of require aren't given directly to refer

13:01 WorldsEndless: Ah, I see. My mind was transposing "require" and "refer" ...

13:07 qsys: I get a ClassNotFoundException when I try to (:gen-class :extends [some.class]) using maven. I have something like (ns my.namespace (:import (some class)) (:gen-class :extends [some.class]))

13:08 and I'm using the com.theoryinpractis:clojure.maven.plugin:1.7.1 maven plugin

13:09 justin_smith: qsys: have you verified that the class you are trying to extend is on the classpath?

13:09 qsys: for some reason, the sme.class is not found (it is present in the maven depencies)

13:09 justin_smith: qsys: you shouldn't need to import, btw

13:09 qsys: so yeah, I would suppose if it's in the maven dependencies, it's in the classpath (but apparently, it's not :p)

13:10 justin_smith: qsys: I don't know maven so well, but is there a way to make maven dump the classpath it would use for a given command?

13:10 qsys: yes, I thought it wasn't needed in the import, but due to the class not found exception, I added it... so I'll remove it

13:10 hmm, I'll check for maven

13:11 justin_smith: qsys: import just changes whether package qualifiers are needed, it doesn't do any class loading magic

13:11 qsys: allright, makes sense...

13:15 not that much logging/debug info with maven. searching for classpath when running plugins.

13:15 justin_smith: qsys: what about looking at the command line args when starting a repl?

13:16 via ps or whatever

13:18 qsys: nothing much about classpaths - don't like that

13:20 justin_smith: qsys: what about 'mvn dependency:build-classpath'

13:22 qsys: when I run "ps x" it shows the full classpath as specified on the command line of any java command I have running

13:22 qsys: then I get the right classpaths - when I add some.class from Java, there's no problem.

13:23 yeah, but with 'ps -x', well, I'm not fast enough: I run maven and it's 'immediately' done before I can say 'ps -x' :)

13:23 justin_smith: qsys: which is why I suggested starting a repl (if needed commenting out the gen-class so the repl runs)

13:23 devth_afk: there's a problem i've never had: mvn being too fast :)

13:24 justin_smith: the repl should stay running until you tell it to stop

13:24 haha

13:24 qsys: ok... thx - lol

13:24 I'm a slow speaker :)

13:28 all mvn jobs from the plugin don't seem to add other mvn dependencies in the classpath... I'll check that plugin config again

13:30 slester: I struggled to get Cursive to actually run my Leiningen project. I ended up having to ragequit and just run things from the command line like I always do. :(

13:34 justin_smith: slester: that seems like it misses out on a bunch of the benefits of using cursive

13:35 j-pb: slester: resyncing with lein often helps

13:35 slester: yeah, I follow the instructions I found to import a project from leiningen but I couldn't figure out how to get Run to work properly

13:35 j-pb: the leiningen tab on the right

13:35 justin_smith: slester: did you see these docs? https://cursive-ide.com/userguide/leiningen.html

13:35 j-pb: and then the sync symbol

13:35 slester: justin_smith: that's the one I followed, yup :(

13:35 justin_smith: slester: at what step did it fail?

13:35 slester: I'll try again later, but whew. IDEA is just huge and complicated.

13:36 I just couldn't get clicking Run to work is all

13:36 qsys: lein is another option... but it does take more steps to build - I'd rather have it done in maven

13:36 slester: maybe I didn't go into the right menu like the one j-pb suggested

13:36 j-pb: slester: to get run working you also need to configure a repl for example

13:36 slester: the REPL worked

13:37 justin_smith: qsys: lein is friendlier for clojure specific stuff though (like clojure.test / clojure specific linters / other clojure test frameworks / etc.)

13:37 j-pb: slester: what didn't then :)?

13:38 slester: I don't know how many ways I can say "the run button" :( but as I said, one of my first times using IDEA so I probably did something wrong

13:38 but it was a lot less plug-and-play than I had imagined when people are tweeting about the release of the Cursive IDE for Clojure I guess

13:40 ridcully: left of the run/debug/chronos/... buttons is a dropdown. there you can "edit configurations"

13:41 j-pb: slester: no but what do you expect the run botton to do? for me a repl would be what I need

13:44 slester: lein run?

13:45 j-pb: hrm, tbh I never use that

13:46 slester: you would probably have to set up a clojure application configuration in intellij then

13:46 however

13:46 I don't see a reason for running lein run

13:46 in development mode you want a repl

13:46 in deploy you want a jar

13:46 ridcully: me neither. but if i extrapolate from the other build tools, you can either run it once from the (right hand side) lein tab (it there is one) or you should be able to add a configuration with that lein <run> task?

13:47 slester: well, I am a newb so it's probable I'm doing it wrong

13:47 j-pb: slester: generally when developing in clojure you want to use the repl

13:47 because it allows you to hotload code into your program while you develop it

13:50 slester: it seems like a big pain to get code in there

13:51 MJB47: most people have a function in their editor to send code to the repl

13:51 slester: like I have no idea how I'd use it effectively. I usually use the REPL to try out code

13:53 j-pb: slester: yeah but you can also call your main from there

13:54 slester: and then you can reevaluate parts of the code while its running

13:54 slester: I guess I need to watch a video or read some more about it, then.

14:12 devth: anyone using spacemacs for clojure?

14:12 https://github.com/syl20bnr/spacemacs

14:16 TimMc: "An Emacs distribution"

14:16 rhg135: how do you deal with state like open sockets in an evented design?

14:16 devth: i'm a heavy vim user but thinking about seeing if all my workflows could be ported to spacemacs.

14:17 rhg135: the kind you can't recreate

14:17 TimMc: Oh dear. Soon we will see a rant parallel to GNU+Linux where someone complains that Emacs is really just the kernel and that $FOO is the toolchain that matters.

14:17 justin_smith: TimMc: most of emacs is just RMS' .emacs

14:17 wink: TimMc: it's Emacs/Linux, not "Linux"

14:19 justin_smith: TimMc: oh, someone could pull an ubuntu, and make an "easy to use" emacs which randomly sends you to amazon.com

14:19 TimMc: justin_smith: Ha, so it has already happened.

14:20 justin_smith: TimMc: some of us still remember the huge Lucid/GNU emacs split (I was too young for the gosmacs / gnumacs split though)

14:21 TimMc: GNU+Emacs

14:21 I didn't start with emacs until maybe 2010.

14:22 justin_smith: part of the motivation for inventing the GPL: https://en.wikipedia.org/wiki/Gosling_Emacs

14:23 devth: i'm of the opinion that something as core as $EDITOR should be used for near-life in order to approach maximum potential proficiency and familiarity. so switching is a big deal :) but i've only used vim since 2009, and this would still be "vim-nature".

14:25 justin_smith: devth: I used vi, then vim, then emacs (back when Viper was the best vi emulation mode available), after many years with emacs I started to get wrist pain so switched to evil (the best current vim emulation mode)

14:25 spacemacs is built on evil mode

14:25 devth: nice. right

14:26 long term i think emacs is positioned to better support lang workflows. scala in emacs is pretty amazing. clojure in vim and emacs are probably nearly on-par.

14:26 haskell in emacs is way better than vim from what i've gathered.

14:26 BRODUS: can anyone recommend a good resource to learn about core.async

14:27 justin_smith: BRODUS: have you walked through the official intro?

14:27 BRODUS: no, im reading the section on braveclojure, im finding its explanations lacking

14:27 qsys: gen-class again... something really weird: when I use (:gen-class :implements [some.Class]), it compiles, however, some.Class is a abstract class... so when I change it to (:gen-class :extends [some.Class])

14:28 I get an ClassNotFoundException

14:28 it's not a classpath issue, since it does compile with :implements

14:29 justin_smith: qsys: maybe this is related to how how abstract classes are implemented in the vm - there are a lot of things that are abstracted one way in java and another in the vm, and clojure as a rule uses the vm's version

14:29 qsys: am I missing something about :extends and abstract classes (clojure 1.7.0, by the way)

14:32 slester: is there a good place to learn about using the REPL to its maximum when developing?

14:37 devth: slester: some good stuff at http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

14:44 spieden: slester: here's my ~/.lein/profiles.clj https://gist.github.com/spieden/5af1b11cadceaeed83b9

14:44 slester: might be old versions -- haven't checked in a while

14:45 slester: devth: thanks!

14:45 and spieden!

15:09 BRODUS: am i understanding this correctly? (doseq [i (range 10 100)] (go (>! c (blocking-io-function i)))) will create 90 blocking processes, each one put on a thread in my thread pool. Since there are only 6 threads(4 core machine), only 6 processes will be able to execute concurrently.

15:10 qsys: allright, so :extend in :gen-class doesn't expect a vector - makes sense, a class can only extend one other class (in Java/on the JVM). sometimes things can be a little subtle

15:10 justin_smith: BRODUS: core.async creates 42+(nprocs*2) threads for its pool

15:11 BRODUS: but yes, this would lock up all 50 threads, then use more as they are available

15:11 which is why clojure.core.async/thread exists - for when you are doing blocking IO in core.async

15:14 BRODUS: if you use async/thread, it will return a channel that you can consume, and your go block can properly park and not own a thread (go (>! c (<! (thread (blocking-io-function i)))))

15:15 *not own a core.async pool thread - of course it still owns a (mostly inactive, blocking on io) thread

15:15 benjyz1: hi. is it possible to name async channels?

15:15 I want to implement publish-subscribe to topics

15:18 justin_smith: benjyz1: core.async/pub takes a "topic function" - you create your value (probably via a hash-map) so that the topic can be looked up in it. core.async/sub takes a topic as an argument.

15:20 BRODUS: justin_smith: i get it, but whats the other kind of thread if its not a core.async pool thread

15:20 justin_smith: BRODUS: a thread

15:21 you can make as many as you want, until the OS stops letting java create more

15:22 BRODUS: thread pools are useful because they let you reuse threads, which is good for performance, but you can always just make a new thread unless the OS tells you otherwise

15:22 see also java.lang.Thread

15:23 BRODUS: justin_smith: why would you want to reuse a thread?

15:23 justin_smith: BRODUS: because it is expensive to make new ones

15:24 BRODUS: core.async/thread actually uses a cached thread pool so even it can reuse threads https://github.com/clojure/core.async/blob/a6dc01d2ebb692a39e923988b0853ff2bd1a431b/src/main/clojure/clojure/core/async.clj#L420 the definition of thread is a couple blocks down from the pool definition there

15:25 benjyz1: interesting. a bunch of async functions have been moved to transducers

15:26 rhg135: but still you are bound by how many the hardware can run at a time, no?

15:26 justin_smith: benjyz1: I think the experience of designing and implementing core.async was part of the motivation for making transducers - they realized how much work they were redoing in order to map / filter / etc. on channels

15:26 rhg135: well, in terms of how many can run, sure, but the question started with a thread that would be blocked for a long duration

15:27 and that's handled with kernel level context switches and interrupts, it doesn't block a hardware thread (or else your computer wouldn't be very usable)

15:27 rhg135: ah I see

15:27 benjyz1: what about message durability? for me the problem is that its far from trivial to wrap TCP semantics in several scenarios

15:28 Peer-to-Peer networks and security is generally hard to do with TCP

15:28 justin_smith: benjyz1: yeah, core.async isn't about TCP or durability

15:28 benjyz1: I thought you meant pub-sub in core.async

15:28 BRODUS: justin_smith: thanks for the help

15:28 justin_smith: BRODUS: np

15:29 benjyz1: yes. I mean pub-sub over the internet via async. I assume both sides run the JVM

15:29 justin_smith: benjyz1: core.async as part of implementing pub-sub over sockets is a whole other can of worms, and you're probably better off using kafka and maybe tying that to core.async on your end if you want to use core.async

15:29 benjyz1: core.async is not a networking tool

15:30 benjyz1: yes absolutely, it is a can of worms

15:31 its kind of reason I'm drawn to Clojure in the first place. doing TCP means in a sense each process can use any language

15:32 Scala has Akka, and there is a wrapper around it called Okku

15:42 spieden: i much prefer core.async/CSP over Akka/Actors

16:33 pilne: ok, clojure has me stumped

16:34 BRODUS: pilne: whatsup?

16:34 pilne: (for [i (range 1 10)] (print i)) is returnning: 123456789(nil nil nil nil nil nil nil nil nil)

16:34 in the REPL

16:34 MJB47: what do you want it to output?

16:35 pilne: the nils confuse me?

16:35 MJB47: for returns a lazy seq

16:35 BRODUS: the list of nils is the output of for

16:35 MJB47: of all the returned values

16:35 print returns nil

16:35 if you dont care about the return values

16:35 use doseq

16:35 or dotimes

16:35 pilne: ohhhhhhhhhhhhh

16:35 BRODUS: the numbers preceding are side effects of the operations within for

16:38 pilne: whereas the for literally returns nothing (nil) on its own

16:40 cfleming: slester: If you're still having problems with a lein project feel free to ping me if you'd like help

16:41 BRODUS: for returns a lazy sequence, each item in the sequence is going to the be result of (print i)

16:41 print will print a string but it returns nil

16:43 pilne: because every function has to return "something" to be considered a function?

16:43 BRODUS: no, print is a function

16:44 it just always returns nil

16:44 justin_smith: pilne: the only things in clojure that I know of that do not return something are System/exit and throw (for obvious reasons you never get a return value when calling either)

16:45 even using interop with java / jvm stuff, if nothing else you'll get a return value of nil

16:45 pilne: well, it might be a bit quirky (for someone like me), but at least it is consistent (:

16:46 MJB47: well

16:46 justin_smith: pilne: that's how a lot of things in clojure are - not what you might be used to, but probably more consistent than what you are used to

16:46 MJB47: its the basis of functional programming

16:47 pilne: clojure is my first real REPL experience other than haskell, which makes it obvious up-front (in all the tutorials i found) that since it the REPL is inside the IOMonad, it will be quirky. So this is a fun new experience overall for me

16:48 justin_smith: pilne: yeah, the whole lang of clojure is in "io" more or less - which means source files and the repl are more mutually consistent, but we also don't have the benefit of purity

16:48 with the exception of the rarely used io! macro

16:49 BRODUS: pilne, heres a function that will print your string and return the string you passed in (defn print-with-return [s] (do (print s) (identity s)))

16:49 justin_smith: pilne: but even in haskell print returns - it's just that you are less likely to get a list of units returned by list processing - you'd get a type error instead more likely

16:49 MJB47: you can use print-str

16:50 justin_smith: BRODUS: #(doto % print)

16:50 MJB47: https://clojuredocs.org/clojure.core/print-str

16:50 justin_smith: MJB47: that's not a printing function though

16:50 that's for getting what print would have printed, but as a string

16:50 MJB47: wut

16:50 oh

16:50 you are correct

16:50 nvm me

16:50 ridcully: i like doto too. it injects easily into existing code

16:51 amalloy: justin_smith: well, map print xs :: [IO a], so you might well not get a type error until later

16:51 BRODUS: nice, haven't seen doto yet

16:51 amalloy: er, IO ()

16:51 justin_smith: amalloy: yeah, my haskell is still very weak

16:52 amalloy: i've been doing the advent of code exercises in haskell

16:52 it's good practice

16:52 justin_smith: cool!

16:52 amalloy: https://github.com/amalloy/advent-of-code if you are interested

16:52 justin_smith: I'm going through bitemyapp's book (slowly)

16:52 cool, I'll need to check that out

16:53 pilne: my gf bought me bitemyapp's book for xmas, but i don't get the download key until xmas eve >.<

16:54 i was smart enough to not argue when she wanted to wear one of the outfits i got her for xmas yesterday though >.<

16:55 what can i say, i'm a functional programming junkie, i've even taken an interest in factor lol

17:00 tem0p: (second [123 1001])

17:00 => 1001

17:00 (second [123 01001])

17:01 justin_smith: tem0p: 01001 means "1001 in octal"

17:01 ,0xff

17:01 clojurebot: 255

17:01 justin_smith: ,010

17:01 clojurebot: 8

17:01 tem0p: justin_smith: so what does that second statement return?

17:01 justin_smith: tem0p: I forget, but it's 1001 in octal

17:01 ,01001

17:01 clojurebot: 513

17:02 justin_smith: ,8r1001

17:02 clojurebot: 513

17:02 tem0p: justin_smith: Urgggh, so I'll have to change it to ["123" "01001"]?

17:02 justin_smith: tem0p: if you want it to print with a leading 0, use a format string

17:03 tem0p: justin_smith: Ahh good idea, thanks!

17:03 justin_smith: ,(format "%05d" 1001)

17:03 clojurebot: "01001"

17:04 tem0p: justin_smith: I was testing with [513000 01001] and getting 513 back lol, so confusing.

17:04 justin_smith: ahh, yeah I can see how that would be confusing

17:07 TEttinger: tem0p: neat the starting zero for octal is an annoyance in many languages. however, clojure adds a new and interesting thing like starting 0 for base 8 or 0x for base 16...

17:08 ,[2r001001]

17:08 clojurebot: [9]

17:08 TEttinger: ,[3r001001 4r001001 5r001001 6r001001 7r001001]

17:08 clojurebot: [28 65 126 217 344]

17:08 TEttinger: ,[13r001001 14r001001 15r001001 16r001001 17r001001]

17:08 clojurebot: [2198 2745 3376 4097 4914]

17:09 justin_smith: ,36rjustinsmith

17:09 clojurebot: 72595113320300741

17:09 TEttinger: and my absolute favorite is using 36r to encode arbitrary alnum strings as numbers, yes

17:09 tem0p: lol

17:09 TEttinger: ,36rTETTINGER

17:09 clojurebot: 82974197147859

17:10 justin_smith: ,(> 36rjustinsmith 36rtettinger)

17:10 clojurebot: true

17:10 justin_smith: :P

17:10 TEttinger: ,(> 29rjustinsmith 35rTOMMYETTINGER)

17:10 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "justi">

17:11 TEttinger: eh?

17:11 ,(> 30rjustinsmith 35rTOMMYETTINGER)

17:11 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "justi">

17:11 TEttinger: ,(> 30rjustinsmith 35rTOMMYETTINGER)

17:11 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "justi">

17:12 TEttinger: ohhh t

17:12 ,(> 31rjustinsmith 35rTOMMYETTINGER)

17:12 clojurebot: false

17:12 TEttinger: wonder why it stopped at i not t

17:12 I thought you stuck a \ufeff in there

17:14 justin_smith: nah, the number formatter wouldn't even take that

17:15 wink: daily wtf

17:18 suddenly my joke proposal for 0sqprFFXIV for roman numbers sounds sane.

17:18 (different language though)

17:18 and it's spqr of course

17:19 justin_smith: ,(clojure.pprint/cl-format "wink: ~@r" 42)

17:19 clojurebot: #error {\n :cause "clojure.pprint"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.pprint"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java.n...

17:19 justin_smith: ,(require 'clojure.pprint)

17:19 clojurebot: nil

17:19 justin_smith: ,(clojure.pprint/cl-format "wink: ~@r" 42)

17:19 clojurebot: #error {\n :cause "Don't know how to create ISeq from: java.lang.Long"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: java.lang.Long"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.core$seq__4116 invokeStatic "core.clj" 137]\n [clojure.co...

17:20 justin_smith: ergh

17:20 ,(clojure.pprint/cl-format nil "wink: ~@r" 42)

17:20 clojurebot: "wink: XLII"

17:20 justin_smith: ,(clojure.pprint/cl-format nil "wink: ~r" 42)

17:20 clojurebot: "wink: forty-two"

17:20 wink: not half as cool :P

17:20 justin_smith: haha

17:21 wink: still, wow

17:22 I'm not sure I'd apply violence to a coworker using that example here though: https://clojuredocs.org/clojure.pprint/cl-format

17:22 (cl-format true "There ~[are~;is~:;are~]~:* ~d result~:p: ~{~d~^, ~}~%"

17:23 "oh sorry, my cat walked over the keyboard"

18:18 devth: ,(def a 1)

18:18 clojurebot: #'sandbox/a

18:19 devth: when you def something in clojurebot how long does it last? does clojurebot auto-reset the sandbox on some interval?

18:19 ,help

18:19 clojurebot: #error {\n :cause "Unable to resolve symbol: help in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: help in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: help in this co...

18:19 justin_smith: devth: yeah, I think it's around 5 minutes

18:19 devth: interesting

18:19 justin_smith: but it's not 5 minutes from when you made the def, it's just every 5 minutes

18:20 devth: yeah. so you could get erased mid-experiment :)

18:20 amalloy: well don't use def then

18:20 devth: would be cool if you could snapshot/save sessions

18:20 mainly curious for my own bot's lang repls :)

18:24 justin_smith: ~help

18:24 clojurebot: Nobody can help with "X doesn't work". Please provide context: what you did, what you hoped would happen, and what happened instead. A stack trace is especially helpful, if applicable.

18:25 justin_smith: well there's a nice domain error for me

18:25 amalloy: dang, that might be the most polite factoid i've written

18:27 * spieden uses reify for the first time.

18:30 spieden: bah, doesn't work with abstract classes

18:32 justin_smith: spieden: try proxy

18:32 unlike reify, proxy can do concrete inheritance

18:34 amalloy: abstract classes :(

18:34 spieden: cool thanks

18:34 yeah so gross =\

18:34 it only has one concrete method

19:19 devth: hm, started using protocols and now i have to `lein clean` all the time

19:20 lots of weird error messages like "No single method: foo of interface ..."

19:21 justin_smith: devth: protocols and cached stuff / reloading don't really play nicely

19:21 devth: i'd expect a repl restart to fix things though

19:21 and at first they did

19:21 justin_smith: devth: lein caches things

19:22 devth: k

19:22 just can't quite figure out when i would have to clean

19:22 justin_smith: devth: iirc target/stale/

19:23 devth: rm -rf it to clear cache?

19:23 mine has a single file: extract-native.dependencies

19:24 justin_smith: I mean this is what lein clean should be cleaning, is the whole target dir

19:24 devth: ah

19:26 i don't know if my code is actually reloading at all. time for some (log/debug "WTF?")

19:28 lol it was a shadowing problem

19:28 justin_smith: oops!

19:29 devth: while trying to debug another problem of a dynamically bound var being unexpectedly nil...

19:31 hm. so if i pass a fn as a callback using #'myfn syntax, when myfn gets called, bindings are not persisted?

19:32 justin_smith: Calling #'myfn as a function always looks up the latest value of that var. If you are using something like tools.namespace the var might have been deleted from the namespace instead of mutated, but otherwise, with normal code reloading, the function calling the var should end up invoking the new value.

19:39 devth: hm. looks you're right.

19:39 still i will remove #' and see what happens.

19:42 do bindings cross ref boundaries?

19:43 the irc lib is taking my callbacks and storing them in a ref

19:45 tem0p: is there a way to add multiple singular elements at once? so something like (<fname> v ({:a a :b b} {:c c :d d})) => [{:a a :b b} {:c c :d d}]

19:47 ridcully: apply conj?

19:47 justin_smith: ,(apply conj [] '({:a a :b b} {:c c :d d}))

19:47 clojurebot: [{:a a, :b b} {:c c, :d d}]

19:47 justin_smith: ,(into [] '({:a a :b b} {:c c :d d}))

19:47 clojurebot: [{:a a, :b b} {:c c, :d d}]

19:47 ridcully: there you have it from authority

19:47 justin_smith: into is just a beefed-up apply conj

19:47 tem0p: Ahh perfect, thanks :)

19:56 devth: this is what's going on: https://gist.github.com/devth/77067d61b7b0922bf6ec (Thread. ...) is being created in the irclj lib https://github.com/Raynes/irclj/blob/master/src/irclj/core.clj#L143

19:56 bindings don't get copied into new Thread instances

19:57 hmm. not sure how to fix since it's in the lib.

19:58 justin_smith: devth: if you use future instead of Thread it will propagate thread bindings

19:58 devth: hmm. maybe i will submit a PR

19:58 Raynes: you around?

20:04 justin_smith: yep that fixed it

20:05 justin_smith: devth: bonus, it also uses the expandable thread pool instead of one off thread creation

20:05 devth: ah cool

20:05 justin_smith: agent-send-off-pool is the one iirc

20:06 devth: https://github.com/Raynes/irclj/pull/35

20:06 gotta go for now. thx for the help (again) justin_smith!

20:08 justin_smith: devth_afk: glad I could help

21:26 BRODUS: this is a really good video on core async https://www.youtube.com/watch?v=VrmfuuHW_6w

21:29 noncom|2: i just found a super weird thing that kills (into {})

21:30 ,(into {} (partition 2 [:a 1]))

21:30 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :at [clojure.lang.ATransientMap conj "ATransientMap.java" 44]}]\n :trace\n [[clojure.lang.ATransientMap conj "ATransientMap.java" 44]\n [clojure.lang.ATransientMap conj "ATransientMap.java" 17]\n ...

21:30 noncom|2: coz

21:30 ,(into {} '((:a 1)))

21:30 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :at [clojure.lang.ATransientMap conj "ATransientMap.java" 44]}]\n :trace\n [[clojure.lang.ATransientMap conj "ATransientMap.java" 44]\n [clojure.lang.ATransientMap conj "ATransientMap.java" 17]\n ...

21:30 noncom|2: but

21:30 ,(into {} [[:a 1]])

21:30 clojurebot: {:a 1}

21:30 noncom|2: wtf?

21:33 is this the intended behavior?

21:35 BRODUS: looks like it, from the first example here: https://clojuredocs.org/clojure.core/into

21:35 justin_smith: ,(vec {:a 1})

21:35 clojurebot: [[:a 1]]

21:35 justin_smith: noncom|2: looks good to me!

21:36 ,(into [] {:a 1})

21:36 clojurebot: [[:a 1]]

21:36 turbofail: ,(conj {} [:a 1])

21:36 clojurebot: {:a 1}

21:36 justin_smith: (more direct comparison)

21:36 turbofail: ,(conj {} '(:a 1))

21:36 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :at [clojure.lang.APersistentMap cons "APersistentMap.java" 42]}]\n :trace\n [[clojure.lang.APersistentMap cons "APersistentMap.java" 42]\n [clojure.lang.RT conj "RT.java" 645]\n [clojure.core$co...

21:36 noncom|2: umm.. see, i get a list.. i want to (->> list (partition 2) (into {}))

21:37 justin_smith: noncom|2: (map vec)

21:37 turbofail: just add a (map vec) after the partition

21:37 noncom|2: oh

21:37 turbofail: basically, conj on a map knows what to do when it sees a vector, but not a sequence

21:37 noncom|2: very strange really

21:38 it could as well understand a two-element (), just like a two-element []

21:38 can't imagine why shouldn't it

21:38 justin_smith: noncom|2: but you can make a map entry out of a vector directly, you can't make one out of a list directly

21:38 noncom|2: esp that most functions return ()s

21:38 justin_smith: yeah, turns out so

21:39 it's just that that is counter-intuitive

21:39 is there any real reason for that?

21:39 some greater good?

21:39 justin_smith: noncom|2: I meant that literally - thecode that make a map entry can use a vector to make a map entry, a list would need converting

21:40 noncom|2: so nobody made the converting default

21:40 noncom|2: aha, that's what

21:40 i see

21:40 justin_smith: noncom|2: like it or not, clojure avoids building some conveniences that would have larger hidden costs

21:41 whether "larger" follows any reasonable standard of measure is another question :)

21:41 noncom|2: well, yes, that makes sense. but in this particular case and with this particular error message it just an unexpected startling stumble

21:42 good that you are here, guys, and can explain

21:42 BRODUS: is it that getting the two elements from the vector is faster than getting them from a list?

21:42 justin_smith: that's true - it's not something that can be caught statically when compiling, and often clojure messages that can't be caught while compiling are very odd

21:42 BRODUS: I'm not totally certain actually

21:44 turbofail: i feel like a performance-based reason is unlikely

21:45 but who knows

21:45 justin_smith: turbofail: try submitting a patch that checks for non-vector sequentials and makes vectors automatically

21:45 turbofail: it will be rejected for performance reasons

21:46 turbofail: they reject patches that do sanity checks at runtime in order to have better failure messages - once again, performance reasons

21:50 turbofail: perhaps. but i feel like this particular thing could be implemented with basically no performance impact

21:50 justin_smith: do tell?

21:54 tem0p: is there a version of into that doesnt add duplicates for vectors? or do I just run (distinct col) over it after?

21:55 justin_smith: ,(into [] (distinct) [1 2 3 3 4 5 1])

21:55 clojurebot: [1 2 3 4 5]

21:55 tem0p: ahhh, perfect, you're awesome, thanks

21:56 justin_smith: tem0p: the only thing is (distinct) won't check for items already in the vector

21:56 ,(into [5] (distinct) [1 2 3 3 4 5 1])

21:56 clojurebot: [5 1 2 3 4 ...]

21:56 justin_smith: stupid cut off

21:56 ,(into [2] (distinct) [1 2 3 3 4 5 1])

21:56 clojurebot: [2 1 2 3 4 ...]

21:56 tem0p: justin_smith: Oh right damn

21:57 justin_smith: If i used a set then I could use union right?

21:57 justin_smith: tem0p: if you don't care about order

21:57 tem0p: justin_smith: yeah I dont mind order, that seems good then :) cheers

21:58 turbofail: hm, actually i see the real reason, looking at the code - it's because if it's not a vector, it assumes that what's coming in is going to be convertable to a sequence of map entries - e.g. another map

21:59 ,(into {} {:a 0 :b 1})

21:59 clojurebot: {:a 0, :b 1}

21:59 turbofail: so basically it's to make conj do what might be the right thing for map arguments

22:00 and, i guess, any other sequences of MapEntries

22:01 if it weren't for that you could totally remove the instanceof check for vectors, and just call clojure.lang.RT.nth to get the first and second args, and that'd be plenty fast for vectors

22:01 (it'd still be slow for lists, but it wouldn't slow down the vector case)

22:03 whoops, messed up my example

22:03 ,(conj {} {:a 0 :b 1})

22:03 clojurebot: {:a 0, :b 1}

22:36 justin_smith: ,(conj :a {:b 2} {:c 3})

22:36 erm

22:36 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to clojure.lang.IPersistentCollection"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to clojure.lang.IPersistentCollection"\n :at [clojure.core$conj__4104 invokeStatic "core.clj" 87]}]\n :trace\n [[clojure.core$conj__4104 invokeStatic "core.clj" 87]\n [clojure.core$conj__4104 doInvoke "core....

22:36 justin_smith: ,(conj {} :a {:b 2} {:c 3})

22:36 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Keyword"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.lang.Keyword"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.lang.APersistentMap cons "APersistentMap.java"...

22:36 justin_smith: oh, right

22:36 ,(conj {} [:a {:b 2}] {:c 3})

22:36 clojurebot: {:a {:b 2}, :c 3}

Logging service provided by n01se.net