#clojure logs

2014-12-26

00:46ryancoleas 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?
00:46ryancolelike in the long run, which would benefit me the most
00:47justin_smithryancole: as a newcomer, I would start by using (require 'my.ns :reload) after saving a new version of the namespace file
00:47justin_smithsave the editor integration for later, when you realize it isn't magic
00:48ryancolei think that was over my head. are you saying to just use repl?
00:48justin_smithI 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.
00:48justin_smithryancole: 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)
00:49justin_smithryancole: also, the most featureful editor integration for clojure is intellij idea, with the cursive plugin
00:50justin_smithryancole: afaik the only sane way to do step debugging of clojure code right now
00:50justin_smith(but I still use emacs because I have used emacs for over a decade and IDEs bug me)
00:52ryancoleok, perhaps clojure's repl is powerful enough to fully support editing code in files and such, without the need for an extra text editor?
00:52ryancoleim familiar with repl for like python where it wasnt commonly used as also the "editor"
00:52justin_smithnot quite. Do the editing in whatever editor you like best (at first), and the repl can reload after you update the code.
00:52ryancolemore so used for like one-off testing, or running files, etc
00:52ryancoleah ok i see
00:53namraryancole: you might also look at this http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded
00:53justin_smithclojure'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
00:53justin_smiththough there are a few constructs that don't play as nicely with that, they are only a few
00:59ryancolecool, im going to go hop in bed and read that workflow blog post. thanks! :)
00:59justin_smithnamra: ryancole: the reloaded workflow is great, but not really the best way to *start* using clojure
00:59justin_smithimho
01:00justin_smitheventually, you'll love it, but better to just do the repl basics first I think
01:00namratrue
01:00namrabut 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.
01:01namraof course using such editor with a plugin comes also in handy ^^
01:01justin_smiththat's an excellent point, yes
01:08namraryancole: have you worked with anything like emacs or vim before?
01:09namrasuch editors are nice when you like to tinker and customize stuff, and don't want a large IDE to get into your way
01:10namraand currently it looks like that there are both for vim and emacs good plugins available to write programms in clojure
01:10ryancolenamra, vim - not emacs
01:10justin_smithfireplace.vim is good
01:10namrayep
01:11justin_smithbut I still think starting without the editor integration helps
01:11namrajustin_smith: i agree with you
01:12namraryancole: 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.
01:13ryancolehaha, vi for emacs
01:13ryancolenice
01:13namraa nice looking and simple ide that comes with integrated leiningen and repl: https://nightcode.info/
01:14justin_smithryancole: 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
01:14namra:D
01:15ryancoleso ive heard :P
01:15namranever tried emacs, but the elisp now looks very appealing. easier than the cryptic vim-syntax ^^
01:16ryancoleim just aiming for the most minimal, basic route into a simple edit code -> run code learning process
01:17ryancoleand as i get familiar with the tools, add in more feature packed editors
01:18namrathen 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
01:24ryancolesweet, sounds good to me :)
01:24ryancoleok guys gotta hop off. ill be reading up on stuff and swing back by later, im sure.
01:24ryancolethanks
02:34santaClaws_hey
02:36santaClaws_can I do those haskell (f.g) x = f (g x) stuff in clojure?
02:38andyf(comp f g) is Clojure's (f . g)
02:47santaClaws_ok cool thing. I have just started, The chapter on maps nad list is uite long . at iloveponies.github.io
02:47santaClaws_*and
02:53santaClaws_I wanted to know about functional programming , I chose clojure, although my codes have an awful lot of parenthesis.
03:03rksmHello, any fipp users here? Is there an easy way to keep comments when pretty printing with fipp.clojure/pprint?
03:15rksmOr for that matter, is there a recommended other way to pretty print clj code?
03:27korpseHow do people use joplin or ragtime in production or from an uberjar?
04:17piranhaI'm having exact trouble like here: http://stackoverflow.com/questions/23489106/cljx-starter-project-browser-repl-issue - any ideas how to solve?
04:17piranhaI've connected to my browser and can't require anything
04:18augustldoes mori (cljs data structures in JS) have any serialization built in?
04:19piranhaaugustl: you convert it to JS structures and then JSON.stringify, if that's your question
04:21octewhat better way is there to get the shortest collection then this: (reduce (fn [x y] (if (> (count x) (count y)) y x)) coll)
04:22hyPiRionocte: (apply min-key count colls)
04:22si14is there anything similar to Prismatic's Graph, but for "decision graphs" like this one https://github.com/for-GET/http-decision-diagram ?
04:23octethanks
04:23si14there is Liberator, but I'm interested in more general "engine"
04:24si14of course it's possible to use just a big bunch of nested if-s, but it quickly becomes uncomfortable
04:27augustlpiranha: I see, was hoping there was a way to avoid the conversion to JS structures :)
04:28piranhaaugustl: well, I guess with transit-js you could write handlers to do that :)
04:55octei'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
04:55octehttp://pastebin.com/X7HxwpyU
04:58si14octe: you may be interested in Dijkstra algorithm. Google gives a lot of relevant posts on "dijkstra clojure" request
05:01si14octe: 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
05:02octeyeah, i know
05:02octei'm just not sure how to do it in a better way :)
05:03octei'm reading up on dijkstras algoorithm
05:16si14octe: it's a bit nontrivial to translate it to Clojure properly from typical "mutable" description, but it's a worthy exercise :)
05:17octeyeah
05:17octeit's an interesting task :)
05:22mearnshjustin_smith: "nothing in the code you pasted uses atom" - that's why i'm stumped...
05:25mearnsh(and yeah I know my use of atom? is confounding but it makes sense here)
05:27andyfare you aware of the data.priority-map library for maintaining maps with items sorted by their values? Very useful for Dijkstra's algorithm
05:57dysfunis 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}
05:58dysfunit seems like a common case
05:58SagiCZ1wait what
05:59SagiCZ1you cant use values to get keys, can you?.. they are not uniqe
05:59dysfunyou *could*, potentially expecting multiple results
05:59dysfunbut it would be slow and daft
06:00SagiCZ1i guess..
06:00dysfunif you want this functionality, there's a function that inverts a map (with those limitations), let me look up the name
06:01sm0keis there some representation for int in clojure like for bigdec and bigint?
06:01SagiCZ1cool i didnt know that.. well what you ask for is not a macro but a destructuring functionality i think
06:01sm0ke,(class 1M)
06:01clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
06:01sm0kehurmm
06:01SagiCZ1,(type 4)
06:01clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
06:02dysfunSagiCZ1: 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.
06:06sm0keedn should ideally differentate between a int and a long
06:06sm0keis my point
06:07SagiCZ1sm0ke: why do you need to?
06:08dysfunSagiCZ1: https://www.refheap.com/95417
06:09SagiCZ1oh.. i see.. i didnt realize that the value and key is the same in the pair
06:13dysfunif they weren't, it wouldn't be the inverse of the destructuring bind :)
06:15Bronsadysfun: fyi there's no such thing as "destructuring bind taken care of by the reader"
06:15Bronsadysfun: the destructuring functionality is just macrology
06:24dysfunhrm, howso?
06:26Bronsa$source destructure
06:26lazybotdestructure is http://is.gd/R9QO9F
06:27Bronsadysfun: destructure is just a regular function, it's used inside a bunch of macros like let and fn
06:31dysfunoh right, cool
06:33SagiCZ1can i avoid calling rand twice here and get the same result?
06:33SagiCZ1,(repeatedly 5 #(vector (rand) (rand)))
06:33clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
06:33SagiCZ1who broke clojurebot?
07:49Frozenlockdysfun: is this what you were looking for? https://www.refheap.com/11818
07:49mearnshjustin_smith: uh sorry, i'm a fool, ignore
08:00dysfunFrozenlock: no, i already refheap'd a quickly thrown together one: https://www.refheap.com/95417
08:02dysfunactually, sorry, i misread your example. yes, that also works
08:02FrozenlockAh sorry. Your's more general. I guess the one I pasted was filtering nil values for some reason.
08:04dysfun*shrug* it was the first thing i came up with
08:04dysfuni figure there's not a great deal that can go wrong
08:04Frozenlockinb4 the planet explodes!!!!
08:06dysfunhrm, that's odd
08:06dysfun,(keyword 'nil)
08:06clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
08:06jonathanji 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?
08:07dysfunjonathanj: it's possible you've outgrown lein-ring, it's really just a small wrapper that'll provide a main()
08:08dysfunit uses jetty under the hood. you can write your own main function and provide :main in the project.clj
08:08dysfunring-server is very easy to use, just a single function call
08:08Frozenlockjonathanj: as dysfun said, you might want to use jetty in your -main. ----> (jetty/run-jetty #'app {:port some-port :join? false})
08:09dysfun(as is jetty. well, if you're not using it as a container, that is...)
08:10jonathanjdysfun, Frozenlock: thank you :)
08:33godd2would you say that [1 2 3] is merely syntactic sugar for (vector 1 2 3) ?
08:40AimHereYes
08:40AimHereThough I'd dispute the phrase 'merely syntactic sugar'
08:40AimHereUnless you're at the level of wiring up your NAND gates yourself, all computer programming is just syntactic sugar
08:42dysfunheh
08:42dysfunnice way of looking at it
08:43dysfundoes anyone know why (keyword 'nil) returns nil? surely at that point it's the symbol nil?
08:44Bronsa,(keyword nil)
08:44clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
08:44Bronsa&(keyword nil)
08:44lazybot⇒ nil
08:44Bronsa&(keyword 2)
08:44lazybot⇒ nil
08:44Bronsa&(keyword (Object.))
08:44lazybot⇒ nil
08:44Bronsadysfun: keyword returns nil if you hand it a nonsensical arg
08:44AimHere(keyword '2)
08:44godd2&(keyword 'nil)
08:44lazybot⇒ nil
08:45AimHere,(keyword '2)
08:45clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
08:45Bronsadysfun: also 'nil is the same as nil
08:45dysfunwhy is a symbol nonsensical?
08:45Bronsadysfun: nil is not a symbol
08:45Bronsa&(symbol? nil)
08:45lazybot⇒ false
08:45Bronsa&(symbol? 'nil)
08:45lazybot⇒ false
08:45dysfunso nil can't be quoted?
08:45Bronsa&(= nil 'nil)
08:45lazybot⇒ true
08:45Bronsadysfun: it can be quoted, it's just not a symbol
08:45Bronsadysfun: like true and false
08:45Bronsaquoting nil, true and false returns nil true and false
08:45Bronsathey are self-evaluating
08:46Bronsajust like quoting a keyword returns that keyword
08:46Bronsa,':foo
08:46clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
08:46Bronsa&':foo
08:46lazybot⇒ :foo
08:46dysfunso in order to store the symbol nil, i would have to cast to symbol first?
08:46Bronsayeah.. you can only obtain it via ##(symbol "nil")
08:46lazybot⇒ nil
08:46dysfunhrm. i'm not sure how i feel about that
08:47Bronsaabout what?
08:47dysfunnil being self-evaluating
08:48Bronsadysfun: it is documented that nil is not a symbol btw
08:48dysfuni'm sure it is
08:48Bronsa"Strings, numbers, characters, true, false, nil and keywords evaluate to themselves."
08:48luxbock##(nil? (symbol "nil"))
08:48lazybot⇒ false
08:48Bronsaand also, "nil is not a Symbol"
08:49dysfuni'm trying to figure out in my head if that's more or less confusing than the alternative
08:49Bronsadysfun: 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
08:50AimHereI thought nil can be a value of any data type
08:50Bronsadysfun: not even talking about the fact that (symbol "nil") evaluates to a truthy value
08:50dysfunwell not really. most programs don't use symbols outside of macros
08:51dysfuni think if you've quoted nil, it's quite clear you meant the symbol
08:52dysfunbut it's not a common case, so i don't think it's a big deal
08:52Bronsadysfun: sure but think about (defn foo [some-map] (get some-map some-key)), and you get back "nil" at the repl
08:52Bronsadysfun: now you have no way to know if that's a symbol or the nil "value", looking at it
08:53dysfunwell, my repl has pretty-printing that works. and your code will know, since strings are truthy
08:55dysfuni guess it comes down to whether you think having the symbol 'nil around is a good thing
08:56dysfunand i think in the general case, probably not
09:24SagiCZ1say 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?
09:28jonathanji'm trying to define a name (used in several places) that is passed in from the command-line
09:28jonathanj(a database uri in this case)
09:28jonathanjusually i'd just pass the value around but in this case it seems like using a ^:dynamic var might be easier?
09:29jonathanji've defined it as (def ^:dynamic foo) and in my main function i do (defonce foo ...)
09:29BronsaSagiCZ1: future-cancel
09:29jonathanjthis 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.
09:30dysfunjonathanj: you want (binding [name val])
09:30SagiCZ1(doc future-cancel)
09:30clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
09:32jonathanjdysfun: *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?
09:32jonathanj(binding [...] (run-jetty ...) ?
09:32si14(sorry, that /me was erroneous)
09:33SagiCZ1si14: do you find it unreadable?
09:34si14SagiCZ1: I wonder if it can be done better. One of the low handing fruits is if-not-let macro, of course
09:34dysfunjonathan: should be fine
09:35SagiCZ1si14: this written in java would be three times as long
09:36si14SagiCZ1: you are right, of course :) I believe it can be improved though
09:36SagiCZ1si14: yeah i would love to hear some improvements myself..
09:38SagiCZ1Bronsa: thank you for future-cancel
10:08klHi
10:08klLooking into core.async
10:08jonathanjhow can i conditionally thread some things? something like (-> X foo bar (if some-cond? (-> quux baz)) quaz)?
10:08klWhen you use a go macro in clojure/core.async - is it a thread of its own?
10:08SagiCZ1go macro does not create a thread
10:09klSagiCZ1: what is it? I'm looking to compare that to an actual golang Goroutine
10:09SagiCZ1it 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:10klSagiCZ1: so every go macro executes, on the main thread?
10:11SagiCZ1yse
10:11SagiCZ1yes
10:11SagiCZ1u can have thread if you use thread blocks
10:11SagiCZ1(thread ...)
10:11SagiCZ1and then use >!! and <!!
10:11dysfunhuh? aren't go blocks thread-local as opposed to specifically on the main thread?
10:12klsomething doesn't sound right about this
10:12SagiCZ1i might be wrong
10:12SagiCZ1the doc say: Asynchronously executes the body, returning immediately to the calling thread.
10:12SagiCZ1and: ...by 'parking' the calling thread rather than tying up an OS thread
10:13SagiCZ1me too actually, dont take my word on it..
10:14SagiCZ1i thought that go blocks and >! <! dont use new threads
10:16dysfunokay, it uses a thread pool
10:20kldysfun: so it basically uses a thread (with a maximum number of threads i.e. pool)
10:20klThis is what I thought
10:26octei 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:26octebad explanation i think
10:26octebut in a mutable/imperative way i'd do something like while ((current = map.get(current)) != null) { resultList.add(current) }
10:27SagiCZ1that would always leave you with one element in the list
10:29octenot really?
10:29SagiCZ1current is still the same thing?
10:29octeit would change for each iteration
10:29SagiCZ1yeah i dont see that in the example
10:29octe = map.get(current)
10:30octehttp://pastebin.com/N5FCKS0C clojure implementation
10:30octeshowing what i mean
10:32octebut obviously not implemented in a very good way..
10:32octebut it works
10:32SagiCZ1yeah
10:32SagiCZ1you can use nil? btw
10:32SagiCZ1instead of not (= nil .. )
10:32octetrue
10:33SagiCZ1i think you could build this list using reduce
10:34SagiCZ1so you have a map like this {:parent "child" :child "grandchild" ..} ?
10:34octeyes
10:34octeending where the key maps to nil
10:35SagiCZ1and you want a path from root to the last children?
10:35octefrom one of the keys to the root, i guess
10:35SagiCZ1i see
10:35octe'(:parent :child :grandchild)
10:36SagiCZ1the 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:37klare there any must-reads after Joy of Clojure?
10:37octewhat would be a better way to represent it?
10:38SagiCZ1clojure.zip is for working with nodes, children, branches etc
10:38SagiCZ1http://clojure.github.io/clojure/clojure.zip-api.html
10:52octeSagiCZ1, http://pastebin.com/fVJ6RvCS that seems to work with reduce
10:53octeif you were curious :)
10:54nuwanda_https://www.youtube.com/watch?v=YgvJqWiyMRY Brandon Bloom talking about representing data in trees with clojure
11:00justin_smithocte: sounds like you may want the adjacency list representation for graphs
11:00justin_smithhttp://en.wikipedia.org/wiki/Adjacency_list
11:01justin_smiththe 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:02bbloomkl: a goroutine is a proper green thread with it's own stack
11:03bbloomkl: go blocks in core.async have their own per-block state, but it's a finite state machine, not a full stack
11:03justin_smithSagiCZ1: and they use their own pool of threads on the jvm version
11:03bbloomdysfun: go block code may run on the original thread depending on readiness of channels and other implementation details
11:03bbloomthere is a thread pool pre-allocated for go blocks
11:03bbloomwhich is similar to how golang multiplexes go routines on to threads
11:04bbloomon cljs, there are no threads
11:04bbloomso go blocks execute via setTimeout (or similar) when there is idle time
11:04bbloomon the jvm, there is a thread pool for go block execution
11:04bbloombut where the go block code runs is never a promise
11:04bbloomi should say "is undefined"
11:04bbloomyeah, but like i said: sometimes go block code can run on the original thread
11:05bbloomgo block bodies should never block the thread w/o using channel operations
11:07octejustin_smith, that sounds fitting
11:08justin_smithbbloom: I think you were (are?) lagging again
11:08justin_smithmaybe not
11:09bbloomjustin_smith: argh. thanks
11:09bbloomi have no way of debugging it
11:10justin_smitherc had a "lag" section of its status bar
11:10justin_smithI don't know if other clients have this...
11:10bbloomi have a /lagcheck command
11:10bbloombut i have to execute it manually
11:10justin_smithyeah, seems like it would be a nice thing to have periodically run and displayed in a status bar automatically
11:12octei think i've created an implementation of dijkstras algorithm
11:12octehttp://pastebin.com/QcQU3n30 how does it look?
11:14octeit still kind of slow for longer paths
11:14justin_smithocte: there are also graph libs, that implement various path finding algorithms (and books full of various graph algorithms you could implement...)
11:15octeyup, i wanted to try myself though :)
11:15justin_smithhttp://www.textbooks.com/BooksDescription.php?BKN=951029&amp;SBC=ME8&amp;kpid=9780262033848N&amp;kpid=9780262033848N&amp;kenshu=02dbe049-1491-fa29-ea40-0000115ff57c&amp;mcid=XKS-7565-39-186-GoogleShopping-PRIDREPLACE-291&amp;gclid=CK_tzqyN5MICFVSSfgodjXgA7g lots of great graph algorithms in this book
11:16justin_smithit's a commonly used textbook, so not super hard to find used
11:18fm75justin_smith: studied on it long time ago, and re-bought it recently for my library :)
11:19justin_smithfm75: it's a good book, I have learned a lot from it
11:20fm75justin_smith: I didn't like too much the fact that arrays are 1-based in the pseudocode - sometimes it was painful
11:21justin_smithyeah, it's not perfect
11:34HamledIs it non-idiomatic or otherwise a bad idea to do something like (let [sentinel (gensym) foo (get coll key sentinel)] (if (= foo sentinel) ...))
11:34justin_smithHamled: (contains? coll key)
11:34Hamleddoes that work for indexed sequences like vectors
11:34justin_smithsame way get does
11:35Hamledokay thanks
11:35justin_smithby checking if the index is there
11:35justin_smith&(contains? [:a :b :c] 1)
11:35lazybot⇒ true
11:36dnolen_Hamled: it's more common to use a namespaced keyword or (Object.)
11:36bbloomHamled: 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:36lazybot⇒ "([map key]); Returns the map entry for key, or nil if key not present."
11:36justin_smithoh yeah, I keep forgetting about find
11:37Hamledah 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:37Hamledthanks :)
11:37justin_smith&(find [:a :b :c] 1)
11:37lazybot⇒ [1 :b]
11:37justin_smithI would not have guessed
11:37justin_smithbut that is nifty
11:38luxbockhad no idea about `find` but I could've used it many times before, nice
11:39luxbockI should try to find a way to use it with what I'm working now so I don't forget about it
11:40justin_smithalso, find should be on the clojure cheatsheet
11:40justin_smithahh, it's in grimoire, of course
11:40Hamledoh I'll have to bookmark that
11:43SagiCZ1thanks to all who reacted to something i wrote, i was out for a second.
11:43SagiCZ1on 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:44SagiCZ1watching Brandon's video atm
11:45justin_smithSagiCZ1: for a simple non-balanced tree I would use (deftype tree [left right]) and a protocol for inserting / removing
11:45justin_smitherr [value left right] of course
11:45SagiCZ1that 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:46justin_smithSagiCZ1: I think IAssociative would be the right one to implement (maybe?)
11:47luxbockSagiCZ1: 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:47octee
11:47octeheh
11:47SagiCZ1luxbock: cool.. so how does that work?
11:48octeturns out most of the time was being spent on getting the children in my function, which was actually a database query
11:48justin_smithwoah, zippers?
11:48justin_smithocte: heh, that would do it
11:49luxbockSagiCZ1: I have three different kinds of nodes, so I had a TreeNode protocol with branch?, children and make-node defined
11:49luxbockbut I switched to just using :type key inside a map instead
11:49octeyup, a path with 17 nodes went from 1s to 130ms when i memoized the db-query function
11:49octe:P
11:50SagiCZ1luxbock: so how does the protocol work now? it gets dispatched acording to the :type?
11:50luxbocknow branch?, children and make-node are just functions, and yeah they do stuff based on the :type key
11:51SagiCZ1luxbock: 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:52luxbockSagiCZ1: 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:52luxbockbut 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:54SagiCZ1luxbock: its really hard at first when you dont know what is available... to correctly design
11:54luxbockyeah indeed
11:58luxbockI'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:58luxbockzippers are fun
11:58justin_smithI've never found a good use for them. Maybe my brain is wired wrong for zipper usage.
11:58SagiCZ1i 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:00luxbockI like to sketch by planning top-down
12:01OscarZ-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:02OscarZ-oh.. just found this: https://github.com/clojure/java.data
12:03OscarZ-it was in the comments for "bean", didnt notice it first
12:16OscarZ-is it possible to require a namespace and with same command switch to that namespace?
12:21ddimayou don't need to require, as by switching to a new ns all symbols will be resolved to that ns
12:21SagiCZ1ddima: and will the file get loaded
12:23OscarZ-im working in a repl and id like to load my namespace which itself does stuff like (:require [clojure.java.data :refer all])
12:24ddimaSagiCZ1: that I'm not sure of, something which I'd need to try out
12:24OscarZ-i'd just want to be able to refer to functions from clojure.java.data in my repl without qualifying them
12:27OscarZ-hmm.. it works when i require my namespace (myrepl) and then do (ns myrepl)
12:30ddimayeah, 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:30ddima(you can use in-ns if you dont need any of the ns-macro magic)
12:30OscarZ-ok, its not too much work :)
12:30SagiCZ1in my editor i always do load and then switch manually
12:30ddimayou could of course override in-ns or something ;)
12:31justin_smith(doto 'foo require in-ns)
12:31OscarZ-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:31ddimaor the more concise version from justin ;)
12:32OscarZ-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:32justin_smithOscarZ-: *ns* is the namespace you are calling from, not the one where the thing was defined
12:32OscarZ-how come it finds the stuff from myrepl as im referring to them in my function?
12:33justin_smiththat's compile time
12:33OscarZ-ok
12:33justin_smithat compile time, it is in that ns, and it sees all the mappings defined in that ns
12:33justin_smithat 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:34OscarZ-i see, ok
12:34justin_smithon the other hand, you can use *ns* in a macro, and cause it to be captured at compile time
12:34justin_smithif you really need such a thing
12:36tomjackis 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:37gfredericksum
12:37justin_smithtomjack: that's the story. It's a dynamic var. It's looked up at runtime, like any other uncaptured var.
12:37gfrederickswell the story should probably talk about compile-time and runtime though
12:37ddimacool story :D
12:37gfredericksin chapter 2
12:38tomjackmy vague memory is that both clj and cljs compilers have magic inside for *ns*
12:38gfredericksnot to mention repls
12:38gfrederickswell who else is going to set it?
12:38justin_smithtomjack: magic, beyond the fact that it is a dynamic var that is used by def/defn to decide where something gets interned?
12:39tomjackI don't remember what the magic was at all -- but if the magic doesn't change the story at all, then great :)
12:39gfrederickstomjack: I think the normal confusion point is that (let [n *ns] (defn f [] n)) does something different from (defn f [] *ns*)
12:40gfrederickseven further confused by the fact that I think those are the same (at a glance) at any normal repl
12:40justin_smithgfredericks: which is why I was careful to say "like any other uncaptured var" :)
12:41OscarZ-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:41gfredericksjustin_smith: more confusing in this case though because most uses of *ns* are at compile-time
12:42gfrederickstrue of other compiler vars I guess, but *ns* is more tempting to use for other dynamic purposes
12:42justin_smithOscarZ-: yeah, everything is fully resolved at compile time
12:43OscarZ-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:43justin_smithOscarZ-: 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:44tomjackI guess the only magic in clojure is resolving '*ns* to the var set up in RT
12:44justin_smithby default, vars are looked up on each call
12:44tomjackand I see no trace of magic in cljs
12:44justin_smithbut you can circumvent that with let capture
12:45justin_smithOscarZ-: 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:46OscarZ-what you mean by "capture" exactly ?
12:46justin_smithOscarZ-: resolve it once, and store that value
12:46justin_smithlike in gfredericks example above
12:47justin_smith(let [ns *ns*] (defn f [] ns))
12:47justin_smiththat captures *ns* value at compile time
12:48OscarZ-ok
12:48OscarZ-so *ns* is a bit like function call
12:48justin_smithOscarZ-: usage of any var is a bit like a function call
12:48justin_smith*ns* is not special in its behavior (it just gets used in special ways)
12:49Bronsa18:47:25 <justin_smith> that captures *ns* value at compile time
12:49OscarZ-but if i have (defn foo [] (println ("ho ho ho!)) (defn bar [] foo)
12:49Bronsaat the risk of being overly pedantic, that's not true :P
12:49justin_smithBronsa: oh, please explain
12:49Bronsajustin_smith: I mean, it's true if you meant "compile time" as in "while loading the namespace"
12:49gfredericksit compiles to code that looks it up in init?
12:49OscarZ-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:50justin_smithOscarZ-: it's easy enough to test
12:50OscarZ-true :)
12:51justin_smithOscarZ-: https://www.refheap.com/95426
12:52justin_smith(I changed it slightly - in a way that makes it more clear I hope)
12:52justin_smithBronsa: OK, yeah, I keep using that "compile time" term a little too loosely I think, thanks
12:53OscarZ-justin_smith, damn it did change :D i thought it wouldnt
12:53justin_smithOscarZ-: vars are mutable
12:53justin_smithand var lookup is not finalized at compilation
12:53justin_smithOscarZ-: thus what I said about capturing vars for performance reasons, etc. etc.
12:54OscarZ-oh.. i see..
12:54justin_smithOscarZ-: 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:54OscarZ-so what gets compiled in, is just the name "foo"..
12:55gfredericksare there any examples of leiningen projects that are setup to run tests on different versions of java?
12:56justin_smithOscarZ-: well, not just the name "foo" but the fully resolved symbol iirc. or is it the var? Bronsa would know.
12:56gfredericksthis 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:57BronsaOscarZ-: justin_smith it resolves the var at compile time & stores that. at runtime it just derefs it
12:57justin_smithBronsa: aha, so if someone cleared the var and recreated a var with the same name something might break?
12:58justin_smithie. ns-unmap
12:58OscarZ-ah right.. the var stays but it can be mutated to point at some new function
12:58gfredericksjustin_smith: probably depends on what they were assuming that would do
12:58OscarZ-you guys explained about vars earlier
12:59mbacyay holiday break
12:59Bronsajustin_smith: yep
12:59Bronsajustin_smith: http://sprunge.us/ATBb?clj
13:00mbactime 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:00mbacthe cycle never really ends : /
13:00justin_smithjust tried it, updated my refheap... interesting https://www.refheap.com/95426
13:01justin_smithBronsa: so here, it is still referring to the old, now unmapped, var
13:01OscarZ-justin_smith, does that mean that the actual var gets baked in?
13:02justin_smithOscarZ-: yeah, I think so. It resolves the var, but derefs the value on each call (since it could have changed)
13:02OscarZ-so there is no lookup ?
13:02Bronsajustin_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:02OscarZ-right ok :)
13:02justin_smithOscarZ-: no lookup, just deref
13:02OscarZ-i think i finally get it
13:03OscarZ-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:03OscarZ-as bar is referring to the var myrepl/foo
13:03justin_smithOscarZ-: right, because it already looked up the var
13:04OscarZ-yes, ok..
13:09OscarZ-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:09SagiCZ1keywords are faster
13:09justin_smithkeywords do O(1) comparison, yeah
13:10justin_smithand they act as the "get" function when applied to a map or set
13:10OscarZ-are they turned into integers or something under the hood?
13:10justin_smiththey are interned, so when you compare them you are effectively comparing two integers
13:10OscarZ-ok
13:11justin_smithall that said, people are often over-enthusiastic about replacing strings with keywords
13:12justin_smithif 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:13OscarZ-what kind of trouble can you get into?
13:13justin_smithnot trouble
13:13justin_smithit's just silly
13:13OscarZ-:)
13:13bbloomno, you can get in to lots of trouble
13:13justin_smithoh?
13:13bbloomfor example, invalid keywords constructed at runtime
13:14bbloomeg keywords shouldn't start with digits, or contain spaces
13:14bbloomor contain a slash
13:14justin_smithaha, so if you tried to serialize to edn, you'd get a broken mess
13:14bbloomautomatic keywordization is just a bad idea
13:15bbloomseriously, everybody stop doing it
13:15tolstoyWhat if you control both sides of the message?
13:15bbloomtolstoy: the day will come when you only have yourself to blame
13:15justin_smithtolstoy: then what do you gain by keywordizing?
13:15tolstoyHeh.
13:15tolstoyIf only!
13:16bbloomfor example, you want a map with URLs as keys
13:16tolstoyMakes the code more readable.
13:16bbloom{"http://omg.com&quot; "127.0.0.1"}
13:16bbloomwhoops: ##(keyword "http://omg.com&quot;)
13:16lazybot⇒ :http://omg.com
13:16bbloomthat's no good.
13:17Bronsa,:http://omg.com
13:17clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
13:17tolstoyThat's why I mentioned controlling both sides, like from a one-page app to an underlying host service.
13:17Bronsa&:http://omg.com
13:17lazybot⇒ :http://omg.com
13:17Bronsa:P
13:17bbloomnow 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:17bbloom,(name :http://omg.com) ; Bronsa
13:17clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
13:17OscarZ-I ran into EDN data format somewhere... what are the biggest benefits for using that instead of JSON ?
13:17bbloom&(name :http://omg.com) ; Bronsa
13:17lazybot⇒ "/omg.com"
13:17Bronsabbloom: I know I know, I was just joking :)
13:17bbloomBronsa: ok but for other ppl who don't know you know every single edge case ;-)
13:18tolstoyThat 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:18Bronsaalso hiredman should stop christmas partying and fix clojurebot
13:19Bronsatolstoy: sadly, it actually does ##:9000
13:19Bronsalazybot: ?
13:19Bronsa&:9000
13:19lazybot⇒ :9000
13:20justin_smithBronsa: with ##(do :9000) notation, you need parens
13:20lazybot⇒ :9000
13:20[blake|Why is that sad?
13:20Bronsa[blake|: because it's allowed but the docs forbid it, and support is also inconsistent
13:20Bronsa&:a/9
13:20lazybotjava.lang.RuntimeException: Invalid token: :a/9
13:20Bronsa&::9
13:20lazybot⇒ :clojure.core/9
13:21Manaphy91Anyone can explain me why I obtain an empty string with this http://pastebin.com/Jueh8Fcr code?
13:21justin_smithManaphy91: for is lazy
13:21justin_smithput a (dorun) around it
13:21tolstoyI was using UUIDs as keys, which is where bbloom's prediction came true.
13:22bbloomtolstoy: that's another good one
13:22Bronsawhat's wrong with using uuids as keys?
13:22justin_smithBronsa: 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:22Bronsaah ok
13:23justin_smithwhich would lead to issues, I bet
13:23tolstoyI was using the string (not the #uuid thing). Some lead with zeros.
13:24tolstoyIt would have been okay if that had broken everywhere (clj vs cljs) but it didn't, so, lots of argh. ;)
13:25Manaphy91@justin_smith with `dorun` is the same thing...
13:25bbloomclojurebot: keywordization |is| just say no
13:25justin_smith&(with-out-str (dorun (for [e [1 2 3]] (println e)))
13:25lazybotjava.lang.RuntimeException: EOF while reading, starting at line 1
13:25clojurebotAck. Ack.
13:25justin_smith&(with-out-str (dorun (for [e [1 2 3]] (println e))))
13:25lazybotjava.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad!
13:25justin_smithManaphy91: it shouldn't be
13:25justin_smith(dorun (for ...))
13:25justin_smiththe problem is that for does nothing if you don't force the value
13:25justin_smitheven better, replace (for ...) with (doseq ...)
13:26Manaphy91@justin_smith perfect!! Thaks a lot!!
13:27ziltiI'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:28justin_smithzilti: you need to use the return value of conj!
13:28justin_smithit is not guaranteed to mutate the argument, it is merely *allowed* to
13:28justin_smithand with more than 8 mapentries, it replaces rather than mutating
13:28ziltihmm
13:29justin_smith(doc conj!)
13:29clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
13:29justin_smith&(doc conj!)
13:29lazybot⇒ "([] [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:29ziltiThis is going to be somewhat of a headache inside a transducer... I found this out because I'm calling "step" multiple times
13:29justin_smithzilti: restructure your code to use the result of conj!, the same way you would if you were using conj in a loop
13:31ziltijustin_smith: Well, this fixed it :) Thanks!
13:31justin_smithnp
13:31Bronsathere's obviously no guarantee that the replacing will happen every 8 args
13:31justin_smithright, that was just a "for example" of course
13:31ziltiIt's nonetheless a weird behaviour, and I don't understand why it gets exposed to the "users"
13:31Bronsait's usually after 32 IIRC
13:32Bronsa8 is just because of the arraymap -> hashmap promotion
13:32justin_smithzilti: it's the way conj! is meant to behave. The weird part is that ignoring the return value ever works.
13:32Bronsazilti: transients are just a performance construct. it's well specified that you *have* to use the return value or bad things will happen
13:32ziltijustin_smith: Yes, that's what I mean - that it actually works sometimes
13:33justin_smithBronsa: I was surprised not to see a more explicit reference / warning in the doc string for conj! actually
13:33ziltiStill, I currently have an atom to store the return value of conj! ... Meh. Really have to refactor this piece now
13:34Bronsajustin_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:35justin_smithmaybe I'll make a doc string PR
13:37Manaphy91&(time (with-out-str (dorun (for [[k v] mark] (println k "->" v)))))
13:37lazybotjava.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad!
13:37justin_smithManaphy91: that would have failed because mark is unbound, anyway
14:30profilI 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:31profilI thought about using monads, but I dont want to pull in such a big dependency just for this small function
14:54bzfAny tips for reading 4 bytes from a FileInputStream as an integer?
15:05justin_smithbzf: you could read it into a byte-array, then make a ByteBuffer from that, and read an int from the ByteBuffer
15:08bzfjustin_smith: Figured out I could just instatiate a DataInputStream from the FileInputStream :)
15:09justin_smithbzf: I am not as familiar with that (and am suspicious of the marshalling stuff), but that looks like it would work.
15:12justin_smiththough DataInputStream is an interface
15:13justin_smithso that sounds a bit more complicated than a ByteBuffer / getInt
15:14justin_smith&*java-version*
15:14lazybotjava.lang.RuntimeException: Unable to resolve symbol: *java-version* in this context
15:15justin_smith&(.getInt (java.nio.ByteBuffer/wrap (byte-array [1 2 3 4])))
15:15lazybot⇒ 16909060
15:15justin_smith^^ I think that's simpler than anything that would give you a DataInputStream would be
15:15justin_smithunless you have a class implementing it handy already
15:17justin_smithbzf: oh wait I was looking at the wrong "DataInputStream" - the one in java.io looks exactly right, yeah
15:18justin_smithbzf: but if you find yourself dealing with things like endianness, ByteBuffer makes that simple to fix
15:19bzfjustin_smith: Alright, thanks :)
15:23SagiCZ1is vector a sequence?
15:23justin_smith,(sequential? [])
15:23clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
15:23justin_smith&(sequential? [])
15:23lazybot⇒ true
15:24SagiCZ1shouldnt this return more than one node? whats wrong with it..
15:24SagiCZ1&(count (tree-seq :x :x [{:x [{:x {:potato 6}} {:x {:o 3}}]}]))
15:24lazybot⇒ 1
15:25justin_smith&(:x [])
15:25lazybot⇒ nil
15:25justin_smiththat's why
15:25justin_smithmaybe you want sequential? instead of one of those :x
15:25justin_smith&(doc tree-seq)
15:25lazybot⇒ "([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:26SagiCZ1i dont understand that example you gave
15:26SagiCZ1where do i do that?
15:26justin_smith[] has no :x key
15:26SagiCZ1there is no empty vector
15:27justin_smith[{:x ...}] has no :x key
15:27justin_smiththe emptiness isn't importatn, the vectorness is
15:27SagiCZ1&(count (tree-seq :x :x {:x [{:x {:potato 6}} {:x {:o 3}}]}))
15:27lazybot⇒ 5
15:27SagiCZ1i think this is what i want
15:27justin_smiththat does look more like what you would want, yes
15:28SagiCZ1thanks :)
15:28justin_smithnp
15:33SagiCZ1so i have this tree.. i want to find a particular node and add children to it.. how can i do that?
15:33SagiCZ1in 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:33SagiCZ1in simple map, i would use assoc
15:33justin_smithassoc-in
15:33justin_smithor update-in
15:33SagiCZ1i would need to know the full path to the node though
15:34justin_smith,(assoc-in {} [:a :b :c] 42)
15:34clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
15:34justin_smith&(assoc-in {} [:a :b :c] 42)
15:34lazybot⇒ {:a {:b {:c 42}}}
15:34justin_smithindeed, you would need to know that
15:34SagiCZ1hmm tree-seq doesnt give me the path..
15:34justin_smithin 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:35justin_smithyeah, tree-seq isn't so good for making a new tree
15:35justin_smithperhaps you want clojure.walk/postwalk
15:35SagiCZ1i could add a uuid to each node and find it later by that.. thats seems like an overkill though
15:35SagiCZ1or maybe tree of atoms?
15:36justin_smithif you want to walk a tree, and update certain branches, use clojure.walk/post-walk
15:36SagiCZ1ok
15:36SagiCZ1i will have a look at that
15:42munderwoHey 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:45justin_smithmunderwo: I hope you realize you have a bunch of illegal keywords in there
15:45munderwooh? what makes a keyword illegal?
15:46justin_smithmultiple / for example in this case
15:47SagiCZ1or starting with a number
15:47munderwoI’d guessed that the multiple / might do it. but starting with a number?
15:48justin_smithmunderwo: anyway (apply merge-with into ...)
15:48justin_smiththat will merge all the maps, using into to combine the vectors
15:49tomjackneither of those uses look suited to keywords
15:49justin_smiththough you may also want to do some merging inside those vectors?
15:49justin_smithno, actually not, the merge-with into suffices for that data at least
15:49SagiCZ1i dont see how clojure.walk helps me.. it doesnt even let me specify how to walk the datastructure like tree-seq
15:50justin_smithSagiCZ1: it already knows how to walk all the clojure data structures
15:50justin_smithand you can conditionally output an altered child at each branch
15:50munderwomagic! thanks justin_smith !
15:50SagiCZ1i have a tree where each node is map with :name and :children .. it doesnt walk it right
15:51justin_smithwhat 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:52justin_smith&(require '[clojure.walk :as walk])
15:52lazybot⇒ nil
15:52RaynesEverybody ends up with a tree where each node is a map of :name and :children.
15:52RaynesEventually.
15:52SagiCZ1&(walk/walk #(println %) identity {:x [{:x [1 2]} 3]})
15:52lazybot⇒ [:x [{:x [1 2]} 3]] {}
15:52dysfunis there a reasonable library for generating DDL?
15:52RaynesI use our DBA for that
15:53dysfunah, well my dba is too lazy
15:53SagiCZ1i feel like my problem really cant be solved in a functional language.. so weird
15:53dysfuni only need postgres support, but since this is open source i'd like to support other engines too
15:53justin_smith&(walk/post-walk (fn [x] (if (contains? x :children) (assoc % :naughty true) x)) {:children {:a 0} :naughty false})
15:53lazybotjava.lang.RuntimeException: No such var: walk/post-walk
15:54justin_smith&(walk/postwalk (fn [x] (if (contains? x :children) (assoc % :naughty true) x)) {:children {:a 0} :naughty false})
15:54lazybotjava.lang.RuntimeException: Unable to resolve symbol: % in this context
15:55justin_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:55lazybot⇒ {:children {:b {:naughty true, :children nil}, :a 0}, :naughty true}
15:56justin_smith^^ SagiCZ1 that's how to do it
15:56SagiCZ1let me process that with my slow brain
15:56justin_smithSagiCZ1: you could run it in your own repl, adding a (println x) if that helps
15:57justin_smithx will end up being every possible branch of the nested data structure, and your function decides what is returned in its place
15:57SagiCZ1i 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:58SagiCZ1*assoc , leaf
15:59justin_smithin that case you could use tree-seq to find the minimal values, and post-walk to act on said minimal values in context
15:59SagiCZ1so how would i find the minimal value with the postwalk?
15:59SagiCZ1treeseq tells me its 7 so i go look for 7?
16:00justin_smithyou test whether it is a leaf, and if so whether it is in your set of minimal values, yes
16:00justin_smithyou use the tree-seq to generate the set of minimal values
16:00SagiCZ1okay
16:01SagiCZ1and why the post walk goes twice into some nodes? like this:
16:01SagiCZ1[:children nil]
16:01SagiCZ1{:children nil}
16:01justin_smiththe first is an entry
16:01justin_smiththe second is the entire map
16:02justin_smithif you had {:a 0 :b 1} you would see [:a 0] [:b 1] {:a 0 :b 1}
16:02SagiCZ1oh i see.. its because its post.... walk
16:02SagiCZ1so first it travels deep.. and then it backs up
16:02justin_smithright, there is also prewalk
16:02justin_smithbut in practice postwalk is often what you want
16:02SagiCZ1we learned this at the university, but it confuses me now
16:03justin_smithalso, your walk/walk example (which does both pre and post walk) replaces the whole data structure with nil
16:03justin_smithas a result of the println :)
16:03SagiCZ1ok i dont think i need both post and pre
16:04justin_smithSagiCZ1: well, the point of walk is it takes two functions, the first is applied in pre, the second in post
16:04justin_smithso your datastructure is replaced by the return value of println
16:04justin_smithwhich is nil
16:04SagiCZ1so it changes the tree as it walks through it?
16:04justin_smithand this happens before the rest of it can be processed
16:05justin_smiththat's the point of these walk functions, yes :)
16:05justin_smithwell, it makes a modified copy
16:05justin_smiththat's what you wanted, right?
16:05SagiCZ1yes
16:05SagiCZ1it feels like killing a butterfly with a tank, but yes, this i can use
16:05nuwanda_couldn't you use pre to compute the minimal values and post to act on them?
16:05SagiCZ1seems very powerful
16:05justin_smithnuwanda_: that's an excellent point
16:06SagiCZ1but i would have to accumulate the minimal value somewhere
16:06justin_smithnuwanda_: thought of course you would likely need a mutable accumulator to store it (tree-seq avoids the mutation aspect)
16:06nuwanda_in the tree itself maybe, then remove them in post
16:07justin_smithnuwanda_: I think updating an atom would be simpler, but also I think finding your min keys via tree-seq is simplest
16:07justin_smiththough it means two steps instead of one
16:07SagiCZ1i dont know.. finding the min keys before feels dirty for some reason
16:08SagiCZ1because then they become a node identifier
16:08SagiCZ1which in imperative language would be just a simple pointer to the particular node
16:08SagiCZ1what if there are too nodes with the same minimal value.. i need to split only one of them
16:08SagiCZ1*two
16:08justin_smithyou could use a mutable deftype and mutate pointers if you really want that kind of thing
16:10SagiCZ1justin_smith: that wouldnt feel clojury
16:11hellofunki 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:13justin_smithhellofunk: 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:13justin_smith*shared
16:13hellofunki feel you
16:14hellofunki guess it's not a common need
16:23craigglennieI 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:23craigglennieor maybe with “map” ?
16:27SagiCZ1i would use doseq
16:27SagiCZ1(doseq [e list-of-e] (put-to-channel chan e))
16:29craigglennieSagiCZ1: 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:29SagiCZ1it is
16:30SagiCZ1is it core.async channel?
16:33craigglennieSagiCZ1: yes, core.async
16:34SagiCZ1yes i think that would be a side effect.. putting something without sideeffect into doseq makes no sense, since it doesnt collect any results
16:34SagiCZ1&(doseq [e (range 10)] (+ e 2)])
16:34lazybotjava.lang.RuntimeException: Unmatched delimiter: ]
16:35SagiCZ1&(doseq [e (range 10)] (+ e 2))
16:35lazybot⇒ nil
16:35hellofunkcraigglennie: 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:35SagiCZ1note that if you use map, it creates lazy sequence that does not get realized unless you take some elements or call (dorun .. )
16:35hellofunkthat is true
16:36craigglennieok, doseq makes more than map then
16:36SagiCZ1it fits better to your use
16:36craigglennieboth because I don’t care about the result, and because map is lazy
16:39SagiCZ1if i am not mistaken (dorun (map .... )) does the same as (doseq ... ) only with different syntax
16:41hellofunkof 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:42justin_smithdoseq and (dorun (for ...)) on the other hand...
16:51hex6No method in multimethod 'process-input' for dispatch value: null, Does it have to have some default dispatch?
17:00justin_smithhex6: where is process-input defined?
17:01justin_smithyou can do (defmethod :process-input :default ...)
17:01justin_smitherr make that (defmethod process-input :default ...)
17:05hex6justin_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:05hex6thanks though
17:05justin_smithoh, I had thought based on your question that you wanted dispatching on null to work
17:06justin_smithand adding :default would do that
17:08hex6yeah, I should probably add that though
17:09craigglenniecore.async channels are unordered? I can’t find any docs that say one way or the other
17:11SagiCZ1craigglennie: do you mean the order in which they process input/output?
17:11SagiCZ1i would think it should be FIFO
17:11craigglennieSagiCZ1: I would have thought FIFO too, but it doesn’t seem to be
17:17SagiCZ1craigglennie: try some more tests.. if you have one consumer and one producer, the order should be kept
17:17SagiCZ1(imho)
17:21craigglennieSagiCZ1: This is what I did in the REPL, it pretty reliably returns out-of-order: https://www.refheap.com/95436
17:21justin_smithcraigglennie: 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:21justin_smithit only holds one value at a time
17:21justin_smithoh, and your (go) blocks run in indeterminate order
17:22justin_smiththey all return immediately to the doseq
17:22justin_smithand the order that they run is unspecified
17:24justin_smithif 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:24justin_smithbut as it is, you have two factors (no buffering, go blocks not running in order) that scramble order
17:25tomjackno need for buffering?
17:26justin_smithtomjack: the default chan is not buffered, it blocks until read, and can only hold one value at a time
17:26tomjackyes, but the producer won't proceed until each value goes in (and comes out)
17:27justin_smithtomjack: but the producers are launched in parallel in a loop, and the order that each of them gets its go isn't deterministic
17:27tomjackoh, yes, I mean in your example with doseq inside go
17:27tomjackit can just be (def c (chan))
17:28justin_smithright, either of my changes would likely suffice on its own
17:28justin_smith(if ordering was desired)
17:29tomjackcraigglennie: also, see onto-chan
17:29craigglennietomjack: Oh, thanks, that looks useful
17:29tomjackand I guess into as well: (<!! (a/into [] (doto (chan) (a/onto-chan [1 2 3 4 5 6]))))
17:35bzfIf 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:36SagiCZ1how would i take-while one more?
17:36SagiCZ1(take-while odd? [3 3 3 9 7 8 4 6 3]) ---> (3 3 3 9 7 8)
17:37bzfSagiCZ1: Doesn't happen to me :)
17:37hellofunkSagiCZ1: well i suppose you could inc the count of the take-while and then take that from the original
17:38justin_smithbzf: ##(= (bit-clear Long/MAX_VALUE 65) Long/MAX_VALUE)
17:38lazybot⇒ false
17:38justin_smithoh, wait...
17:39hellofunk&(take (inc (count (take-while odd? [3 3 3 9 7 8 4]))) [3 3 3 9 7 8 4])
17:39lazybot⇒ (3 3 3 9 7 8)
17:39justin_smith(= (bit-clear Long/MAX_VALUE 65) (bit-clear Long/MAX_VALUE 1))
17:39justin_smith&(= (bit-clear Long/MAX_VALUE 65) (bit-clear Long/MAX_VALUE 1))
17:39lazybot⇒ true
17:39justin_smithbzf: ^^ it wraps after 64
17:40justin_smithbzf: likely the jvm impl only looks at the lowest 6 bits of the arg
17:41bzfjustin_smith: Oh, so it doesn't compare against the full integer?
17:41justin_smithno integers are involved there
17:41justin_smithit's two longs
17:41bzf%s/integer/number/ :)
17:41justin_smithbut it only uses the lowest 6 bits of the second long (or so it seems)
17:46bzfShouldn'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[blake|For reviewing later. Not either.
17:52craigglennie[blake|: What kind of review do you want to do?
17:52craigglennie[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[blake|craigglennie: Yeah...It rankles but it might be the simplest and not too piggy.
17:54craigglennie[blake|: Since you’re using clojure, taxi has a get-screenshot function
17:54SagiCZ1how could i rewrite this using clojure's looping constructs? https://www.refheap.com/95438
17:54RaynesFor 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[blake|(inc craigglennie)
17:56lazybot⇒ 1
17:57[blake|Not sure how this works with a client browser, tho'.
17:58hellofunkSagiCZ1: you are just generating a seq of :a's is that right?
17:59SagiCZ1hellofunk: no dont simplify it that much
17:59SagiCZ1lets say i am updating acc in some way
17:59SagiCZ1not necesarily conj
17:59hellofunkwell, in any case, reduce is probably your friend in most cases where an accumulator is produced from a sequence
18:00SagiCZ1maybe reduce, but i need to stop after n iterations
18:00hellofunki 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:01hellofunkwith reduce, if you only want to deal with n iterations, then just take n from your initial coll
18:02SagiCZ1this should work https://www.refheap.com/95439
18:04hellofunkSagiCZ1: take a look at iterate
18:04craigglennieSo 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:04hellofunk&(doc iterate)
18:04lazybot⇒ "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
18:04craigglennieIs that referring to sliding-buffer? I don’t want to lose any of my items
18:04craigglennieOr should I just create a channel with a huge buffer? That feels like a bit of a hack
18:05hellofunkcraigglennie: yes. you can use either depending on how important it is that all items on teh channel are eventually processed.
18:05hellofunkcraigglennie: it's not a hack, that's how it works. up to you to decide what is more important.
18:06craigglenniehellofunk: 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:07craigglennieCan I have a buffered channel that, when empty, would call a function to get some more data?
18:07hellofunkcraigglennie: 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:08craigglenniehellofunk: Pity, I was hoping I wouldn’t have to think about that kind of thing
18:08craigglenniehellofunk: 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:09craigglennieIt seems like lazy-seq maybe would do that?
18:09hellofunkcraigglennie: a channel and a sequence are two very different things.
18:11craigglennieI 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:12hellofunkcraigglennie: 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:16craigglenniehellofunk: Yes, that could work
18:17craigglennieI’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:18SagiCZ1i dont see why you couldnt use core.async
18:18craigglennieIn Python I’d use a queue and a number of threads or processors reading from the queue
18:18craigglennieSagiCZ1: Is it the best choice, or just a choice?
18:19craigglennieIt seems like it should work...
18:19SagiCZ1you could use something like pmap maybe.. or maually manage the futures.. but this should work and look nicer
18:19craigglennies/processors/processes
18:19justin_smithcraigglennie: 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:20justin_smithSagiCZ1: with a scraper, each scraped page is going to result in more links to follow, so pmap wouldn't suffice
18:20craigglenniejustin_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:21SagiCZ1justin_smith: i see.. scratch that then
18:21SagiCZ1craigglennie: if you don't have any experience with clojure, maybe this is a little too hard to start with..
18:22SagiCZ1i am learning clojure for months, and core.async didnt see easy to me when i tried to use it couple days ago
18:22justin_smithcraigglennie: 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:22TEttinger4clojure to the rescue!
18:22SagiCZ1TEttinger: are there any core.async exercises?
18:22TEttingerI don't think so, but if you're just starting out, it's probably a good place to start
18:24SagiCZ1i second that
18:25ben_vulpesi'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:26justin_smithben_vulpes: *out* is a dynamic binding that is not always propagated to new threads
18:26justin_smithben_vulpes: look for a buffer with a name like *nrepl server*
18:27justin_smiththat will be the failover when the output to the cider buffer is not propagated
18:27ben_vulpesconfig.el shows special buffers hidden...fixing...
18:29ben_vulpesawesome, justin_smith. what do I want to bind *out* to, and what's the best way to get that wired in regularly?
18:29justin_smithben_vulpes: create threads using future and it is handled automatically
18:29justin_smithor you can pass in *out* to the function the thread runs, and bind it dynamically there
18:29justin_smith(binding [*out* captured-out-value] ...)
18:31justin_smithOOPS I parted by mistake
18:31Bronsajustin_smith: we all laughed at you while you weren't looking
18:31justin_smithporkys is spamming
18:32justin_smith(I was trying to part from the pm channel and parted here instead, mid conversation)
18:34ben_vulpesjustin_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:34justin_smithben_vulpes: it's not passed properly, so it gets the root binding, which is your terminal
18:35Dynastydoes clojure allow variable shadowing?
18:35justin_smithin 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:35ben_vulpeshm, so this https://github.com/Raynes/irclj/blob/master/src/irclj/core.clj#L143 thread call might be the culprit then?
18:35justin_smithben_vulpes: basically, shitty design in cider
18:35ben_vulpesboo.
18:36justin_smithben_vulpes: I bet if you replaced that thread call with a call to future, that would propagate *out* properly
18:36justin_smithor you could store a binding to the *out* stream in the cider repl, and use it explicitly when printing
18:37justin_smithDynasty: vars cannot be shadowed, but bindings can (via function arguments, or let)
18:37Dynastyokay thanks
18:37justin_smithand vars can be defined to have thread-local bindings (leading to odd behavior like I am discussing with ben_vulpes here)
18:37ben_vulpesdownright kooky.
18:38ben_vulpesjustin_smith: now for the million dollar question - what is the right value for *out*?
18:38ben_vulpeson a fresh cider repl i get #<PrintWriter java.io.PrintWriter@47ee14d4>
18:39justin_smithben_vulpes: the value it has when you are in the repl buffer, obviously
18:39ben_vulpesbecause that's what's not getting passed into the thread
18:39justin_smithso you need to capture it, and bind it somewhere that your thread can find it when printing
18:39justin_smithright
18:40ben_vulpeswell that's bloody irksome.
18:40justin_smithif cider attached the process to the repl buffer, *out* would fall back to that buffer, and things would be much more sensible
18:40justin_smithbut they attach the process to a weird hidden buffer that they don't expect anyone to ever look at, which is weird
18:43ben_vulpesman i am now strongly tempted to just watch the repl-server buffer instead of getting printing properly in my emacs buffer
18:43ben_vulpes:(
19:12supersymhttps://wiki.theory.org/YourLanguageSucks#Clojure_sucks_because
19:12supersymaw.. only 1 reason with clojure, lol
19:12supersymdumb one too "Lisp syntax provides no way of seeing what's a function etc. - No visual distinction"
19:13justin_smithman, I could come up with 20 good reasons clojure sucks, and that wouldn't even make the fucking list
19:13justin_smithand I am a huge fan of clojure
19:14supersymright ^^
19:15TEttinger,(str (map inc [1 2 3]))
19:15clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
19:15TEttingerlol
19:16justin_smithTEttinger: great example of something that sucks though ##(str (map inc [1 2 3]))
19:16lazybot⇒ "clojure.lang.LazySeq@7c42"
19:16TEttingerthat should not be an accesscontrolexception, hiredman!
19:16TEttingerI just fixed a bug related to that
19:17TEttinger...while furthur codegolfing my cthulhutext generator
19:17TEttinger,(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:17clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
19:17TEttinger&(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:17lazybot⇒ "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:17TEttingerah, error somewhere in there
19:18justin_smith? looked OK to me
19:19TEttingerthere's just a logic bug, it allowed gr as an ending consonant
19:19justin_smith"Sax!" - scariest otherworldly creature ever
19:19TEttinger&(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:19lazybot⇒ "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:20TEttingerwell, 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:21Mikkebryanzera: i mean, move the <script> reference to angular.js
19:21TEttingerrich is trying to figure out state and identity so he swapped his brain through time with a Yith
19:21justin_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:24Mikkevonnegut, http://plnkr.co/edit/Q6lBcquZc2329FjTFHEI?p=preview <-- seems to work okay can you show what's different in yours?
19:25justin_smithMikke: maybe you meant that for a different channel?
19:26Mikkejoules: what's your point?
19:27justin_smithMikke: joules, vonnegut, and bryanzera are not in this channel, this is #clojure
19:29Mikke(RaeCarruth) OnlyOne: can I have some nudes with my pringles? * SammoSideKick sword in the hand.
19:31Mikkeride*
19:31Mikkeaw thx RaeCarruth
19:34MikkeWe started a massive fight in gawminers
19:37Mikkeahahah
19:50windobutechnomancy?
19:50clojurebottechnomancy is <jweiss> oh man this sucks, why didn't anyone warn me about protocols
19:50windobuoh
19:55windobuwelcomne.
20:02justin_smithwindobu: hello
20:03justin_smithare you looking for technomancy? I think he moved recently and may be less active in IRC for a bit
20:18tom39291(-> "foo" (fn [x] x)) fails, but I expect it to return "foo"
20:19justin_smithtom39291: ##(macroexpand '(-> "foo" (fn [x] x)))
20:19lazybotjava.lang.IllegalArgumentException: Parameter declaration foo should be a vector
20:19justin_smithtom39291: anyway, it becomes (fn "foo" [x] x)
20:19justin_smithwhich causes the above error
20:19justin_smithtom39291: ##(macroexpand-1 '(-> "foo" (fn [x] x)))
20:19lazybot⇒ (fn "foo" [x] x)
20:19justin_smiththere we go, nice
20:20justin_smithtom39291: ##(macroexpand-1 '(-> "foo" ((fn [x] x))))
20:20lazybot⇒ ((fn [x] x) "foo")
20:21justin_smithtom39291: ##(-> "foo" ((fn [x] x)))
20:21lazybot⇒ "foo"
20:21tom39291justin_smith: Thanks. Will have a think why that is correct.
20:22justin_smithtom39291: this may be another hint: ##((-> [x] (fn x) "foo")
20:22justin_smithdid I nest my parens bad? I think I did
20:22justin_smith&((-> [x] (fn x)) "foo")
20:22lazybot⇒ "foo"
20:23justin_smithfn isn'
20:23justin_smitht "special", it's first arg is a vector
20:23TEttingeror a symbol
20:23justin_smithtrue
20:26justin_smithanyway, never use code like (-> [x] (fn x)) that's terrible and evil and only serves to demonstrate what -> does
20:42ambrosebs,(-> -> ())
20:42clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
20:42justin_smithambrosebs: clojurebot is acting up ##(-> -> ())
20:42ambrosebs&(-> ->)
20:42lazybotjava.lang.IllegalArgumentException: Can't call nil
20:42lazybotjava.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->
20:43ambrosebs##(-> -> ((fn [->] 1)))
20:43lazybotjava.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->
20:43ambrosebswell that was fun
20:44ambrosebsporkys just spammed me
20:44justin_smithyeah, he got me too, the mods have forsaken us for the holidays
20:46ambrosebscool
20:46ambrosebs##(-> ((fn [->])) ->)
20:46lazybotclojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17526/fn--17527
20:47justin_smithoh, wow
20:47justin_smiththat's getting close to something truly terrible
20:47ambrosebs##((-> (fn [->]) ->))
20:47lazybotclojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17537/fn--17538
20:47ambrosebs##((->> (fn [->]) ->))
20:47lazybotclojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17548/fn--17549
20:48ambrosebs##((->> -> (fn [->]) ))
20:48lazybotclojure.lang.ArityException: Wrong number of args (0) passed to: sandbox11388/eval17559/fn--17560
20:48ambrosebs:)
20:50ambrosebs##(->> ->> (fn [->>] ->>))
20:50lazybot⇒ #<sandbox11388$eval17570$fn__17571 sandbox11388$eval17570$fn__17571@6d102211>
20:50ambrosebs##(->> (->> ->> (fn [->>] ->>)) '->>)
20:50lazybot⇒ ->>
20:50justin_smithreminds me of salmon season
20:53ambrosebs##(-> [x 1] (let x))
20:53lazybot⇒ 1
20:55ambrosebs##(-> 1 `(let 1))
20:55lazybotclojure.lang.ArityException: Wrong number of args (2) passed to: core/seq
20:55ambrosebs##(macroexpand `(let 1))
20:55lazybotjava.lang.IllegalArgumentException: clojure.core/let requires a vector for its binding in sandbox11388:
20:56justin_smith&(macroexpand-1 `(let 1))
20:56lazybotjava.lang.IllegalArgumentException: clojure.core/let requires a vector for its binding in sandbox11388:
20:56justin_smithhmm
20:56ambrosebs&(macroexpand-1 ``(let 1))
20:56lazybot⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list 1)))
20:57ambrosebs &(macroexpand-1 '`(let 1))
20:57justin_smithI think the leading space threw it off
20:57ambrosebs&(macroexpand-1 '`(let 1))
20:57lazybot⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/let)) (clojure.core/list 1)))
20:58ambrosebs&(= ``(let 1) '`(let 1))
20:58lazybot⇒ true
21:00ambrosebs&((fn clojure.core/fn [a] (if a (clojure.core/fn nil) 2)) 1)
21:00lazybotjava.lang.IllegalArgumentException: Parameter declaration should be a vector
21:00hbccbh(doc doc)
21:00clojurebot#<AccessControlException java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")>
21:02ambrosebs&((fn fn [a] (if a (fn nil) 2)) 1)
21:02lazybotjava.lang.IllegalArgumentException: Parameter declaration should be a vector
21:21nubHi! 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:21nubDoes anyone know what might be going on?
21:24nubActually it works if I run lein-repl from the terminal. But with my Emacs nREPL it doesn't display the chart.
21:25justin_smithnub: emacs in an X window or emacs in a terminal?
21:26nubemacs gui on OSX
21:28nubjustin_smith: actually it did display, but it popped up behind my emacs window
21:28nubjustin_smith: do you know if there's a way to make the graphs appear in the foreground?
21:29justin_smithnub: no I don't, I am sure that is OS specific
21:29nubjustin_smith: oh ok, thanks!
21:29justin_smiththere may be a jframe method for popping to the foreground that you could invoke on the chartframe?
21:29justin_smithI assume the chartframe is a subclass of a jframe
21:32justin_smithnub: looks like java.awt.Window has .toFront
21:32justin_smithif you have a handle to the top level window object (or if that ChartFrame inherits from Window)
21:33justin_smithhttp://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:33justin_smithso that should just work
21:34nubjustin_smith: oh cool, thanks!
22:47windobu4chan is down :/
23:51Dynastyis there a function to conduct a pre-walk on a tree with an accumulator?
23:53Dynastynvm I can probably make it work with zippers