#clojure log - Aug 31 2015

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

0:00 TEttinger: there's a lazy-cat?

0:00 justin_smith: TEttinger: have you ever seen a cat that wasn't lazy?

0:00 :P

0:00 (doc lazy-cat)

0:00 clojurebot: "([& colls]); Expands to code which yields a lazy sequence of the concatenation of the supplied colls. Each coll expr is not evaluated until it is needed. (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))"

0:00 TEttinger: I mean, yes. I have a cat who was raised by dogs and thinks he is a dog

0:01 (plays with water, completely unafraid of almost everything, greets strangers instead of running like any other cat)

0:01 (doc reductions)

0:01 clojurebot: "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

0:03 joness2: i am not sure how lazy-cat works.. is it a macro that prevents strict evaluation?

0:03 justin_smith: joness2: exactly - all laziness in clojure requires function indirection or macros that prevent evaluation

0:03 if you dig down deep enough at least

0:04 Bronsa: oh well

0:04 looks like direct linking is broken

0:04 justin_smith: ?

0:04 TEttinger: Bronsa: a grimoire thing?

0:04 Bronsa: http://dev.clojure.org/jira/browse/CLJ-1809

0:04 TEttinger wat

0:05 TEttinger no idea why you thought of grimoire but it's about a new 1.8 feature

0:05 TEttinger: oh, sorry, I just saw "direct linking" and couldn't remember if you did grimoire or who else did

0:05 Bronsa: I think I understand what's going wrong but it's a mess :/

0:06 TEttinger ah, no that's arrdem

0:06 TEttinger: brrnem

0:08 Bronsa: when's 1.8 scheduled, is it on some sort of fast track relative to 1.6-1.7?

0:08 Bronsa: TEttinger I seem to understand so, you'll have to ask puredanger

0:08 I'm a mere contributor, not part of the core team that make such decisions :)

0:09 TEttinger: I don't really know what the new features are. If I had to guess, monaducers

0:09 "because monads and transducers are so hot right now"

0:10 is clojure in clojure off the target list?

0:10 Bronsa: TEttinger cinc has never been an official target

0:11 TEttinger: err, maybe target is wrong word, goal to work toward?

0:12 Bronsa: no official plans, just unofficial efforts

0:12 TEttinger: ah ok

0:12 Bronsa: (mine :P)

1:00 H4ns: what self-hosted CI tool do you recommend for clojure? i've been using jenkins, but it is so ugly. teamcity does not seem to offer anything specific to clojure, but it looks slightly better. anything else?

1:01 justin_smith: I've only used jenkins, it worked OK

2:07 Jaood: ´œ∑´®†\üø¨ˆπåß∂∂ƒ©©˙∆˚¬…ææ

2:07 Empperi: exactly that

2:07 I agree 100%

2:08 H4ns: we use Jenkins and it's fine as long as you don't need full deploy pipeline management

2:08 it *can* do that too but it's hairy

2:09 planning to move into Go CD

2:21 H4ns: thanks, justin_smith and Empperi - i guess we'll just put up with the ugliness and continue using jenkins. it works well for us, too.

4:50 Rancid-punk: 2j Hi guys

4:50 Who is this man ? http://s22.postimg.org/cv0461qsh/Ratzinger_vreu7o.jpg

4:51 Bronsa: Rancid-punk: trolling is not welcome in this channel

6:58 Olajyd: Hi clojurians :)

7:01 I’m having a little issue with using the clj-time, I tried using the t/after and t/before to check if a particular date falls within the range, but I’m getting this error: `No such var: clj-time.core/equal?` even after requiring the clj-time 0.11.0 in the project.clj. Any ideas?

7:01 :)

7:08 oddcully: Olajyd: it might help, if you could provide a minimal failing example in a gist/refheap/...

7:08 Olajyd: ok

7:09 in a min

7:13 oddcully: https://www.refheap.com/109013

7:15 Alias for clj-time.core is `t` and alias for clj-time.format is `tf`

7:22 oddcully: Olajyd: without trying anything, the first two things: a) why do you not use t/equals? (most likely not related to the error) and b) equal? was added in 0.10.0

7:28 Olajyd: ok

7:28 odccully , got it now, bumped the version to 0.10.0 and it worked

7:29 was previously 0.9.0

8:20 noncom: is there any library that can generate a webform for a clojure map that is required to be filled?

8:20 wink: sounds like an ace idea :P

8:21 noncom: heh :)

8:30 oddcully: (map #(str "<input type=text name=" % "/>") (keys themap))

8:37 noncom: oddcully: nice start that would be! :)

8:42 neurostorm: lein repl does not seem to find my resources/log4j.xml file. several warnings are issued. should anything be added in the project.clj file except the dependency?

8:43 oddcully: noncom: since this is a little splitted between here and #clojurescript. above is not ordered

8:44 noncom: neurostorm: lein resource-paths? https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L160

8:45 neurostorm: this level is better for you, i think: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L281 (or maybe not)

8:48 neurostorm: thanks!

8:58 (.exists (clojure.java.io/file (clojure.java.io/resource "log4j.xml"))) ; reports true, but still i get:

8:58 log4j:WARN No appenders could be found for logger (io.netty.util.internal.logging.InternalLoggerFactory).

8:58 log4j:WARN Please initialize the log4j system properly.

8:58 log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

9:01 ok, seems to be a error in the xml. sorry

9:03 crazydiamond: Hi. If I need to have map with like 10 mln keys, would be in-memory Datomic DB more performant than just Clojure map?

9:07 Just got java.lang.OutOfMemoryError: GC overhead limit exceeded O_o

9:11 cenzhe: hi guys

9:11 what is the most effective way to keep a thread-safe count

9:12 my attempt now is: (def a-cache (atom {}))

9:12 (def inc-base-0 (fnil inc 0))

9:12 (defn record-one [n] (swap! a-cache update n inc-base-0))

9:14 but the performance is not satisfactory. I got the code embeded in my program, takes an extra 2 seconds to complete, and this routine get called around 550k times

9:15 I guess I need to avoid the boxing and unboxing of the count? like how?

9:16 expez: cenzhe: perhaps keep the count with an agent

9:16 cenzhe: cool idea

9:16 I'll add that in

9:17 anything else?

9:17 noncom: cenzhe: also, for things you need to do really fast, it is possible to use some direct java code. like you could have your counters written in java

9:17 as for the agent - i am not sure. agents are not guaranteed to be synchronized. of course in this case the count addition task likely won't take long, but you're walking thin ice..

9:18 cenzhe: noncom: I believe clojure can do things just as fast as Java with careful coding and proper optimization techniques

9:18 Me wrong?

9:18 noncom: cenzhe: another option would be to restructure your code. perhaps having a global count variable is not what you really need here. so, it will depend

9:19 cenzhe: in most cases, yes. but sometimes it is worth to write some 10 lines of java and be as fast as possible than have unstable or ugly clojure code that only tries to approach the same speed

9:21 cenzhe: as per your mentioned "proper optimization and careful coding" - i was referring it when i said that probably you could restructure your program to avoid the global counter

9:21 cenzhe: I don't quite follow the "global counter" part

9:21 noncom: what are the other alternatives?

9:22 noncom: cenzhe: you're keeping a counter, am i not right? here's your original question: "what is the most effective way to keep a thread-safe count?"

9:22 cenzhe: yes, actually a handful of counters

9:22 noncom: cenzhe: an alternative would be to include then in a (let ...) of a higher function

9:22 i cannot say more since i am not fully aware of your scenario

9:23 cenzhe: noncom: I guess this is to avoid the var deref cost, right?

9:23 noncom: right

9:23 but i am not sure it is applicable to your scenario

9:24 if you call the function on an external stimuli, like a key press, then you have to keep something global so the state can persist across the key presses

9:24 cenzhe: that seems to be possible, but I haven't tried this before, not sure how much boost I'll get

9:24 noncom: so, 1) java code, 2) include in a let of a higher function 3) use an atom.

9:25 if i'd care for speed, id use 1 :D

9:25 cenzhe: :D thanks for the leads

9:26 I just realize that my CPU are mostly occupied, the agent method may not work actually

9:26 I'll try the let first, and see how far that goes

9:46 noncom: crazydiamond: that's too much. although you could tweak JVM to get that heap... bu

9:46 you said 10 mln objects, you really need a db

9:46 coz

9:46 crazydiamond: noncom, yep, I realized that. thanks

9:47 Hi all. How do I sent Clojure vec like ["foo", "bar"} via Clojure JNA to C function that excepts char** ?

9:47 sdegutis: I'm writing a blog post on mutability in Clojure's core, and I thought a sanity check would be prudent. Is there anything wrong with my conclusion, that Clojure inherently (and unidiomatically) relies on mutability for making defmulti/defmethod work?

9:48 spacepluk: sdegutis: I think all vars are mutable

9:50 sdegutis: But typically the community's agreed-upon idiomatic style is to write a var declaratively and pull it into the namespace that requires it.

9:51 In this case, the namespace defining the defmulti would then be required to :require the namespaces that have the defmethods.

9:51 Except that severely limits the "extensibility" of defmethod itself, since the creator of this "interface" is then required to know all the implementors.

9:52 So the only way to keep that extensibility is to *force* the implementation of these two methods to rely on mutating the defmulti whenever it comes across a defmethod.

9:57 spacepluk: sdegutis: why do you need to require the implementors namespace? :?

9:58 sdegutis: spacepluk: If you write a defmulti, and a defmethod in another namespace, but never require that namespace, then calling the defmulti with the dispatch-value used in that namespace will result in a no-matching-whatever error.

9:58 spacepluk: I mean the side exetending the multimethod requires the multimethod, I think that's ok

9:58 I see

9:59 but in a real usecase you'd be using the extender namespace I think

9:59 s/using/requiring/

10:01 I'm still learing clojure though, I might be missing something

10:01 n

10:01 sdegutis: We had a bug in our system a few years ago because we were using a web framework that required the namespace needed based on the request being made, so sometimes the ns with the extender wasn't required for quite a long time. It caused a lot of bugs that took us a while to figure out.

10:02 spacepluk: yeah, extending types is a lot like monkey-patching

10:02 it's probably not a good idea to do it dynamically at runtime

10:02 sdegutis: That's what I'm saying though, all extending of types currently happens at runtime.

10:03 spacepluk: yup

10:03 sdegutis: The problem only happens when you try to require namespaces at runtime instead of inside (ns (:require ...)).

10:03 spacepluk: with runtime I mean after the app starts

10:03 sdegutis: Ah right.

10:04 spacepluk: these are the "cons" of dynamic languages I guess :)

10:06 zetlen: hey folks. is it frowned upon to try and ask questions in #clojure-beginners and here at the same time?

10:11 sdegutis: go for it

10:20 Dear Emacs users in here: what Clojure packages do you use?

10:38 troydm: can anyone suggest core.logic tutorial?

10:48 ryuo: i have been considering the merits of various Lisp dialects. is there some reason to prefer closure to others such as common lisp or scheme?

10:50 blkcat: jvm integration would seem like a pretty major one

10:51 opqdonut: I love the persistent built-in data structures

10:51 and the parallelism and concurrency stuff

10:51 ryuo: by persistent, you mean how some Lisp implementations can save machine state to be reloaded later?

10:52 opqdonut: no

10:52 I mean that the structures are immutable (but efficient)

10:52 e.g. adding an element to the end of a vector gives you a new vector

10:53 means you don't need to worry about leaking references to your private structures, or insert deep copies everywhere

10:53 spacepluk: yeah, I really like that too

10:53 and jvm/js interop is a big plus

10:54 I also like the syntax sugar for the different data structures

10:54 hardcore lispers would disagree I guess

10:55 ryuo: i come from the world of low level C. i've been trying to break into functional, but Lisp is somewhat confusing to navigate in terms of where I expend my efforts.

10:55 I should*

10:56 opqdonut: yeah it's not easy

10:56 spacepluk: if you're trying to interop with c code gambit or chicken might be better for you

10:56 there's clojure-terra but it's not finished

10:56 opqdonut: for getting stuff done you could look at clojure, but if you don't need the jvm or want to learn an "authentic" lisp go for some scheme variant

10:57 ryuo: Hm.

10:58 opqdonut: but it doesn't really matter, it's easy to transition from clojure to scheme or vice versa

10:59 just do something and see what happens

11:00 spacepluk: yup, switching from low-level to a functional style is the hard thing to do

11:02 maybe lua might help there, it's pretty much scheme with syntax

11:03 ryuo: i was thinking it wouldn't be too bad, considering i have a talent for abstract math...

11:04 hm.

11:05 spacepluk: it's not too bad, just try to make something :)

11:06 ryuo: C did teach me that it is important to know a great deal about language nuances.

11:07 if you want to use it to do a lot of programming at least.

11:07 spacepluk: the good thing about lisps is that the language itself doesn't have a lot of nuances, it's as simple as it gets.

11:08 ryuo: the rest is grasping the sheer flexibility you have?

11:08 spacepluk: yes hehehe

11:08 do you have any specific needs? or is it just for learning?

11:08 ryuo: well, i was wanting to learn a higher level language of the Lisp family to use for developing a MUD server's content.

11:09 i was thinking C is a poor choice here due to the higher development costs.

11:10 it takes longer to make anything useful with C. you have to implement a lot of support code before you get to the real content.

11:10 spacepluk: clojure sounds like a good fit for that

11:12 ryuo: is it still possible to draw from C libraries? i was planning to at least use C libraries to handle networking, unless java has some telnet lib.

11:12 spacepluk: I'm sure there are some

11:12 you can use JNI or JNA for the c code but it's not fun

11:14 or maybe this -> https://github.com/bagucode/clj-native

11:14 ryuo: okay, then is there some recommended reading for a through introduction to clojure? oreilly has a number of books but

11:14 thorough*

11:14 some appear to be for advanced topics in clojure.

11:15 i still plan to write C code, but i need to also learn to use higher level languages.

11:15 i can't limit myself to only low level. that's how i feel.

11:16 spacepluk: I read these: http://www.braveclojure.com/ https://www.manning.com/books/the-joy-of-clojure-second-edition

11:17 I think you might like lua, it's very easy to interact with c code and you can write functional code with it

11:17 ryuo: one other question. how stable is clojure for API? i'm used to C where APIs typically remain the same indefinitely.

11:17 spacepluk: specially luajit's ffi is great

11:17 I think clojure itself is pretty stable

11:17 ryuo: at least for ISO and POSIX.

11:17 ZimaBlue`: ryuo: I wouldn't recommend Joy Of Clojure, I read that already knowing bits about FP and found it way too hard. Probably the hardest textbook I've ever read. braveclojure is a good intro and currently enjoying "clojure programming"

11:19 ryuo: ZimaBlue`, I assume you had experience with non-FP before?

11:19 i've used C for the last 7 years and enjoyed it, but i need something more.

11:19 shell scripts only go so far as well.

11:20 hm.

11:21 luxbock: ryuo, you could also look at Racket

11:21 I haven't really used it much, but my impression is that it has an easier FFI support than Clojure

11:22 ryuo: so many Lisp implementations. -head explodes-

11:22 haha

11:22 spacepluk: heheh

11:22 ryuo: you can also go this way http://www.buildyourownlisp.com/ :D

11:22 luxbock: John Carmack is using Racket to script his VR work

11:22 ryuo: maybe it would be best if i just studied what Lisps have in common.

11:23 for now. i wonder if there is a book for that. =p

11:23 ZimaBlue`: the original paper by mcarthy

11:23 called something like recursive functions of symbolic expressions

11:23 http://www-formal.stanford.edu/jmc/recursive.pdf

11:24 luxbock: also, Structure and Intepretation of Computer Programs, which uses Scheme (which Racket is a dialect of)

11:25 ryuo: ah.

11:25 ZimaBlue`: it's pretty readable, I think I read that the compiler code in it has a couple of issues but you get the idea. Also halfway through he gets bored and invents GC

11:25 spacepluk: I think you'll learn more effectively if you can apply the stuff to real projects you're working on, that's what made it for me with lua/js

11:25 you see the benefits immediately

11:26 ryuo: that's the funny thing. it took me years of writing stupid things before I was good enough with C to do anything productive.

11:26 I was used to high level doing so much implicitly.

11:26 haha

11:26 luxbock: I have also heard many people praise this book http://www.ccs.neu.edu/home/matthias/HtDP2e/

11:27 but I haven't read it myself, it's on the TODO list :)

11:27 spacepluk: little schemer is also very cool

11:27 and it's an easy read

11:27 luxbock: yeah, very funny as well

11:27 ryuo: the best application i've found for C was optimizing tasks that i couldn't find another way to speed up.

11:28 spacepluk: c is good for using c libraries hehe

11:28 are you familiar with oop?

11:29 ryuo: vaguely. mainly the general ideas i had to apply in a C context.

11:29 a structure plus common functions.

11:29 noncom: how can i create a routing table for compojure so that it gets re-resolved on each http access to my server? ideally i'd like to store everything in a {} that i can update from time to time

11:29 spacepluk: good, don't waste your time :P

11:29 ryuo: that's about all it is in C.

11:29 tdammers: C is kind of cleansing

11:30 useful for the rare occasions where you need a lot of control, at the expense of safety

11:30 ryuo: spacepluk, waste my time in C?

11:30 spacepluk: OOP

11:30 ryuo: yet it is what is so wildly advocated.

11:30 all they talk about is OOP in my college courses.

11:31 lol

11:31 tdammers: OOP is a local optimum

11:31 spacepluk: most people don't understand oop though

11:31 hfaafb: no true OOP

11:31 tdammers: and frankly, the original Kay OOP isn't such a bad idea at all

11:31 luxbock: I recently read http://arcanesentiment.blogspot.sg/2013/09/why-concatenative-programming-matters.html which makes me want to give Factor a try

11:32 ryuo: there's so many paradigms.

11:32 luxbock: there's tons of great posts in that blog

11:32 tdammers: but ironically, one of the languages that most closely does that isn't considered OOP at all, but "functional"

11:32 ryuo: even array programming. XD

11:32 spacepluk: tdammers: agreed

11:32 TMA: ryuo: OOP is easily explained to a pointy haired boss (on the level: see you have a car that has four wheels; let call each piece an object)

11:32 tdammers: yeah

11:32 OOP looks familiar to management types

11:33 luxbock: oh whops, I meant to link http://evincarofautumn.blogspot.com/2012/02/why-concatenative-programming-matters.html

11:33 spacepluk: most people think that OOP is about shoehorning design patterns in your code and overengineering until you have to thow away the whole thing

11:34 at least that's my perception of it, with the people I've worked with

11:34 hfaafb: that's not what people think OOP is, that's what people experienced in big legacy monolithic repos

11:34 ryuo: huh. it talks about composition vs application.

11:34 hfaafb: like the ... eventual outcome of large oop systems

11:34 ryuo: what's the difference? at some point it has to executed...

11:34 tdammers: spacepluk: consider yourself lucky... it means that the people you've worked with are at least semi-enlightened

11:34 spacepluk: hehehe

11:35 fuck that's depressing

11:35 ryuo: i always thought composition was just combining functions to form a new kind of function

11:35 tdammers: ryuo: the difference isn't about how it gets executed; it's about how you keep your code manageable

11:35 luxbock: ryuo: yeah that whole explanation he gives for it is what really made me appreciate the post

11:35 tdammers: oh wait, different discussion

11:35 crazydiamond: Hi. How do I install library like this to use from Clojure? https://github.com/dren-dk/HunspellJNA I've installed it by "mvn install" but (import 'dk.dren.hunspell.Hunspell) raises java.lang.ClassNotFoundException

11:38 luxbock: crazydiamond are you using Leiningen?

11:38 crazydiamond: luxbock, boot

11:38 luxbock, it's like leiningen in terms of :dependencies etc

11:39 spacepluk: crazydiamond: is it running with the correct classpath?

11:40 crazydiamond: spacepluk, at least I have access to other libs from ~/.m2 , like datomic

11:41 spacepluk: crazydiamond: are the native binaries included in the jar? :?

11:41 crazydiamond: dunno, but I have some in my system :)

11:41 spacepluk: I don't really know how that works, just shooting ideas

11:42 crazydiamond: it passed tests

11:42 during mvn install

11:42 spacepluk, it seems quite hard to get it working :-(

11:42 spacepluk: it looks like the bundle the binaries in a different jar, maybe it's a separate dependency?

11:42 crazydiamond: ah, you mean Java binaries

11:43 not C

11:43 spacepluk: no the native binaries

11:43 crazydiamond: (it's the lib that gives access to C lib via JNA)

11:43 spacepluk: I think they put them in a jar

11:44 check for hunspell-linux* hunspell-win* etc.

11:44 maybe they are in a separate maven package

11:47 lambda-smith: Man, Clojure is so nice, I couldn't stop using it

11:47 crazydiamond: spacepluk, I've just added to :dependencies in my build.boot, and it works

11:48 spacepluk: ah cool, then it was the classpath

11:49 sdegutis: What's your usual technique on having a test-service (e.g. for email) and replacing it with a live-service (e.g. AWS-SES) when your program is live?

11:50 spacepluk: reader conditionals? :?

11:50 I have no usual technique though since I'm a noob hehe

11:51 sdegutis: Hmm I wonder... I bet the people who normally could answer this have me on /ignore

11:52 spacepluk: hehehe

11:53 sdegutis: Hi justin_smith.

11:59 justin_smith: sdegutis: hello

11:59 sdegutis: You must be really productive at work today justin_smith.

11:59 justin_smith: just getting started

12:02 spacepluk: is there any async alternative to monger?

12:02 justin_smith: doesn't monger support fire and forget? I thought that was the default with mongo stuff.

12:03 or do you mean like queries with callbacks

12:03 spacepluk: I don't know, it looks like it blocks the current thread

12:03 because it returns the result of the queries

12:03 yes

12:05 sdegutis: spacepluk: The nature of Mongo is that all queries block the entire Mongo server, in order to ensure consistent results.

12:06 We moved to Datomic in large part for that reason.

12:06 spacepluk: that doesn't mean that you need to block the client though

12:06 sdegutis: Datomic Free is working amazingly for us.

12:06 spacepluk: I really want to try that

12:09 but for this I need mongodb :/

12:11 I guess I can just use the java driver but monger looked so good :(

12:11 justin_smith: spacepluk: you could use (future (callback (monger/query ....)))

12:11 unless the java driver does something nicer I guess

12:12 also what about using monger and then using the java driver directly for the features monger doesn't support?

12:12 spacepluk: will that spawn a thread for every query? I'm still learing clojure's in and outs

12:12 that's a good idea

12:13 justin_smith: spacepluk: each call to future uses a thread from the thread pool

12:13 the thread gets returned to the pool when the callback returns

12:13 spacepluk: the limits the number of concurrent queries, right?

12:13 s/the/that/

12:13 justin_smith: the thread pool is unlimited

12:13 well, limited by what your OS can do thread wise I guess

12:13 spacepluk: that sounds scary hehehe

12:14 justin_smith: you can also use core.async or your own thread pool if you want something more controlled

12:14 you could mitigate this by putting one callback on a series of queries all in one future

12:14 or by making a thread pool doing queries where you specify the max size

12:15 noncom: does anyone know how to get data from backend into a reagent form ?

12:15 i want the page to be generated with data from the backend... is this possible at all?

12:15 justin_smith: noncom: I typically use a websocket

12:15 noncom: justin_smith: can you give a tiny code example?

12:16 justin_smith: noncom: or you can have a backend service that serves up your form I guess

12:16 noncom: websockets and tiny examples don't really go together so nicely...

12:16 noncom: oh ok

12:16 spacepluk: justin_smith: thank you, that's very helpful :)

12:16 justin_smith: unless you were planning on a websocket architecture, what about a service on your backend that returns your base form for reagent as json?

12:16 noncom: i'm just trying to get some real data into html forms generated in luminus, which uses reagent on this

12:17 justin_smith: OK

12:17 well, you could make luminus put real data in there right?

12:17 noncom: no

12:17 justin_smith: is it really that inflexible?

12:17 noncom: i think i'm missing something, that's what. i can't believe it is that inflexible

12:18 yes, a backend service that returns forms is how i always did it in the past

12:18 justin_smith: noncom: eg. I'd think you could make a function that takes a template, fills in some parts of it, and returns a new template for the frontend reagent to use

12:18 noncom: but you see, luminus has new features now so i am tryin to explore them

12:18 justin_smith: noncom: or you could have a ajax/json service that gives the data to reagent...

12:19 sdegutis: justin_smith: how do you select between services (e.g. an email-service) depending on your environment, so that you get an in-memory service when running tests or running a dev environment, and a live one in production?

12:19 justin_smith: noncom: OK, best of luck

12:19 noncom: justin_smith: yeah.. i just don't know how to organize data transfer between my clj and cljs code..

12:19 eh, this is all too much.. i have to figure out many things before i get there.. or just use the old approach - simply make the backend generate the forms

12:20 justin_smith: sdegutis: I use environ usually - my latest madness is to have a "config" component that sets up all this environment specific stuff (or at least populates an options map so my other components can be configured)

12:20 sdegutis: by component do you mean stuartsierra/component ?

12:20 justin_smith: noncom: I think the json/ajax approach is straightforward enough - reagent makes ajax request, gets json data, fills in data used for rendering, renders page

12:21 sdegutis: indeed

12:21 noncom: yes. now i just have to find out how to add ajax request and data display to reagent templates..

12:21 justin_smith: noncom: reagent should already be taking data from memory (an ratom right?) and using that to render

12:21 sdegutis: Hmm everyone seems to be using Component these days.

12:22 justin_smith: noncom: the only extra step is making an ajax request and putting data from the result into your ratom(s)

12:22 sdegutis: I built my app before the days of Component so I don't really know how I'd restructure it to fit that in hree.

12:22 *here

12:22 justin_smith: sdegutis: using environ to select your config map from a map of maps should work with or without component, component just makes the whole thing cleaner

12:23 noncom: justin_smith: you mean that reagents atom incapsulates ajax interaction?

12:23 sdegutis: Right, I was going on a tangent :P

12:23 justin_smith: sdegutis: or alternately instead of a map of maps you can have a directory of edn files staging.clj dev.clj prod.clj

12:23 noncom: I mean make an ajax request and in the callback put data you get from the request into the ratom in order to change parts of the page

12:24 sdegutis: justin_smith: my current approach is to use (System/getProperty "myapp.env") to get the env name, and then selecting a plain Clojure map of settings based on that.

12:24 noncom: ah i see, right

12:24 sdegutis: justin_smith: the problem with this approach is it only describes the settings for the live environment, or whether to use the memory-environment -- it can't actually switch between them.

12:24 justin_smith: noncom: websockets have a similar logic, but are faster (it's one connection that stays open instead of separate requests that get negotiated)

12:25 sdegutis: that's the part that component makes easier

12:25 shut down components, reset config, start up components

12:25 noncom: justin_smith: i used websockets a bit before. do you think that they are better than ajax in almost any case?

12:25 sdegutis: justin_smith: So each service has a default in-memory implementation, just made up of normal vars, like (defn send-email [to from subject body] ...), and there's an alternative implementation in an adjacent namespace that actually uses the real service (e.g. SES), along with a function in that namespace called go-live! which just uses alter-var-root to replace the default implementation in the other namespace with this function in t

12:25 his namespace.

12:25 justin_smith: noncom: I prefer them where they are supported, definitely - much smoother

12:25 sdegutis: This technique feels... a bit weird.

12:26 noncom: i see

12:26 justin_smith: sdegutis: yeah, I prefer having a component which provides the configurable part of the emailer

12:27 noncom: also, if you ever want such a thing, websockets free you from the request/response paradigm - you can have pushes of data in either direction, and whether that needs a response can be negotiable

12:28 noncom: yeah, i once made a prototype of an online RTS with them.. seemed really pleasant to work with

12:28 but somehow it all seems a bit clunky.. the whole web thing

12:30 sdegutis: justin_smith: Hmm. Thanks. I'll have to think on this for a while and try to wrap my head around it.

12:32 noncom: justin_smith: have you ever worked with reagent sessions + ajax?

12:33 justin_smith: now i managed to get ajax working and i got this kind of code: http://joxi.ru/Y2Lj69ehaPbWr6

12:33 feels a bit weird :D

12:35 justin_smith: btw what are you using for websockets? immutant?

12:45 oddcully: noncom: your gut feeling is right

12:45 the more you keep stuff like this out of your html/hiccup/... the better

12:45 tell some fn or some message bus (e.g. core async), that something needs to be done

12:46 then let it happen and when it happended update the atom/datascript/state/...

12:46 which the propagates into an update of the html

12:47 s/the/&n/

12:54 sdegutis: ,(-> :foo {:bar})

12:55 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

12:55 sdegutis: :(

12:55 ,(-> :foo (hash-map :bar))

12:55 clojurebot: {:foo :bar}

12:55 sdegutis: :D

12:57 sobel: gah, i can't get clojure.java.jdbc/insert! to work on my (Oracle) table to save myself. is there a special trick w/oracle?

12:57 i can select so i know the connection is there but insert! seems to generate bad sql. ORA-00926: missing VALUES keyword

13:03 sdegutis: Is there a less vacuous way of accomplishing this?

13:03 ,(->> ["command" "web" "port" "8080"] (partition 2) (map (fn [[a b]] [(keyword a) b])) (apply concat) (apply hash-map))

13:03 clojurebot: {:command "web", :port "8080"}

13:11 ystael: sdegutis: clojure.walk/keywordize-keys

13:12 sdegutis: ,(->> ["command" "web" "port" "8080"] (apply hash-map) (clojure.walk/keywordize-keys))

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

13:12 sdegutis: ,(require 'clojure.walk)

13:12 clojurebot: nil

13:12 sdegutis: ,(->> ["command" "web" "port" "8080"] (apply hash-map) (clojure.walk/keywordize-keys))

13:12 clojurebot: {:command "web", :port "8080"}

13:12 sdegutis: ystael: I like your style.

13:12 ystael: glad i could help :)

13:15 justin_smith: noncom: sente, http-kit implementation

13:16 noncom: i see

13:34 lper: howdy, has anyone here had success using gen-class to override a protected method (javax.swing.JPanel/paintComponent) without reflection warnings?

13:44 vince`: \help

13:45 erc-list

13:46 /erc-list

13:46 //channel

13:46 /erc-list

13:47 amalloy: sobel: nobody can guess what is wrong with your insert! if you don't paste an example call to it. and of course it's *possible* that oracle doesn't support even the most basic sql, but i'd first guess that it's my own code

13:49 noncom: justin_smith: i am exploring the example with websockets in luminus. i did everything as in the tutorial, however, i am gettin some strange error in the server log

13:49 the response of the ws compojure handler is {:status 200, :body #<UndertowWebsocketChannel org.projectodd.wunderboss.web.async.websocket.UndertowWebsocketChannel@4fe927d1>}

13:50 so it is trying to return the websocket object as a result

13:50 but then there comes the error: Cannot JSON encode object of class: class org.projectodd.wunderboss.web.async.websocket.UndertowWebsocketChannel: org.projectodd.wunderboss.web.async.websocket.UndertowWebsocketChannel@4fe927d1

13:51 could you shed some light on this? i am sure i am not supposed to send a java object as a response body

13:51 buharin: hello

13:51 :)

13:51 amalloy: noncom: i am pretty sure you are

13:51 buharin: I start reading Clojure for the Brave and True

13:51 amalloy: it's a Channel into which stuff gets written

13:52 buharin: cause I thought I am brave and true enough to read it

13:52 amalloy: i'd guess that the issue is rather that you're wrapping a json middleware around a route that doesn't return json (instead returning a websocket)

13:52 buharin: but I am afraid that there are no jobs for clojure and it is waste of time

13:52 :(

13:52 noncom: amalloy: so, i am sending it to the html frontend? why then compojure complains that it cannot JSON-encode it ..

13:52 ah, i am supposed to encode it somehow?

13:53 buharin: that depends. actually clojure is getting pretty much of a foothold on the world-wide arena...

13:53 amalloy: i am claiming that you are probably encoding it when you're not supposed to

13:53 probably with some json middleware, as i said

13:54 noncom: buharin: even in my country where clojure invitations are rare, i am able to apply clojure to my daily work and it gives very good results and brings pleasure

13:54 amalloy: that error is rather unlikely to be coming from compojure itself, because compojure doesn't do any json encoding

13:54 expez: anyone have a leiningen hook I can look at? The docs seem to be somewhat out of date.

13:55 noncom: amalloy: ah, so this is just some middleware getting in the way? the object should be sent without any encoding

13:55 ?

13:55 amalloy: that is my guess

13:55 buharin: noncom, oh ok

13:55 amalloy: but i don't know what you are doing aside from following some tutorial

13:56 noncom: amalloy: heh, nothing else. i am actually, moving very closely to the luminus tutorial

13:56 probably the tutorial on websockets diverges from the rest of the tutorial, i will look more closely to its github repo

14:11 lambda-smith: So guys, any news on the GUI front? Is Seesaw still the best option?

14:12 justin_smith: lambda-smith: I'd say a majority of our frontends (at least out of those vocal here) are html / cljs. I've seen some people using JavaFX via interop as well.

14:13 lambda-smith: Hi see, thanks justin_smith

14:30 sdegutis: lambda-smith: yeah most people use cljs/html/reagent afaik

14:30 lambda-smith, justin_smith: I've toyed with using Reagent inside Electron.

14:31 lambda-smith: Yeah, it seems like web app/using Electron is the way to go nowaday.

14:31 Oh well, I guess it's about time I learn Electron + Clojure web stack

14:32 sdegutis: Personally I just stuck with plain old Electron + JavaScript (+ a few libs of course). Clojure isn't a significant improvement over JS, so it's not worth the difficulties it causes.

14:32 justin_smith: man, "reagent electron" is a shitty google search

14:33 sdegutis: One of the worst in fact.

14:33 Extremely real science term.

14:33 justin_smith: adding javascript helped, but really now

14:33 sdegutis: Btw is the overhead of (#'foo) significantly higher than (foo)?

14:33 justin_smith: sdegutis: crit/bench will give you the info you seek

14:33 lambda-smith: sdegutis: what kind of overhead?

14:34 sdegutis: I'm considering changing my massive entry-point (defroutes ...) to have things like #'user-routes instead of user-routes for dynamic reloading to work better.

14:34 CPU I guess.

14:34 justin_smith: lambda-smith: it needs to do the var indirection on every call

14:34 sdegutis: justin_smith: never heard of that, thanks

14:34 lambda-smith: Hm.. I see

14:34 justin_smith: sdegutis: criterium.core/bench

14:34 sdegutis: (woo finally made it to reddits front page, my life's checklist is almost complete)

14:34 tcrayford____: actually so does calling it without the var quote, right?

14:35 justin_smith: tcrayford____: the difference is how often / under what circumstances lookup is forced

14:35 #'foo is looked up anew on every invocation, foo can be inlined, or if used as an arg to a first class function is only looked up on the invocation of said function (which may used that looked up value N times)

14:36 tcrayford____: in sdegutis ' usage, he passes #'foo to a handler which spends the rest of the app lifetime derefing #'foo on every usage, where if passed foo it would have only looked it up once

14:36 tcrayford____: ah, yep

14:36 uh haha

14:36 sdegutis: So I guess it might be slower. But it's the JVM so probably not noticeably slower in produciton.

14:37 tcrayford____: bahaha

14:37 (if (:development env) #'user-routes user-routes) it's fine

14:37 justin_smith: tcrayford____: hey we could even make a macro for that!

14:39 sdegutis: Will that thread well inside -> ?

14:39 Oh wait it's inside (defroutes) not (->)

14:51 It's not working.

14:52 My code isn't noticing my redefined function.

15:03 What could cause a redefined function (redefined with `C-c C-k` while CIDER is running) to not be seen and used by the running code?

15:05 sobel: Can anyone help me figure out how to diagnose my fairly fundamental problem getting clojure.java.jdbc/insert! to work...at all?

15:06 i can query but insert! complains: SQLSyntaxErrorException ORA-00926: missing VALUES keyword

15:08 sdegutis: Please Help. I ran (jetty/run-jetty #'my-handler {:port 8080}) and now inside CIDER I evaluated (defn my-handler [] {:status 200 :body "ok so far"}) and refresh but the change is not visible.

15:08 What am I doing wrong??

15:08 lazybot: sdegutis: Definitely not.

15:09 mdeboard: what

15:09 @ lazybot

15:09 sdegutis: mdeboard: lazybot has really lame responses programmed in for when you type ?? at the end of something

15:10 It's annoying but you learn to just get used to it.

15:10 mdeboard: oh

15:14 clojurian: Hi, I'm having trouble with dynamic reloading using CIDER. First I ran (run-jetty #'my-handler). Loaded my page and the handler shows. Now, inside CIDER, I evaluated a new definition of my-handler using C-x C-e, and refreshed my browser, but the change is not visible. What am I missing or doing wrong?

15:15 justin_smith: $mail sdegutis so not even an exception thrown because your handler got an arg and you didn't define it to take one?

15:15 lazybot: Message saved.

15:15 mdeboard: Sure clojurian is sdegutis

15:15 Surely*

15:16 clojurian: Well there goes my one shot at trying to ask this question of all those who have me on /ignore

15:16 justin_smith: I still haven't found this thing called "electron" that can be used in combination with the "reagent" library because electron+reagent is just giving me a bunch of chemistry results

15:16 TimMc: mdeboard: I was confused why you said that, but it's probably based on messages I had ignroed.

15:16 sdegutis: justin_smith: Oh I thought you knew what it was already.

15:17 justin_smith: https://github.com/atom/electron/

15:17 justin_smith: OK they renamed atom

15:17 I know what atom is

15:17 sdegutis: justin_smith: right not even an exception was thrown

15:17 justin_smith: *was

15:17 sdegutis: justin_smith: no they renamed atom-shell

15:17 mdeboard: TimMc, lol

15:17 sdegutis: justin_smith: Atom is still Atom

15:17 mdeboard: I have no idea who sdegutis is, was just trying ot help out justin_smith :P

15:17 sdegutis: What did TimMc say?

15:17 TimMc: because surely a complaint about cider being weird is not very specific.

15:18 justin_smith: OK

15:18 sdegutis: I can't see it at all but I don't have him on ignore.

15:18 Ooooh.. I see.. TimMc private messaged mdeboard to let him know I'm a troll he should /ignore.

15:18 Friendliest community ever. A+.

15:18 mdeboard: I regret so much about my actions in the last 5 minutes now

15:18 pretend I said nothing

15:18 sdegutis: done

15:18 justin_smith: no exception, nothing

15:19 not in the emacs-cider-repl, not in the terminal repl.. nothing

15:19 cfleming: $mail snowell: That's great, thanks! You can reformat using Code->Reformat Code, or whatever you have that bound to (the menu will show you). If you have code selected, only that code will be reformatted.

15:19 lazybot: Message saved.

15:19 cfleming: $mail hante_monsta: You can configure all the indentation in Cursive - if you're having problems doing that, let me know.

15:19 lazybot: Message saved.

15:21 sdegutis: Okay already #clojure, I can take a hint. Enjoy your peace and quiet without trolls like me ruining it.'

15:22 TimMc: mdeboard: Consider the logs wiped.

15:22 but now my messages to you look weird!

15:22 mdeboard: I appreciate your business advice re: my frozen yogurt stand

15:27 TimMc: :-)

15:29 amalloy: sobel: i already gave you a suggestion

15:30 as you can see if you scroll back, my suggestion was to gist an example insert! that's not working. otherwise the only thing we have to work with is "it doesn't work", and the only useful advice to give is "have you tried turning it off and back on again?"

15:38 sobel: amalloy: i didn't see that earlier. i eventually narrowed it to problems mapping tags to table names

15:52 host: Hello beautiful Clojuristas! I've recently changed OS to Windows (needed Photoshop). Is Clojure development on that OS plausible? Or pain in the bum?

15:55 Rurik: host, use an IDE for sanity

15:55 host: Rurik: Light Table + Leiningen is enough?

15:56 Bronsa: host: I'd suggest IntelliJ

15:56 host: Bronsa: Why?

15:56 Bronsa: with cursive

15:56 host: cursive is really good

15:56 https://cursiveclojure.com/

15:56 host: Bronsa: Does it have instant feedback?

15:56 Bronsa: it's easy to setup and really powerful

15:57 host: or instarepl of some sort?

15:57 Bronsa: host: it has an integrated repl

15:57 no, not like lighttable's instarepl

15:57 host: Bronsa: instarepl is a killer feature for me

15:57 so I guess cursive is not in my type

15:58 but I will look at it

15:58 Bronsa: oh well, then it sounds like light table is actually what you want :)

15:58 host: I've also had issues with \n and \r\n here, are pitfalls like this common on Windows?

15:59 like these*

16:00 tdammers: sheesh... you don't need an IDE for clojure

16:01 Rurik: tdammers, command line on windows sucks

16:02 tdammers: did I say "command line"?

16:03 vaitel: I'm using Emacs + cider on windows; it seems to work pretty well.

16:03 Bronsa: tdammers: nobody said you *need* an IDE

16:04 ashwink005: can anyone tell me how do I make a sqlite db SELECT call

16:05 SELECT * FROM database WHERE id=x name=y

16:05 how do I pass in the variables? i.e. x and y

16:07 anyone please!

16:08 host: Maybe something with "let" statement? But I'm a noob, you don't have to listen to me

16:09 ashwink005: no I know I need to call the jdbc library's function

16:09 Bronsa: ashwink005: https://github.com/ogrim/clojure-sqlite-example

16:09 ashwink005: but what and how do I pass the SELECT string

16:11 Bronsa: yeah how do I add arguments to the where clause

16:11 Bronsa: any idea? (def output (query db "select * from news"))

16:11 Bronsa: https://github.com/clojure/java.jdbc#example-usage

16:23 ashwink005: Bronsa: thanks I'll look into it

17:11 how do I make a post request in Clojure?

17:11 is the hiccup form the only way

17:12 surtn: ashwink005: clj-http should work - https://github.com/dakrone/clj-http#post

17:22 ZimaBlue`: I'm having some project.clj problem, when I add my source paths it gives me could not locate on classpath. The relevant line is: :source-paths ["src/cljs" "src/demo"] and that matches the directory structure but I always get Could not locate demo/core__init.class or demo/core.clj on classpath.

17:22 but with the source commented out, it's fine

17:25 expez: ZimaBlue`: like you don't have a src/demo/demo/core.clj file, which is what leiningen is looking for

17:26 s/like/likely/

17:26 ZimaBlue`: so just change "src/demo" to "src" and you'll be good to go.

17:31 ZimaBlue`: expez: thanks, but I don't understand - is it adding together my prefixed demo in the main and suffixed demo in the src string?

17:31 expez: ZimaBlue`: the default value for source-paths is ["src" "test"], you told it to consider src/demo the root of your source directory

17:32 ZimaBlue`: so if you have a namespace named demo.core then leiningen will look at the root for a folder named demo and then look for a file there called core.clj

17:33 ZimaBlue`: I think I understand, thank you!

17:57 I'm still failing, now cljs isn't working:

17:57 structure: src/cljs/demo/app.cljs, code: (ns demo.app)

17:57 (.write js/document "Hello, ClojureScript!")

17:57 config:

17:57 :cljsbuild {:builds

17:57 [{:source-paths ["src/cljs"] :compiler {

17:57 :output-to "resources/public/js/app.js"

17:57 troydm: how can I make sure that cider-nrepl is loaded?

17:57 ZimaBlue`: :optimizations :whitespace

17:57 :pretty-print true}}]}


17:57 troydm: when I type lein repl and I have cider-nrepl in user profile in .lein/profiles.clj how can I make sure it's actually loaded?

17:59 oddcully: ZimaBlue`: please don't paste large portions of code here. use a gist/refheap/... instead

17:59 ZimaBlue`: also "isn't working" might need some more elaboration

18:01 ZimaBlue`: sorry - what I mean is that when I go into resources, there isn't a compiled js file. I'll use that link in future - not been on irc mnuch before.

18:02 dnolen: ZimaBlue`: there's also a #clojurescript channel these days

18:03 ZimaBlue`: I would make a gist w/ your project.clj and your project structure so people can examine that.

18:03 ZimaBlue`: ok, I'll repost the question over there. Thanks

18:13 kwladyka: Did you hear about remote job for Clojure Junior or in Europe with relocation? :)

18:45 expez: troydm: when you call cider-jack in (in emacs) you'll get a warning if the middleware is missing or misconfigured. If you want to check in `lein repl` if the middleware is active (although I can't see why) you can check for the presence of any of cider.nrepl.* namespaces

18:52 troydm: expez: ic

19:02 hiredman: /win 19

19:09 ashwink005: what does -> mean in clojure

19:09 can't google it

19:10 Rurik: ashwink005, threading macro

19:10 TEttinger: ashwink005: yep, there's a good resource for ungoogleable symbols in clojure

19:10 ashwink005: TEttinger: could u send me a link?

19:10 TEttinger: https://yobriefca.se/blog/2014/05/19/the-weird-and-wonderful-characters-of-clojure/

19:10 ashwink005: Rurik: thanks :)

19:16 TEttinger: ashwink005: you may also want to bookmark clojuredocs and/or grimoire

19:17 ashwink005: TEttinger: I have bookmarked clojure docs. But couldn't find the name of the operator

19:17 thanks man :)

19:18 TEttinger: http://conj.io/ is the quick reference page of grimoire

19:19 troydm: grimoire only contains core library right?

19:20 TEttinger: nope http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.string

19:20 need to click the + but it does have all the standard stuff

19:21 "oh you wish you were using common lisp do you?" http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.pprint/cl-format

20:23 gargsms: I am a Clojure newbie. I made a Compojure project and configured the routes. I can do GET properly but in case of POST, I get `Invalid Anti Forgery Token` error. Any help?

20:28 thearthur: gargsms: the corasponding get request should be sending you a csfr prevention token (Cross Sire Request Forgery)

20:28 gargsms: thearthur, How do I do that?

20:29 thearthur: this needs to be passed to the post request to prevent CSRF attacks (on all web applications, this is not Clojure specific)

20:29 gws: gargsms: https://github.com/ring-clojure/ring-anti-forgery

20:29 gargsms: you've probably configured that, and you can either disable it for now to test your routes, or pass the __anti-forgery-token form parameter

20:35 as the README mentions you can get the value that is associated with that parameter by calling ring.util.anti-forgery/anti-forgery-field

20:37 which will generate the HTML necessary, rather. You can get the actual value out of a dynamic var in that lib if you want to create some custom HTML

20:47 troydm: is there a builtin function that would remove element from a list returning a new copy of list?

20:48 rhg135: rest

20:48 or pop

20:51 justin_smith: troydm: you don't need copies of immutable data

20:51 rhg135: neither of those copy

20:52 rhg135: justin_smith: I didn't see the copy

20:52 why would you want it though?

20:53 justin_smith: probably because he didn't realize clojure lists were immutable, or didn't understand the implications of that fact

20:54 rhg135: that was the right answer for what troydm wanted, I was just being pedantic about the assumed details

20:55 * rhg135 now can't see copy and list in the same sentence

20:56 justin_smith: rhg135: clojure-blindness

20:56 rhg135: indeed

20:57 troydm: justin_smith: let's say I want to implement a function that would give me all possible permutations of a list, how would I go about implementing it? I have no clue

20:57 rhg135: being more pedantic, that is more due to the persistence

20:57 non-persistent lists might get copied for perf

21:00 justin_smith: troydm: clojure.combinatorics has that function if you just need the functionality

21:01 troydm: but the general pattern in clojure is to write a recursive function where each iteration gets more results until you have created all of them

21:01 troydm: justin_smith: I know about that, but I'm more interested in implementing it by my own

21:04 justin_smith: troydm: so - how I would break it down - first take the elements of the list, and pass those as the "head" and all other members of the list as the "tail elements" for each recursive call. Then for the recursive calls generate a new set of heads and tails. recursively concatenate all results of this, stopping when each tail hits empty list

21:04 hmm, that's not very clear is it

21:06 troydm: justin_smith: hmm, I got general idea

21:10 gargsms: gws, I have the value. I tried passing it in the `X-Csrf-Token` header from the browser. I still get the same error.

21:17 gws: you're getting the value from the server and sending it back on each POST, or you've copied the value from some point in time and are passing that to test?

21:17 gargsms: Ah. Finally. Somehow I got it working.

21:17 justin_smith: troydm: here's a broken version that shouldn't be far from working https://www.refheap.com/109034

21:17 gargsms: Thanks thearthur gws

21:18 troydm: justin_smith: ic, thx

21:19 justin_smith: ,((juxt take drop) 3 (range 10))

21:19 clojurebot: [(0 1 2) (3 4 5 6 7 ...)]

21:22 TEttinger: I can't remember, does the group of all permutations of a, say, 10-element list include 1-element and 2-element sublists or just re-orderings of the 10-element?

21:25 justin_smith: TEttinger: "a rearrangement of the elements of an ordered list into a one-to-one correspondance with itself"

21:25 TEttinger: if order doesn't matter, that's a combination, not a permutation right?

21:25 justin_smith: if order doesn't matter, permutation isn't defined

21:26 TEttinger: (and there are less comb's than perm's)

21:29 like if the store sells 6 kinds of fruit, and I can buy any number of any of the kinds of fruit, and I want to know how many item numbers will be on the receipt (so quantity doesn't matter if > 0), that's a combination (there are 63 here, since you don't get a receipt if you buy nothing)

21:29 but if it was something like arranging 6 different fruits in a line on a table, that's a different problem

21:54 justin_smith: TEttinger: well I figured out a way to do it, but it feels like a silly solution https://www.refheap.com/109034

21:55 I am sure that can be golfed down to like 1/4 the size

22:06 TEttinger: justin_smith: yeah I think you're right about the size

22:06 ,(let [limit 6] (nth (iterate #(for [p %, n (range (inc (count p)))] (concat (take n p) [(count p)] (drop n p))) [[0]]) (dec limit)))

22:06 clojurebot: ((5 4 3 2 1 ...) (4 5 3 2 1 ...) (4 3 5 2 1 ...) (4 3 2 5 1 ...) (4 3 2 1 5 ...) ...)

22:06 TEttinger: &(let [limit 7] (nth (iterate #(for [p %, n (range (inc (count p)))] (concat (take n p) [(count p)] (drop n p))) [[0]]) (dec limit)))

22:06 lazybot: Execution Timed Out!

22:06 TEttinger: haha

22:06 &(let [limit 5] (nth (iterate #(for [p %, n (range (inc (count p)))] (concat (take n p) [(count p)] (drop n p))) [[0]]) (dec limit)))

22:06 lazybot: ⇒ ((4 3 2 1 0) (3 4 2 1 0) (3 2 4 1 0) (3 2 1 4 0) (3 2 1 0 4) (4 2 3 1 0) (2 4 3 1 0) (2 3 4 1 0) (2 3 1 4 0) (2 3 1 0 4) (4 2 1 3 0) (2 4 1 3 0) (2 1 4 3 0) (2 1 3 4 0) (2 1 3 0 4) (4 2 1 0 3) (2 4 1 0 3) (2 1 4 0 3) (2 1 0 4 3) (2 1 0 3 4) (4 3 1 2 0) (3 4 1 2 0) (... https://www.refheap.com/109038

22:07 TEttinger: there should be 120 elements there

22:07 justin_smith: fancy

22:07 I'm bad at lazy stuff

22:08 TEttinger: it can be quickly adapted to just get the nth item from the original list, too

22:09 &(let [limit 5 original [:a :b :c :d :e]] (map (partial map nth original) (nth (iterate #(for [p %, n (range (inc (count p)))] (concat (take n p) [(count p)] (drop n p))) [[0]]) (dec limit))))

22:09 lazybot: java.lang.UnsupportedOperationException: nth not supported on this type: Keyword

22:09 TEttinger: aww

22:10 &(let [limit 5 original [:a :b :c :d :e]] (map #(map (partial nth original) %) (nth (iterate #(for [p %, n (range (inc (count p)))] (concat (take n p) [(count p)] (drop n p))) [[0]]) (dec limit))))

22:10 lazybot: ⇒ ((:e :d :c :b :a) (:d :e :c :b :a) (:d :c :e :b :a) (:d :c :b :e :a) (:d :c :b :a :e) (:e :c :d :b :a) (:c :e :d :b :a) (:c :d :e :b :a) (:c :d :b :e :a) (:c :d :b :a :e) (:e :c :b :d :a) (:c :e :b :d :a) (:c :b :e :d :a) (:c :b :d :e :a) (:c :b :d :a :e) (:e :c :b ... https://www.refheap.com/109039

22:11 TEttinger: I had a bit of help from wikipedia and 14th century math whizzes in India :)

22:11 justin_smith: haha, cheater

22:11 TEttinger: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order

22:12 (that's not the algo I used though)

22:12 this one, with no opts https://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm

22:16 chouser: can I play?

22:16 justin_smith: oh, please do

22:16 with any luck I might learn something

22:17 chouser: &((fn perm [r m p] (if (> m 0) (mapcat #(comb (disj r %) (dec m) (conj p %)) r) [p])) '#{a b c d e} 5 [])

22:17 lazybot: java.lang.RuntimeException: Unable to resolve symbol: comb in this context

22:17 chouser: heh

22:17 justin_smith: what is comb ?

22:17 chouser: &((fn perm [r m p] (if (> m 0) (mapcat #(perm (disj r %) (dec m) (conj p %)) r) [p])) '#{a b c d e} 5 [])

22:17 lazybot: ⇒ ([a e c b d] [a e c d b] [a e b c d] [a e b d c] [a e d c b] [a e d b c] [a c e b d] [a c e d b] [a c b e d] [a c b d e] [a c d e b] [a c d b e] [a b e c d] [a b e d c] [a b c e d] [a b c d e] [a b d e c] [a b d c e] [a d e c b] [a d e b c] [a d c e b] [a d c b e] [... https://www.refheap.com/109040

22:17 justin_smith: ahh

22:17 nice!

22:17 chouser: Works with sets, so no good if the input it meant to have duplicates.

22:19 That's an oldie, btw. 11 June 2008.

22:19 justin_smith: it's a classic problem, that just happens to hit some aspects of clojure programming I am pretty bad at

22:21 chouser: oh, I didn't mean to suggest you were bad at anything, just that I was cheating off my former self.

22:21 justin_smith: oh, no, I volunteered that part :)

22:22 that's the reason I was asking for improvements / other approaches

22:22 chouser: If you always want the full set of inputs:

22:22 &((fn perm [r p] (if (seq r) (mapcat #(perm (disj r %) (conj p %)) r) [p])) '#{a b c d e} [])

22:22 lazybot: ⇒ ([a e c b d] [a e c d b] [a e b c d] [a e b d c] [a e d c b] [a e d b c] [a c e b d] [a c e d b] [a c b e d] [a c b d e] [a c d e b] [a c d b e] [a b e c d] [a b e d c] [a b c e d] [a b c d e] [a b d e c] [a b d c e] [a d e c b] [a d e b c] [a d c e b] [a d c b e] [... https://www.refheap.com/109041

23:14 justin_smith: someday I hope to attain this level of craftsmanship http://i.imgur.com/BUpsUAF.gifv

23:29 TEttinger: (inc chouser)

23:29 lazybot: ⇒ 23

23:30 TEttinger: justin_smith: IS THAT TRANSPARENT WOOD

23:32 justin_smith: TEttinger: it's wood cut so incredibly thin that you can see through it

23:32 by hand

23:32 TEttinger: and I thought the joins they do were amazing

23:32 wow

23:32 jeaye: Is it the technique or the tool?

23:32 justin_smith: an act of remarkable skill and handicraft - he probably spent decades getting that good

23:32 jeaye: I'm sure the tool is a part of it too

23:33 anyway, metaphorically it is all about how much he crafted and honed his craft which is what will inspire me to become a better programmer

23:34 TEttinger: https://www.youtube.com/watch?v=W1pvUlQgYtk

23:36 justin_smith: TEttinger: having worked on American mcmansion style construction sites, the comparison is really embarrassing

23:36 TEttinger: I can imagine!

23:37 justin_smith: it's amazing what these guys do with hand tools

23:41 TEttinger: it's interesting because japan doesn't have endless quantities of lumber that they could just throw more sequoias at a building project, and doesn't have much iron that historically could have been used for mass-producing large heavy weapons (like the horribly successful 10-15-foot spike of metal called a pike and used heavily by disposable peasants in european wars)

23:41 japan's traditional building techniques emphasize not wasting materials

23:42 it makes you wonder about what scarcities drive programming innovation

23:43 justin_smith: TEttinger: developer attention span and discipline

23:43 which leads us to things like fp and OO which at least in theory keep the worst outcomes from happening when we forget what we were doing :)

23:43 TEttinger: clojure got a lot of attention initially because the multicore revolution was starting, and it seems to have already ended, but clojure is still (thankfully) in use

23:46 it seems like a lot of clojure's big new ideas are going to be needed for future developments (GPU programming could really benefit from some kind of immutability when you have hundreds or thousands of tiny compute units)

Logging service provided by n01se.net