#clojure log - Dec 26 2014

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

0:46 ryancole: as a newbie to clojure, what editor should i be using on windows? is light table the way to go, or should i try something like emacs?

0:46 like in the long run, which would benefit me the most

0:47 justin_smith: ryancole: as a newcomer, I would start by using (require 'my.ns :reload) after saving a new version of the namespace file

0:47 save the editor integration for later, when you realize it isn't magic

0:48 ryancole: i think that was over my head. are you saying to just use repl?

0:48 justin_smith: I like emacs as a long term user, but cider gets broken a lot with new releases, so it can be frustrating. I have been using inferior lisp lately instead.

0:48 ryancole: yes, you can reload code in the repl with require, after saving it. The editor integration just maps that to a keypress (and has shortcuts for things like docs of course)

0:49 ryancole: also, the most featureful editor integration for clojure is intellij idea, with the cursive plugin

0:50 ryancole: afaik the only sane way to do step debugging of clojure code right now

0:50 (but I still use emacs because I have used emacs for over a decade and IDEs bug me)

0:52 ryancole: ok, perhaps clojure's repl is powerful enough to fully support editing code in files and such, without the need for an extra text editor?

0:52 im familiar with repl for like python where it wasnt commonly used as also the "editor"

0:52 justin_smith: not quite. Do the editing in whatever editor you like best (at first), and the repl can reload after you update the code.

0:52 ryancole: more so used for like one-off testing, or running files, etc

0:52 ah ok i see

0:53 namra: ryancole: you might also look at this http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

0:53 justin_smith: clojure's repl is interesting in that you can leave it running as you update code, and it can reload all your new definitions etc. without needing a restart

0:53 though there are a few constructs that don't play as nicely with that, they are only a few

0:59 ryancole: cool, im going to go hop in bed and read that workflow blog post. thanks! :)

0:59 justin_smith: namra: ryancole: the reloaded workflow is great, but not really the best way to *start* using clojure

0:59 imho

1:00 eventually, you'll love it, but better to just do the repl basics first I think

1:00 namra: true

1:00 but it give a nice overview what is possible with the repl, and that one is not really required to use a specific editor that has plugins to interact with a repl.

1:01 of course using such editor with a plugin comes also in handy ^^

1:01 justin_smith: that's an excellent point, yes

1:08 namra: ryancole: have you worked with anything like emacs or vim before?

1:09 such editors are nice when you like to tinker and customize stuff, and don't want a large IDE to get into your way

1:10 and currently it looks like that there are both for vim and emacs good plugins available to write programms in clojure

1:10 ryancole: namra, vim - not emacs

1:10 justin_smith: fireplace.vim is good

1:10 namra: yep

1:11 justin_smith: but I still think starting without the editor integration helps

1:11 namra: justin_smith: i agree with you

1:12 ryancole: then i'd go with vim or vim-like, so you don't need to dive into emacs, if time is scarce. but there's still evil-mode ^^, to make a transition to emacs a little bit easier.

1:12 * justin_smith uses evil mode

1:13 ryancole: haha, vi for emacs

1:13 nice

1:13 namra: a nice looking and simple ide that comes with integrated leiningen and repl: https://nightcode.info/

1:14 justin_smith: ryancole: I use it because I like the features of emacs (eg. especially org-mode and gpg integration), and I like the extension language being a real language I can tolerating coding in, but I hate the default keybindings, they are sadistic

1:14 namra: :D

1:15 ryancole: so ive heard :P

1:15 namra: never tried emacs, but the elisp now looks very appealing. easier than the cryptic vim-syntax ^^

1:16 ryancole: im just aiming for the most minimal, basic route into a simple edit code -> run code learning process

1:17 and as i get familiar with the tools, add in more feature packed editors

1:18 namra: then what justin_smith said seems a good way, take an editor your familiar with, edit you code within it and use the repl to reload the files and test your stuff within the repl

1:24 ryancole: sweet, sounds good to me :)

1:24 ok guys gotta hop off. ill be reading up on stuff and swing back by later, im sure.

1:24 thanks

2:34 santaClaws_: hey

2:36 can I do those haskell (f.g) x = f (g x) stuff in clojure?

2:38 andyf: (comp f g) is Clojure's (f . g)

2:47 santaClaws_: ok cool thing. I have just started, The chapter on maps nad list is uite long . at iloveponies.github.io

2:47 *and

2:53 I wanted to know about functional programming , I chose clojure, although my codes have an awful lot of parenthesis.

3:03 rksm: Hello, any fipp users here? Is there an easy way to keep comments when pretty printing with fipp.clojure/pprint?

3:15 Or for that matter, is there a recommended other way to pretty print clj code?

3:27 korpse: How do people use joplin or ragtime in production or from an uberjar?

4:17 piranha: I'm having exact trouble like here: http://stackoverflow.com/questions/23489106/cljx-starter-project-browser-repl-issue - any ideas how to solve?

4:17 I've connected to my browser and can't require anything

4:18 augustl: does mori (cljs data structures in JS) have any serialization built in?

4:19 piranha: augustl: you convert it to JS structures and then JSON.stringify, if that's your question

4:21 octe: what better way is there to get the shortest collection then this: (reduce (fn [x y] (if (> (count x) (count y)) y x)) coll)

4:22 hyPiRion: octe: (apply min-key count colls)

4:22 si14: is there anything similar to Prismatic's Graph, but for "decision graphs" like this one https://github.com/for-GET/http-decision-diagram ?

4:23 octe: thanks

4:23 si14: there is Liberator, but I'm interested in more general "engine"

4:24 of course it's possible to use just a big bunch of nested if-s, but it quickly becomes uncomfortable

4:27 augustl: piranha: I see, was hoping there was a way to avoid the conversion to JS structures :)

4:28 piranha: augustl: well, I guess with transit-js you could write handlers to do that :)

4:55 octe: i'm writing a function to find the shortest path between two nodes in a graph, it seems to work but is quite slow and i'm not sure how to do it in a faster way without having some kind of mutable state

4:55 http://pastebin.com/X7HxwpyU

4:58 si14: octe: you may be interested in Dijkstra algorithm. Google gives a lot of relevant posts on "dijkstra clojure" request

5:01 octe: generally speaking, you have quite a lot of overhead in your algorithm. e.g., this (filter #(not (lazy-contains? (flatten path) %1)) (get-neighbours current)) piece will have quadratic complexity because you are flattening and scanning for each of neighbours

5:02 octe: yeah, i know

5:02 i'm just not sure how to do it in a better way :)

5:03 i'm reading up on dijkstras algoorithm

5:16 si14: octe: it's a bit nontrivial to translate it to Clojure properly from typical "mutable" description, but it's a worthy exercise :)

5:17 octe: yeah

5:17 it's an interesting task :)

5:22 mearnsh: justin_smith: "nothing in the code you pasted uses atom" - that's why i'm stumped...

5:25 (and yeah I know my use of atom? is confounding but it makes sense here)

5:27 andyf: are you aware of the data.priority-map library for maintaining maps with items sorted by their values? Very useful for Dijkstra's algorithm

5:57 dysfun: is there a macro for doing the inverse of {:keys [foo bar]}, i.e. i have vars foo and bar and i want a shorthand for doing {:foo foo :bar bar}

5:58 it seems like a common case

5:58 SagiCZ1: wait what

5:59 you cant use values to get keys, can you?.. they are not uniqe

5:59 dysfun: you *could*, potentially expecting multiple results

5:59 but it would be slow and daft

6:00 SagiCZ1: i guess..

6:00 dysfun: if you want this functionality, there's a function that inverts a map (with those limitations), let me look up the name

6:01 sm0ke: is there some representation for int in clojure like for bigdec and bigint?

6:01 SagiCZ1: cool i didnt know that.. well what you ask for is not a macro but a destructuring functionality i think

6:01 sm0ke: ,(class 1M)

6:01 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

6:01 sm0ke: hurmm

6:01 SagiCZ1: ,(type 4)

6:01 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

6:02 dysfun: SagiCZ1: well in this case, that's a destructuring bind taken care of by the reader, yes. this is just shorthand to allow me to be lazy. I can see how it would be a trivial macro. but we're assuming i'm going to pass in a fixed set of items anyway and since the names are calculable trivially, i'm not concerned with the ramifications of potentially duplicating things etc.

6:06 sm0ke: edn should ideally differentate between a int and a long

6:06 is my point

6:07 SagiCZ1: sm0ke: why do you need to?

6:08 dysfun: SagiCZ1: https://www.refheap.com/95417

6:09 SagiCZ1: oh.. i see.. i didnt realize that the value and key is the same in the pair

6:13 dysfun: if they weren't, it wouldn't be the inverse of the destructuring bind :)

6:15 Bronsa: dysfun: fyi there's no such thing as "destructuring bind taken care of by the reader"

6:15 dysfun: the destructuring functionality is just macrology

6:24 dysfun: hrm, howso?

6:26 Bronsa: $source destructure

6:26 lazybot: destructure is http://is.gd/R9QO9F

6:27 Bronsa: dysfun: destructure is just a regular function, it's used inside a bunch of macros like let and fn

6:31 dysfun: oh right, cool

6:33 SagiCZ1: can i avoid calling rand twice here and get the same result?

6:33 ,(repeatedly 5 #(vector (rand) (rand)))

6:33 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

6:33 SagiCZ1: who broke clojurebot?

7:49 Frozenlock: dysfun: is this what you were looking for? https://www.refheap.com/11818

7:49 mearnsh: justin_smith: uh sorry, i'm a fool, ignore

8:00 dysfun: Frozenlock: no, i already refheap'd a quickly thrown together one: https://www.refheap.com/95417

8:02 actually, sorry, i misread your example. yes, that also works

8:02 Frozenlock: Ah sorry. Your's more general. I guess the one I pasted was filtering nil values for some reason.

8:04 dysfun: *shrug* it was the first thing i came up with

8:04 i figure there's not a great deal that can go wrong

8:04 Frozenlock: inb4 the planet explodes!!!!

8:06 dysfun: hrm, that's odd

8:06 ,(keyword 'nil)

8:06 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

8:06 jonathanj: i don't understand how to deploy lein-ring applications to production using an uberjar, ring options have to be in a :ring key in the project so how do i override/set these in production?

8:07 dysfun: jonathanj: it's possible you've outgrown lein-ring, it's really just a small wrapper that'll provide a main()

8:08 it uses jetty under the hood. you can write your own main function and provide :main in the project.clj

8:08 ring-server is very easy to use, just a single function call

8:08 Frozenlock: jonathanj: as dysfun said, you might want to use jetty in your -main. ----> (jetty/run-jetty #'app {:port some-port :join? false})

8:09 dysfun: (as is jetty. well, if you're not using it as a container, that is...)

8:10 * dysfun went to play with it as a container, found it had spewed tons of xml everywhere, gave up

8:10 jonathanj: dysfun, Frozenlock: thank you :)

8:33 godd2: would you say that [1 2 3] is merely syntactic sugar for (vector 1 2 3) ?

8:40 AimHere: Yes

8:40 Though I'd dispute the phrase 'merely syntactic sugar'

8:40 Unless you're at the level of wiring up your NAND gates yourself, all computer programming is just syntactic sugar

8:42 dysfun: heh

8:42 nice way of looking at it

8:43 does anyone know why (keyword 'nil) returns nil? surely at that point it's the symbol nil?

8:44 Bronsa: ,(keyword nil)

8:44 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

8:44 Bronsa: &(keyword nil)

8:44 lazybot: ⇒ nil

8:44 Bronsa: &(keyword 2)

8:44 lazybot: ⇒ nil

8:44 Bronsa: &(keyword (Object.))

8:44 lazybot: ⇒ nil

8:44 Bronsa: dysfun: keyword returns nil if you hand it a nonsensical arg

8:44 AimHere: (keyword '2)

8:44 godd2: &(keyword 'nil)

8:44 lazybot: ⇒ nil

8:45 AimHere: ,(keyword '2)

8:45 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

8:45 Bronsa: dysfun: also 'nil is the same as nil

8:45 dysfun: why is a symbol nonsensical?

8:45 Bronsa: dysfun: nil is not a symbol

8:45 &(symbol? nil)

8:45 lazybot: ⇒ false

8:45 Bronsa: &(symbol? 'nil)

8:45 lazybot: ⇒ false

8:45 dysfun: so nil can't be quoted?

8:45 Bronsa: &(= nil 'nil)

8:45 lazybot: ⇒ true

8:45 Bronsa: dysfun: it can be quoted, it's just not a symbol

8:45 dysfun: like true and false

8:45 quoting nil, true and false returns nil true and false

8:45 they are self-evaluating

8:46 just like quoting a keyword returns that keyword

8:46 ,':foo

8:46 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

8:46 Bronsa: &':foo

8:46 lazybot: ⇒ :foo

8:46 dysfun: so in order to store the symbol nil, i would have to cast to symbol first?

8:46 Bronsa: yeah.. you can only obtain it via ##(symbol "nil")

8:46 lazybot: ⇒ nil

8:46 dysfun: hrm. i'm not sure how i feel about that

8:47 Bronsa: about what?

8:47 dysfun: nil being self-evaluating

8:48 Bronsa: dysfun: it is documented that nil is not a symbol btw

8:48 dysfun: i'm sure it is

8:48 Bronsa: "Strings, numbers, characters, true, false, nil and keywords evaluate to themselves."

8:48 luxbock: ##(nil? (symbol "nil"))

8:48 lazybot: ⇒ false

8:48 Bronsa: and also, "nil is not a Symbol"

8:49 dysfun: i'm trying to figure out in my head if that's more or less confusing than the alternative

8:49 Bronsa: dysfun: imgagine how confusing it would be if every time something returned "nil" you had to figure out if it was the symbol nil or the "value" nil

8:50 AimHere: I thought nil can be a value of any data type

8:50 Bronsa: dysfun: not even talking about the fact that (symbol "nil") evaluates to a truthy value

8:50 dysfun: well not really. most programs don't use symbols outside of macros

8:51 i think if you've quoted nil, it's quite clear you meant the symbol

8:52 but it's not a common case, so i don't think it's a big deal

8:52 Bronsa: dysfun: sure but think about (defn foo [some-map] (get some-map some-key)), and you get back "nil" at the repl

8:52 dysfun: now you have no way to know if that's a symbol or the nil "value", looking at it

8:53 dysfun: well, my repl has pretty-printing that works. and your code will know, since strings are truthy

8:55 i guess it comes down to whether you think having the symbol 'nil around is a good thing

8:56 and i think in the general case, probably not

9:24 SagiCZ1: say you have an application with gui and there is a way to start some long running tasks.. there should always be an option to interrupt that task and stop it.. say it runs in a thread in future, how would i go about interrupting it?

9:28 jonathanj: i'm trying to define a name (used in several places) that is passed in from the command-line

9:28 (a database uri in this case)

9:28 usually i'd just pass the value around but in this case it seems like using a ^:dynamic var might be easier?

9:29 i've defined it as (def ^:dynamic foo) and in my main function i do (defonce foo ...)

9:29 Bronsa: SagiCZ1: future-cancel

9:29 jonathanj: this gives me a warning though: Warning: *database-uri* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *database-uri* or change the name.

9:30 dysfun: jonathanj: you want (binding [name val])

9:30 SagiCZ1: (doc future-cancel)

9:30 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

9:32 jonathanj: dysfun: *database-uri* is used from several functions (called from various places probably from other threads if i understand how jetty works) so how do i used binding in this case?

9:32 * si14 how do you deal with a bunch of nested if/let/if-lets, like this one https://gist.github.com/si14/121f25077cf842088348 ?

9:32 jonathanj: (binding [...] (run-jetty ...) ?

9:32 si14: (sorry, that /me was erroneous)

9:33 SagiCZ1: si14: do you find it unreadable?

9:34 si14: SagiCZ1: I wonder if it can be done better. One of the low handing fruits is if-not-let macro, of course

9:34 dysfun: jonathan: should be fine

9:35 SagiCZ1: si14: this written in java would be three times as long

9:36 si14: SagiCZ1: you are right, of course :) I believe it can be improved though

9:36 SagiCZ1: si14: yeah i would love to hear some improvements myself..

9:38 Bronsa: thank you for future-cancel

10:08 kl: Hi

10:08 Looking into core.async

10:08 jonathanj: how can i conditionally thread some things? something like (-> X foo bar (if some-cond? (-> quux baz)) quaz)?

10:08 kl: When you use a go macro in clojure/core.async - is it a thread of its own?

10:08 SagiCZ1: go macro does not create a thread

10:09 kl: SagiCZ1: what is it? I'm looking to compare that to an actual golang Goroutine

10:09 SagiCZ1: it is just a block of code that gets executed via callback.. the callback mechanism is hidden.. but no new threads are spawned.. cant really compare it to golang

10:10 kl: SagiCZ1: so every go macro executes, on the main thread?

10:11 SagiCZ1: yse

10:11 yes

10:11 u can have thread if you use thread blocks

10:11 (thread ...)

10:11 and then use >!! and <!!

10:11 dysfun: huh? aren't go blocks thread-local as opposed to specifically on the main thread?

10:12 kl: something doesn't sound right about this

10:12 SagiCZ1: i might be wrong

10:12 the doc say: Asynchronously executes the body, returning immediately to the calling thread.

10:12 and: ...by 'parking' the calling thread rather than tying up an OS thread

10:13 * dysfun has only just started playing with core.async

10:13 SagiCZ1: me too actually, dont take my word on it..

10:14 i thought that go blocks and >! <! dont use new threads

10:16 dysfun: okay, it uses a thread pool

10:20 kl: dysfun: so it basically uses a thread (with a maximum number of threads i.e. pool)

10:20 This is what I thought

10:26 octe: i have a map where each key is a parent and the value is the child and i want to from one key create a list of the relations

10:26 bad explanation i think

10:26 but in a mutable/imperative way i'd do something like while ((current = map.get(current)) != null) { resultList.add(current) }

10:27 SagiCZ1: that would always leave you with one element in the list

10:29 octe: not really?

10:29 SagiCZ1: current is still the same thing?

10:29 octe: it would change for each iteration

10:29 SagiCZ1: yeah i dont see that in the example

10:29 octe: = map.get(current)

10:30 http://pastebin.com/N5FCKS0C clojure implementation

10:30 showing what i mean

10:32 but obviously not implemented in a very good way..

10:32 but it works

10:32 SagiCZ1: yeah

10:32 you can use nil? btw

10:32 instead of not (= nil .. )

10:32 octe: true

10:33 SagiCZ1: i think you could build this list using reduce

10:34 so you have a map like this {:parent "child" :child "grandchild" ..} ?

10:34 octe: yes

10:34 ending where the key maps to nil

10:35 SagiCZ1: and you want a path from root to the last children?

10:35 octe: from one of the keys to the root, i guess

10:35 SagiCZ1: i see

10:35 octe: '(:parent :child :grandchild)

10:36 SagiCZ1: the maps in clojure are not really meant to used this way i think.. but you can have a look at tree-seq and clojure.walk which should solve this issue

10:37 kl: are there any must-reads after Joy of Clojure?

10:37 octe: what would be a better way to represent it?

10:38 SagiCZ1: clojure.zip is for working with nodes, children, branches etc

10:38 http://clojure.github.io/clojure/clojure.zip-api.html

10:52 octe: SagiCZ1, http://pastebin.com/fVJ6RvCS that seems to work with reduce

10:53 if you were curious :)

10:54 nuwanda_: https://www.youtube.com/watch?v=YgvJqWiyMRY Brandon Bloom talking about representing data in trees with clojure

11:00 justin_smith: octe: sounds like you may want the adjacency list representation for graphs

11:00 http://en.wikipedia.org/wiki/Adjacency_list

11:01 the nice thing about an adjacency list, is it can represent a fully general graph (including potentially cycles) without using a mutable or cyclic datastructure

11:02 bbloom: kl: a goroutine is a proper green thread with it's own stack

11:03 kl: go blocks in core.async have their own per-block state, but it's a finite state machine, not a full stack

11:03 justin_smith: SagiCZ1: and they use their own pool of threads on the jvm version

11:03 bbloom: dysfun: go block code may run on the original thread depending on readiness of channels and other implementation details

11:03 there is a thread pool pre-allocated for go blocks

11:03 which is similar to how golang multiplexes go routines on to threads

11:04 on cljs, there are no threads

11:04 so go blocks execute via setTimeout (or similar) when there is idle time

11:04 on the jvm, there is a thread pool for go block execution

11:04 but where the go block code runs is never a promise

11:04 i should say "is undefined"

11:04 yeah, but like i said: sometimes go block code can run on the original thread

11:05 go block bodies should never block the thread w/o using channel operations

11:07 octe: justin_smith, that sounds fitting

11:08 justin_smith: bbloom: I think you were (are?) lagging again

11:08 maybe not

11:09 bbloom: justin_smith: argh. thanks

11:09 i have no way of debugging it

11:10 justin_smith: erc had a "lag" section of its status bar

11:10 I don't know if other clients have this...

11:10 bbloom: i have a /lagcheck command

11:10 but i have to execute it manually

11:10 justin_smith: yeah, seems like it would be a nice thing to have periodically run and displayed in a status bar automatically

11:12 octe: i think i've created an implementation of dijkstras algorithm

11:12 http://pastebin.com/QcQU3n30 how does it look?

11:14 it still kind of slow for longer paths

11:14 justin_smith: octe: there are also graph libs, that implement various path finding algorithms (and books full of various graph algorithms you could implement...)

11:15 octe: yup, i wanted to try myself though :)

11:15 justin_smith: http://www.textbooks.com/BooksDescription.php?BKN=951029&SBC=ME8&kpid=9780262033848N&kpid=9780262033848N&kenshu=02dbe049-1491-fa29-ea40-0000115ff57c&mcid=XKS-7565-39-186-GoogleShopping-PRIDREPLACE-291&gclid=CK_tzqyN5MICFVSSfgodjXgA7g lots of great graph algorithms in this book

11:16 it's a commonly used textbook, so not super hard to find used

11:18 fm75: justin_smith: studied on it long time ago, and re-bought it recently for my library :)

11:19 justin_smith: fm75: it's a good book, I have learned a lot from it

11:20 fm75: justin_smith: I didn't like too much the fact that arrays are 1-based in the pseudocode - sometimes it was painful

11:21 justin_smith: yeah, it's not perfect

11:34 Hamled: Is it non-idiomatic or otherwise a bad idea to do something like (let [sentinel (gensym) foo (get coll key sentinel)] (if (= foo sentinel) ...))

11:34 justin_smith: Hamled: (contains? coll key)

11:34 Hamled: does that work for indexed sequences like vectors

11:34 justin_smith: same way get does

11:35 Hamled: okay thanks

11:35 justin_smith: by checking if the index is there

11:35 &(contains? [:a :b :c] 1)

11:35 lazybot: ⇒ true

11:36 dnolen_: Hamled: it's more common to use a namespaced keyword or (Object.)

11:36 bbloom: Hamled: it's not super idiomatic, but it's not a bad idea either. in addition to contains?, which justin_smith mentioned, there's also ##(doc find)

11:36 lazybot: ⇒ "([map key]); Returns the map entry for key, or nil if key not present."

11:36 justin_smith: oh yeah, I keep forgetting about find

11:37 Hamled: ah yeah I had been thinking about find and I think my experience with other languages made me figure it wouldn't work with vectors

11:37 thanks :)

11:37 justin_smith: &(find [:a :b :c] 1)

11:37 lazybot: ⇒ [1 :b]

11:37 justin_smith: I would not have guessed

11:37 but that is nifty

11:38 luxbock: had no idea about `find` but I could've used it many times before, nice

11:39 I should try to find a way to use it with what I'm working now so I don't forget about it

11:40 justin_smith: also, find should be on the clojure cheatsheet

11:40 ahh, it's in grimoire, of course

11:40 Hamled: oh I'll have to bookmark that

11:43 SagiCZ1: thanks to all who reacted to something i wrote, i was out for a second.

11:43 on the topic of trees.. i am trying to write an algorithm that divides data into a non-balanced binary tree and i need to be able to easily traverse the leaves of this tree.. what would be the best data representation? i am not sure if a simple map can cut it

11:44 watching Brandon's video atm

11:45 justin_smith: SagiCZ1: for a simple non-balanced tree I would use (deftype tree [left right]) and a protocol for inserting / removing

11:45 err [value left right] of course

11:45 SagiCZ1: that would be a first time when i would really need to implement a protocol in clojure.. maybe its about time i learn about that

11:46 justin_smith: SagiCZ1: I think IAssociative would be the right one to implement (maybe?)

11:47 luxbock: SagiCZ1: I'm working on a project that uses zippers to represent game trees, and when I started out I was just learning about protocols, so I made all my nodes records and then created some protocols to use them with, but now I just finished re-writing all of that to just use regular maps

11:47 octe: e

11:47 heh

11:47 SagiCZ1: luxbock: cool.. so how does that work?

11:48 octe: turns out most of the time was being spent on getting the children in my function, which was actually a database query

11:48 justin_smith: woah, zippers?

11:48 octe: heh, that would do it

11:49 luxbock: SagiCZ1: I have three different kinds of nodes, so I had a TreeNode protocol with branch?, children and make-node defined

11:49 but I switched to just using :type key inside a map instead

11:49 octe: yup, a path with 17 nodes went from 1s to 130ms when i memoized the db-query function

11:49 :P

11:50 SagiCZ1: luxbock: so how does the protocol work now? it gets dispatched acording to the :type?

11:50 luxbock: now branch?, children and make-node are just functions, and yeah they do stuff based on the :type key

11:51 SagiCZ1: luxbock: i really like how you simplified the problem.. i dont think you needed a protocol there necessarily... in my problem the creation of tree is just a necessary structure for the algo to work so i am reluctant to build a library around it

11:52 luxbock: SagiCZ1: yeah, I just used them because I was learning about them at the time, and in a way I'm glad I did because now I understand them better

11:52 but I think this simpler approach is better in the end. It wasn't use the nodes that I rewrote. I had over-engineered a bunch of other stuff as well while learning about new things :)

11:54 SagiCZ1: luxbock: its really hard at first when you dont know what is available... to correctly design

11:54 luxbock: yeah indeed

11:58 I'm just now racking my brain trying to figure out a function to translate the existing tree structures I have to expand them by inserting new branches in the middle of the tree

11:58 zippers are fun

11:58 justin_smith: I've never found a good use for them. Maybe my brain is wired wrong for zipper usage.

11:58 SagiCZ1: i always feel like just thinking and almost never typing in clojure.. then i look at my work from the past 10 hours and its just couple lines of code.. i feel stupid

12:00 luxbock: I like to sketch by planning top-down

12:01 OscarZ-: theres "bean" function to turn java beans to maps, but is there something to do it the other way ? given a map and java class, it would return instance of the class filled with properties from the map ?

12:02 oh.. just found this: https://github.com/clojure/java.data

12:03 it was in the comments for "bean", didnt notice it first

12:16 is it possible to require a namespace and with same command switch to that namespace?

12:21 ddima: you don't need to require, as by switching to a new ns all symbols will be resolved to that ns

12:21 SagiCZ1: ddima: and will the file get loaded

12:23 OscarZ-: im working in a repl and id like to load my namespace which itself does stuff like (:require [clojure.java.data :refer all])

12:24 ddima: SagiCZ1: that I'm not sure of, something which I'd need to try out

12:24 OscarZ-: i'd just want to be able to refer to functions from clojure.java.data in my repl without qualifying them

12:27 hmm.. it works when i require my namespace (myrepl) and then do (ns myrepl)

12:30 ddima: yeah, it doesnt load it, just checked. I dont think there is something like this per default, just wrap it yourself a la (do (require foo) (in-ns foo))

12:30 (you can use in-ns if you dont need any of the ns-macro magic)

12:30 OscarZ-: ok, its not too much work :)

12:30 SagiCZ1: in my editor i always do load and then switch manually

12:30 ddima: you could of course override in-ns or something ;)

12:31 justin_smith: (doto 'foo require in-ns)

12:31 OscarZ-: i still dont fully understand how the namespaces work.. in my repl, im first at namespace user, in my file myrepl.clj im defining (ns myrepl)) and some functions

12:31 ddima: or the more concise version from justin ;)

12:32 OscarZ-: in one of the function in myrepl namespace i put (println *ns*), im surprised that it prints out "user" when i call it from user namespace

12:32 justin_smith: OscarZ-: *ns* is the namespace you are calling from, not the one where the thing was defined

12:32 OscarZ-: how come it finds the stuff from myrepl as im referring to them in my function?

12:33 justin_smith: that's compile time

12:33 OscarZ-: ok

12:33 justin_smith: at compile time, it is in that ns, and it sees all the mappings defined in that ns

12:33 at runtime, in the repl, when you call the compiled code, *ns* will refer to the namespace you are in when you call the function

12:34 OscarZ-: i see, ok

12:34 justin_smith: on the other hand, you can use *ns* in a macro, and cause it to be captured at compile time

12:34 if you really need such a thing

12:36 tomjack: is there a story you can tell where *ns* is just a normal dynamic var, which correctly explains the semantics of *ns* if not the facts?

12:37 gfredericks: um

12:37 justin_smith: tomjack: that's the story. It's a dynamic var. It's looked up at runtime, like any other uncaptured var.

12:37 gfredericks: well the story should probably talk about compile-time and runtime though

12:37 ddima: cool story :D

12:37 gfredericks: in chapter 2

12:38 tomjack: my vague memory is that both clj and cljs compilers have magic inside for *ns*

12:38 gfredericks: not to mention repls

12:38 well who else is going to set it?

12:38 justin_smith: tomjack: magic, beyond the fact that it is a dynamic var that is used by def/defn to decide where something gets interned?

12:39 tomjack: I don't remember what the magic was at all -- but if the magic doesn't change the story at all, then great :)

12:39 gfredericks: tomjack: I think the normal confusion point is that (let [n *ns] (defn f [] n)) does something different from (defn f [] *ns*)

12:40 even further confused by the fact that I think those are the same (at a glance) at any normal repl

12:40 justin_smith: gfredericks: which is why I was careful to say "like any other uncaptured var" :)

12:41 OscarZ-: if i have a namespace and define functions "foo" and "bar" with defn, and bar is calling foo, how is the foo reference realized in function bar? is foo compiled as the var that name "foo" pointed at compile-time ?

12:41 gfredericks: justin_smith: more confusing in this case though because most uses of *ns* are at compile-time

12:42 true of other compiler vars I guess, but *ns* is more tempting to use for other dynamic purposes

12:42 justin_smith: OscarZ-: yeah, everything is fully resolved at compile time

12:43 OscarZ-: ok.. and if i put (def foo something-else) in the end, it doesnt have any effect anymore on function bar as it was already compiled?

12:43 justin_smith: OscarZ-: that's where capture comes in - are you resolving the var, or have you stored the value it pointed to at a prior time

12:44 tomjack: I guess the only magic in clojure is resolving '*ns* to the var set up in RT

12:44 justin_smith: by default, vars are looked up on each call

12:44 tomjack: and I see no trace of magic in cljs

12:44 justin_smith: but you can circumvent that with let capture

12:45 OscarZ-: this is an optimization trick actually - you can improve performance in a tight loop by capturing vars, so they don't get looked up repeatedly

12:46 OscarZ-: what you mean by "capture" exactly ?

12:46 justin_smith: OscarZ-: resolve it once, and store that value

12:46 like in gfredericks example above

12:47 (let [ns *ns*] (defn f [] ns))

12:47 that captures *ns* value at compile time

12:48 OscarZ-: ok

12:48 so *ns* is a bit like function call

12:48 justin_smith: OscarZ-: usage of any var is a bit like a function call

12:48 *ns* is not special in its behavior (it just gets used in special ways)

12:49 Bronsa: 18:47:25 <justin_smith> that captures *ns* value at compile time

12:49 OscarZ-: but if i have (defn foo [] (println ("ho ho ho!)) (defn bar [] foo)

12:49 Bronsa: at the risk of being overly pedantic, that's not true :P

12:49 justin_smith: Bronsa: oh, please explain

12:49 Bronsa: justin_smith: I mean, it's true if you meant "compile time" as in "while loading the namespace"

12:49 gfredericks: it compiles to code that looks it up in init?

12:49 OscarZ-: is that foo function forever locked to be the one that is called from bar ? even if i do (def foo [] (print "ha ha ha")) afterwards

12:50 justin_smith: OscarZ-: it's easy enough to test

12:50 OscarZ-: true :)

12:51 justin_smith: OscarZ-: https://www.refheap.com/95426

12:52 (I changed it slightly - in a way that makes it more clear I hope)

12:52 Bronsa: OK, yeah, I keep using that "compile time" term a little too loosely I think, thanks

12:53 OscarZ-: justin_smith, damn it did change :D i thought it wouldnt

12:53 justin_smith: OscarZ-: vars are mutable

12:53 and var lookup is not finalized at compilation

12:53 OscarZ-: thus what I said about capturing vars for performance reasons, etc. etc.

12:54 OscarZ-: oh.. i see..

12:54 justin_smith: OscarZ-: this is useful, because it means we can redefine our code in the repl or by reloading our namespaces and things stay consistent / updated

12:54 OscarZ-: so what gets compiled in, is just the name "foo"..

12:55 gfredericks: are there any examples of leiningen projects that are setup to run tests on different versions of java?

12:56 justin_smith: OscarZ-: well, not just the name "foo" but the fully resolved symbol iirc. or is it the var? Bronsa would know.

12:56 gfredericks: this feels awkward to me because I know how to set up the java-cmd in a leiningen profile, but the value thereof seems machine-sensitive, so putting in in the project seems bad

12:57 Bronsa: OscarZ-: justin_smith it resolves the var at compile time & stores that. at runtime it just derefs it

12:57 justin_smith: Bronsa: aha, so if someone cleared the var and recreated a var with the same name something might break?

12:58 ie. ns-unmap

12:58 OscarZ-: ah right.. the var stays but it can be mutated to point at some new function

12:58 gfredericks: justin_smith: probably depends on what they were assuming that would do

12:58 OscarZ-: you guys explained about vars earlier

12:59 mbac: yay holiday break

12:59 Bronsa: justin_smith: yep

12:59 justin_smith: http://sprunge.us/ATBb?clj

13:00 mbac: time to start and make impressive progress on personal coding projects then starve them from lack of love when the holidays are over and i'm back to working fulltime

13:00 the cycle never really ends : /

13:00 justin_smith: just tried it, updated my refheap... interesting https://www.refheap.com/95426

13:01 Bronsa: so here, it is still referring to the old, now unmapped, var

13:01 OscarZ-: justin_smith, does that mean that the actual var gets baked in?

13:02 justin_smith: OscarZ-: yeah, I think so. It resolves the var, but derefs the value on each call (since it could have changed)

13:02 OscarZ-: so there is no lookup ?

13:02 Bronsa: justin_smith: right, (def x y) when x is already defined just replaces the var root. if it's not mapped, you get a new var

13:02 OscarZ-: right ok :)

13:02 justin_smith: OscarZ-: no lookup, just deref

13:02 OscarZ-: i think i finally get it

13:03 i also tried to redefine foo in user namespace, then call myrepl/bar, it doesnt change even though *ns* is user during the bar call

13:03 as bar is referring to the var myrepl/foo

13:03 justin_smith: OscarZ-: right, because it already looked up the var

13:04 OscarZ-: yes, ok..

13:09 what are the reasons for having keywords like :a :b, in some places you can use strings and keywords interchangeably, but i guess there are good reasons to have keywords as their own things?

13:09 SagiCZ1: keywords are faster

13:09 justin_smith: keywords do O(1) comparison, yeah

13:10 and they act as the "get" function when applied to a map or set

13:10 OscarZ-: are they turned into integers or something under the hood?

13:10 justin_smith: they are interned, so when you compare them you are effectively comparing two integers

13:10 OscarZ-: ok

13:11 justin_smith: all that said, people are often over-enthusiastic about replacing strings with keywords

13:12 if you take a json map from some API, transform it, then return json again, it's silly to turn the keys into keywords, that can only make things more complex

13:13 OscarZ-: what kind of trouble can you get into?

13:13 justin_smith: not trouble

13:13 it's just silly

13:13 OscarZ-: :)

13:13 bbloom: no, you can get in to lots of trouble

13:13 justin_smith: oh?

13:13 bbloom: for example, invalid keywords constructed at runtime

13:14 eg keywords shouldn't start with digits, or contain spaces

13:14 or contain a slash

13:14 justin_smith: aha, so if you tried to serialize to edn, you'd get a broken mess

13:14 bbloom: automatic keywordization is just a bad idea

13:15 seriously, everybody stop doing it

13:15 tolstoy: What if you control both sides of the message?

13:15 bbloom: tolstoy: the day will come when you only have yourself to blame

13:15 justin_smith: tolstoy: then what do you gain by keywordizing?

13:15 tolstoy: Heh.

13:15 If only!

13:16 bbloom: for example, you want a map with URLs as keys

13:16 tolstoy: Makes the code more readable.

13:16 bbloom: {"http://omg.com" ""}

13:16 whoops: ##(keyword "http://omg.com")

13:16 lazybot: ⇒ :http://omg.com

13:16 bbloom: that's no good.

13:17 Bronsa: ,:http://omg.com

13:17 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

13:17 tolstoy: That's why I mentioned controlling both sides, like from a one-page app to an underlying host service.

13:17 Bronsa: &:http://omg.com

13:17 lazybot: ⇒ :http://omg.com

13:17 Bronsa: :P

13:17 bbloom: now you need to go retrofit all your old code that assumed global keywordization to be parameterized by a schema, so that you can prevent keywordization in one special case

13:17 ,(name :http://omg.com) ; Bronsa

13:17 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

13:17 OscarZ-: I ran into EDN data format somewhere... what are the biggest benefits for using that instead of JSON ?

13:17 bbloom: &(name :http://omg.com) ; Bronsa

13:17 lazybot: ⇒ "/omg.com"

13:17 Bronsa: bbloom: I know I know, I was just joking :)

13:17 bbloom: Bronsa: ok but for other ppl who don't know you know every single edge case ;-)

13:18 tolstoy: That said, I did have a nice hour wondering what the hell was going on before I discovered that ClojureScript allows keywords starting with numbers, and Clojure doesn't.

13:18 Bronsa: also hiredman should stop christmas partying and fix clojurebot

13:19 tolstoy: sadly, it actually does ##:9000

13:19 lazybot: ?

13:19 &:9000

13:19 lazybot: ⇒ :9000

13:20 justin_smith: Bronsa: with ##(do :9000) notation, you need parens

13:20 lazybot: ⇒ :9000

13:20 [blake|: Why is that sad?

13:20 Bronsa: [blake|: because it's allowed but the docs forbid it, and support is also inconsistent

13:20 &:a/9

13:20 lazybot: java.lang.RuntimeException: Invalid token: :a/9

13:20 Bronsa: &::9

13:20 lazybot: ⇒ :clojure.core/9

13:21 Manaphy91: Anyone can explain me why I obtain an empty string with this http://pastebin.com/Jueh8Fcr code?

13:21 justin_smith: Manaphy91: for is lazy

13:21 put a (dorun) around it

13:21 tolstoy: I was using UUIDs as keys, which is where bbloom's prediction came true.

13:22 bbloom: tolstoy: that's another good one

13:22 Bronsa: what's wrong with using uuids as keys?

13:22 justin_smith: Bronsa: auto-keywordizing UUID

13:22 [blake|: Bronsa: I was gonna say it's not an issue in Smalltalk, but then I checked and it's also inconsistent. =P

13:22 Bronsa: ah ok

13:23 justin_smith: which would lead to issues, I bet

13:23 tolstoy: I was using the string (not the #uuid thing). Some lead with zeros.

13:24 It would have been okay if that had broken everywhere (clj vs cljs) but it didn't, so, lots of argh. ;)

13:25 Manaphy91: @justin_smith with `dorun` is the same thing...

13:25 bbloom: clojurebot: keywordization |is| just say no

13:25 justin_smith: &(with-out-str (dorun (for [e [1 2 3]] (println e)))

13:25 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

13:25 clojurebot: Ack. Ack.

13:25 justin_smith: &(with-out-str (dorun (for [e [1 2 3]] (println e))))

13:25 lazybot: java.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad!

13:25 justin_smith: Manaphy91: it shouldn't be

13:25 (dorun (for ...))

13:25 the problem is that for does nothing if you don't force the value

13:25 even better, replace (for ...) with (doseq ...)

13:26 Manaphy91: @justin_smith perfect!! Thaks a lot!!

13:27 zilti: I'm working with a transient map, and it seems I can only conj! 8 MapEntry instances to it, afterwards it ignores them. How can I work around that?

13:28 justin_smith: zilti: you need to use the return value of conj!

13:28 it is not guaranteed to mutate the argument, it is merely *allowed* to

13:28 and with more than 8 mapentries, it replaces rather than mutating

13:28 zilti: hmm

13:29 justin_smith: (doc conj!)

13:29 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

13:29 justin_smith: &(doc conj!)

13:29 lazybot: ⇒ "([] [coll] [coll x]); Adds x to the transient collection, and return coll. The 'addition' may happen at different 'places' depending on the concrete type."

13:29 zilti: This is going to be somewhat of a headache inside a transducer... I found this out because I'm calling "step" multiple times

13:29 justin_smith: zilti: restructure your code to use the result of conj!, the same way you would if you were using conj in a loop

13:31 zilti: justin_smith: Well, this fixed it :) Thanks!

13:31 justin_smith: np

13:31 Bronsa: there's obviously no guarantee that the replacing will happen every 8 args

13:31 justin_smith: right, that was just a "for example" of course

13:31 zilti: It's nonetheless a weird behaviour, and I don't understand why it gets exposed to the "users"

13:31 Bronsa: it's usually after 32 IIRC

13:32 8 is just because of the arraymap -> hashmap promotion

13:32 justin_smith: zilti: it's the way conj! is meant to behave. The weird part is that ignoring the return value ever works.

13:32 Bronsa: zilti: transients are just a performance construct. it's well specified that you *have* to use the return value or bad things will happen

13:32 zilti: justin_smith: Yes, that's what I mean - that it actually works sometimes

13:33 justin_smith: Bronsa: I was surprised not to see a more explicit reference / warning in the doc string for conj! actually

13:33 zilti: Still, I currently have an atom to store the return value of conj! ... Meh. Really have to refactor this piece now

13:34 Bronsa: justin_smith: it would be better to have it in the docstring of `transient` i think. but yeah, agreed that having it only mentioned in clojure.org might cause confusion

13:35 justin_smith: maybe I'll make a doc string PR

13:37 Manaphy91: &(time (with-out-str (dorun (for [[k v] mark] (println k "->" v)))))

13:37 lazybot: java.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad!

13:37 justin_smith: Manaphy91: that would have failed because mark is unbound, anyway

14:30 profil: I am writing a small validation function for form params from ring. But I find my function very ugly, how could I improve it? make it more idiomatic? https://www.refheap.com/95427

14:31 I thought about using monads, but I dont want to pull in such a big dependency just for this small function

14:54 bzf: Any tips for reading 4 bytes from a FileInputStream as an integer?

15:05 justin_smith: bzf: you could read it into a byte-array, then make a ByteBuffer from that, and read an int from the ByteBuffer

15:08 bzf: justin_smith: Figured out I could just instatiate a DataInputStream from the FileInputStream :)

15:09 justin_smith: bzf: I am not as familiar with that (and am suspicious of the marshalling stuff), but that looks like it would work.

15:12 though DataInputStream is an interface

15:13 so that sounds a bit more complicated than a ByteBuffer / getInt

15:14 &*java-version*

15:14 lazybot: java.lang.RuntimeException: Unable to resolve symbol: *java-version* in this context

15:15 justin_smith: &(.getInt (java.nio.ByteBuffer/wrap (byte-array [1 2 3 4])))

15:15 lazybot: ⇒ 16909060

15:15 justin_smith: ^^ I think that's simpler than anything that would give you a DataInputStream would be

15:15 unless you have a class implementing it handy already

15:17 bzf: oh wait I was looking at the wrong "DataInputStream" - the one in java.io looks exactly right, yeah

15:18 bzf: but if you find yourself dealing with things like endianness, ByteBuffer makes that simple to fix

15:19 bzf: justin_smith: Alright, thanks :)

15:23 SagiCZ1: is vector a sequence?

15:23 justin_smith: ,(sequential? [])

15:23 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

15:23 justin_smith: &(sequential? [])

15:23 lazybot: ⇒ true

15:24 SagiCZ1: shouldnt this return more than one node? whats wrong with it..

15:24 &(count (tree-seq :x :x [{:x [{:x {:potato 6}} {:x {:o 3}}]}]))

15:24 lazybot: ⇒ 1

15:25 justin_smith: &(:x [])

15:25 lazybot: ⇒ nil

15:25 justin_smith: that's why

15:25 maybe you want sequential? instead of one of those :x

15:25 &(doc tree-seq)

15:25 lazybot: ⇒ "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of th... https://www.refheap.com/95432

15:26 SagiCZ1: i dont understand that example you gave

15:26 where do i do that?

15:26 justin_smith: [] has no :x key

15:26 SagiCZ1: there is no empty vector

15:27 justin_smith: [{:x ...}] has no :x key

15:27 the emptiness isn't importatn, the vectorness is

15:27 SagiCZ1: &(count (tree-seq :x :x {:x [{:x {:potato 6}} {:x {:o 3}}]}))

15:27 lazybot: ⇒ 5

15:27 SagiCZ1: i think this is what i want

15:27 justin_smith: that does look more like what you would want, yes

15:28 SagiCZ1: thanks :)

15:28 justin_smith: np

15:33 SagiCZ1: so i have this tree.. i want to find a particular node and add children to it.. how can i do that?

15:33 in imperative code i would have a function that returns a reference to the node, and mutate it, which would update it in the tree as well

15:33 in simple map, i would use assoc

15:33 justin_smith: assoc-in

15:33 or update-in

15:33 SagiCZ1: i would need to know the full path to the node though

15:34 justin_smith: ,(assoc-in {} [:a :b :c] 42)

15:34 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

15:34 justin_smith: &(assoc-in {} [:a :b :c] 42)

15:34 lazybot: ⇒ {:a {:b {:c 42}}}

15:34 justin_smith: indeed, you would need to know that

15:34 SagiCZ1: hmm tree-seq doesnt give me the path..

15:34 justin_smith: in order to mutate the node, you would also need to find that path, though you may not have stored it in a single place

15:35 yeah, tree-seq isn't so good for making a new tree

15:35 perhaps you want clojure.walk/postwalk

15:35 SagiCZ1: i could add a uuid to each node and find it later by that.. thats seems like an overkill though

15:35 or maybe tree of atoms?

15:36 justin_smith: if you want to walk a tree, and update certain branches, use clojure.walk/post-walk

15:36 SagiCZ1: ok

15:36 i will have a look at that

15:42 munderwo: Hey all. So I have this data structure https://www.refheap.com/95433 … and I want to collapse it so its one map with each value being the combined list of values. How would one go about doing that? is there a higher order function that does this? Im using a for loop to generate it, which might be the wrong way to go about it….

15:45 justin_smith: munderwo: I hope you realize you have a bunch of illegal keywords in there

15:45 munderwo: oh? what makes a keyword illegal?

15:46 justin_smith: multiple / for example in this case

15:47 SagiCZ1: or starting with a number

15:47 munderwo: I’d guessed that the multiple / might do it. but starting with a number?

15:48 justin_smith: munderwo: anyway (apply merge-with into ...)

15:48 that will merge all the maps, using into to combine the vectors

15:49 tomjack: neither of those uses look suited to keywords

15:49 justin_smith: though you may also want to do some merging inside those vectors?

15:49 no, actually not, the merge-with into suffices for that data at least

15:49 SagiCZ1: i dont see how clojure.walk helps me.. it doesnt even let me specify how to walk the datastructure like tree-seq

15:50 justin_smith: SagiCZ1: it already knows how to walk all the clojure data structures

15:50 and you can conditionally output an altered child at each branch

15:50 munderwo: magic! thanks justin_smith !

15:50 SagiCZ1: i have a tree where each node is map with :name and :children .. it doesnt walk it right

15:51 justin_smith: what does "doesn't walk it right" mean? it should hit every single nested value in the tree, the trick is only acting on the apropriate branches (and returning the original otherwise)

15:52 &(require '[clojure.walk :as walk])

15:52 lazybot: ⇒ nil

15:52 Raynes: Everybody ends up with a tree where each node is a map of :name and :children.

15:52 Eventually.

15:52 SagiCZ1: &(walk/walk #(println %) identity {:x [{:x [1 2]} 3]})

15:52 lazybot: ⇒ [:x [{:x [1 2]} 3]] {}

15:52 dysfun: is there a reasonable library for generating DDL?

15:52 Raynes: I use our DBA for that

15:53 dysfun: ah, well my dba is too lazy

15:53 SagiCZ1: i feel like my problem really cant be solved in a functional language.. so weird

15:53 dysfun: i only need postgres support, but since this is open source i'd like to support other engines too

15:53 justin_smith: &(walk/post-walk (fn [x] (if (contains? x :children) (assoc % :naughty true) x)) {:children {:a 0} :naughty false})

15:53 lazybot: java.lang.RuntimeException: No such var: walk/post-walk

15:54 justin_smith: &(walk/postwalk (fn [x] (if (contains? x :children) (assoc % :naughty true) x)) {:children {:a 0} :naughty false})

15:54 lazybot: java.lang.RuntimeException: Unable to resolve symbol: % in this context

15:55 justin_smith: &(walk/postwalk (fn [x] (if (and (map? x) (contains? x :children)) (assoc x :naughty true) x)) {:children {:a 0 :b {:children nil}} :naughty false})

15:55 lazybot: ⇒ {:children {:b {:naughty true, :children nil}, :a 0}, :naughty true}

15:56 justin_smith: ^^ SagiCZ1 that's how to do it

15:56 SagiCZ1: let me process that with my slow brain

15:56 justin_smith: SagiCZ1: you could run it in your own repl, adding a (println x) if that helps

15:57 x will end up being every possible branch of the nested data structure, and your function decides what is returned in its place

15:57 SagiCZ1: i see that you are associng based on whether its a map and has children.. but what if i want to access only on a node that has some minimal value out of all the leave nodes.. i would have to walk with some state there

15:58 *assoc , leaf

15:59 justin_smith: in that case you could use tree-seq to find the minimal values, and post-walk to act on said minimal values in context

15:59 SagiCZ1: so how would i find the minimal value with the postwalk?

15:59 treeseq tells me its 7 so i go look for 7?

16:00 justin_smith: you test whether it is a leaf, and if so whether it is in your set of minimal values, yes

16:00 you use the tree-seq to generate the set of minimal values

16:00 SagiCZ1: okay

16:01 and why the post walk goes twice into some nodes? like this:

16:01 [:children nil]

16:01 {:children nil}

16:01 justin_smith: the first is an entry

16:01 the second is the entire map

16:02 if you had {:a 0 :b 1} you would see [:a 0] [:b 1] {:a 0 :b 1}

16:02 SagiCZ1: oh i see.. its because its post.... walk

16:02 so first it travels deep.. and then it backs up

16:02 justin_smith: right, there is also prewalk

16:02 but in practice postwalk is often what you want

16:02 SagiCZ1: we learned this at the university, but it confuses me now

16:03 justin_smith: also, your walk/walk example (which does both pre and post walk) replaces the whole data structure with nil

16:03 as a result of the println :)

16:03 SagiCZ1: ok i dont think i need both post and pre

16:04 justin_smith: SagiCZ1: well, the point of walk is it takes two functions, the first is applied in pre, the second in post

16:04 so your datastructure is replaced by the return value of println

16:04 which is nil

16:04 SagiCZ1: so it changes the tree as it walks through it?

16:04 justin_smith: and this happens before the rest of it can be processed

16:05 that's the point of these walk functions, yes :)

16:05 well, it makes a modified copy

16:05 that's what you wanted, right?

16:05 SagiCZ1: yes

16:05 it feels like killing a butterfly with a tank, but yes, this i can use

16:05 nuwanda_: couldn't you use pre to compute the minimal values and post to act on them?

16:05 SagiCZ1: seems very powerful

16:05 justin_smith: nuwanda_: that's an excellent point

16:06 SagiCZ1: but i would have to accumulate the minimal value somewhere

16:06 justin_smith: nuwanda_: thought of course you would likely need a mutable accumulator to store it (tree-seq avoids the mutation aspect)

16:06 nuwanda_: in the tree itself maybe, then remove them in post

16:07 justin_smith: nuwanda_: I think updating an atom would be simpler, but also I think finding your min keys via tree-seq is simplest

16:07 though it means two steps instead of one

16:07 SagiCZ1: i dont know.. finding the min keys before feels dirty for some reason

16:08 because then they become a node identifier

16:08 which in imperative language would be just a simple pointer to the particular node

16:08 what if there are too nodes with the same minimal value.. i need to split only one of them

16:08 *two

16:08 justin_smith: you could use a mutable deftype and mutate pointers if you really want that kind of thing

16:10 SagiCZ1: justin_smith: that wouldnt feel clojury

16:11 hellofunk: i should probably study the various tree APIs before i ask this, but is it possible for each child to get a sequence of all its parents back to root?

16:13 justin_smith: hellofunk: you would need some stateful accumulator closed over by the function arg (likely something shard by the two function args to walk/walk, the pre would append to it, the post would pop elements from the end)

16:13 *shared

16:13 hellofunk: i feel you

16:14 i guess it's not a common need

16:23 craigglennie: I have an existing list of values that I want to add to a channel one at a time - what’s the best way to do this? Recursion? Seems like it would be common enough for there to be a shortcut

16:23 or maybe with “map” ?

16:27 SagiCZ1: i would use doseq

16:27 (doseq [e list-of-e] (put-to-channel chan e))

16:29 craigglennie: SagiCZ1: Cool, thanks. The docs for doseq says “Repeatedly executes body (presumably for side-effects)” - is putting a value in a channel considered a side effect?

16:29 SagiCZ1: it is

16:30 is it core.async channel?

16:33 craigglennie: SagiCZ1: yes, core.async

16:34 SagiCZ1: yes i think that would be a side effect.. putting something without sideeffect into doseq makes no sense, since it doesnt collect any results

16:34 &(doseq [e (range 10)] (+ e 2)])

16:34 lazybot: java.lang.RuntimeException: Unmatched delimiter: ]

16:35 SagiCZ1: &(doseq [e (range 10)] (+ e 2))

16:35 lazybot: ⇒ nil

16:35 hellofunk: craigglennie: you could use map as you suggested but since you are not concerned with the results of the process, then no point constructing a sequence with map

16:35 SagiCZ1: note that if you use map, it creates lazy sequence that does not get realized unless you take some elements or call (dorun .. )

16:35 hellofunk: that is true

16:36 craigglennie: ok, doseq makes more than map then

16:36 SagiCZ1: it fits better to your use

16:36 craigglennie: both because I don’t care about the result, and because map is lazy

16:39 SagiCZ1: if i am not mistaken (dorun (map .... )) does the same as (doseq ... ) only with different syntax

16:41 hellofunk: of course that only applies if you are working with a single sequence. they become more different as soon as you add a second set of bindings to doseq or more than 2 args to map

16:42 justin_smith: doseq and (dorun (for ...)) on the other hand...

16:51 hex6: No method in multimethod 'process-input' for dispatch value: null, Does it have to have some default dispatch?

17:00 justin_smith: hex6: where is process-input defined?

17:01 you can do (defmethod :process-input :default ...)

17:01 err make that (defmethod process-input :default ...)

17:05 hex6: justin_smith: found my problem, I had failed to supply one of the arguments in the correct form, so it was as it said; it tried to dispatch null

17:05 thanks though

17:05 justin_smith: oh, I had thought based on your question that you wanted dispatching on null to work

17:06 and adding :default would do that

17:08 hex6: yeah, I should probably add that though

17:09 craigglennie: core.async channels are unordered? I can’t find any docs that say one way or the other

17:11 SagiCZ1: craigglennie: do you mean the order in which they process input/output?

17:11 i would think it should be FIFO

17:11 craigglennie: SagiCZ1: I would have thought FIFO too, but it doesn’t seem to be

17:17 SagiCZ1: craigglennie: try some more tests.. if you have one consumer and one producer, the order should be kept

17:17 (imho)

17:21 craigglennie: SagiCZ1: This is what I did in the REPL, it pretty reliably returns out-of-order: https://www.refheap.com/95436

17:21 justin_smith: craigglennie: the default channel is effectively fifo, but has no buffer - which means that it will block if it is unread, but the order that waiting puts go onto it would be indeterminate

17:21 it only holds one value at a time

17:21 oh, and your (go) blocks run in indeterminate order

17:22 they all return immediately to the doseq

17:22 and the order that they run is unspecified

17:24 if you did (def c (chan 10)) and (go (doseq [i [1 2 3 4 5 6]] (>! c i))) you would get the results back in order

17:24 but as it is, you have two factors (no buffering, go blocks not running in order) that scramble order

17:25 tomjack: no need for buffering?

17:26 justin_smith: tomjack: the default chan is not buffered, it blocks until read, and can only hold one value at a time

17:26 tomjack: yes, but the producer won't proceed until each value goes in (and comes out)

17:27 justin_smith: tomjack: but the producers are launched in parallel in a loop, and the order that each of them gets its go isn't deterministic

17:27 tomjack: oh, yes, I mean in your example with doseq inside go

17:27 it can just be (def c (chan))

17:28 justin_smith: right, either of my changes would likely suffice on its own

17:28 (if ordering was desired)

17:29 tomjack: craigglennie: also, see onto-chan

17:29 craigglennie: tomjack: Oh, thanks, that looks useful

17:29 tomjack: and I guess into as well: (<!! (a/into [] (doto (chan) (a/onto-chan [1 2 3 4 5 6]))))

17:35 bzf: If I do (bit-clear 6516 64), just to see if I'm too tired to be continuing, the number can't be greater than 64?

17:36 SagiCZ1: how would i take-while one more?

17:36 (take-while odd? [3 3 3 9 7 8 4 6 3]) ---> (3 3 3 9 7 8)

17:37 bzf: SagiCZ1: Doesn't happen to me :)

17:37 hellofunk: SagiCZ1: well i suppose you could inc the count of the take-while and then take that from the original

17:38 justin_smith: bzf: ##(= (bit-clear Long/MAX_VALUE 65) Long/MAX_VALUE)

17:38 lazybot: ⇒ false

17:38 justin_smith: oh, wait...

17:39 hellofunk: &(take (inc (count (take-while odd? [3 3 3 9 7 8 4]))) [3 3 3 9 7 8 4])

17:39 lazybot: ⇒ (3 3 3 9 7 8)

17:39 justin_smith: (= (bit-clear Long/MAX_VALUE 65) (bit-clear Long/MAX_VALUE 1))

17:39 &(= (bit-clear Long/MAX_VALUE 65) (bit-clear Long/MAX_VALUE 1))

17:39 lazybot: ⇒ true

17:39 justin_smith: bzf: ^^ it wraps after 64

17:40 bzf: likely the jvm impl only looks at the lowest 6 bits of the arg

17:41 bzf: justin_smith: Oh, so it doesn't compare against the full integer?

17:41 justin_smith: no integers are involved there

17:41 it's two longs

17:41 bzf: %s/integer/number/ :)

17:41 justin_smith: but it only uses the lowest 6 bits of the second long (or so it seems)

17:46 bzf: Shouldn't (bit-and x (bit-not y)) be the same as (bit-clear x y)?

17:49 [blake|: Not directly Clojure related (except I'm doing it in a Clojure program) but I want to save part of a web page for reviewing either. Thought about HTML, but there's no formatting info. Thought about a JPG but that seems excessive. Any ideas?

17:49 For reviewing later. Not either.

17:52 craigglennie: [blake|: What kind of review do you want to do?

17:52 [blake|: If you’re extracting content you should probably save the HTML, if you just want to visually inspect it then capturing a JPG seems like a good approach

17:53 [blake|: It's a single page form, users put in inputs on left, output show up on right. Just want to look at (and maybe print) the form.

17:53 craigglennie: Yeah...It rankles but it might be the simplest and not too piggy.

17:54 craigglennie: [blake|: Since you’re using clojure, taxi has a get-screenshot function

17:54 SagiCZ1: how could i rewrite this using clojure's looping constructs? https://www.refheap.com/95438

17:54 Raynes: For the 5 people on the planet using laser, notice of deprecation: https://github.com/Raynes/laser#deprecated-laser

17:56 [blake|: craigglennie: Interesting. Thanks!

17:56 (inc craigglennie)

17:56 lazybot: ⇒ 1

17:57 [blake|: Not sure how this works with a client browser, tho'.

17:58 hellofunk: SagiCZ1: you are just generating a seq of :a's is that right?

17:59 SagiCZ1: hellofunk: no dont simplify it that much

17:59 lets say i am updating acc in some way

17:59 not necesarily conj

17:59 hellofunk: well, in any case, reduce is probably your friend in most cases where an accumulator is produced from a sequence

18:00 SagiCZ1: maybe reduce, but i need to stop after n iterations

18:00 hellofunk: i guess you'd need to provide a more meaningful example of what you want to achieve because yours is as simple as (repeat 5 :a)

18:01 with reduce, if you only want to deal with n iterations, then just take n from your initial coll

18:02 SagiCZ1: this should work https://www.refheap.com/95439

18:04 hellofunk: SagiCZ1: take a look at iterate

18:04 craigglennie: So I tried to add too much (I guess) stuff to my channel, and got an assertion error: “No more than 1024 pending puts are allowed on a single channel. Consider using a windowed buffer.”

18:04 hellofunk: &(doc iterate)

18:04 lazybot: ⇒ "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

18:04 craigglennie: Is that referring to sliding-buffer? I don’t want to lose any of my items

18:04 Or should I just create a channel with a huge buffer? That feels like a bit of a hack

18:05 hellofunk: craigglennie: yes. you can use either depending on how important it is that all items on teh channel are eventually processed.

18:05 craigglennie: it's not a hack, that's how it works. up to you to decide what is more important.

18:06 craigglennie: hellofunk: How would you handle the case of an infinite / unknown number of items that need to be processed, and the requirement that none be dropped?

18:07 Can I have a buffered channel that, when empty, would call a function to get some more data?

18:07 hellofunk: craigglennie: well if your items continue to come in, you just need to make sure the buffer is large enough to hold as many as you think you will have before your taking logic does its deed. you can have 1 million items on the channel but have a buffer of 10K if your taking is fast enough to ensure you'll never get more than 10K piled up

18:08 craigglennie: hellofunk: Pity, I was hoping I wouldn’t have to think about that kind of thing

18:08 hellofunk: I’d like something like a generator in Python. It could keep track of the number of items in the channel and add more when it was empty or running low

18:09 It seems like lazy-seq maybe would do that?

18:09 hellofunk: craigglennie: a channel and a sequence are two very different things.

18:11 craigglennie: I guess I can just create a channel with a huge buffer. I do have some idea of how much could be in the channel

18:12 hellofunk: craigglennie: don't know your specifics but you could throttle your put!s or combined values into a single put! instead of many put!s if that applies to you.

18:16 craigglennie: hellofunk: Yes, that could work

18:17 I’m not sure core.async is the right framework for what I’m trying to do: I want to have a queue/channel of URLs, and a fixed number of consumers that process the URL (scraping using taxi, in this case)

18:18 SagiCZ1: i dont see why you couldnt use core.async

18:18 craigglennie: In Python I’d use a queue and a number of threads or processors reading from the queue

18:18 SagiCZ1: Is it the best choice, or just a choice?

18:19 It seems like it should work...

18:19 SagiCZ1: you could use something like pmap maybe.. or maually manage the futures.. but this should work and look nicer

18:19 craigglennie: s/processors/processes

18:19 justin_smith: craigglennie: there's no reason you can't use a queue and threads reading from the queue in Clojure, but people like core.async as an abstraction over queue usage

18:20 SagiCZ1: with a scraper, each scraped page is going to result in more links to follow, so pmap wouldn't suffice

18:20 craigglennie: justin_smith: Ok, that was my understanding, too. I’m familiar with threads and queues, but I’m trying to learn clojure, so I should probably use core.async

18:21 SagiCZ1: justin_smith: i see.. scratch that then

18:21 craigglennie: if you don't have any experience with clojure, maybe this is a little too hard to start with..

18:22 i am learning clojure for months, and core.async didnt see easy to me when i tried to use it couple days ago

18:22 justin_smith: craigglennie: core.async is just one way to use queues in Clojure, there is also clojure.lang.PersistentQueue and the various queues offered by java.util.concurrent

18:22 TEttinger: 4clojure to the rescue!

18:22 SagiCZ1: TEttinger: are there any core.async exercises?

18:22 TEttinger: I don't think so, but if you're just starting out, it's probably a good place to start

18:24 SagiCZ1: i second that

18:25 ben_vulpes: i'm having a bit of a wacky problem with cider/emacs. when i run my irclj-bot at a terminal repl, when it catches messages it prints them right to the console. what in cider would be trapping these messages?

18:26 justin_smith: ben_vulpes: *out* is a dynamic binding that is not always propagated to new threads

18:26 ben_vulpes: look for a buffer with a name like *nrepl server*

18:27 that will be the failover when the output to the cider buffer is not propagated

18:27 ben_vulpes: config.el shows special buffers hidden...fixing...

18:29 awesome, justin_smith. what do I want to bind *out* to, and what's the best way to get that wired in regularly?

18:29 justin_smith: ben_vulpes: create threads using future and it is handled automatically

18:29 or you can pass in *out* to the function the thread runs, and bind it dynamically there

18:29 (binding [*out* captured-out-value] ...)

18:31 OOPS I parted by mistake

18:31 Bronsa: justin_smith: we all laughed at you while you weren't looking

18:31 justin_smith: porkys is spamming

18:32 (I was trying to part from the pm channel and parted here instead, mid conversation)

18:34 ben_vulpes: justin_smith: i think that i'm still confused as to why the *out* binding would be passed correctly when using the irclj library from my terminal, but not getting passed correctly when invoked from cider.

18:34 justin_smith: ben_vulpes: it's not passed properly, so it gets the root binding, which is your terminal

18:35 Dynasty: does clojure allow variable shadowing?

18:35 justin_smith: in emacs, it's not passed properly, so it gets the root binding, which is that weird *nrepl server* buffer that most people don't even know exist

18:35 ben_vulpes: hm, so this https://github.com/Raynes/irclj/blob/master/src/irclj/core.clj#L143 thread call might be the culprit then?

18:35 justin_smith: ben_vulpes: basically, shitty design in cider

18:35 ben_vulpes: boo.

18:36 justin_smith: ben_vulpes: I bet if you replaced that thread call with a call to future, that would propagate *out* properly

18:36 or you could store a binding to the *out* stream in the cider repl, and use it explicitly when printing

18:37 Dynasty: vars cannot be shadowed, but bindings can (via function arguments, or let)

18:37 Dynasty: okay thanks

18:37 justin_smith: and vars can be defined to have thread-local bindings (leading to odd behavior like I am discussing with ben_vulpes here)

18:37 ben_vulpes: downright kooky.

18:38 justin_smith: now for the million dollar question - what is the right value for *out*?

18:38 on a fresh cider repl i get #<PrintWriter java.io.PrintWriter@47ee14d4>

18:39 justin_smith: ben_vulpes: the value it has when you are in the repl buffer, obviously

18:39 ben_vulpes: because that's what's not getting passed into the thread

18:39 justin_smith: so you need to capture it, and bind it somewhere that your thread can find it when printing

18:39 right

18:40 ben_vulpes: well that's bloody irksome.

18:40 justin_smith: if cider attached the process to the repl buffer, *out* would fall back to that buffer, and things would be much more sensible

18:40 but they attach the process to a weird hidden buffer that they don't expect anyone to ever look at, which is weird

18:43 ben_vulpes: man i am now strongly tempted to just watch the repl-server buffer instead of getting printing properly in my emacs buffer

18:43 :(

19:12 supersym: https://wiki.theory.org/YourLanguageSucks#Clojure_sucks_because

19:12 aw.. only 1 reason with clojure, lol

19:12 dumb one too "Lisp syntax provides no way of seeing what's a function etc. - No visual distinction"

19:13 justin_smith: man, I could come up with 20 good reasons clojure sucks, and that wouldn't even make the fucking list

19:13 and I am a huge fan of clojure

19:14 supersym: right ^^

19:15 TEttinger: ,(str (map inc [1 2 3]))

19:15 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

19:15 TEttinger: lol

19:16 justin_smith: TEttinger: great example of something that sucks though ##(str (map inc [1 2 3]))

19:16 lazybot: ⇒ "clojure.lang.LazySeq@7c42"

19:16 TEttinger: that should not be an accesscontrolexception, hiredman!

19:16 I just fixed a bug related to that

19:17 ...while furthur codegolfing my cthulhutext generator

19:17 ,(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

19:17 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

19:17 TEttinger: &(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

19:17 lazybot: ⇒ "Shiap. Thainosh thiash nex fte-ugg... Glutialt, glothets, situg. Lugr nyuggang! Nyikith satsegg yaix zvraltol shets... Cthaikh, pol... Nokh tes paits sigith shughe'elt ke'iax! Saishats, thelt... Ketogl yaingaish... Yiaghig sorkiat nyorlu-ugl puk kiarlot shatsi-ugh! ... https://www.refheap.com/95445

19:17 TEttinger: ah, error somewhere in there

19:18 justin_smith: ? looked OK to me

19:19 TEttinger: there's just a logic bug, it allowed gr as an ending consonant

19:19 justin_smith: "Sax!" - scariest otherworldly creature ever

19:19 TEttinger: &(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 7"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[[(N["h""gl""gr""nd"])(v)]])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

19:19 lazybot: ⇒ "Yai-ongush, cthaiglaeg, les liag shuts. Piarl! Le'ugh ge'iashiark giatuth piggia-aig, yosiakh. Zvro-aighaho nyath ka-irl, kogh gaigg cthep ftail zvret... Thai'erkikh... Ta'il cthag, kaik. Yep, tox paggogg tanerl... Pagh, ftotsaha, kerk! Shukh gul gai-aino-is, kiathi... https://www.refheap.com/95447

19:20 TEttinger: well, I'm pretty pleased, it packs more features in shorter code now

19:20 [blake|: Can anyone explain why Hastur just showed up in my cubicle?

19:21 Mikke: bryanzera: i mean, move the <script> reference to angular.js

19:21 TEttinger: rich is trying to figure out state and identity so he swapped his brain through time with a Yith

19:21 justin_smith: [blake|: serves you right for making siri read IRC out loud to you

19:22 [blake|: justin_smith: There are drawbacks. (Related: Anyone know where I can get a very, very tiny pair of gloves and hat?)

19:24 Mikke: vonnegut, http://plnkr.co/edit/Q6lBcquZc2329FjTFHEI?p=preview <-- seems to work okay can you show what's different in yours?

19:25 justin_smith: Mikke: maybe you meant that for a different channel?

19:26 Mikke: joules: what's your point?

19:27 justin_smith: Mikke: joules, vonnegut, and bryanzera are not in this channel, this is #clojure

19:29 Mikke: (RaeCarruth) OnlyOne: can I have some nudes with my pringles? * SammoSideKick sword in the hand.

19:31 ride*

19:31 aw thx RaeCarruth

19:34 We started a massive fight in gawminers

19:37 ahahah

19:50 windobu: technomancy?

19:50 clojurebot: technomancy is <jweiss> oh man this sucks, why didn't anyone warn me about protocols

19:50 windobu: oh

19:55 welcomne.

20:02 justin_smith: windobu: hello

20:03 are you looking for technomancy? I think he moved recently and may be less active in IRC for a bit

20:18 tom39291: (-> "foo" (fn [x] x)) fails, but I expect it to return "foo"

20:19 justin_smith: tom39291: ##(macroexpand '(-> "foo" (fn [x] x)))

20:19 lazybot: java.lang.IllegalArgumentException: Parameter declaration foo should be a vector

20:19 justin_smith: tom39291: anyway, it becomes (fn "foo" [x] x)

20:19 which causes the above error

20:19 tom39291: ##(macroexpand-1 '(-> "foo" (fn [x] x)))

20:19 lazybot: ⇒ (fn "foo" [x] x)

20:19 justin_smith: there we go, nice

20:20 tom39291: ##(macroexpand-1 '(-> "foo" ((fn [x] x))))

20:20 lazybot: ⇒ ((fn [x] x) "foo")

20:21 justin_smith: tom39291: ##(-> "foo" ((fn [x] x)))

20:21 lazybot: ⇒ "foo"

20:21 tom39291: justin_smith: Thanks. Will have a think why that is correct.

20:22 justin_smith: tom39291: this may be another hint: ##((-> [x] (fn x) "foo")

20:22 did I nest my parens bad? I think I did

20:22 &((-> [x] (fn x)) "foo")

20:22 lazybot: ⇒ "foo"

20:23 justin_smith: fn isn'

20:23 t "special", it's first arg is a vector

20:23 TEttinger: or a symbol

20:23 justin_smith: true

20:26 anyway, never use code like (-> [x] (fn x)) that's terrible and evil and only serves to demonstrate what -> does

20:42 ambrosebs: ,(-> -> ())

20:42 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

20:42 justin_smith: ambrosebs: clojurebot is acting up ##(-> -> ())

20:42 ambrosebs: &(-> ->)

20:42 lazybot: java.lang.IllegalArgumentException: Can't call nil

20:42 java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->

20:43 ambrosebs: ##(-> -> ((fn [->] 1)))

20:43 lazybot: java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->

20:43 ambrosebs: well that was fun

20:44 porkys just spammed me

20:44 justin_smith: yeah, he got me too, the mods have forsaken us for the holidays

20:46 ambrosebs: cool

20:46 ##(-> ((fn [->])) ->)

20:46 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17526/fn--17527

20:47 justin_smith: oh, wow

20:47 that's getting close to something truly terrible

20:47 ambrosebs: ##((-> (fn [->]) ->))

20:47 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17537/fn--17538

20:47 ambrosebs: ##((->> (fn [->]) ->))

20:47 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17548/fn--17549

20:48 ambrosebs: ##((->> -> (fn [->]) ))

20:48 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17559/fn--17560

20:48 ambrosebs: :)

20:50 ##(->> ->> (fn [->>] ->>))

20:50 lazybot: ⇒ #<sandbox11388$eval17570$fn__17571 sandbox11388$eval17570$fn__17571@6d102211>

20:50 ambrosebs: ##(->> (->> ->> (fn [->>] ->>)) '->>)

20:50 lazybot: ⇒ ->>

20:50 justin_smith: reminds me of salmon season

20:53 ambrosebs: ##(-> [x 1] (let x))

20:53 lazybot: ⇒ 1

20:55 ambrosebs: ##(-> 1 `(let 1))

20:55 lazybot: clojure.lang.ArityException: Wrong number of args (2) passed to: core/seq

20:55 ambrosebs: ##(macroexpand `(let 1))

20:55 lazybot: java.lang.IllegalArgumentException: clojure.core/let requires a vector for its binding in sandbox11388:

20:56 justin_smith: &(macroexpand-1 `(let 1))

20:56 lazybot: java.lang.IllegalArgumentException: clojure.core/let requires a vector for its binding in sandbox11388:

20:56 justin_smith: hmm

20:56 ambrosebs: &(macroexpand-1 ``(let 1))

20:56 lazybot: ⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list 1)))

20:57 ambrosebs: &(macroexpand-1 '`(let 1))

20:57 justin_smith: I think the leading space threw it off

20:57 ambrosebs: &(macroexpand-1 '`(let 1))

20:57 lazybot: ⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list 1)))

20:58 ambrosebs: &(= ``(let 1) '`(let 1))

20:58 lazybot: ⇒ true

21:00 ambrosebs: &((fn clojure.core/fn [a] (if a (clojure.core/fn nil) 2)) 1)

21:00 lazybot: java.lang.IllegalArgumentException: Parameter declaration should be a vector

21:00 hbccbh: (doc doc)

21:00 clojurebot: #<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>

21:02 ambrosebs: &((fn fn [a] (if a (fn nil) 2)) 1)

21:02 lazybot: java.lang.IllegalArgumentException: Parameter declaration should be a vector

21:21 nub: Hi! I'm trying to display a chart with incanter, but it just spits this out in my repl instead of dislpaying a chart: #<ChartFrame org.jfree.chart.ChartFrame[frame2,0,23,500x400,layout=java.awt.BorderLayout,title=Incanter Plot,resizable,normal,defaultCloseOperation=DISPOSE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,22,500x378,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minim

21:21 Does anyone know what might be going on?

21:24 Actually it works if I run lein-repl from the terminal. But with my Emacs nREPL it doesn't display the chart.

21:25 justin_smith: nub: emacs in an X window or emacs in a terminal?

21:26 nub: emacs gui on OSX

21:28 justin_smith: actually it did display, but it popped up behind my emacs window

21:28 justin_smith: do you know if there's a way to make the graphs appear in the foreground?

21:29 justin_smith: nub: no I don't, I am sure that is OS specific

21:29 nub: justin_smith: oh ok, thanks!

21:29 justin_smith: there may be a jframe method for popping to the foreground that you could invoke on the chartframe?

21:29 I assume the chartframe is a subclass of a jframe

21:32 nub: looks like java.awt.Window has .toFront

21:32 if you have a handle to the top level window object (or if that ChartFrame inherits from Window)

21:33 http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/ChartFrame.html yeah, ChartFrame inherits from java.awt.Window, so it has the .toFront method

21:33 so that should just work

21:34 nub: justin_smith: oh cool, thanks!

22:47 windobu: 4chan is down :/

23:51 Dynasty: is there a function to conduct a pre-walk on a tree with an accumulator?

23:53 nvm I can probably make it work with zippers

Logging service provided by n01se.net