#clojure log - Feb 20 2014

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

0:00 noprompt: bob2: of course. that and ml.

0:00 s1gs3gv: try to be positive mark[oz] ... it'll feel good.

0:00 johnwalker: or rust

0:00 sm0ke: erlang

0:00 s1gs3gv: 1980

0:00 bob2: noprompt, did you find haskell's type system to be significantly more valuable than scala's?

0:00 mark[oz]: s1gs3gv: I just feel like the same conversations happen, no matter which language I'm playing with.... "does it scale?" "is it better then language X"

0:01 sm0ke: go

0:01 s1gs3gv: it is a legit concern

0:01 mark[oz]: we can make anything scale... geez people scale c++

0:01 sm0ke: lua can be scaled

0:01 bob2: s1gs3gv, without context, it isn't

0:01 noprompt: bob2: i never used scala. i took one look at it and literally said "fuck no".

0:01 bob2: noprompt, hah, fair enough

0:01 mark[oz]: s1gs3gv: if google can keep 14 copies of the internet in memory, then you'll be fine :)

0:01 johnwalker: noprompt: ugh, yeah me too, except it was in the context of the coursera introduction

0:01 s1gs3gv: ok, with remote akka actors i can scale thru configuration

0:02 without writing any new code

0:02 bob2: so does running more app servers count as "scale thru configuration"?

0:02 mark[oz]: you could always throw a load balancer in front of a few instances right?

0:02 varnish, etc.

0:02 s1gs3gv: yes, if i don't have to change my code, just the config

0:02 * mark[oz] is oversimplying the process

0:03 bob2: then any language counts, if you write mostly-stateless apps

0:03 johnwalker: twitchplayspokemon seems to scale

0:03 noprompt: like i said, i mostly enjoy type safe languages just not syntax.

0:04 bob2: clojure is type-safe, it's just not statically typed

0:04 noprompt: call me a smug lisp weenie. syntax adds an unecissary barrier between you and your program.

0:04 bob2: fair enough.

0:05 johnwalker: s1gs3gv: look for the technique that you want to use to scale your app, and check how it works in clojure

0:05 dsrx: my favorite scala thing is List(1,2,3).toSet() # => Boolean = false

0:07 noprompt: wut?

0:08 inahandizha: http://VisitsToMoney.com/index.php?refId=386970

0:08 dsrx: it ends up becoming something like (List(1,2,3).toSet).apply( () )

0:09 and since list is covariant the inferencer makes that list a List[Any], and checks for membership of () in it

0:09 something like that

0:10 s1gs3gv: so, i am considering mark[oz] question regarding the differences between scalability thru configuration using akka remoting and using loadbalancers

0:17 really that throws the burden of application scalability on the system admistrators rather than the software architects

0:18 it should be possible just to netboot a system and have it join the application service

0:18 mark[oz]: s1gs3gv: you need to tackle each component of the application to determine where it best sits

0:18 and I don't believe there is burden, just various solutions

0:19 s1gs3gv: mark[oz]: when you require administrative action to scale a system, you introduce a point of failure

0:20 bob2: " application scalability" is absolutely the software developer and architect's problem

0:20 poorly designed and implemented apps will never scale

0:21 mark[oz]: facebook would disagree

0:21 so would reddit and twitter

0:21 it's just tougher

0:21 bob2: heh

0:22 mark[oz]: I'm on a 16million pi app that's is being scaled across 3 web servers, and still as one db.

0:22 s1gs3gv: which db ?

0:22 mark[oz]: we have solid caching, memcached, memoization, varnihs, etc.

0:23 s1gs3gv:postgres.

0:23 s1gs3gv: hidden behind an ORM btw

0:24 s1gs3gv: what kind of hardware is running the db ?

0:24 mark[oz]: it'll be RDS soon. but it's a beefy dell 2950 (3 years old though)

0:25 s1gs3gv: and this is a clojure app ?

0:25 mark[oz]: nope.

0:25 python... so prob slower then the jvm :)

0:25 s1gs3gv: well ...

0:25 mark[oz]: but my point stands... it shouldn't matter?

0:25 s1gs3gv: what shouldn't matter ?

0:26 johnwalker: clojure is faster than python

0:27 s1gs3gv: everything is faster than python, except ruby lol

0:27 johnwalker: is php faster than python?

0:27 s1gs3gv: dunno. i don't do php :)

0:27 scala is

0:29 anyways, the takeaway i am getting is that clojure is slower than scala but some think it make up for it by being a better match to the problem spaces and that you can scale clojure apps using load balancers.

0:29 have i got that right ?

0:29 Cr8: i..

0:30 s1gs3gv: ?

0:30 Cr8: it's hard to say that a -language- is slower or faster than another

0:30 especially two jvm languages

0:30 unless one is groovy

0:30 s1gs3gv: lol

0:31 Cr8: I'd say Clojure and Scala are pretty similar in terms of closeness to the underlying runtime though

0:32 and there's always https://github.com/ztellman?tab=repositories when you need an escape hatch

0:33 s1gs3gv: thats kinda interesting. ty.

0:34 Cr8: (by which i mean ztellman has several different projects that allow you to step around some of the things in clojure when you need to for performance reasons)

0:34 vertigo, proteus, probably more

0:35 That is one of the differences I'd say that exists between Clojure and Scala is that Clojure does a lot less in the way of actual *enforcement* of its sensibilities

0:36 s1gs3gv: right

0:36 Cr8: which may be something you like or don't, depending on your situation

0:36 s1gs3gv: sure

0:37 there are times when covariance and contravarience hurt the brain

0:38 but it seems to pay dividends

0:39 can u summarize the benefits of *not having* a static type system in clojure

0:41 Cr8: probably not. One though is that it is a bit at odds with its goal of being a language that sits very thinly on-top of some host platform (enabling stuff like ClojureScript very easily)

0:41 technomancy: not having Java's type system is pretty great

0:41 Cr8: ^^

0:41 technomancy: it would be really difficult to build something that is both 0) good and 1) allows for decent JVM interop

0:43 Cr8: and now you have the weird effect of touching the JVM "types" at a lower level than you would from Java even

0:44 since Java has things that don't "exist" at the JVM layer (generics, inner classes)

0:44 s1gs3gv: so what is great about not having the java type system ?

0:44 perl doesn't have it either ...

0:45 technomancy: define good

0:45 Cr8: if you had a static type system and it was significantly different from Java's it complicates the interop layer

0:46 s1gs3gv: but that is hidden in the implementation. as an application programmer i don't need to worry about it.

0:46 technomancy: s1gs3gv: catches common errors without imposing lots of unnecessary mental overhead

0:46 Cr8: heh

0:47 I've never used FFI of any form without eventually having to study the implementation to deal with something

0:47 s1gs3gv: FFI ?

0:47 Cr8: (foreign function interface, though here I use it to mean interop layers in general)

0:48 s1gs3gv: as an application programmer using a jvm language that interoperates with java classes, why should i care

0:49 in fact, i shouldn't have to care

0:50 i think i'm missing something here that y'all are trying to explain ...

0:51 scala and clojure both target the jvm and interoperate with java classes

0:51 scala has a static type system, clojure doesn't

0:51 that has benefits and costs

0:51 convince me that the costs outweigh the benefits if u can

0:52 technomancy: I don't care; if Scala doesn't drive you crazy then that's fine by me =)

0:53 `szx: s1gs3gv: why don't you just try it out and decide for yourself?

0:53 bob2: why? if you like scala, go for it

0:53 no one but you (and your coworkers) cares what you use or prefer

0:53 s1gs3gv: lol. thats what i thought !

0:53 i like both.

0:53 but clojure is so slow ...

0:54 technomancy: slow clojure programs are slow

0:54 fast clojure programs are fast

0:54 there's nothing about clojure that makes it impossible to write programs that are as fast as the fastest scala programs

0:55 s1gs3gv: so why do the benchmark game benchmarks suck ?

0:55 technomancy: because benchmarks are stupid

0:55 s1gs3gv: ohhh, excuse me. sorry.

0:56 technomancy: no one who knows how to write clojure has bothered to spend a bunch of time optimizing against a silly gamed metric

0:56 s1gs3gv: i don't think any of those programs are optimized.

0:56 technomancy: right, because no one cares

0:57 s1gs3gv: its still an apples to apples comparison

0:58 technomancy: benchmark games are like arguing on the Internet

0:58 whoever has more time to sink into a fruitless cause always wins

0:58 s1gs3gv: it shouldn't be necessary to optimize an idiomatic clojure program to get good performance.

0:58 that is a bad tradeoff

0:59 technomancy: what good is a fast program that isn't correct?

0:59 do you want a language that makes it easy to write fast code and difficult to make it correct, or vice versa?

0:59 s1gs3gv: are you suggesting that idiomatic clojure programs are less likely to be correct

0:59 technomancy: no

1:00 alew: if you want performance, you should use a language built with speed in mind, like c

1:00 s1gs3gv: are you suggesting that idiomatic clojure programs are more likely to be correct ?

1:00 technomancy: yes

1:01 s1gs3gv: so you are implying there is a tradeoff between idiomatic usage and performance ?

1:01 alew: that's true of every single language

1:01 s1gs3gv: not really

1:02 i don't have a problem with it if there are ways to deal with scalability

1:02 technomancy: scala comes out better in the games because it makes it easier to write imperatvie code

1:02 s1gs3gv: in fact i think idiomatic usage trumps performance

1:02 technomancy: imperative code is more difficult to write correctly in a concurrent setting

1:02 s1gs3gv: yes

1:02 i'm not arguing imperative vv functional

1:03 technomancy: imperative vs functional *is* the same argument as fast vs correct

1:03 s1gs3gv: phhhwww

1:03 technomancy: in the context of clojure vs scala

1:03 s1gs3gv: i've written a lot of correct imperative programs

1:03 alew: in what language is the idomatic solution also always the fastest?

1:04 s1gs3gv: i think the primar concern in language choice is how closely the language models the abstraction we use when thinking about the problem space

1:04 but i want to ensure that my solution scales reliably without adminstrative action

1:05 alew: what about erlang?

1:05 s1gs3gv: 1980

1:05 sorry, thats a reasonable question. but out of scope in a clojure/scala conversation

1:06 i really like clojure, but the benchmarks suck

1:07 technomancy: if you think you can't write fast code in clojure you should read http://meshy.org/2009/12/13/widefinder-2-with-clojure.html

1:07 if you base your decisions on alioth benchmarks you deserve what you get =)

1:08 s1gs3gv: i'll read it. thanks for the link.

1:09 take it easy folks. ttyl. late here ...

1:10 ssafejava: thanks for the links technomancy, always glad to have you in channel

1:10 technomancy: alioth used to penalize you for startup time too

1:10 not sure if they still do

1:11 but that made it totally misleading for server software

1:12 read the meshy.org article ... and pray you never have to deal with optimization at that level yourself =)

1:12 ssafejava: np; cheers. calling it a night.

1:13 ssafejava: night

1:43 quizdr: I have a map of maps, therefore a lazy sequence that contains other lazy sequences. I just want to print it all out, but it seems I have to get fancy with mapping printlns on top of printlns; is there an easier way? doall only realizes the top-level map

1:44 bob2: pprint?

1:45 Cr8: map {:foo "bar"} or map (map foo [bar baz]) ?

1:45 map {:foo "bar"} <-- not lazy

1:46 quizdr: Cr8 yes, map of map, actually three levels deep.

1:46 bob2 that only works on top level

1:46 Cr8: pprint or pr-str should realize the whole structure

1:47 quizdr: Cr8 ok let me take a closer look.

1:47 Cr8: er, (prn) rather

1:47 if you want to print it out

1:48 pr-str would return the string that would be printed using pr

1:49 quizdr: (print) is for humans

1:49 (pr) is for printing things such that they are fully represented and can be read back in

1:49 quizdr: Cr8 gotcha

1:49 Cr8: with (println) and (prn) respectively if you want newlines after

1:51 hhenkel: Hi all, I'm running in an error trying to use at-at as a scheduler library with http-hit communicating over channels. The error is: Exception in thread "main" java.lang.ClassCastException: clojure.core.async.impl.channels.ManyToManyChannel cannot be cast to java.lang.Runnable

1:52 So my guess is, that it is not a good idea to use return a channel at that point in the code but rather return the data and put it then in the channel?

1:55 amalloy: hhenkel: an error message is much, much less useful than an entire stacktrace

1:57 hhenkel: amalloy: That's not a big deal: https://www.refheap.com/42612

1:59 amalloy: i know very little about at-at, but it sure looks to me like you are calling schedule-requests with a core.async channel, when it wants a Runnable

1:59 (and since clojure functions implement Runnable, you may in fact just want to be passing it a fn)

2:02 Cr8: at-at is a pretty thin wrapper around http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

2:02 and it looks like you tried to hand at-at/every a channel where it expected a function (or other Runnable thing)

2:03 hhenkel: amalloy: Cr8: added the functions to https://www.refheap.com/42612

2:04 Cr8: hhenkel: every expects an interval

2:04 hhenkel: Cr8: Yes, that's what I thought might be the problem. So it's better to return the result of the http request then?

2:04 Cr8: ahah waity

2:04 *wait

2:04 you want to run that http-post every timed-request ms

2:05 right

2:05 just toss a # at the front of line 15 =P

2:05 hhenkel: Cr8: Yes, exactly.

2:05 Cr8: you're actually passing it the result of *calling* http-post

2:05 you want to pass a function that *will* call http-post

2:06 (every <interval> <function> <pool>) ; (every 1000 (fn [] (println "I get printed every 1000ms")) my-pool)

2:06 (every 1000 (println "I return nil") my-pool) <-- throws nullpointerexception because it tries to call nil as a function

2:07 hhenkel: Cr8: okay, okay...I think I see the issue...I'll give it a try.

2:07 ;)

2:08 Cr8: I've done this same thing using at-at myself.

2:12 webus: hi! i'm locking for remote job on clojure

2:12 hhenkel: Cr8: Looks much better now...totally strange that it works once it is done right.

2:12 Cr8: funny that

2:12 hhenkel: (inc Cr8)

2:13 lazybot is gone?

2:13 ddellacosta: ,(inc Cr8)

2:13 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Cr8 in this context, compiling:(NO_SOURCE_PATH:0:0)>

2:13 Cr8: huh it was here earlier

2:13 ddellacosta: &(inc Cr8)

2:13 Cr8: guess it got borked

2:13 ddellacosta: hmm

2:13 Cr8: ddellacosta: it's actually not in the channel :)

2:14 ddellacosta: Cr8: ah

2:14 clojurebot: where is lazybot?

2:14 Cr8: is it its brother's keeper

2:14 ddellacosta: jeez, the bots are really slacking off today

2:14 lazy bots

2:21 juliankrause: Hello, I am following this doc http://clojure-doc.org/articles/tutorials/vim_fireplace.html on how to get my repl set up correctly. However, when I try and run the tests I get: ClassNotFoundException clojure.tests java.net.URLClassLoader$1.run (URLClassLoader.java:366)

2:21 I am using OpenJDK 7 on debian. Is this a problem? Is there a way to get more details?

2:23 Ooops, I realized what it is, running (clojure.tests/run-tests) fails with that.

2:23 Thanks

2:57 TravisD: Do refs provide validation because you may not control the transactions that update the ref?

3:03 arrdem: ddellacosta: you don't do inc with code eval. it's its own system.

3:03 (inc ddellacosta)

3:04 which apparently is offline..

3:04 TravisD: care to elaborate?

3:05 TravisD: arrdem: Ah, I watched a talk by Rich Hickey about simplicity tonight. It seems like you should be able to have validation and mutation as orthogonal concepts. I was trying to figure out why they are coupled together

3:06 arrdem: The talk was relevant because he started using the word "complect", which is why i was thinking about it in the first place

3:08 arrdem: TravisD: AFAIK ref transactions provide no validation. You can achieve validation by using ref update hooks, but it's not something I've done.

3:09 TravisD: Ah, maybe it's just for convenience then. What I was thinking of is this: (def some-ref (ref 0 :validator #(> % 0))

3:09 arrdem: lemme look around a bit, I may be entirely offbase here.

3:10 I appologize. there is official support for ref validation.

3:10 http://clojure.org/refs#Refs%20and%20Transactions

3:10 amalloy: TravisD: #(> % 0) is just pos?, isn't it?

3:10 arrdem: http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/set-validator!

3:10 TravisD: amalloy: sounds like it :)

3:10 I just made something up on the spot. not too familiar with the available predicates yet

3:13 mskou72: I have something like this: (def x [{:a 1 :d #{}} {:a 2 :d #{}}]) , but how do i put items in the set and get a new x?

3:14 ddellacosta: arrdem: ah, didn't realize...thanks

3:18 mskou72: if you want to do the same thing to all :d sets, you could do something like (map (fn [v] (update-in v [:d] #(conj % :foo))) x)

3:18 mskou72: well only fx for maps where (= :a 2)

3:20 ddellacosta: mskou72: in that case just add a predicate I suppose: (map (fn [v] (if (= 2 (:a v)) (update-in v [:d] #(conj % :bar)) v)) x)

3:21 mskou72: thanks, will try!

3:21 bob2: are you sure you want a randomly mutable global?

3:22 ddellacosta: mskou72: more generally, if you are still figuring out how to structure your data, consider what you will want to access/update and how, and think about the ways that clojure gives you to make it easier. Sometimes that pays off.

3:22 bob2: what do you mean?

3:22 bob2: I don't see anything mutable anywhere in mskou72's question or my answer

3:26 mskou72: bob: the (def x part was just to present the problem in a runable manner...

3:47 lizzin: is there a way to destructure a map in a def? say (def [x y] (group-by #(< % 5) (shuffle (range 10))))?

3:48 ddellacosta: lizzin: you mean defn? You don't pass args into a def like that.

3:49 lizzin: and if you are asking about defn, then the answer is yes, you certainly can. This is a great article on destructuring: http://blog.jayfields.com/2010/07/clojure-destructuring.html

3:50 lizzin: i am familiar with defn. just wondering if was also possible to create two vars w/ a single def while destructing that map

3:51 ddellacosta: lizzin: no, the first arg to def is a symbol, not bindings/params.

3:53 lizzin: ddellacosta: seems a bit odd that this is not allowed. but binding via let etc should work just fine

3:53 hhenkel: Hi all, is it possible to pass multiple values to a function using the "arrow" notation?

3:54 ddellacosta: lizzin: why is it odd? Honestly I can't really think of a use case that would need you to do this kind of thing

3:54 bob2: mskou72, ah, sorry, I misunderstood

3:55 ddellacosta: lizzin: simply set the var to be the value of the group-by, then it's very easy to refer to things using built-in mechanisms that Clojure provides.

3:55 bob2: hhenkel, you can pass a container and destructure it in the function, but -> and ->> only pass in one arg themselves

3:56 lizzin: ddellacosta: true. it just something i've found useful in scala

3:56 hhenkel: bob2: okay, thanks.

3:57 lizzin: ddellacosta: i just started learning clojure. so i'm sure my views on this are sure to change

3:58 ddellacosta: lizzin: another thing is that function args/let bindings are setting local scope; you would be setting indefinite (global) scope with this proposed mechanism.

3:58 lizzin: I'm not sure there is much of an arg there other than semantic consistency, though.

3:58 lizzin: yeah, in general it's good to get a feel for the tools Clojure gives you for getting ahold of your data--it is very powerful but takes a bit of time to "think in Clojure" so to speak.

4:04 lizzin: ddellacosta: i have much to learn. thanks for the help

4:05 ddellacosta: lizzin: as do we all. :-) Sure, any time, hope I was helpful!

4:05 TravisD: Since random number generators are not pure (unless you include the seed as an argument, which seems uncommon), should you be careful about their use in otherwise pure code?

4:07 dsrx: passing RNG state around inside a closure or contained within an object or with a state monad or something isn't really that uncommon

4:07 TravisD: yeah, I wrote some simulation stuff in Haskell that used a state monad to thread the seed through the program

4:08 but that felt kind of tedious in the end

4:09 quizdr: I'm finding it a bit odd that partition returns a sequence, which you'd understand to be ordered, yet conj prepends to the front, unlike other ordered sequences like vector. Is this confusing or expected?

4:10 lizzin: ddellacosta: you definitely were!

4:18 dsrx: the 'place' that conj happens depends on the collection; lists are one example where it's prepended (because they're singly linked lists)

4:46 nathan7: quizdr: conj just does the most efficient 'add this to the sequence' it can do

4:46 for a single-linked list, that's at the front, for a vector, that's at the back

4:47 conj is guaranteed to be constant-time

5:04 hhenkel: What are the best options/prefered types when I'm facing such an exception: nth not supported on this type: PersistentArrayMap

5:10 clgv: hhenkel: what do you want to extract from the map?

5:11 hhenkel: clgv: I don't want to extract anything... ;) I'm providing a datastructure to http-kit to be used within a post request.

5:12 clgv: https://www.refheap.com/42670

5:13 clgv: hhenkel: oh then you provide the wrong data structure or the wrong layout

5:14 hhenkel: http-kit is clearly assuming a sequential data structure there - maybe even a vector

5:14 check the docs about what data you need to provide

5:15 hhenkel: clgv: yes, thought so...updated the refheap with my code...gues I have to rethink line 8 then.

5:16 clgv: looks like I need a vector for that.

5:17 clgv: what's that: (keyword "form-params") ? why not :form-params?

5:17 hhenkel: maybe you need a vector of requests? just check what the docs say ;)

5:25 hhenkel: clgv: How do I create a vector then? I'm limited with my knowledge regarding options to process the data.

5:26 clgv: As far as I understand I need a different operation then the doall / map because this gives me a lazyseq

5:26 clgv: hhenkel: you need some introductory text to clojure if you ask that

5:27 hhenkel: clgv: I'm trying to understand the oreilly book at the moment...

5:28 clgv: hhenkel: If I were you I'd read the http-kit docs to find out what the used call needs to get as data

5:28 and then go from there

5:39 sm0ke: conj is not constant time

5:40 it took over 3 days i guess

5:40 :D

5:46 rurumate: Is there a way to enable auto-reload of modified source files with liberator?

5:49 bob2: rurumate, 'lein ring server'does that already

5:57 rurumate: bob2: ok, that's what I used to do before liberator, and it worked

5:57 sm0ke: whats is liberator?

5:58 rurumate: now I cloned the liberator project and run lein examples, and have to restart after a change

5:58 sm0ke: it's a project on github

5:58 sm0ke: rurumate: whats it good for?

5:59 rurumate: sm0ke: not sure yet, but it seems to require less setup work for a new project

5:59 than raw compojure

5:59 I'm lazy you know

5:59 sm0ke: hmm how can compojure be more work!! the req response is a map!

6:00 thanks to ring

6:00 rurumate: sm0ke: for example, many useful ring handlers are already there

6:00 sm0ke: it seems to have some fancy graph based thingy

6:01 rurumate: ring handlers and middlewares are completely different things

6:01 Anderkent: well that's the thing, it doesn't really do anything for you; sometimes it's nice to work on a higher level of abstraction than just request-response

6:01 rurumate: oops sorry, I meant middlewares

6:01 sm0ke: and can be resused in any app based on ring

6:01 need to read about it

6:08 rurumate: hmm, no liberator users here?

6:08 it has almost 500 stars, I wasnt't expecting this

6:15 sm0ke: rurumate: did you try what bob2 suggested?

6:15 rurumate: if its based on ring, lein ring server should be good enough

6:16 rurumate: https://github.com/weavejester/lein-ring

6:22 clgv: rurumate: I can ping one of the maintainers if he is around ;)

6:28 no luck yet..

6:31 rurumate: clgv: yes please, thanks

6:32 google didn't help me much, I think this should go into liberator's README.markdown

6:32 or the wiki start page

6:41 clgv: rurumate: maybe you need to start the server from the REPL. then updating code would be pretty easy without additional magic

6:51 sm0ke: hey is it necessary for deftype to implement an interface? ##(deftype ValarMorghulis [s] (getName [_] x))

6:51 the doc here has a spec* http://clojuredocs.org/clojure_core/clojure.core/deftype

6:52 what happened to lazybot?

6:52 ,(deftype ValarMorghulis [s] (getName [_] x))

6:52 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol>

6:52 sm0ke: ,(deftype ValarMorghulis [s] (getName [_] s))

6:52 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol>

6:53 clgv: sm0ke: to implement a method in a deftype you need an interface

6:53 or a protocol

6:54 sm0ke: hmm than the statement that gen-class and deftype are similar is just plain wrong

6:56 clgv: sm0ke: similarity does not mean they are identical, they just share some common properties

6:57 rurumate: clgv: thanks, I'll try the repl way

6:57 cheers

6:59 sm0ke: ugh, i am lost when it comes to defining types

6:59 Anderkent: sm0ke: functions on deftype must fulfill a protocol / interface

6:59 that's by design

6:59 sm0ke: defprotocol, definterface, then defrecord, extend-type, deftype, then proxy, reify, gen-class.. blah blah bleh

7:00 Anderkent: right, they're all different tools for different purposes; (with perhaps exception of gen-class, which is the low-level mechanism)

7:01 .. I think there was a cool graph of 'what datatype to use' somewhere, but cant find it now

7:01 sveri: hi, did someone here integrate friend into a luminus/http-kit project and has some example code or any other resources for this?

7:01 sm0ke: http://chasemerick.files.wordpress.com/2011/07/choosingtypeforms2.png

7:02 there is no extend-record, extend-type on that

7:02 Anderkent: yeah, that's it :P

7:02 because they're not datatypes, they're ways fo bending an existing datatype to support new interfaces

7:03 i.e. you're defining a protocol and want to provide implementations for types you don't control

7:11 sm0ke: ,(defprotocol IncStr (inc [s]))

7:11 clojurebot: Warning: protocol #'sandbox/IncStr is overwriting function inc\n#<SecurityException java.lang.SecurityException: denied>

7:11 sm0ke: :P

7:11 clgv: don't annoy clojurebot! otherwise he may join lazybot in the tavern ;)

7:12 sm0ke: the sandboxing is bullet proof

7:23 how wise it would be to have something like...(ns org.abc) (deftype....) (ns back.to.original). in a source code?

7:23 the point being deftype could be given a custom package strucutre?

7:27 clgv: sm0ke: very stupid, since clojure cannot require that namespace since class loading is done via a namespace-file-location correspondence

7:28 sm0ke: clgv: is that true? why is it permitted on a repl then?

7:28 clgv: but if you want a different namespace for the deftype just create the appropriate file for that namespace

7:29 sm0ke: yeah that is true. on the repl when you define a namespaces it is created in memory. when you define the namespace in a file and require it from a different file there is the mentioned convention so that the namespace can be found and loaded into memory

7:30 sm0ke: ,(doc ns)

7:30 clojurebot: "([name docstring? attr-map? references*]); Sets *ns* to the namespace named by name (unevaluated), creating it if needed. references can be zero or more of: (:refer-clojure ...) (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class) with the syntax of refer-clojure/require/use/import/load/gen-class respectively, except the arguments are unevaluated and need not be quoted. (:gen-class .....

7:31 clgv: just remember ech namespace needs his own file. but one namespaces can be implemented in different files for better organization of large namespaces see clojure.core

7:31 sm0ke: the docstring just explains how ns is used^^

7:32 sm0ke: clgv: what do you mean by one namespace can be implemented in different files?

7:32 clgv: sm0ke: you can simply try your scenario. write a second file (ns my.example (:require org.abc)) where (ns back.to.original) ... (ns org.abc) ... (ns back.to.original)

7:33 and see if failing ;)

7:33 sm0ke: see clojure.core

7:33 sm0ke: clgv: hey that would obvisouly fail

7:34 wait..

7:34 hmm i am interested to know what would happen if i put (ns xyz) in middle of a source code

7:34 clgv: any setup with two ns-forms within a single file will fail

7:34 sm0ke: ah

7:35 clgv: you can't properly require xyz if the file where it is contained was not loaded in advance

7:37 sm0ke: so do you propose i either use gen-class or create folder like org.stupid.java.packaging.howlong.cani.dothis ?

7:39 clgv: sm0ke: if you really need that long package yeah

7:39 sm0ke: :P

7:41 anyways, getting off now

7:41 later!

7:41 TimMc: clgv: But if one were to require the "containing" namespace, the other would become available, yeah?

7:42 clgv: TImMc: yeah

7:42 TimMc: not that I'm encouraging such shenanigans

7:42 clgv: just like the (ns) form executed in the repl

7:43 TimMc: it is just the classloader logic that cannot find the file where the "contained" namespace is in

7:44 we should switch from files to database as storage for programming. no more file oriented organization ;)

7:45 a petty that the lighttable feature for composing the workspace view out of different functions did not survive...

7:49 TimMc: It didn't? :-(

7:49 clgv: last time I tried I could not find it.

7:49 about 3-4 weeks ago

7:57 TimMc: https://groups.google.com/forum/#!topic/light-table-discussion/0DAuy2Trfjw

8:00 mercwithamouth: would any of you clojure afficionadas be willing/interested in starting a video tutorial site like railscasts? Not 'with' me but 'for' those like me =P

8:00 paid service of course...

8:04 clgv: mercwithamouth: some did write books to help you ;)

8:08 mercwithamouth: clgv: lol very true..and i've bought all of them =P

8:17 clgv: mercwithamouth: and read all of them yet? ;)

8:33 wink: mercwithamouth: well there is videos.lispcast.com, but not many

10:23 stain: hi, is it possible to use (extend-type) or similar to make beans of a Java interface also implement ISeq or ITransientMap or similar? (without modifying the Java source)

10:24 or would I have to do my own new multimethods?

10:25 if I try (extend-type com.example.MyJavaThing clojure.lang.ITransientMap (..)) I get: IllegalArgumentException interface clojure.lang.ITransientMap is not a protocol

10:26 Anderken1: you can't add interfaces to java classes, but you can proxy them and add the interfaces to your proxy

10:27 gfredericks: sometimes

10:27 Anderken1: sometimes.

10:27 gfredericks: ,(proxy [clojure.lang.Keyword] [])

10:27 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching ctor found for class sandbox.proxy$clojure.lang.Keyword$0, compiling:(NO_SOURCE_PATH:0:0)>

10:27 gfredericks: ,(proxy [clojure.lang.Keyword] ["foo"])

10:27 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching ctor found for class sandbox.proxy$clojure.lang.Keyword$0, compiling:(NO_SOURCE_PATH:0:0)>

10:27 gfredericks: ,(proxy [clojure.lang.Keyword] ["foo" "bar"])

10:27 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching ctor found for class sandbox.proxy$clojure.lang.Keyword$0, compiling:(NO_SOURCE_PATH:0:0)>

10:27 stain: ok.. but then I would have to proxy it everwhere I retrieve the Java objects?

10:27 then I could rather just create brand new Clojure object at each of those points

10:28 Anderken1: that's usually the right thing to do, yes

10:30 stain: but I can create multimethods around my Java classes, right? Say a (convert-to-clojure) method with different implementations for each of my Java classes

10:32 Anderken1: yes in theory, though I'm struggling to imagine a use case for that; usually when interacting with java you know straight away what class you'll be getting and can do whatever you want with it without the indirecton of a multimethod

10:35 clgv: stain: yes you can. I did it for an R interface

10:38 _bart: Let's say I have (def beats {0 [kick] 1 [kick snare]}) and (def arps {0 [a] 1 [b]}), how do I merge the two so that I get a (def c {0 [kick a] 1 [kick snare b]})?

10:39 Anderken1: ,(doc merge-with)

10:39 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."

10:39 _bart: (the hashes hold a 'bar' for the sequencer, and I have multiple bars for multiple instruments)

10:39 Anderken1: so (merge-with conj beats arps)

10:40 uhm, I ment concat

10:40 ,(merge-with concat {1 [1 2 3]} {1 [4]})

10:40 clojurebot: {1 (1 2 3 4)}

10:40 clgv: better use into

10:41 Anderken1: yeah, that's better

10:41 _bart: ah that looks great, why would I use into?

10:41 Anderken1: you'll get the same type

10:41 clgv: concat may bite you when you use that code too often

10:41 `cbp: into is also faster

10:41 Anderken1: ,(merge-with into {:a #{:b :c}} {:a #{:b :d}})

10:41 clgv: stacking up lazy sequences with concat too often results in a stackoverflow

10:41 clojurebot: {:a #{:c :b :d}}

10:41 Anderken1: ,(merge-with concat {:a #{:b :c}} {:a #{:b :d}})

10:41 clojurebot: {:a (:c :b :b :d)}

10:42 _bart: ah okay, thanks

10:42 sdegutis_: I always avoid conj.

10:42 _bart: ,(doc into)

10:42 clojurebot: "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

10:42 sdegutis_: I never seem to want to add onto a sequence in an undefined order.

10:43 Anyone else with me on this?

10:43 _bart: can I also merge 3 maps ith this code?

10:43 sdegutis_: Or am I crazy?

10:43 Anderken1: sdegutis_: so you don't use into either?

10:43 _bart: with*

10:43 clgv: sdegutis_: I almost only use vectors for sequential data. except from macro implementations

10:43 `cbp: you're crazy

10:43 sdegutis_: I use into only for (into {} ...)

10:44 clgv: But once you run it through map or filter, it's not a vector anymore.

10:44 Anderken1: I only use (into {} [[k v] [k v] ...])

10:44 Anderken1: well, for maps and sets the order doesnt matter anyway; vec and list are the only places you'd care I suppose, and there I usually avoid conj

10:44 llasram: Huh

10:44 sdegutis_: llasram: Huh.

10:44 clgv: sdegutis_: well I guess I do not often have the need to add to such a sequence after filter again.

10:45 for map there is mapv ;)

10:45 ,(apropos "filter")

10:45 clojurebot: (filterv filter)

10:45 clgv: oh right, filterv as well^^

10:45 llasram: I see knowing if a value is a seq vs a vector as pretty much the same as knowing if it's a string vs a database connection

10:45 sdegutis_: clgv: When you get a sequence from another of your functions, it may have been mapped or filtered or not.

10:45 `cbp: so what do you use instead of conj? :-D

10:45 sdegutis_: clgv: So I always have this hesitation of not being sure at all of what type my sequences are.

10:46 `cbp: Usually just concat.

10:46 Anderkent: llasram: huh. For me it's more like map or sorted-map

10:46 `cbp: That is horrifying!

10:46 Anderkent: in most cases you don't care

10:46 clgv: sdegutis_: as I said. adding single elements to such a sequence didnt pop up that much in my projects

10:46 sdegutis_: `cbp: Yep.

10:47 Anderkent: (i.e. just `seq` it and forget about the problem :D)

10:47 llasram: Anderkent: Right, but when you do care, then you just know, or document, or check, or coerce, or whatever else is appropriate to the problem

10:47 sdegutis_: I've had to do it a few times, for example adding a header row to a CSV table.

10:47 Anderkent: llasram: sure.

10:47 sdegutis_: It just happens that I always care about where it's being added to the sequence at.

10:47 clgv: sdegutis_: you can use (list* header data) to be sure what you get ;)

10:48 Anderkent: unless you think you know it's a set so you don't bother checking and then nil comes in

10:48 clgv: works for vectors as well

10:48 sdegutis_: That just sounds so idempotent though.

10:49 pcn: newbie quetion here: is there a typical way to take a config file, e.g. .ini file, and read it with a module, and turn values that contain commas into lists?

10:50 I'm struggling with getting the mapping back from clojure-ini, then checking a subset of keys for values with commas

10:50 `cbp: sdegutis_: I feel like (into [header] table) would be preferable as it's faster and you dont turn it into a seq. Unless the table is a lazy seq then a conj would do the trick

10:50 pcn: then returning the new mapping with lists in their place

10:51 sdegutis_: Could be so.

10:51 May be so.

10:52 pjstadig: ,(clojure.string/split "foo,bar" #",")

10:52 clojurebot: ["foo" "bar"]

10:52 pjstadig: pcn: ^

10:52 if you know a key in a map you want to do that to, then you can use update-in

10:53 ,(update-in {:foo "bar,baz"} [:foo] clojure.string/split #",")

10:53 clojurebot: {:foo ["bar" "baz"]}

10:53 `cbp: pcn: maybe you can try instaparse for parsing config files

10:54 pcn: could be. I think my needs are better served by clojure-ini for now, but when I'm more comfortable in the language, maybe

10:55 `cbp: Oh i didn't realize that library existed

10:58 hhenkel: Is there a way to set the body of a post request with http-kit?

11:07 `cbp: hhenkel: I believe you add a :body key to the options map in http/post

11:08 hhenkel: Also :form-params are part of the body

11:08 (and override it)

11:11 AeroNotix: so, I was thinking that (clojure.data.json/read .... :bigdec boolean) shouldn't just be for decimal numbers, but for all numbers. Right?

11:11 At the moment if the number is decimal... i.e. N.N then it converts

11:13 hhenkel: `cbp: yes, I had that...was missing a slash at the end of the url resulting in a strange behavior.

11:16 ellisd23: Howdy. I'm a pythoner at the moment and I'm looking to fully dive into Clojure after some sporadic dabbling in FP in the past. Does anyone have any good ideas or links to places with good ideas on small side projects I could hack on that would immerse me in Clojure and show me what it's good at?

11:18 wink: ellisd23: I can present you a wildly random assortment of 113 clojure bookmarks, otherwise not so sure I can help https://pinboard.in/u:winks/t:clojure/

11:19 ellisd23: wjlroe, thanks, I'll take a look :-)

11:19 `cbp: ellisd23: clojure is good at concurrency. Maybe you can try making a webapp with a chat using websockets, which is pretty easy in clojure and pretty hard in python

11:20 ellisd23: `cbp, ooh, interesting

11:20 wink: `cbp: I don't think it's that hard with tornado, but then again I never tried

11:21 `cbp: wink: I tried with flask + uwsgi + gevent and man was that hard

11:21 wink: `cbp: hehe ok :)

11:21 I probably would've tried mongrel2 + brubeck first

11:23 ellisd23: `cbp, I guess I don't understand the concurrency aspect. If I had written such a thing in Django, obviously parallel requests can be handled for receiving the chat messages

11:25 pcn: ellisd23: my experience is that twisted (not tornado, however) has a lot of sharp edges, and gets single-cpu limited.

11:25 `cbp: ellisd23: yeah with django you'll have to handle those requests in parallel which means one instance per request which is very limiting.

11:25 pcn: The workarounds suggested are overwhelmingly complex for the beneft derived.

11:25 `cbp: ellisd23: in clojure you just handle them asynchronously with one thread per request or even with callbacks

11:26 pbostrom: ellisd23: perhaps a better example is if the chat app send messages that mutate some shared application state on the server, like user A logs out at the same instant user B sends a message to user A

11:31 `cbp: ellisd23: basically the django implementation wouldn't scale at all

11:33 ontoillogical: How do I properly time a pmap?

11:33 (time (pmap #(+ % % ) (range 10000))) doesn't do what I want it to do

11:35 hyPiRion: wrap it in a doall

11:35 (time (doall (pmap ...)))

11:35 `cbp: or a dorun if you wanna be able to look at the time result :-p

11:36 ontoillogical: oh of course

11:36 thanks!

11:48 benmoss: dnolen_: have you seen http://facebook.github.io/react/blog/2014/01/02/react-chrome-developer-tools.html ?

11:48 works decently well with om it seems

11:50 jonathanj: `cbp: should be easy with Twisted ;)

11:54 technoma`: nothing's easy in twisted =(

11:57 jonathanj: it's an OT conversation for this channel, but i would really love for people who say that (and there do seem to be quite a number) to explain to me where they were tripped up

11:57 dnolen_: benmoss: yes, we should submit a patch so that we can get names in

11:57 technoma`: I had the misfortune of taking over maintenance of a twisted app

11:58 the API for reading public keys as part of the SSH server implementation was pretty much undocumented and didn't make a lot of sense

11:58 dnolen_: benmoss: that said, I think we still want instrumentation that's browser agnostic, I'm pondering how to do this properly for Om.

11:58 technoma`: luckily I didn't have to make many modifications to that codebase, but every single one I made was painful

11:59 dnolen_: benmoss: basically the idea is that any call to om/build could be intercepted

11:59 and you can wrap in an instrumentation component

12:00 sm0ke_: llasram: one quick question, can i do this any better (->> (avro/binary-encoded schema record) (avro/decode schema) type str)

12:01 llasram: so basically i want to know the type of the record, the above is obviosly inefficent

12:06 jonathanj: technoma`: ah, yes, unfortunately people who don't "get" Twisted tend to write a lot of unmaintainable code and then run away

12:06 technoma`: well then when I joined the #twisted channel it was full of people trying their best to convince themselves that async is the only reasonable way to write network servers, and yes, all this pain is totally worth it in the end

12:06 mikerod: Strange, I have a - Caused by: java.lang.ClassFormatError: Invalid method Code length 297606 in class file file/path/name - that *only* occurs with AOT-compilation

12:06 well, technically only when I write class files

12:07 llasram: sm0ke_: Oh, -- you want to know the schema in a union that abracad will select to encode a particular object?

12:07 sm0ke_: llasram: right

12:07 mikerod: I can make this happen in the REPL by doing `(binding [*compile-files* true] (macro-generating-too-much-code))`

12:07 llasram: sm0ke_: I honestly can't think of a clean way to do that off the top of my head... OOC, what's your use-case for it?

12:08 Anderkent: mikerod: but having the macro in a file and then doing (require 'my.ns) doesn't trigger it?

12:08 mikerod: However, when I do not have *compile-files* set, I see no issue with the method size

12:08 Anderkent: weird.

12:08 mikerod: Anderkent: no,

12:08 sm0ke_: llasram: i want to vertically partition the data file location by creating sub folders named by type

12:09 llasram: so given a union of schema i cant read a partiular type by reading files from that subfolder

12:11 sdegutis: technoma`: so it wasn't just me then, they really were doing that

12:11 sm0ke_: llasram: do you think it would be possible to attach type metadata to the encoded record?

12:11 mikerod: Anderkent: I do not get the exception even when calling clojure.core/load

12:12 sm0ke_: llasram: so basically i can encode a record to bytes. take the meta,, then append the bytes

12:12 i dont know if it makes any sense

12:12 llasram: sm0ke_: So I think it'd be better to do this outside of the Avro layer. Having a union schema implies that each given record in the set (e.g. in the file) could be anything in the union

12:12 If you want to partition by type into separate files, then it seems like you should first partition by type, then write each file w/ the schema for that type

12:14 sm0ke_: llasram: yes that too makes sense, but ideally the used should have independence of having a complex schema union

12:14 user*

12:14 mikerod: Well, never mind. load does fail with the same exception, it just doesn't print it out. :)

12:17 llasram: sm0ke_: Well. Hmm. Maybe. Unfortunately I don't have any good ideas right now though :-)

12:17 lpetit: clgv: hello

12:17 clgv: lpetit: hi

12:18 lpetit: clgv: do you use CCW these days?

12:18 `szx: functional thinking question: i'd like to iterate over all pairs in a sequence (using e.g. math.combinatorics) and update the results of the computation on *both* items

12:18 clgv: lpetit: yeah. never stopped to

12:18 sm0ke_: llasram: thats ok, the use case is peculiar i see

12:19 clgv: lpetit: 8-10 hours a day 5 days a week ;)

12:19 lpetit: clgv: so I have a question for you. Would you have objections to have Ctrl-Alt-S always start in debug mode instead of run mode ?

12:19 clgv: wow :-)

12:19 clgv: lpetit: well I can rebind the keys, right?

12:20 sm0ke_: anyways i think the extra ser/de step is little cost to pay for partitioned data

12:20 clgv: lpetit: debug mode. you mean eclipse's debug launcher?

12:20 lpetit: clgv: yes, the question is about that, not about the exact key binding

12:22 clgv: lpetit: what would be the implications? eclipse asking me at least once to switch perspective and working breakpoints as default

12:22 lpetit: clgv: currently, when you're in a file, and you type ctrl-alt-c (or whatever you've rebound it to), you get (if no repl is active) : 1/ start in background, in "run launcher mode", of a java process for the project ; 2/ open a REPL View ; 3/ send the editor's code to the REPL ; 4/ switch the REPL's current ns to the editor's ns ; 5/ give focus to the REPL View. Right ?

12:23 clgv: yeah.

12:23 lpetit: clgv: hmmm, I think it depends on the exact settings. In my current configuration (but maybe not the default, maybe I've tweaked it, don't remember), it only tries to switch if code with breakpoints is hit.

12:24 yeah, working breakpoints as a default, that would be

12:24 so that the easiest think to do is also the more powerful one

12:24 clgv: well, if there are no disturbing effects I have no objections.

12:25 but I hardly use breakpoints. when I started with clojure I used them pretty often but that decreased

12:25 lpetit: clgv: I've managed to get this exact workflow work for leiningen projects, with the difference that it's leiningen which manages the start of the project VM.

12:25 clgv: lpetit: great.

12:26 lpetit: so all the leiningen magic will work?

12:26 lpetit: clgv: you may be annoyed by old breakpoints you had set going to life, with the new settings.

12:26 clgv: lpetit: well that'll happen only once

12:26 sdegutis: lazybot died

12:27 lpetit: clgv: yes, all leiningen magic. So for instance :injections taken into account

12:27 clgv: lpetit: then I could finally fix the missing `doc` and `source` by leiningen configuration ;)

12:27 lpetit: clgv: indeed

12:28 I guess so, what would you do for that in leiningen, exactly?

12:30 clgv: lpetit: I guess I'd try vinyasa to map them into clojure.core (https://github.com/zcaudate/vinyasa)

12:31 lpetit: the simple answer is to just require clojure.repl after a namespace is loaded

12:32 lvh: hi

12:33 I'm looking desperately for a github project I found recently that used clojure and clojurescript; it composed three major projects. The last was definitely om (the react wrapper), I think the first was compojure, and the other one was datomic

12:33 clgv: lpetit: the simple solution is probably :injections as I checked

12:33 bbloom: lvh: was it dnolen's om-sync ?

12:34 lvh: dacom!

12:34 bbloom: nope: https://github.com/bellkev/dacom

12:34 bbloom: lvh: ah ok, b/c i thought david had an *example* in the om or om-sync wiki with all 3 of those

12:34 lvh: I thought it was codam but google kept thinking I wanted "condom"...

12:34 oh, awesome

12:34 lpetit: clgv: :injections will just send some code for evaluation when the repl server starts

12:36 clgv: lpetit: huh? as I read in the past it is prepended to every evaluation

12:36 lpetit: I wouldn't bet on it, but I may be wrong

12:36 clgv: lpetit: https://github.com/technomancy/leiningen/blob/stable/sample.project.clj#L209

12:37 technomancy: yes, it's for every eval-in-project call

12:37 clgv: oh. so only once per repl?

12:37 technomancy: typically that's when the JVM starts, but for eval-in :nrepl it will happen for processes that have been running for a while

12:38 no, it can happen repeatedly

12:38 depending on how eval-in-project is called

12:38 sandbags: anyone aware of a library equivalent to the Ruby RVG library ("RVG (Ruby Vector Graphics) is a facade for RMagick's Draw class that supplies a drawing API based on the Scalable Vector Graphics W3C recommendation.")?

12:39 google isn't turning anything useful up

12:39 lpetit: clgv: well, I'm not sure :injections works with lein repl :headless at all (either on command line or via ccw)

12:39 sandbags: ah found something tikkba

12:40 sorry for the noise

12:40 clgv: lpetit: I had no chance to try it in CCW so far ;)

12:40 `cbp: sandbags: it's not noise

12:41 sandbags: there's also analemma

12:41 lpetit: clgv: i guess if :injections does not work with repl :headless, we should try to fix it at the heart, in leiningen itself. Probably by doing some kind of middleware which would always prepend code received via nrepl connections for evaluation ...

12:42 sandbags: `cbp: yeah i was just looking at that one too

12:42 `cbp: i'm looking to dynamically generate an image from a logo and some text obtained via a REST API call

12:42 lpetit: That way, this would work the same either via "lein repl" (and the embedded repl client) and "lein repl :headless"

12:43 clgv: lpetit: well repl-y fixes the clojure.repl issue at the frontend

12:44 lpetit: at *one* front-end, the command-line one. And only for Linux/OS X I guess.

12:44 TEttinger: sandbags, there's even AWT for that if you wanted to do it with no dependencies

12:45 sandbags: TEttinger: i'm looking to output as a PNG

12:45 TEttinger: right, I use AWT for that

12:45 sandbags: it's been ~14 years since i used AWT

12:45 TEttinger: heh

12:45 sandbags: oh, right

12:45 things change :)

12:45 does AWT work headless?

12:45 clgv: lpetit: yeah ok. that's true it is only that frontend...

12:46 sandbags: i'll be doing this on an EC2 instance running probably debian

12:46 TEttinger: I actually have no idea, I have it running as a console app, but it might need some kind of graphics capability

12:49 I wrote this a long time ago and have been tweaking it continually for different fonts I need rendered https://dl.dropboxusercontent.com/u/11914692/mess.clj

12:50 sandbags: thanks TEttinger

12:52 TEttinger: sandbags, I uh wouldn't try running it as-is, but the general method should be clear enough of how to interact with AWT from clojure. if you do want to run it, it expects https://dl.dropboxusercontent.com/u/11914692/unicode.txt in the same dir... and a bunch of undocumented command line args

12:53 sandbags: heh, yeah i was just looking at it as source material :)

12:57 sdegutis: Jim Weirich's last commit, plus comments: https://github.com/jimweirich/wyriki/commit/d28fac7f18aeacb00d8ad3460a0a5a901617c2d4 -- I'm surprised nobody's commented "He's dead, Jim."

12:57 A little longer and he would have gotten into Clojure probably. All the Rubyists are doing it.

12:57 technomancy: he gave a talk on clojure at strange loop

12:57 sandbags: i believe he said he was dabbling

12:57 technomancy: it was awesome

12:58 well, a talk on the Y combinator, given in Clojure and Emacs

12:58 sdegutis: Although I guess it would be disrespectful to say "He's dead, Jim."

12:59 pcn: you think?

12:59 sdegutis: I'm starting to think so.

12:59 pcn: Yeah. I kind of hope no-one does that

12:59 llasram: sdegutis: And how are you enjoying your visit to our planet? ;-)

13:00 sdegutis: It's okay so far. Missing the context free grammar back home.

13:01 I like your "soda pop" though.

13:01 `cbp: first concat instead of conj now this

13:01 you done gone insane

13:01 sdegutis: Oh sorry, is it just "pop"? I thought that was slang for "punch".

13:05 It's possible Jim isn't really dead.

13:06 He hasn't tweeted or committed recently, but the only news that he's passed is that someone said RIP on his github commit.

13:06 Hope this isn't a prank.

13:07 kitallis: really?

13:07 sdegutis: More likely I'm probably just in denial.

13:07 First stage of grieving and all that.

13:10 Also I avoid dynamic vars like the plague. Is this healthy?

13:10 technomancy: yes

13:10 sdegutis: I'm tempted to use one right now, to toggle whether you're an admin previewing the site, or just a normal user.

13:10 technomancy: that's what they said about the black death too

13:11 "it's just a few rats; what's the worst that could happen?"

13:11 sdegutis: The alternative is changing API functions to take another argument (:preview?), or possibly duplicating page code to render under a new URL or something.

13:11 technomancy: ps. don't listen to me

13:11 sdegutis: Why not?

13:11 technomancy: because I lie a lot

13:12 sdegutis: Wait... is that.. is that a lie?

13:13 technomancy: seriously though, I think it's a matter of dividing code into the functional core and imperative shell. things that would be terrible in library code might be acceptable when used at the "outside" of the codebase

13:13 sdegutis: (trptcolin: was Jim Weirich the one who showed up at our 8LU in LVille a few years ago? Or was that someone else?)

13:13 technomancy: because as long as the core is functional, and the shell is small enough, you can fit everything you need to know into your head at once.

13:13 sdegutis: technomancy: hmm, now that you mention it, that sounds like a familiar paradigm

13:14 Like, as long as the dynamic var never strays into the core, then it's okay.

13:14 technomancy: dynamic vars add complexity overhead. as long as they don't blow your complexity budget, they can be a reasonable trade-off if you know their scope won't be too broad

13:14 sdegutis: Except in this case, that's exactly what it'd be doing. Which makes me noivous.

13:14 technomancy: pretty much, yeah

13:14 trptcolin: sdegutis: i don't remember seeing him here, but met him at a few confs around here. such a nice person.

13:14 sdegutis: Hmm. Now I wonder who that guy was. I think he was a Jim. He wrote a book, and I think he gave us a mug.

13:15 technomancy: yeah, Jim was one of the friendliest and most welcoming programmers I knew

13:15 the Emacs Starter Kit was actually his idea that I ran with

13:15 sdegutis: So it was *you*!!

13:15 trptcolin: sdegutis: oh, you're thinking of james grenning i believe

13:15 sdegutis: Ah yes.

13:16 Too many Jims.

13:16 Er, I mean, Jim names. Not too many people.

13:17 * sdegutis can't dig himself out of this hole

13:17 zerowidth: sdegutis: evan phoenix said he had confirmation from several sources before tweeting about it

13:17 sdegutis: :/

13:19 `cbp: Dynamic vars are bad! They make me afraid of putting things on other threads

13:19 sdegutis: Hmm, that's an interesting consideration.

13:20 You'd have to be sure to read it first and pass it to the other thread if anything.

13:20 technomancy: in your core you need to write code that works in any threading context. in your shell, you can usually know what threading context a given defn will be used in.

13:21 sdegutis: So let's say you have a webapp (in this context, is it "let's

13:21 " or "lets"?)

13:22 technomancy: let us

13:22 sdegutis: In this case, we can only assume each request runs in its own thread (might not be true, but safest assumption).

13:23 So the only time you'd want to do other threading is when you're explicitly doing background work. At which case you're ideally spinning up the thread at the high-level of the request, not low-down into whatever the request handler is doing.

13:23 Hmm, in that case, dynamic vars seem perfect! Because you'd statically know which core functions are on what thread.

13:34 * technomancy nods

13:34 technomancy: oh, plus you have laziness to consider

13:34 but typically at the outside you have all you need to make an informed choice

13:35 sdegutis: Thanks all.

13:38 sandbags: definitely liking gorilla repl

13:41 sdegutis: Mostly for graphs/charts, right?

13:46 sandbags: well as a playtime repl it's also pretty nice

13:46 technomancy: dammit

13:46 sandbags: but the USP's are the Markdown/Latex note support

13:46 technomancy: I was gonna do portable rich-content repls as my clojure/west talk

13:46 sandbags: save/load session

13:47 i'm hoping adding MathML isn't too hard as it's been ~20 years since i did any Latex

13:47 technomancy: now people are going to keep going off and implementing this stuff in editor-specific ways, aren't they

13:47 sandbags: not sure what that talk doesn't still fly

13:48 llasram: technomancy: Until you stop them / show them how its done!

13:48 technomancy: llasram: but I'm not even using clojure any more =P

13:48 I don't want to write a bunch of code just to stop people from doing something I think is wrong-headed

13:48 but if people keep pulling this stuff I might have to

13:49 bbloom: technomancy: surely if your yak shaving powers are insufficient, we must call cemerick

13:49 technomancy: or abandon all hope

13:49 technomancy: bbloom: already in the middle of a massive yak shave, sorry

13:49 bbloom: mmmm yak fur

13:49 technomancy: https://secure.flickr.com/photos/technomancy/12642312163/

13:50 michaniskin: that's the best time to get involved with more yak shaves though!

13:50 bbloom: technomancy: are you seriously going to make your own keyboard?

13:50 michaniskin: the Inception Shave is how it's done, didn't you know?

13:50 bbloom: technomancy: that's pretty hardcore.

13:50 technomancy: bbloom: just waiting for the microcontroller to arrive in the mail

13:50 sdegutis: technomancy: not using clojure anymore, hmm? do you still maintain lein?

13:51 technomancy: sdegutis: here and there

13:51 bbloom: technomancy: i bow at the feet of your yak blade

13:51 TimMc: I don't understand Flickr anymore.

13:51 bbloom: technomancy: i'm clicking through more photos. is this a mini keyboard for you kid?

13:51 technomancy: bbloom: no, he's just modelling it

13:52 bbloom: technomancy: ah ok

13:52 i like the big green buttons :-P

13:52 technomancy: I wouldn't go otaku for my kids =)

13:52 (no labels, I mean)

13:52 not till they're at least ten anyway

13:52 bbloom: haha

13:52 that coffee shop looks familiar...

13:52 * bbloom stalks

13:52 bbloom: ok i'm done :-P

13:54 TravisD: technomancy: Is there some underlying idea behind those cool looking keyboards?

13:54 Like, a reason you made them, instead of using what's available

13:55 technomancy: TravisD: a few main things

13:55 0) mechanical switches have a really crisp feel to them that make me happy

13:56 1) most keyboards are staggered by row, which comes from trying to avoid typewriter jams. I like mine staggered by column, because I'm a human with fingers of different lengths.

13:56 2) having an on-board microcontroller with firmware you can reprogram on the fly is awesome

13:56 TravisD: hehe, cool :) How many have you made?

13:56 Seems like something that would take some practice

13:56 turbofail: i prefer to enforce a uniform finger length

13:56 technomancy: TravisD: I've assembled one from a kit, which I posted about here: http://technomancy.us/172

13:57 bbloom: i use a kenesis contoured for reasons #0 and #1, but RE: #2 it has a microcontroller for programming which i haven't used since the day i got it and remapped caps lock to control

13:57 technomancy: TravisD: and I'm in the middle of building one from scratch: https://github.com/technomancy/atreus

13:57 bbloom: does it support unshifted parens? that's one of my favourite tricks

13:57 TimMc: turbofail: I know someone who doesn't trim his pinky nails because that gives him better reach...

13:58 TravisD: technomancy: cool, thanks :)

13:58 bbloom: technomancy: i assume i could make it do that somehow, but my brain already has a hard enough time going back to my laptop keyboard & i don't wanna have to drag around a keyboard to coffee shops like *cough* some folks

13:58 amalloy: that's why you'll never be cool, bbloom

13:58 * bbloom hangs head in shame

13:58 technomancy: bbloom: yeah, that's actually why I don't have a kinesis

13:59 even the ergodox is a bit of a beast to drag to coffee shops, that's why I started working on my own

13:59 turbofail: TimMc: ha. i was envisioning something a little more violent.

13:59 bbloom: technomancy: when you're finished with that yak, you should totally shave a whole flock (herd? what do you call multiple yaks?)

14:00 technomancy: by that, i mean, you should totally make a tri-component laptop where the display separates from the two halves of the keyboard

14:00 how hard could it be really?

14:00 if you don't do it, amalloy won't think you're cool

14:01 technomancy: bbloom: I'm definitely going to be keeping copious notes in case anyone else wants to build one

14:01 the ergodox runs $240 if you get in on a group-buy with volume discounts; mine can be made for about $100 plus shipping

14:01 I mean, assuming I get it working

14:01 bbloom: heh

14:02 benkay: any Listora folks in the room?

14:06 dnolen_: Om 0.5.0 going out, support React 0.9.0

14:06 supports

14:09 TEttinger: bbloom, oh man.

14:10 fredyr: dnolen_: oh, does support means require 0.9.0?

14:10 bbloom: TEttinger: ?

14:10 dnolen_: fredyr: yes

14:10 fredyr: dnolen_: that might explain what im seeing right now then

14:10 dnolen_: :)

14:11 dnolen_: fredyr: I've updated all the docs / tutorials etc. Feel free to fix up anything I may have missed.

14:11 fredyr: or if it's actually in the Om repo, point it out.

14:11 fredyr: dnolen_: sure, but this was on my part

14:12 dnolen_: did update cljs version and om, but missed the new react version

14:12 dnolen_: will def let you know if i find anything

14:12 dnolen_: fredyr: cool thx

14:12 TEttinger: bbloom, the old dell axims came with external keyboards that unfolded kinda like that http://i.ebayimg.com/00/s/MTIwMFgxNjAw/z/60oAAMXQyfFSA7Bp/$(KGrHqN,!k8FH6eRO)GKBS!7Bont0Q~~60_1.JPG?set_id=8800005007

14:13 bbloom: TEttinger: ha! i remember playing with something like that once, crazy

14:13 TEttinger: it had a good motion too

14:14 it would unfold into a shape like http://g-ecx.images-amazon.com/images/G/01/ciu/1f/88/ade9c060ada0c18b51a20210.L.jpg

14:28 sdegutis: I can't help but think that macros complicate things too much for too little gain.

14:29 AimHere: Writing macros is complicated and painful. Once they're properly wrote, they make your life easier

14:30 sdegutis: Still.

14:33 AimHere: Besides, the solution if you're having that very problem is don't use macros

14:33 fredyr: dnolen_: i'm getting a mysterious error with build-all when trying to upgrade to 0.5.0

14:34 dnolen_: my component function never gets called, but i get a couple of numbers in the dom

14:34 amalloy: AimHere: if you find writing macros complicated and painful, you're either writing macros that are too complex, or you don't have enough practice writing them

14:34 dnolen_: fredyr: did you make the necessary changes outlined in 0.5.0-rc1?

14:36 muhoo: technomancy: did you abandon the keyboard pants?

14:36 technomancy: muhoo: basically they were too much work to get in and out of when I needed to use the loo

14:37 `cbp: the keyboard pants?

14:37 im dying

14:37 sdegutis: :'(

14:37 oops typo i meant :)

14:38 amalloy: `cbp: http://www.flickr.com/photos/technomancy/4397554484/

14:39 `cbp: hah

14:39 technomancy: muhoo: I do plan on creating a mount for my keyboard that hangs below the surface of my desk and lets me type in a more neutral position

14:39 amalloy: this was back around the time of the first conj, i think?

14:39 fredyr: dnolen_: where do i find those?

14:39 technomancy: kind of a compromise between keyboard pants and the conventional position

14:39 dnolen_: fredyr: CHANGES.md

14:39 amalloy: technomancy: +100 to that idea, by the way - i've done that at my last two jobs

14:40 dnolen_: fredyr: also the React blog

14:40 technomancy: amalloy: cool

14:40 I'm hoping to build something with tenting

14:40 amalloy: eh?

14:40 muhoo: .... tenting?.... o_O

14:41 technomancy: amalloy: so my hands don't have to lay out flat

14:41 kinda like this http://www.thehumansolution.com/kinesis-ascent-multi-tent-accessory-kit.html

14:41 but hanging below the surface of the desk

14:42 amalloy: ninjudd had one of those

14:42 fredyr: dnolen_: right, i saw that, but i don't see them breaking anything w/ build-all, right?

14:42 amalloy: before he discovered the kinesis, i guess

14:42 dnolen_: fredyr: hard to say, I haven't encountered any issues with build-all

14:42 fredyr: I have examples that use it and I test against Om TodoMVC

14:43 which also uses it

14:43 fredyr: dnolen_: yeah, its probably something ive done

14:44 dnolen_: it works if i swap it for build f (first entries)

14:50 dnolen_: it seems to have something to do with mapping over the cursor

14:51 dnolen_: i got it to work with a manual (mapv (fn [x] (om/build entry-component x)) entries)

14:51 dnolen_: but using map gave the same error

14:53 amalloy: ~map

14:53 clojurebot: map is hard

14:53 dnolen_: fredyr: you should be able to find your problem with source maps.

14:53 amalloy: well, i was going for "map is LAZY", but close enough

14:53 dnolen_: fredyr: I see no reason for mapv to work over map

14:54 fredyr: dnolen_: hmm ok, thanks i'll try to dig into it

14:56 TravisD: For a datatype T, are T. and ->T identical functions?

14:57 amalloy: TravisD: no, because T. isn't a function

14:57 TravisD: ah

14:59 amalloy: I'm just looking at the documentation. Is it a reader macro for (new T ...), which is a special form?

14:59 maybe not a reader-macro.

15:00 llasram: TravisD: I don't think there's an official name. I call them "pseudo-macros"

15:01 They're expanded by the compiler during macro-expansion

15:02 bbloom: llasram: it's a reader macro. clojure offers several types of (non-extensible!) reader macros

15:03 llasram: bbloom: No, I don't think so

15:03 ,`(Example.)

15:03 clojurebot: (Example.)

15:03 llasram: ,`(.example again)

15:03 clojurebot: (.example sandbox/again)

15:03 llasram: Compiler, not reader

15:03 bbloom: llasram: good point

15:03 llasram: ok then, it's a compiler-macro :-)

15:04 TravisD: I don't know much about macros, but can one macro create new macros? Then it might make sense that defrecord introduces the DataType. macro

15:04 llasram: But at least does happen as part of macro-expansion

15:04 ,(macroexpand `(Example.))

15:04 clojurebot: (new Example)

15:04 llasram: ,(macroexpand `(.example here))

15:04 clojurebot: (. sandbox/here example)

15:04 TravisD: oh weird, so it actually works even for things that aren't datatypes

15:04 like, arbitrary symbols

15:05 bbloom: llasram: ok then, it's a compiler-macro :-)

15:05 llasram: TravisD: Yeah `Symbol.` and `.symbol` are magic "compiler-macro" syntax

15:05 (as we will now call them)

15:05 TravisD: that's a bit sad :(

15:06 llasram: It is an odd complication, but the result is convenient

15:06 TravisD: yeah, true

15:07 I guess it's not really any different from special forms

15:08 like, the compiler already has a few special cases. It's not /so/ strange to add a whole family of special cases, if they're convenient

15:12 bbloom: syntax is inherently special cases

15:12 that's what syntax is

15:12 clojure decided that syntax should be minimal, but the correct amount is slightly more than scheme

15:12 seems reasonable to me :-P

15:13 pjstadig: "slightly more"?

15:14 bbloom: pjstadig: scheme has strings with escape sequences and the cons dot notation, and numbers, ratios, etc

15:14 pjstadig: what did clojure add? a few extra sets of matching braces, repurposed dot, and the deref @ operator?

15:14 pjstadig: yeah, slightly more :-P

15:14 pjstadig: do you consider destructuring as syntax?

15:15 bbloom: yes, but now you're getting in to the question of where does syntax live

15:15 i consider any function that takes position arguments to be syntax :-P

15:16 pjstadig: well i mean i'm not necessarily disagreeing with you

15:16 i wouldn't say there's "buttloads more" syntax in clojure

15:16 but i might go a smidge higher than slightly more

15:17 bbloom: *shrug* pick a word

15:17 pjstadig: haha

15:17 i define my word to be semantically not whatever your word is :-p

15:18 dnolen_: pjstadig: well, modern Scheme has a lot a syntax now I would say, it's been ~16 years since you could say Scheme was truly minimal syntax wise.

15:26 maglop: Hi; I'm looking to preprocess a file line by line with lazy-seq before I pass it on to enlive. I don't see a way to get a Reader or InputStream interface to a seq, though. Am I approaching this badly?

15:30 Wild_Cat: maglop: line-seq, maybe?

15:32 maglop: That gets me the first part, but then I need to somehow get back to exposing that as bytes as a Reader

15:33 rhg135: any thoughts https://bitbucket.org/rhg135/gutter

15:33 Wild_Cat: maglop: so you need something that takes a Reader and transforms it to another Reader that returns a lazy seq of the first Reader's lines?

15:34 rhg135: it isn't too bad?

15:34 Wild_Cat: maglop: isn't that the definition of the BufferedReader interface?

15:35 maglop: Wild_Cat: maybe? I will be changing the data on the way, though

15:35 benmoss: rhg135: you know about enliven?

15:35 enlive rather

15:35 rhg135: yup

15:35 i've used it too

15:36 had some crazy idea jsou was faster

15:36 maglop: Takes a Reader, modifies the data on a line by line basis, and then exposes the modified data as a Reader

15:38 sdegutis_: Clojure has 0% syntax.

15:38 Absolutely none.

15:38 rhg135: nah

15:38 more like %3

15:39 well it depends

15:39 it isn't necessary to lear but its nice

15:50 sdegutis_: Okay, let's compromise and say it's about 80% syntax.

15:51 But that the 20% that's semantics happens to be really super consistent.

15:53 amalloy: except nth

15:53 that is super inconsistent

15:54 rhg135: how is nth inconsistent?

15:54 amalloy: it's the only sequence function that takes the collection as its first arg

15:55 (nth coll n), (take n coll), (map f coll)

15:56 dkinzer: yeah, but it's consistent with it's origin in scheme. http://hyperpolyglot.org/lisp

15:56 amalloy: it's also one of very few functions that will be either O(1) or O(n) depending on what you pass it

15:56 dkinzer: yes, i'm aware of why we have this function; that doesn't make it consistent with clojure

15:56 dkinzer: historical consistency sometimes trumps other stuff.

15:56 amalloy: dkinzer: well, send a pull request replacing first/rest with car/cdr

15:56 dkinzer: amalloy: true.

15:57 :)

16:00 though racket uses both (car, first) and (cdr, rest).. but maybe racket is not really scheme.

16:03 technomancy: butlast having no hyphen =\

16:03 joegallo: ugh, yes

16:03 technomancy: you know: real, hard-hitting issues

16:06 amalloy: i dunno, i'm okay with butlast's name. but-last isn't really better, because there's no...verb? that sounds silly, but mashing an adjective together with a modifier feels better to me than doing it with a verb

16:08 sveri1: hi, i am trying to login with the friends library and i use this code: http://pastebin.com/ajnhffa4 However, everytime i submit my form i get a 404 error back saying the resource was not found, any ideas what I am missing here?

16:08 amalloy: the fact that butlast isn't lazy and drop-last is...*that* bothers me

16:08 technomancy: yeah, know that I think about it the "you use a hyphen for identifiers containing two words" comes from CL, not clojure

16:08 *now

16:08 sdegutis_: amalloy: it returns a single element though, not a whole coll

16:08 amalloy: sdegutis_: not true at all

16:08 sdegutis_: oh

16:08 amalloy: please disconfuse me

16:09 ,(nth [1 2 3] 1)

16:09 clojurebot: 2

16:09 amalloy: &(butlast [1 2 3 4])

16:09 oh, you're talking about forever ago

16:09 sdegutis_: yep, im always behind the times

16:09 amalloy: wait what? 2?

16:09 sdegutis_: 0-based

16:09 amalloy: oh, that was clojurebot. lazybot is ignoring me

16:09 sdegutis_: lazybot is dead

16:09 dkinzer: not so weird also when you consider that most of the core operators don't have hyphens.

16:09 amalloy: i thought 2 was the answer to (butlast [1 2 3 4]) and i was going to change careers

16:10 sdegutis_: i mean, missing

16:10 amalloy: wow, what kind of trauma have you been going through that such a small discontinuity is the straw that killed the camel with two stones?

16:11 amalloy: lazybot, i summon thee!

16:11 dkinzer: ,(butlast [1 2 3 4])

16:11 clojurebot: (1 2 3)

16:11 sdegutis_: WHOA.

16:11 that was cool

16:11 amalloy: *chuckle*

16:11 TravisD: amalloy: Convenient timing? Or does it somehow monitor the channel through the other bots?

16:12 amalloy: i just restarted him

16:12 &1

16:12 lazybot: ⇒ 1

16:12 technomancy: how about this: assoc works on vectors, but not dissoc

16:14 sdegutis_: I followed the mailing list thread about that. That's about the time I started realizing maybe Clojure isn't going in the best direction.

16:14 &()

16:14 lazybot: ⇒ ()

16:14 sdegutis_: That too.

16:15 Every time you see an unquoted set of parentheses, it's a function call. Except when they're empty, then it's a literal list.

16:15 ,(= () '())

16:15 clojurebot: true

16:15 sdegutis_: Oh man. That's totally a nerdy robot emoticon!

16:17 devn: sdegutis_: I have Leah Hanson's ear on Romeo. I think she's going to stop by sometime this week and give me some guidance.

16:17 She's working on the type checker.

16:17 mklappstuhl_: whats an idiomatic way to check if a "stringA" starts with "str" ?

16:17 technomancy: sdegutis_: also in letfn, proxy, and reify, paren sets don't indicate function calls but definitions

16:18 sdegutis_: devn: sweet

16:18 devn: mklappstuhl_: you could use java

16:18 ,(.startsWith "abc" "a")

16:18 clojurebot: true

16:18 technomancy: (and maybe a few other hosty macros)

16:18 amalloy: also deftype and defrecord, which technomancy prefers to believe don't exist

16:18 sdegutis_: technomancy: I totally agree: out of all languages, Clojure is probably the most consistent.

16:18 devn: ,(re-find #"^a" "abc")

16:18 clojurebot: "a"

16:18 llasram: mklappstuhl_: ##(.startsWith "stringA" "str")

16:18 lazybot: ⇒ true

16:18 bbloom: +1 for the re- approach

16:18 technomancy: amalloy: la la la can't hear you

16:18 amalloy: and sometimes in fn/defn: (fn ([x] x) ([x y] (+ x y)))

16:19 llasram: Huh, I thought that went to lazybot

16:19 devn: ,I like using re-* personaly

16:19 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: I in this context, compiling:(NO_SOURCE_PATH:0:0)>

16:19 llasram: ,(.startsWith "stringA" "str")

16:19 clojurebot: true

16:19 devn: personally

16:19 llasram: Whoa, I was lagged

16:19 devn: llasram: no worries :)

16:19 technomancy: sdegutis_: "all languages" being "th eset of languages you can get paid to work in"?

16:19 devn: heh

16:19 sdegutis_: technomancy denies deftype? But.. how else do you define functions in Clojure programs?

16:20 technomancy: No, all languages.

16:20 I've never seen or heard of a more consistent language than Clojure.

16:20 dkinzer: The empty parentheses one is totally weird.

16:20 sdegutis_: Prove me wrong please. I really want to be wrong.

16:20 technomancy: sdegutis_: have you learned forth?

16:21 sdegutis_: dkinzer: I'm very grateful to find someone who agrees with me on this; last time I brought it up, I got a lot of "nah that's totally consistent and expected and good and normal"

16:21 technomancy: That toy language?

16:21 devn: does anyone here have any opinions on postgres-friendly sql abstractions in clojure beyond jdbc, something that's a bit more "i don't know SQL but have used ActiveRecord" friendly? How about one that /isn't/ korma?

16:21 sdegutis_: technomancy: Can you write *actual programs* in it?

16:21 That do, like, useful things?

16:21 I thought it was an esolang.

16:21 technomancy: actually kind of tempted to write my keyboard firmware in forth

16:21 sdegutis_: !

16:22 devn: my god technomancy, you are a bad ass.

16:22 dkinzer: sdegutis_: nah, I agree with you; it doesn't make any sense. It's supposed to be an empty set so why not just return the something with the set syntax?

16:22 technomancy: devn: well I haven't *done* it

16:22 devn: you will have forth-powered, laptop pants

16:22 err keyboard pants

16:22 technomancy: I wimped out and ordered an AVR microcontroller instead so it could run one of the existing firmwares

16:22 sdegutis_: technomancy: no, he's right actually; I've never met anyone who talked about writing firmware; that's pretty hard core

16:23 technomancy: but I specifically bought this ARM-based one because I wanted to run a forth or scheme on it

16:23 sdegutis_: you should hang out in #geekhack

16:23 devn: technomancy: omg they have a freenode channel?!

16:23 sdegutis_: Nope. I don't want to *always* feel like I'm writing in QBasic while everyone around me is inventing anti-gravity force fields.

16:23 devn: geekhack is a fantastic community

16:24 sdegutis_: Just once in a while :)

16:24 technomancy: devn: except for the caveat of "uses php-based forum software non-ironically" I agree =)

16:24 devn: :) It gets the job done. *shrug*

16:24 sdegutis: oh man, i wrote a phpbb competitor once in.. php

16:25 devn: So, one more attempt: Do you guys have a suggestion on a SQL abstraction lib that isn't Korma and provides a semi-friendly interface to postgres?

16:25 sdegutis: Is Datomic an option?

16:25 devn: I've used jdbc, but I'm going to be leveling someone up and want to ease him in.

16:26 sdegutis: unfortunately no.

16:26 sdegutis: Sorry.

16:29 xuser: devn: java.jdbc has a minimal DSL I think

16:29 mklappstuhl_: I'm surprised how how hard some simple things in clojure can be sometimes. I want to filter a list of strings based on an input string. It's fairly trivial using .startsWith but using re-find it becomes quite a bit more complex

16:31 sdegutis: mklappstuhl_: the Clojure philosophy is to use the platform when it's more convenient I think

16:32 mklappstuhl_: I've used #(.startsWith %) with filter I think

16:32 technomancy: mklappstuhl_: oh man, that reminds me of another of my gripes

16:32 if regexes were ifn this would be easy

16:32 you probably just want partial re-find though

16:32 BobSchack: devn https://github.com/krisajenkins/yesql if you're not looking an ORM.

16:32 ToBeReplaced: how do i type-hint ProcessBuilder to avoid reflection?

16:32 sdegutis: technomancy: isn't %() preferred over partial btw?

16:34 mklappstuhl_: sdegutis, issue with platform is, that it varies from platform to platform :D

16:34 technomancy: sdegutis: not by me =P

16:35 dkinzer: ,[(identical? '() ()) (identical? '() []) (= '() []) (= '() #{})]

16:35 clojurebot: [true false true false]

16:35 sdegutis: mklappstuhl_: there's only one platform, Java. don't let anyone tell you otherwise!

16:35 * sdegutis puts a curtain over CLR and JS

16:37 mklappstuhl_: sdegutis, I'm actually using cljs right now ;D

16:37 amalloy: &(identical? () (list))

16:37 lazybot: ⇒ true

16:37 sdegutis: mklappstuhl_: nice

16:37 amalloy: *chuckle* if CL did that, the entire macro system would collapse

16:40 whodidthis: any tips on doing multiple channels over a single channel?=(

16:41 ToBeReplaced: whodidthis: mix and mult for n-to-1 and 1-to-n

16:41 sdegutis: So, I heard some people talking about Common Lisp recently. Seems like a good production read Lisp. What do you all think?

16:41 *ready

16:42 technomancy: "production" is a funny word

16:42 what are you producing?

16:42 HTTP responses, I guess?

16:42 it makes me think of factory assembly lines

16:43 ToBeReplaced: I'm looking for a way to invoke (ProcessBuilder. (into-array ["echo" "hi"])) without causing reflection -- any recommendations? afaik i can't type-hint the complex type

16:43 sdegutis: You know, Production.

16:43 Like, where the code goes when I deploy to the nodes.

16:44 amalloy: ToBeReplaced: ^"[Ljava.lang.String"

16:44 sdegutis: The thing that executes "ENV=production sudo rake server:start".

16:44 technomancy: ToBeReplaced: I don't think it's possible for reflection to be a bottleneck when launching processes FWIW

16:44 amalloy: errrr, might need to be ^"[Ljava.lang.String;"

16:44 &(class (into-array ["x"]))

16:44 lazybot: ⇒ [Ljava.lang.String;

16:45 amalloy: well, that's true too. but maybe you want to be able to `lein check` and not get any warnings

16:45 ToBeReplaced: amalloy: correct, thanks, didn't know i could put quotes around it

16:45 technomancy: you're right, it's not a bottleneck -- it was ugly with lein check and it's an easy standard to hold people to

16:46 technomancy: ah, sure

17:06 akurilin: Anybody here using Migratus? I'm wondering if multiple statements in a migration all get wrapped into one single transaction. I'm looking at the source and it seems to be the case, but I just wanted a sanity check: https://github.com/pjstadig/migratus/blob/master/src/migratus/database.clj#L43

17:16 bitemyapp: technomancy: :env/blah keywords in Leiningen defproject, how do I "or"?

17:18 technomancy: bitemyapp: hrm... I think you might need unquote or read-eval for that

17:18 bitemyapp: you know what, n/m, it's only for GPG stuff I guess.

17:18 we're not using it for that, we just wanted a fallback for something nicer than ~

17:18 but we'll stick with ~ for now then

17:18 technomancy: thanks, reading the source answered my question, sorry to bother you :(

17:19 technomancy: cheers

17:19 technomancy: no worries

17:23 `szx: is there a nicer way to do a commutative memoize than combining all the arguments into e.g. one set?

17:24 e.g. https://www.refheap.com/43097

17:24 ordnungswidrig: technomancy: are there known issues with with-profile, clojure-version-deps and test?

17:25 amalloy: well, a set won't work at all

17:25 technomancy: ordnungswidrig: what's clojure-version-deps?

17:25 amalloy: since (add 1 1 1 1)

17:25 you almost need like a frequency map, if you really don't care at all about parameter order

17:26 `szx: yeah, bad example - they are unique in my case

17:26 ordnungswidrig: technomancy: i try to vary the dependency on the clojure version in profiles for testing

17:27 `szx: amalloy: i guess = would be a better example than + in this case

17:27 ordnungswidrig: technomancy: like in http://technomancy.us/158

17:29 technomancy: ordnungswidrig: I don't know of any issues around that

17:30 ordnungswidrig: technomancy: I end up with this: https://www.refheap.com/43098

17:46 technomancy: ordnungswidrig: I don't think that has anything to do with Leiningen

17:48 ordnungswidrig: technomancy: lein test works, lein with-profile dev,1.5 test fails with the above error.

17:49 technomancy: sure

17:49 because your code calls contains? on a lazy seq

17:49 older versions of clojure fail silently on that

17:50 FSVO "your"

17:58 ordnungswidrig1: technomancy: oh dear, you're right. the default I defined is 1.4, not 1.5. thanks a lot!

17:59 technomancy: no problem

18:10 tjd: is there a builtin function f such that (f g x) == (g x)?

18:11 joegallo: like, (invoke inc 1) == (inc 1) ;; (not that invoke exists, just asking if that's what you're getting at

18:11 hyPiRion: tjd: Could you give an use case? Generally you can just remove f

18:11 amalloy: tjd: no, there isn't

18:11 seancorfield: seems like the closest thing for be apply: (apply g [x]) == (g x)

18:12 amalloy: hyPiRion: well, that function is useful in cases where you're not writing it as a literal

18:12 tjd: apply is close but not quite

18:12 joegallo: ,((fn [f & args] (apply f args)) inc 1)

18:12 tjd: since it destructures the arg

18:12 clojurebot: 2

18:12 Bronsa: well. ##(deliver inc 1)

18:12 lazybot: ⇒ 2

18:12 amalloy: (condp invoke x, even? :even, odd? :odd), for example

18:12 or (map invoke list-of-thunks)

18:14 hyPiRion: Where's FUNCALL when you need it

18:15 technomancy: hyPiRion: it's hiding in clojure.core/deliver

18:15 (for arity 1 anyway)

18:16 tjd: (deliver inc 1) oh... oh my.

18:17 hyPiRion: Well, it's a neat hack, I'll give you that

18:17 technomancy: like many things, I learned it from amalloy

18:26 dsrx: ha

18:30 TimMc: or trampoline, if you know the return value isn't a function :-P

18:30 $findfn + 2 3 5

18:30 lazybot: []

18:30 TimMc: Oh come on, lazybot/

18:30 That's pretty lazy, even for you.

18:36 technomancy: heh

18:49 seancorfield: Bronsa: just looking at that (deliver inc 1) ... that's weird :) but the source of deliver shows why that happens... TIL: you can deliver a promise by calling it with a value!

18:50 technomancy: Welcome to Clojure, where everything[1] is a function!

18:50 [1] - except regexes; those are dumb.

18:50 hyPiRion: it's not like picolisp though

18:51 In Picolisp, (1 2 3) is like saying (defn 1 [& args] (apply list 1 args)), except more efficient

18:55 technomancy: I'm not entirely sure I *want* to understand that

18:57 hyPiRion: Oh, that came out wrongly. All numbers are functions, so (1 2 3) is the same as (list 1 2 3)

18:57 they are sort-of like autoquoted

18:57 technomancy: wow

18:58 bob2: is there some way to put part of my ~/.lein/profiles.clj in another file? I have it checked it into vc, but would like to be able to put some non-vc'd stuff in there too

18:58 Raynes: &(trampoline + 1 2 3)

18:58 lazybot: ⇒ 6

18:58 technomancy: bob2: there is!

18:58 hang on, I know this one...

18:58 Raynes: TimMc: Not sure why he didn't get that. Maybe his sandbox is getting stuck on trampoline for some ridiculous reason.

18:59 hyPiRion: http://software-lab.de/doc/ref.html#ev

18:59 technomancy: bob2: I think you can do ~/.lein/profiles.d/myprofile.clj

18:59 bob2: technomancy, oh, score

18:59 hyPiRion: yup

19:07 bob2: technomancy, hm, that appears to not be loaded

19:08 ah, sorry

19:08 that creates a new profile

19:11 technomancy: yeah

19:12 you can't split up one profile

19:12 well

19:12 bob2: I'm not gonna make user.clj :)

19:12 technomancy: you might be able to define :user as a composite of :user/private and :user/public

19:13 so crazy it just might work

19:13 oh, heh

19:13 sure, name it something else

19:13 hyPiRion: it's exactly one in a million chance

19:17 bob2: cool, with-profile works

19:17 thanks!

19:18 technomancy: with-profile?

19:20 bob2: just gave up, put the creds in ~/.lein/profiles.d/mything.clj and run it with 'lein with-profile mything ring server-headless'

19:23 technomancy: oh, sure

19:23 I thought you wanted stuff to be picked up implictly, which is harder

19:25 bob2: I did, but it's not super important for now

19:25 technomancy: I'm curious if it works though =)

19:28 bob2: for documenting an (ns), is it preferable to use a ^:doc annotation, or a string in the ns form?

19:36 technomancy: string, definitely

19:36 noonian: why is a string prefered?

19:37 technomancy: less punctuation

19:39 weavejester: Quick question: is it a common issue for the cljs compiler to run out of heap space?

19:39 amalloy: weavejester: i've heard about that happening fairly often with source maps; i don't know if it's still an issue

19:40 weavejester: amalloy: Hm, I'm not using a source map.

19:40 I just wiped my target directory, and suddenly it throws a heap space error.

19:41 https://gist.github.com/weavejester/6af8522f4bc22fc58e06

19:41 In case anyone's interested.

19:42 I'm guessing that failing to compile cljs.core is not a common issue, or else it would have been noticed :)

19:42 noonian: i'd try lein cljsbuild clean if you wiped target manually and your js is being outputed somewhere else

19:43 weavejester: Shouldn't make a difference, but trying it now

19:44 Hm, nope: https://gist.github.com/weavejester/e35240240e49c4c54b91

19:45 Maybe the clojurescript compiler just needs a lot of memory

19:53 amalloy: weavejester: default maximum heap size is 1GB or 1/4 of all ram, whichever is less (for oracle's jvm)

19:54 weavejester: amalloy: Free RAM or total RAM?

19:54 amalloy: total

19:55 free would be quite poor, because of mmapped files and disk buffers/caches

19:55 weavejester: amalloy: Hm, I'm not sure that's true, then. I have 4GB of RAM, so in theory "lein cljsbuild" should have up to 1GB to play with.

19:56 amalloy: But it dies with less than 200M

19:56 amalloy: Same thing with a project that used, datomic, incidentally.

19:56 amalloy: I need to manually specify -Xmx1g

19:57 amalloy: well, all i have is http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html and http://docs.oracle.com/javase/7/docs/technotes/guides/vm/server-class.html

19:59 weavejester: amalloy: Well, whatever the docs say, the version of Java 1.7 on my Macbook doesn't default to 1G! :)

19:59 hiredman: it also depends on which jvm (server/client)

19:59 weavejester: amalloy: Maybe Apple's version is changed slightly.

20:00 amalloy: hiredman: yeah, but basically no modern machines count as client for oracle's jvm

20:00 (as noted in my secnod link)

20:00 hiredman: amalloy: on my mac I get different versions when I pass -server or not

20:00 amalloy: and is that oracle's jvm?

20:00 hiredman: oh, fuh, never mind, I mist read the string

20:00 weavejester: I believe so...

20:01 Though I'm not sure a dual-core counts as "two CPUs"

20:01 hiredman: somehow a whole word just didn't register

20:01 weavejester: Which is needed for Java to guess that it's -server

20:01 AmnesiousFunes: Heavy users of tools.namespace: what parts/functions do you use/need the most?

20:01 hiredman: weavejester: another thing to keep in mind is if you are using lein to run stuff, lein will pass arguments to the jvm

20:02 weavejester: hiredman: Ohh, point.

20:02 technomancy: -client doesn't exist any more

20:02 hiredman: like -client

20:02 technomancy: unless you're on a 32-bit sytem

20:02 hiredman: technomancy: well, the version of lein I have installed still passes -client

20:03 it seems to still get a server jvm, but it still passes -client

20:03 technomancy: hiredman: sorry, I mean it doesn't exist in the JVM

20:03 it's silently ignored

20:03 weavejester: Lein seems to default to mx512M

20:04 hiredman: weavejester: you may have JVM_OPTS set in your environment

20:06 weavejester: hiredman: Nope, that environment var is empty... although, it could also be a system property?

20:06 Yeah, curiously if I set :jvm-opts ["-server"] that doesn't work - it runs out of memory

20:07 But :jvm-opts ["-Xmx1g"] does work

20:07 The docs would suggest the two are synonymous for a machine with 4GB of RAM.

20:07 hiredman: weavejester: jvm-opts in project.clj don't override leins, unless you do ^:replace

20:08 weavejester: hiredman: So why does :jvm-opts ["-Xmx1g"] work?

20:08 hiredman: weavejester: because -Xmx1g doesn't have to be the first argument

20:08 weavejester: hiredman: Ahh

20:11 hyPiRion: hiredman: they've been overriding lein's default for some time, actually

20:11 see technomancy/leiningen#1230

20:11 lazybot, can you please live for like more than one hour? :(

20:12 https://github.com/technomancy/leiningen/pull/1230

20:13 hiredman: hyPiRion: that assumes you are running whatever the latest lein release is

20:14 hyPiRion: yeah. 2.3.0 or later

20:14 hiredman: hyPiRion: since I use lein to pin version dependencies to avoid the treadmill of constantly chasing upgrades, you can imagine my attitude towards chasing lein upgrades

20:15 weavejester: amalloy, hiredman: thanks for the suggestions, btw

20:37 taw23: Newbie to clojure here. Can someone explain why (list a b c) gives an error about symbol resolution but '(a b c) doesn't?

20:38 dacc: taw23: the first element is evaluated as a function call unless you quote it

20:38 ambrosebs: taw23: an unquoted symbol tried to resolve itself

20:38 dacc: er, yeah that's more to the point

20:39 ,(list 'a 'b 'c)

20:39 clojurebot: (a b c)

20:40 amalloy: &(let [a 1, b 2, c 3] [(list a b c) '(a b c)])

20:40 ,(let [a 1, b 2, c 3] [(list a b c) '(a b c)])

20:40 clojurebot: [(1 2 3) (a b c)]

20:42 taw23: Not sure who I was just talking to, but that explanation doesn't make a lot of sense to me

20:42 I'm used to a variable needing to be declared or assigned to be used at all

20:43 dacc: taw23: they aren't variables but symbols. naked ones attempt to resolve to a definition, while quoted ones can be used as regular values

20:44 TravisD: Is it cider that gives me all these nice quotes in the status bar of emacs?

20:44 hyPiRion: TravisD: yep

20:44 TravisD: cool, is there a list of them somewhere?

20:44 dacc: taw23: not sure using them as values comes up much except when passing to e.g. defn, which is a macro and so doesn't required the quoting

20:45 taw23: dacc, eh, still thoroughly confused :-S

20:45 noonian: symbols in clojure are first class values unlike in something like java

20:45 taw23: but what is a symbol if not a assigned to a value?

20:45 bob2: tldr you can just not do (list a b c) or '(a b c) until you understand symbols better

20:45 dacc: taw23: heh, maybe get a good intro book. i'm working through the o'reilly one and it explains this stuff pretty well

20:46 taw23: yeah maybe i will

20:46 noonian: so foo and bar are symbols, and the evaluation rules for symbols in clojure is to try to resolve to something they are bound to

20:46 taw23: and quoting doesn't attempt to resolve it?

20:46 bob2: yes

20:46 noonian: after (def a 10), a will resolve to 10

20:47 but without defining it first, evaluating the symbol a will throw an error because it couldn't be resolved

20:47 taw23: yeah, that much makes sense, I guess it's just that single quote notation that I find bizzare

20:47 noonian: if you quote a symbol it will evaluate to a value of type Symbol

20:47 ,(type (quote foo))

20:47 clojurebot: clojure.lang.Symbol

20:47 bob2: the single quote thing is an almost-universal lisp-ism

20:48 hyPiRion: bob2: it's still very strange for people unfamiliar with lisps

20:48 taw23: if a b and c were all properly defined as numbers, '(a b c) and (list a b c) would actually have different contents? The first being the symbols themselves and the latter being their values?

20:48 hyPiRion: taw23: yes

20:48 noonian: yeah, most non-lisp languages don't have an analogous concept

20:49 taw23: hyPiRion, ah, that makes a bit more sense then

20:49 noonian: quote quotes an entire form

20:49 bob2: hyPiRion, right

20:50 noonian: ,(let [c 17] (quote (a b (unquote c) d)))

20:50 clojurebot: (a b (unquote c) d)

20:50 noonian: ,(let [c 17] (quote (a b ~c d)))

20:50 clojurebot: (a b (clojure.core/unquote c) d)

20:50 noonian: hmm, unquote only works in syntax quote?

20:51 turbofail`: yep

20:52 which is why you're able to hijack unquote for your own purposes in your own macros

20:53 right1: i just had the weirdest lighttable bug where it was writing out "(" to a tab that wasnt in focus and everything else on my current tab...

20:53 i thought my keyboard was broken

20:55 turbofail`: ,((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))

20:55 clojurebot: ((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))

20:56 turbofail`: an oldie but goodie

20:56 AimHere: That's just Lisp's way of saying "Yields the source code when preceded by it's quotation"

20:57 taw23: right1, I once almost formatted my entire computer because I for the life of me couldn't figure out where a particular bug was coming from. Turns out I had placed a book on the spacebar of an extra keyboard I had plugged in under my desk

20:58 AmnesiousFunes: right1: Any more info on that? Can you replicate the issue?

20:58 right1: sorry, i couldn't figure out how to replicate it

20:59 AmnesiousFunes: If it happens again, feel free to ping me in #lighttable

20:59 right1: okay

20:59 TimMc: Raynes: I figure lazybot timed out.

21:15 gfredericks: ,'~~~~~~~~~~~!

21:15 clojurebot: (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote (clojure.core/unquote #))))))))))

21:16 gfredericks: ,'~:-D

21:16 clojurebot: (clojure.core/unquote :-D)

21:19 TravisD: Is there anything particularly wrong with this definition of .. (which I'll call chain): (defmacro chain [& xs] (reduce (partial list '.) xs)) ?

21:20 It's not exactly the same as .., since it allows for a single argument

21:21 amalloy: TravisD: that doesn't look very useful to me - it's not close to .., is it?

21:21 noonian: well, it wouldn't work with forms that take arguments right?

21:21 amalloy: &(reduce (partial list '.) '(a b c d))

21:21 ,(reduce (partial list '.) '(a b c d))

21:21 clojurebot: (. (. (. a b) c) d)

21:21 amalloy: so i guess that's what noonian is saying

21:22 noonian: ,(reduce (partial list '.) '(a b (c c2 c3) d))

21:22 clojurebot: (. (. (. a b) (c c2 c3)) d)

21:22 TravisD: Ah

21:22 amalloy: oh, funny. i guess that works, doesn't it

21:23 noonian: that's correct syntax: (. x (c c2 c3)) is the "explicit" form of (. x c c2 c3)

21:24 TravisD: if it works, it's by accident. I thought .. was just used to access deeply nested methods

21:24 noonian: amalloy: huh, i've never seen that syntax

21:24 thanks

21:24 TravisD: parameterless methods

21:24 jarjar_p_: hello ;-)

21:24 quizdr: if I have a map and I want to alter its values, or its keys, or both, but still have a map in the end, I'm finding I'm often using mapcat over the map, then hash-map it back together. Is this an acceptable idiom?

21:24 jarjar_p_: Anyone have any idea why this wouldn't print anything...

21:24 println (clojure.string/join "-" (hash-set (repeatedly 3 #(random-string 3))))

21:25 amalloy: gross, quizdr

21:25 noonian: i think you want update-in

21:25 amalloy: into/for is better than hashmap/mapcat

21:25 noonian: ,(doc update-in)

21:25 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

21:25 amalloy: noonian: no, he wants to modify each key or each value

21:26 noonian: ah, yeah then for or reduce

21:26 amalloy: ,(let [m {:x 1, :y 2}] (into {} (for [[k v] m] [k (inc v)])))

21:26 clojurebot: {:y 3, :x 2}

21:26 quizdr: thanks guys, i'll try to rearrange my habit.

21:26 i like that amalloy

21:28 amalloy: jarjar_p_: you didn't call println, you just evaluated it for side effects

21:28 noonian: ,(let [m {:x 1, :y 2}] (reduce (fn [res [k v]] (assoc res k (inc v))) {} m))

21:28 clojurebot: {:x 2, :y 3}

21:28 noonian: yeah, into is nicer

21:28 jarjar_p_: amalloy: lol i'm quite a n00b

21:31 quizdr: here's the ridiculous way i was doing it:

21:31 ,(apply hash-map (mapcat #(vector (first %) (-> % second inc)) {:a 1 :b 2}))

21:31 clojurebot: {:a 2, :b 3}

21:32 quizdr: worth noting that it is not actually much more characters long, but obviously not as easy

21:39 sandbags: I'm slightly baffled by an error I am getting "IllegalArgumentException No matching ctor found for class mces.core$__GT_pred$fn__4734 clojure.lang.Reflector.invokeConstructor (Reflector.java:163)" all the Google hits refer to Java interop, which I am not doing here.

21:40 bob2: refheap your code

21:40 sandbags: i'm posting it, but i'm interested in what the error is actually saying

21:41 https://gist.githubusercontent.com/mmower/d20bdf176a993476109d/raw/2eee256fceefb6a83379b4973e7e12afdec17361/gistfile1.txt

21:42 i can post more if needed

21:43 quizdr: sandbags what is pos.x ?

21:43 sandbags: quizdr: a symbol

21:44 quizdr: do you get the error regardless of the symbol or value you pass there?

21:44 i.e. if you just pass true or false

21:44 noto2: try ~criteria ?

21:45 TEttinger: in the call to ->pred

21:45 err map ->pred

21:45 sandbags: the functions being built by ->pred work if called indepdently

21:45 quizdr: noto2 the criteria in the macro is not in syntax quotes

21:45 sandbags: quizdr: yes, because i am processing that in the macro into a different form

21:46 TEttinger: not sure what you're asking/suggesting

21:46 TEttinger: oh, sorry, missed your nick change

21:46 TEttinger: nvm, I really know very little about macros

21:46 quizdr: sandbags i know i was just pointing that out to noto2

21:46 sandbags: quizdr: ah, sry, misread you

21:47 ->pred appears to build a valid function that works, hang on a sec

21:49 quizdr: sandbags if you just enter (search world true) or false do you still get the error?

21:49 sandbags: i updated the gist

21:49 quizdr: i'll try

21:50 i get a different error

21:50 that's probably because you can't map true

21:51 quizdr: what happens if you just enter pos.x at the repl, what value do you get?

21:51 sandbags: that's not going to work

21:51 there is no symbol pos.x

21:52 TEttinger: sandbags, uhhhh link again? I think the old link is to a specific revision

21:52 quizdr: oh i gotcha. well that's a tree i won't bark up

21:52 sandbags: it's a synthetic syntax to refer to something like {:pos {<ent-id {:x }}

21:52 TEttinger: https://gist.github.com/mmower/d20bdf176a993476109d

21:53 it's nearly 3am so possibly i am not at my best, sorry :)

21:54 quizdr: the buddha says "He who is wise, drinks green tea. Also, he does not code for a stretch exceeding 17 consecutive hours."

21:54 sandbags: i'm still not grokking what the exception is actually saying, possibly because I'm not au fait with how clojure turns functions into classes

21:55 i started at about 00:30 if that helps :)

21:55 quizdr: so that's nearly 27 hours then!

21:55 sandbags: well if you add it all up over the years it's probably a lot more than that

21:56 TEttinger: sandbags, hm. I wonder if it could be AOT compilation-related

21:58 sandbags: i think you just veered above my pay-grade

21:59 TEttinger: heh. then it probably isn't, if you had any gen-class stuff in your file it could be related to ahead-of-time compiled code not being up-to-date

22:00 sandbags: no, there's no Java interop at all in this stuff

22:00 TEttinger: but if you aren't doing anything with gen-class then it's a very strange error indeed

22:00 oh!

22:00 just realized something

22:00 sandbags: i'm a little puzzled by the change in NS reflected in the prompt

22:00 not sure if that's a red-herring

22:01 do tell

22:01 noonian: sandbags: don't you just want to call ->pred and not map it?

22:01 TEttinger: mces.core$__GT_pred$fn__4734 refers to the anonymous fn inside ->pred

22:01 sandbags: yes

22:01 ->pred is, essentially, a function builder

22:01 returning it wrapped in a {:component <fn>}

22:01 noonian: "c1# (->pred criteria)" instead of "c1# (map ->pred criteria)"

22:02 oh nvm

22:02 sandbags: noonian: no, there may be multiple criteria

22:02 noonian: yeah, i didn't parse the varargs

22:03 sandbags: the syntax i am replacing is (find-entities world [{:pos #(= (:x %) 1} ...])

22:03 so i'm translating (search world (= pos.x 1) ...) into that

22:04 TEttinger: hmmm... but your example uses '= instead of =

22:05 i mean I have no idea how to use macros at this point, so my advice is probably not very helpful, but have you tried evaluating this from a file with a non-"user" ns? like the one it keeps switching to, a file in the mces ns

22:06 sandbags: yes

22:06 noonian: well for one i'd remove the #'s because you're not sticking any symbols in the generated code

22:08 sandbags: noonian: fair point

22:11 TEttinger: if you change the example to = it still works

22:12 TEttinger: ((:pos (->pred '[= pos.x 2])) {:x 2}) => true

22:12 TEttinger: ah ok

22:13 dsrx: ,'('= =)

22:13 clojurebot: ((quote =) =)

22:13 David: oin clojurescript

22:13 whoops, sorry about that

22:14 sandbags: to rule out the downstream code i replaced find-entities with println and i still get the same error

22:14 but i'm going to recycle my repl jus tin case

22:15 ambrosebs: ,(doc ==)

22:15 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

22:16 sandbags: yep

22:16 dsrx: (== 4.0 4)

22:16 ambrosebs: returns non-nil implies you can check success with (not (nil? %))..

22:16 dsrx: ,(== 4.0 4)

22:16 clojurebot: true

22:17 ambrosebs: my brain

22:17 sm0ke: ,(== 4.000000000000000000000000000000000000001 4)

22:17 clojurebot: true

22:18 ambrosebs: ,(not (nil? (== 1 2))

22:18 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:18 ambrosebs: ,(not (nil? (== 1 2)))

22:18 clojurebot: true

22:18 ambrosebs: bad doc

22:18 that is all

22:22 sandbags: i've added a couple more more comments to the gist https://gist.github.com/mmower/d20bdf176a993476109d one showing the find-entities call, the other a disassembly of the anon-func

22:22 not sure if anyone can see anything funky in the disassembled code, it's a little beyond me

22:30 TEttinger: I'm wondering why you're using flatten, actually...

22:30 ~flatten

22:30 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

22:31 sandbags: TEttinger: actually i don't need to any more, that's a hold-over from something i was doing before

22:31 in fact what i want is vec

22:31 TEttinger: that's a relief

22:31 also, mapv may be what you want

22:31 ,(doc mapv)

22:31 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

22:33 sandbags: replacing flatten with vec gives me an identical call to what i expect, modulo the issue with the anon-function

22:35 https://gist.github.com/mmower/a7e5f6d78f1f2537a4d1 <- updated code & example runs

22:36 i still have no idea what the IllegalAccessError: No matching ctor found for class <blah> is really saying

22:37 TEttinger: ctor is a constructor, but I have no idea why it couldn't make one for an anon fn

22:37 sandbags: sorry, yes, i understand the concept, but I've no idea what ctor it's looking for or why it wouldn't find one

22:37 it's been an age since i looked at Java or Java byte-code

22:37 amalloy: you're calling eval on a closure

22:38 (let [x 1, f (fn [] x)] (eval f))

22:38 you really shouldn't eval functions at all ever, but if they aren't closures it happens to work

22:39 sandbags: sorry where i am calling eval on a closure? I call (eval op) because op will be the symbol '=

22:39 and i need the function =

22:40 amalloy: sandbags: (mces.core/find-entities world [{:pos #<core$__GT_pred$fn__10298 mces.core$__GT_pred$fn__10298@61dc7878>}]) is clearly not what you want to macroexpand to, because you couldn't possibly write that code yourself: it has a function object in it

22:41 sandbags: amalloy: when you say a "function object" are you talking about something other than a function?

22:42 amalloy: sandbags: #(% x) is the notation you would use, in source code, to describe a function. when the compiler *evaluates* that, it gets a function

22:42 sandbags: yes

22:42 amalloy: you can't embed a function directly into your source code, right? you need to use the notation for it

22:42 sandbags: ah, damn

22:42 yes i see it now

22:43 i mean i see what you're saying

22:43 amalloy: i can't figure out what you're trying to do in search and in ->pred, but the end result is evaluating something too many times

22:43 TEttinger: {(keyword component) #(op ((keyword slot) %1) value)})) ; like this?

22:43 sandbags: TEttinger: essentially yes, except op won't work

22:44 if you look at the find-entities call you can see it's translating into

22:45 okay so i probably want to quote the function in ->pred

22:45 amalloy: yeah, i think that's probably it

22:45 sandbags: although that leaves some trailling work to do because it's now qualifying e.g. op

22:46 but it's 3:46am and I suspect I am not compos mentis enough to handle this ;-)

22:46 thanks amalloy

22:46 and TEttinger

22:46 amalloy: `#(~(eval op) (~(keyword slot) %1) ~value) probably

22:47 TEttinger: glad it's working a bit better

22:47 sandbags: amalloy: you little beauty

22:47 yes indeed

22:47 (search world (= pos.x 29) => #{#uuid "5306c8b0-c93d-4284-aa36-2826b62a65ec"}

22:47 TEttinger: woo!

22:48 sandbags: so a stupid idea i had about 5 hours ago becomes working code :)

22:49 of course the next step is to rewrite the macro to handle boolean logic, that ought to be fun ... but i think i'll leave that for a clearer head

22:49 thanks again guys

22:50 TEttinger: (inc amalloy)

22:50 oh is lazybot not here?

22:52 sandbags: right... to sleep, g'night

22:53 amalloy: TEttinger: he's been disconnecting a lot recently

22:53 i'll bring him back

22:54 TEttinger: (inc amalloy)

22:54 lazybot: ⇒ 85

22:54 amalloy: $mail Raynes if lazybot keeps crashing i'll ask lance to fire you

22:54 lazybot: Message saved.

22:54 amalloy: gotta get those priorities straight

22:56 Raynes: amalloy: lol

22:56 $mail

22:59 amalloy: Lance will get right on the firing me stuff

22:59 * Raynes nods

22:59 Raynes: amalloy: Thanks for starting him, didn't notice he was down.

22:59 amalloy: twice today, mate

22:59 vladimust: is lazybot written in clojure? where's the repo, so I can read the code?

22:59 amalloy: earlier it was more dramatic: i shouted "lazybot, i summon thee!" right before he /joined

23:00 $google clojure lazybot github

23:00 lazybot: [Raynes/lazybot · GitHub] https://github.com/Raynes/lazybot

23:01 vladimust: thanks, I've been looking for some good clojure code to read

23:11 Can you guys recommend me any good clojure repos to read?

23:14 amalloy: haha, decided against lazybot already?

23:16 vladimust: ah no, I don't have internet at home

23:16 so I download a whole bunch of clojure repos and resources for the week

23:16 and read them/code at home

23:17 all clojure and no internet makes vladimust a very slow learner

23:18 seancorfield: at least you have a REPL and the docs handy locally vladimust :)

23:19 vladimust: Yup, it's great. :)

23:58 chare: unmute me please

Logging service provided by n01se.net