#clojure log - Apr 07 2014

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

1:19 kras: How do I control the number of parallel threads using pmap?

1:20 Lets say I have 80 parallel jobs but want to use a pool of 10 workers only i.e, 10 threads at a time

1:24 `szx: kras: https://github.com/TheClimateCorporation/claypoole

1:41 arrdem: hum... so I have this handy dandy xsd schema file... is there a toolkit that will allow me to generate record definitions and an appropriate data.xml importer from it?

2:16 miseria: "el deseo de vivir un millon de años, me obligan a buscar y matar la muerte, antes que ella me convierta en calavera" bienvenidos: http://castroruben.com *temo_a_un_ser_sin_rival*

2:18 deadghost: noprompt, how far as you along with sass for garden; I'll help out if I can

2:19 *are

2:19 noprompt: deadghost: not very far. i've been hung up on other stuff at the moment. but it's pretty easy to hack on.

2:20 deadghost: noprompt, is it up on github?

2:22 noprompt: deadghost: yeah, https://github.com/noprompt/thorn

2:22 deadghost: if you want me to explain more msg me

2:22 deadghost: email or pm?

2:22 noprompt: pm is fine

3:56 sm0ke: if i have some static enums define in an inner class with weird name like org.my.com.Abcdefghijk$Lmnop

3:56 and i want to use enums inside a condp =

3:57 how do i avoid Abcdefghijk$Lmnop/ENUM1 ...

3:57 opqdonut: have a clojure file that defines nicer names for them

3:58 sm0ke: why doesnt clojure allows import *

3:58 opqdonut: you can write a macro to do that :P

3:59 sm0ke: bleh

4:22 ambrosebs: instaparse case for parsing multi-line C-style comments?

4:36 <MultiLineComment> ::= '/*' InsideMultiLineComment* '*/'

4:36 <InsideMultiLineComment> ::= !( '*/' | '/*' ) (#'.' | LineTerminator) | MultiLineComment

4:36 from https://github.com/Engelberg/instaparse/blob/master/docs/ExperimentalFeatures.md#auto-whitespace

6:48 dsrx: weasel users - new 0.2.0 release includes support for clojurescript 2202

6:53 whodidthis: instaparse is such amaze

7:29 devn: wow. so parse.

7:29 such insta.

7:46 pradeepc_: Hello how can i check if an element exists in a vector.

7:47 beamso: ,(contains? [1 2 3 4] 3)

7:48 clojurebot: true

7:48 opqdonut: nope

7:48 ,(contains? [:a :b :c :d] 3)

7:48 clojurebot: true

7:48 beamso: ouch

7:48 opqdonut: contains? checks whether the index is valid, i.e. whether you have a valid key

7:48 ambrosebs: ,(some #{:a} [:a :b :c])

7:48 clojurebot: :a

7:48 opqdonut: yep, that's the right one

7:49 but it doesn't work for finding a nil, unfortunately

7:49 AimHere: If you're doing that a lot, you might want to consider switching to a set or a map instead, of course

7:49 ambrosebs: ,(some (some-fn nil? false? #{:a}) foo)

7:49 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0:0)>

7:50 opqdonut: :)

7:52 pradeepc_: AimHere: I want to check the ip of each client request and block if it exists in the blacklist.

7:52 opqdonut: yeah use a set for that

7:52 AimHere: Unless you have a good reason for them to be ordered, then go with a set

7:53 ambrosebs: ,(contains? #{:foo :bar} :foo)

7:53 clojurebot: true

7:54 opqdonut: ,(#{"123" "456"} "123")

7:54 clojurebot: "123"

7:54 AimHere: Given what an IP address is, there might be some sort of funky fast bespoke data structure that you can knock up that's more efficient

7:56 ambrosebs: I prefer contains.

7:56 pradeepc_: AimHere: can you point me somewhere.

7:56 ambrosebs: unless the operator is a set literal

7:57 AimHere: I can't, no. That was just a random thought popping into my head. I recommend you go with the set first, because it'll be quick and easy to knock up; if there's performance problems then consider looking up how grown-ups optimize their IP blacklists.

7:58 beamso: wouldn't people use network addresses and submasks to optimise?

7:58 pradeepc_: AimHere ambrosebs Thanks.

8:08 sm0ke: ,(.getConstructor Integer Integer)

8:08 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Class cannot be cast to [Ljava.lang.Class;>

8:09 clgv: sm0ke: you need an array of classes instead of a class

8:09 gfredericks: ,(.getConstructor Integer (into-array [Integer]))

8:09 clojurebot: #<NoSuchMethodException java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Integer)>

8:09 sm0ke: hmm

8:09 gfredericks: ,(.getConstructor Integer (into-array [Long]))

8:09 clojurebot: #<NoSuchMethodException java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Long)>

8:09 gfredericks: ,(.getConstructor Integer (into-array [Integer/TYPE]))

8:09 clojurebot: #<Constructor public java.lang.Integer(int)>

8:09 sm0ke: what da..?

8:09 gfredericks: Integer/TYPE is the type of primitive ints

8:10 compare:

8:10 ,(type (make-array 1 Integer))

8:10 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Class>

8:10 gfredericks: ,(type (make-array Integer 1))

8:10 clojurebot: [Ljava.lang.Integer;

8:10 gfredericks: ,(type (make-array Integer/TYPE 1))

8:10 clojurebot: [I

8:11 clgv: ,(.getCanonicalName (type (make-array Integer/TYPE 1)))

8:11 clojurebot: "int[]"

8:11 sm0ke: ok so i have a use case where i define a record and wont too lookup its constructor lets say

8:11 ,(defrecord MyRec [a b])

8:11 clojurebot: sandbox.MyRec

8:11 clgv: ,(.getCanonicalName (type (make-array Integer 1)))

8:11 clojurebot: "java.lang.Integer[]"

8:12 clgv: ,(.getConstructor MyRec (into-array [Object Object]))

8:12 clojurebot: #<Constructor public sandbox.MyRec(java.lang.Object,java.lang.Object)>

8:12 sm0ke: ,(.getConstructor (Class/forName "sandbox.MyRec") Object Object)

8:12 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: getConstructor for class java.lang.Class>

8:12 sm0ke: aha

8:12 thanks clgv

8:12 ,(.getConstructor (Class/forName "sandbox.MyRec") (into-array [Object Object]))

8:12 clojurebot: #<Constructor public sandbox.MyRec(java.lang.Object,java.lang.Object)>

8:12 sm0ke: just checking :D

8:13 so why isnt Object/TYPE

8:13 clgv: there is no primitive object ;)

8:15 sm0ke: ,(Integer. (Integer. 1))

8:15 clojurebot: 1

8:15 sm0ke: ,(.getConstructor Integer (into-array [Integer]))

8:15 clojurebot: #<NoSuchMethodException java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Integer)>

8:16 sm0ke: ,(.getConstructor Integer (into-array [Integer/TYPE]))

8:16 clojurebot: #<Constructor public java.lang.Integer(int)>

8:16 sm0ke: wtf

8:17 am is missing something here?

8:17 am i*

8:17 clgv: sm0ke: you are missing autoboxing and autounboxing

8:17 ambrosebs: http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html?is-external=true#constructor_summary

8:18 sm0ke: sneaky

8:18 makes sense

8:18 thanks

8:19 so java is dynamically type to some sense

8:19 typed*

8:19 beamso: i wouldn't say that

8:20 sm0ke: int and Integer are different types!

8:20 beamso: it's more that Integer came after int

8:20 and the JVM attempts to help you go between the two, but you can get a NPE in certain circumstances (i.e. Integer -> int)

8:22 sm0ke: ,(.newInstance (.getConstructor (Class/forName "sandbox.MyRec") (into-array [Object Object])) 1 2)

8:22 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: sandbox.MyRec>

8:23 clgv: sm0ke: no. afaik the compiler inserts code for you to do the (un-)boxing of Integer/ints

8:24 your session namespace probably expired

8:25 sm0ke: ,(defrecord MyRec [a b])

8:25 clojurebot: sandbox.MyRec

8:25 sm0ke: ,(.newInstance (.getConstructor (Class/forName "sandbox.MyRec") (into-array [Object Object])) 1 2)

8:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: newInstance for class java.lang.reflect.Constructor>

8:25 sm0ke: ,(.newInstance (.getConstructor (Class/forName "sandbox.MyRec") (into-array [Object Object])) (into-array [1 2]))

8:25 clojurebot: #sandbox.MyRec{:a 1, :b 2}

8:29 sm0ke: (inc clgv)

8:29 lazybot: ⇒ 15

8:31 clgv: :D

9:18 lunk: hello, how can i take two seq's of equal length, one of digits and one of booleans, and emit from digits when the corresponding boolean is true?

9:18 for loops are doing cross products

9:21 tbaldridge: arrdem: ping

9:22 arrdem: tbaldridge: good morning...

9:22 tbaldridge: arrdem: you had a question?

9:25 arrdem: tbaldridge: enjoyed your c.t.a(.jvm) talk, only thing that really stuck out to me was your comments about a potential SSA layer below or beyond c.t.a. What's the activity there? Not a project I'm aware of.

9:26 TEttinger: ,(let [digits [1 2 3] bools [true false true]] (filter number? (map #(if %1 %2) bools digits))) ; lunk

9:26 clojurebot: (1 3)

9:27 tbaldridge: arrdem: I've threatened to write it, that's about it. core.async uses a form of SSA, but I'd like to pull that out and make it an actual library. Any non-bytecode output platform could possibly take advantage of it.

9:27 mdrogalis: SSA?

9:27 arrdem: mdrogalis: static single assignment

9:28 mdrogalis: arrdem: Thanks.

9:28 arrdem: mdrogalis: it's a ... style of bytecode, typically register machine modeling which makes some compiler analysis techniques much simpler to use.

9:28 tbaldridge: clojurebot: SSA is https://en.wikipedia.org/wiki/Static_single_assignment

9:28 clojurebot: In Ordnung

9:28 TEttinger: In Ordnung

9:28 [06:25;32] * hoeck has quit (Ping timeout: 255 seconds)

9:28 [06:25;41] * si

9:28 arrdem: s/bitecode/compiler internal representation/g

9:28 TEttinger: dammit

9:28 lunk: TEttinger: yes!

9:28 tbaldridge: for once Wikipedia's view of something is actually quite nice

9:28 TEttinger: clojurebot: SSA |is| https://en.wikipedia.org/wiki/Static_single_assignment

9:28 clojurebot: 'Sea, mhuise.

9:29 TEttinger: hm

9:29 mdrogalis: Thanks for the info. Neat.

9:30 arrdem: tbaldridge: I guess my only issue with that is it seems like the kind of "only updated here" or "never updated" proofs you could do on values given a SSA structure you could probably do on the normal t.a tree.

9:30 not that I'm really opposed to reimplementing more of LLVM in Clojure for Clojure...

9:31 lunk: TEttinger: clever, i knew i was going down the wrong path. TY sir

9:31 tbaldridge: arrdem: yeah, I mean it's super useful for core.async as I basically take the SSA and emit it as a case+lets to create the state machine

9:31 TEttinger: no prob lunk

9:32 tbaldridge: But I think it could be useful for emitting to platforms that don't have "everything as an expression". For example, PyPy's RPython writes SSA code as C

9:32 arrdem: tbaldridge: yeah I'm reading that now. slick!

10:00 Bronsa: Is there a good reason why `some` doesn't take multiple colls?

10:01 I find myself doing (some true? (map pred c1 c2)) quite often

10:03 AimHere: Bronsa, what's the obvious interpretation of (some foo? a b c) ?

10:03 That question broke him, evidently.

10:04 opqdonut: as he said, (some true? (map foo? a b c))

10:04 I think it's weird that map is multi-arity but e.g. some and filter are not

10:04 AimHere: So you have to add in another function as well as the extra collections

10:04 It's not obvious to me

10:04 Bronsa: AimHere: sorry emacs crashed

10:04 opqdonut: AimHere: no, the foo? just gets passed multiple arguments

10:05 Bronsa: AimHere: look at the source of some

10:05 it's pretty straightforward to implement that for multiple colls

10:05 opqdonut: the true? is just a way of implementing it

10:05 Bronsa: just add another arity that calls pred on (first c1) (first c2)

10:05 AimHere: Ah, sorry, not thinking clearly

10:06 But then, if I was to see (some pred? a b c), I could also read it as (some pred? (concat a b c)

10:06 Bronsa: AimHere: no, that follows the same pattern as e.g. map

10:07 (map f a b c) applies f to (first a) (first b) (first c)

10:07 AimHere: That's your intuition, though some doesn't act like 'map' to my mind

10:07 some takes a pred and a collection and spits out a member of that collection. Looks more like nth to me!

10:08 Bronsa: AimHere: it doesn't spit out a member of the collection

10:08 it spits out the result of calling f to a member of that collection

10:08 ,(some inc (range))

10:08 clojurebot: 1

10:09 AimHere: Fair enough, but it's unlike map in some ways

10:09 Yours is one interpretation, but not the only one. It's non-obvious

10:09 Bronsa: sure, I was just drawing a parallel

11:15 ambrosebs: any tips for figuring out where instaparse gets stuck if it overflows the heap? is there a "current token" variable?

11:19 bbloom: ambrosebs: isn't "parses" lazy? you might be able to see some ambiguity if you just print the parses stream until it does

11:19 (note: i've only used instaparse for very simple use cases and haven't had to debug any grammars yet)

11:20 ambrosebs: bbloom: ah I'll try

11:34 zeeshanlakhani: If anyone's done work w/ test.check or double.check, how could I write a generator that needed to combine two types... one gen/string and the other a regex on that string, for example?

11:34 reiddraper: zeeshanlakhani: how specifically do you want to combine them?

11:35 zeeshanlakhani: more than likely you'll want to use gen/fmap or gen/bind

11:35 zeeshanlakhani: hey reid! Yeah, I was trying to get it to work w/ gen/bind, but in the midst of trying to generate them from prismatic schema's s/both

11:36 if I return two separate generators, i should just be able to combine them w/ gen bind?

11:37 reiddraper: zeeshanlakhani: gen/bind lets you take the randomly generated value from one generator and make a new generator out of it. fmap allows you to apply a function to a value generated. so really just depends on what you want to do

11:37 zeeshanlakhani: maybe you could describe in prose what you want

11:38 zeeshanlakhani: Yeah, the basics of what I want is that I have from a schemata a type that needs to be both a string and a string that fits a certain reg. expression. I just want to generate a set of samples that apply to both those types.

11:39 I feel like I'm saying that I need a generator that's aware of the constraint of an input generator

11:40 reiddraper: zeeshanlakhani: hmm

11:40 zeeshanlakhani: Does that make any sense? :)

11:41 reiddraper: zeeshanlakhani: not quite sure i'm following. do you have these generators already written? if so, can you be more explicit about how you want to compose them

11:42 xsyn: are incanter's datasets indexed out of the gate?

11:43 someone was describing R's dataframes, saying that they're really efficient due to their indexing

11:43 I was interested if incanter had the same functionality

11:43 s/if/as to whether/

11:48 ambrosebs: bbloom: phew parses is pretty amazing

11:48 bbloom: yup!

11:52 zeeshanlakhani: To be honest reid, the more I look at our prismatic schema-uses, the more I'm seeing a type that's more like a field's value will be both a map and a non-empty collection, which, if that's the case gen/such-that will be exactly what i need (predicate and gen) for most cases and fmap for others. Think I was over-complicating the situation :D

11:52 pdurbin: xsyn: due to their indexing?

11:53 reiddraper: zeeshanlakhani: cool. also take a look at gen/not-empty, which is a prewritten (such-that not-empty ...)

11:55 zeeshanlakhani: yep, will do. Thank you reid! So much fun using test.check

11:55 reiddraper: zeeshanlakhani: np, and happy to hear :)

11:57 ambrosebs: instaparse.core/parses + clojure.data/diff = holy crpa

12:01 bbloom: ambrosebs: interactively debugging ambiguity beats the pants off cryptic shift/reduce errors, huh?

12:03 ambrosebs: bbloom: never used a parser in my life

12:03 apparently a great place to start

12:05 bbloom: ambrosebs: traditional parser generators only parse a subset of CFG. you get a weird error message if you accidentally create a grammar that isn't in the subset.... but the source of the issue is usually *very far* from the symptom

12:05 gtrak: Is it just me or is the lifecycle of core.async channels and implications a little unclear and discomforting? Trying to figure out how to test a small thing, considering implementing it with callbacks instead, but maybe I'm missing something fundamental, I have no idea :-). If I could instrument which channel(s) is/are getting blocked, then that would help immensely.

12:06 ambrosebs: bbloom: ah that sucks

12:06 bbloom: ambrosebs: yeah, trade off is that instaparse's generalized algorithm can be *very* memory hungry

12:08 but in practice it's not a big deal b/c you can debug your grammar interactively, find sources of ambiguity, excessive left recursion, etc, and eliminate those

12:08 it's kinda like dynamic vs static typing ;-)

12:08 ambrosebs: :)

12:09 I assume ambiguity is a severe performance problem

12:10 bbloom: so i dunno enough about instaparse's internals, but it doesn't have to be a perf problem

12:11 but my understanding is that instaparse's algorithm ALWAYS supports back tracking

12:11 which means high memory overhead for the parse context, to support that backtracking

12:11 in general, you need most of that context saved for unlimited lookahead

12:12 i'd really like to see tools to help you prove/falsify properties about grammars, like verifying that a grammar is LL(N)

12:39 doky: hello is there any option to concat string in regexp ? and produce a map with it ? somethng like (map #(% (re-find #%" [\w ]+" "-p password -u username")) ("-p", "-u") ) ?

12:42 what results to {:-p "password" :-u "username"}

12:42 justin_smith: doky that question is confusing

12:42 first off, map does not produce a hashmap, it maps over some input

12:42 TimMc: doky: No, but Pattern has a quote-for-regex method, and for this use-case you probably want clojopts anyhow.

12:43 justin_smith: yeah, it looks like clojopts may be what you want https://github.com/amalloy/clojopts

12:44 doky: TimMc: but i need to parse string in cycle .. if no .. a can call different regexp and assoc results to map

12:56 noprompt: the latest version of clojurescript randomly throws wacky errors.

12:56 java.lang.Exception: JSON error (unexpected character): ^@

12:57 like, uh, what?

12:57 dnolen_: ^

12:57 hiredman: looks like a null character

12:57 dnolen_: noprompt: more details needed

12:57 noprompt: i don't even know if i could give you any

12:58 before that it was

12:58 java.lang.IndexOutOfBoundsException:

12:58 and no vectors were used.

12:58 or at least not in the part i changed.

12:58 it could be one of the libraries though.

12:58 AimHere: These errors don't look any weirder than normal clojure/javascript errors

12:58 noprompt: but this wasn't happening before with the same code.

12:58 hiredman: noprompt: are you using cljsbuild auto build?

12:58 noprompt: sometimes it's just a matter of adding some whitespace and saving the file again and everythign compiles fine.

12:59 hiredman: yes.

12:59 hiredman: noprompt: check for multiple autobuild processes

13:00 noprompt: hiredman: yeah, i'm familiar with "those" errors. there's only one cljsbuild process rolling though.

13:00 dnolen_: noprompt: paste a stack trace and maybe I'll see something

13:01 noprompt: dnolen_: https://www.refheap.com/73054

13:04 dnolen_: noprompt: looks like it's blowing up on the source maps, that what we use clojure.data.json for

13:04 noprompt: dnolen_: you can ignore the [cljsbuild] that's just a tag we have for the output

13:05 dnolen_: any clue what might cause it?

13:05 dnolen_: noprompt: look at the json is it valid?

13:07 noprompt: dnolen_: looking into it.

13:11 seangrove: bbloom: I've been thinking about it, I'm pretty sold on the idea of Auckland-style layout model. With the right UI it makes a lot more sense for developers than raw iOS-style constraints

13:12 bbloom: seangrove: yup. then the next though that follows is that you that to be the default top-level layout, but you'll still want hierarchical layout managers

13:14 seangrove: bbloom: I control the top-level layout of these regions, but delegate layout within those regions to some other layout system?

13:14 bbloom: seangrove: right, since some layouts are super simple and make sense like "stack layout"

13:15 seangrove: why bother with a constraint solver if you're just going to do y+=height ?

13:15 noprompt: auckland-style?

13:15 bbloom: seangrove: and some layouts are non-linear, so a linear constraint solver isn't a good plan at all

13:15 seangrove: i'll let you explain

13:15 (curious to hear your take on it anyway)

13:17 seangrove: bbloom: Been explaining it in person quite a bit, haven't yet over irc

13:17 noprompt: Reasonably simple idea - have you worked with a designer and see how they sketch things out in PS or Sketch?

13:18 noprompt: seangrove: yes. myself.

13:18 seangrove: well, and other designer friends.

13:18 bbloom: seangrove: and now you're doing customer development!

13:18 noprompt: seangrove: i was a designer a long time before i was a programmer.

13:18 seangrove: bbloom: It's in no way my product :P

13:18 noprompt: Nice. So what I've seen is designers settings higher-level constraints on a design by defining regions

13:19 Essentially starting with guidelines

13:19 noprompt: ha, yeah. just drag one from the ruler.

13:19 seangrove: Exactly

13:19 noprompt: and then snap elements to it.

13:19 bbloom: seangrove: instant understanding. that's how you know you've got a good user mental model ;-)

13:20 seangrove: So for a top-level layout, you define these regions, and then set rules about them "This region in the middle is always this height, but it can expand in this direction if necessary, figure it out for me", etc

13:20 bbloom: i humbly request that you retune your classifier from "crazy homeless man on street corner" more towards "mo fuckin' profit"

13:20 er prophet

13:20 (dec spelling)

13:20 lazybot: ⇒ -1

13:20 seangrove: Freudian slip??

13:20 lazybot: seangrove: Definitely not.

13:20 bbloom: ~botsnack

13:20 clojurebot: Thanks! Can I have chocolate next time

13:21 seangrove: lazybot, I <3 you

13:21 bbloom: dammit. wrong bot

13:21 seangrove: noprompt: Anyway, you define these regions, and then your components inhabit them

13:21 Maybe with another layer of layout managers in between, though

13:22 noprompt: seangrove: right. so does that involve a constraint solver or is it lower on the totum pole of how much shit i have to read to grok how it all works. :-P

13:22 bbloom: noprompt: it may or may not be built on top of a constraint solver

13:22 seangrove: noprompt: So you can imagine as a designer I set the guidelines, set the rules, strt dragging in your components into the regions, setting their data bindings to your app state, and then, finally, applying styling

13:22 bbloom: ideally, yes, but most use cases can be implemented by solving trivial proportions

13:23 seangrove: noprompt: No we can reason about layout, app-state data, component behavior, and styling separately

13:23 bbloom: you may want to say "this region keeps a 4:3 aspect ratio" and the layout evaluator may decide to implement that as a proper linear constraint

13:23 noprompt: right

13:27 seangrove: noprompt: But if you have those pieces in place, you can mould apps like you're working with clay - pieces that do what you want (layout, transform data, or style), but no more, so you can componse them together

13:28 oinksoft: is anything available for or built into clojure for managing workers? like supervisor/gen_server in OTP?

13:28 seangrove: noprompt: I'm starting to see that as the holy-grail of UI programming.

13:28 oinksoft: or are clojure people using threads for this? immutable data structures are friendly (essential) for the OTP design

13:29 so i thought perhaps something similar to OTP existed

13:29 technomancy: sadly there's nothing like OTP (anywhere)

13:29 except OTP itself

13:30 but yeah, there are typically no problems with using threads for that kind of thing

13:30 oinksoft: ok, thanks technomancy

13:30 tbaldridge: and when you do, there is core.async </shameless ad>

13:31 gtrak: tbaldridge: I'm having a hard time visualizing what's going wrong in my core.async impl, are there any sort of introspection facilities that might be useful for debugging? I saw in the impls there's some ways to get counts on the buffers and things.

13:31 oinksoft: tbaldridge: is that battle tested stuff?

13:31 tbaldridge: to the extent that goroutines are battle-tested ..

13:32 seangrove: oinksoft: Nothing in the Clojure world will be as battle-tested as OTP ;)

13:32 oinksoft: seangrove: well yea :p

13:32 i just meant, is core.async experimental or people are using this for real work?

13:32 bmabey: oinksoft: we've been using core.async in production on the server almost as soon as it came out and we haven't had many issues at all

13:33 oinksoft: bmabey: nice! anything to be aware of? i do like the look of this api

13:33 technomancy: it's not really trying to solve the same problems as OTP though, is it?

13:33 or rather, it targets a small subset of the problems

13:33 bmabey: I have wanted OTP like supervisors with core.asycn in the past

13:33 gtrak: I guess I could maybe write a macro that creates a gensym and stacktrace for each channel instance and polls counts once in a while.

13:34 bmabey: sometimes go processes blow up on an unexpected error and I just want them to simply restart

13:34 oinksoft: technomancy: yea, i can see how this would be useful though, so i was curious, it reminded me of goroutines

13:34 bmabey: so having reusable policies to manage those restarts would be helpful

13:35 technomancy: oinksoft: sure, not saying it's not useful =)

13:35 oinksoft: technomancy: i see otp like a padded cell :)

13:36 gtrak: bmabey: I would just wrap the internals in a with-error-fn macro that does a try-catch, used it with println initially.

13:36 i guess if you pass in a function, recur wouldn't work.

13:37 but that just requires a more complex macro :-)

13:37 seangrove: bbloom dnolen_: I'm contemplating a visit out there the be able to join in some of these mind-blowing conversations ;)

13:38 technomancy: oinksoft: the tooling around distributed async flows is just a lot better in erlang; on the jvm it's a lot more common to have trouble debugging once you give up the ability to get a proper stack trace.

13:38 bmabey: grandy__: right, and that is what I did and moved on :) I never went the next step of extracting it but it seems like a lot of people using core.async would need something like this

13:38 dnolen_: seangrove: you're always welcome to come hang out in Brooklyn with us

13:39 bmabey: oinksoft: you do need to be aware of not-blocking the go-routines. Here is a post explaining it: http://martintrojer.github.io/clojure/2013/07/07/coreasync-and-blocking-io/

13:39 oinksoft: technomancy: yea, the remote debugging capabilities are pretty nice in erlang

13:39 bmabey: so core.async uses all of the go terminology (goroutine, channel, etc.)?

13:40 tbaldridge: hopefully something like OTP is developed at some point for core.async. But as always the question will be what OTP for CSP even means.

13:40 seangrove: dnolen_: Sounds good, I'll start thinking about it a bit then

13:40 bmabey: tbaldridge: yeah, and I'm hoping someone with a lot of experience in both and provide some insight

13:41 tbaldridge: bmabey: sadly I think that's one of the issues...people seem to either be experts with actors or CSP not both :-(

13:41 hiredman: well, microsoft's orleans thing claims not to need otp because of whatever

13:41 bmabey: tbaldridge: I have a friend at google who does a lot of go and he says they just panic, kill the whole process, and let the cluster start things back up again

13:41 gtrak: bmabey: lol, that's encouraging

13:41 hiredman: (but it sort of quacks like otp)

13:41 http://research.microsoft.com/en-us/projects/orleans/

13:42 technomancy: bmabey: part of that is just because go is no good at live introspection

13:42 bmabey: technomancy: and fast at starting up

13:42 bbloom: we definitely need something like linked/trees of processes

13:43 gtrak: bbloom: I could imagine a prismatic-graphlike thing that allows for introspection.

13:43 bmabey: bbloom: of course it all comes back to trees for you :P joking aside, I agree

13:44 tbaldridge: and two things (in my mind) that are keeping that from happening in core.async right now are 1) first class processes, 2) the ability to kill a go (requires #1)

13:45 bbloom: we need more introspection in general. don't worry, i'm on it :-)

13:45 gtrak: how can I help?

13:45 bbloom: gtrak: wait patiently for a bit ;-)

13:46 gtrak: besides tiny little one-off macros, that's my usual method for figuring things out :-)

13:46 bbloom: tbaldridge: processes are already reified, what's holding them back from becoming first-class?

13:46 tbaldridge: is it just API design?

13:47 bmabey: bbloom: you never get a handle on the process though, just the channel it returns

13:47 bbloom: bmabey: right, but in the implementation they are a state machine object

13:47 tbaldridge: right, and the whole API is callback based so there's nothing there that describes how to terminate a callback, or even if that can be done

13:47 gtrak: what's first-class? I imagine that means a set of lifecycle protocols.

13:48 tbaldridge: any impl I've thought about has had big caveats. For example: "(kill! pid) - kills the process the next time it attempts to read write or alt"

13:48 bmabey: first class means you can assign it to a var, put in a datastructure, return it from a fn, blah, blah

13:48 bbloom: gtrak: first-class means that processes are things you can manipulate in the language directly as any other object/value

13:48 tbaldridge: but that doesn't help at all with a process stuck in a loop.

13:48 bmabey: which you can with core.async's state machines as bbloom as pointed out but the API doesn't return them to allow you to do that

13:49 bbloom: tbaldridge: presumably you can instrument loops to check the kill flag

13:49 tbaldridge: may murder perf tho...

13:49 gtrak: ah, so just, more control on the continuum of opaque to transparent?

13:49 tbaldridge: sure...but what does that even mean if you want the same api to work for (thread) ?

13:49 bbloom: gtrak: transparency is orthogonal

13:49 ,(fn [x] (* x 2))

13:49 bmabey: yeah, (thread) is tricky...

13:49 clojurebot: #<sandbox$eval25$fn__26 sandbox$eval25$fn__26@1cbeebb>

13:49 bbloom: ^^ that's opaque, but first-class

13:50 but in my interpreter, soon to be jit, you'd get something like #eclj.Function{:args [x] :expr (* x 2)} :-)

13:50 bmabey: having the channel that is returned from a go process be linked to said process seems natural.. what if closing that channel would result in the process being killed? is that a horrible idea?

13:50 gtrak: ah

13:51 yea, I mean it seems like the channel from a go-block is the 1:1 link, analogous to function-object:semantics

13:51 tbaldridge: bmabey: I don't know yet :-) And whatever happens I need to talk to Rich about all this at some point. And he has the final say on this stuff.

13:51 gtrak: the fact that it's a channel.. doesn't mean that's all it could be.

13:51 bbloom: speaking of, tbaldridge: i'm almost finished separating syntax from the interpreter. there is a shallow "parse"/"analyze" phase & first-class "syntax objects" a la racket

13:52 tbaldridge: bbloom: nice

13:52 bmabey: gtrak: true, a Process protocol could be introduced or something which the returned val impls. as well as the Channel protocol

13:53 bbloom: tbaldridge: it's pretty cool b/c it looks sorta like the traditional analyzer, but there is no recursion. instead, the recursion that exists in eval will (eventually) be intercepted to produce deep ASTs. ie the analyzer will be parse+partial-eval

13:55 gtrak: I've been playing with om, so I'm in the lifecycle protocols mindset :)

13:58 oinksoft: ok, i've got a big question. program abstraction in clojure? in an OOP language, for instance, maybe i have an adapter layer and my API user provides the implementation they desire to my adapter (like a DB adapter). how are API users doing this in clojure?

13:58 i see in some cases people use (binding so define some value for a library

13:59 but at a high level something feels very clumsy here

13:59 justin_smith: oinksoft: multimethods or protocols pretty often

13:59 gtrak: oinksoft: try to avoid binding please :-)

13:59 justin_smith: binding is fragile

13:59 oinksoft: gtrak: yea, it looked very ugly to me

13:59 justin_smith: oinksoft: define a multi or proto in your lib, and then let a user provide an impl

13:59 gtrak: any library that uses it is likely to be making bad assumptions. It's more ok in an app.

14:00 oinksoft: let's say i am designing an API for catching fish. now i don't care how you catch them, you can use a rod and reel, a spear, a net ... is the API user going to call (catch-fish reel-that-implements-fish-catching-protocol)?

14:00 gtrak: they can use reify, extend-type or whatever they like.

14:00 oinksoft: in an OOP langauge I can register this with reel object in some way so i am not passing it around all the time

14:00 justin_smith: oinksoft: yeah, and define catch-fish as a multimethod or a protocol method

14:01 gtrak: oinksoft: you could define an adapter to an existing type with extend-type.

14:01 oinksoft: a frustration i have when doing lots of heavy erlang programming comes when i want to make my API flexible. you use callback modules, but anyway i am blabbering...

14:01 justin_smith: oinksoft: fp is about replacing globals with args - things really work when you do it that way

14:02 oinksoft: justin_smith: yea, this is smeothing i revisit a lot .. api design is so important.

14:02 gtrak: for instance, 'slurp' calls clojure.java.io/reader on its arg, which might be a String, which is a 'final' class, meaning it cannot be extended. in clojure.java.io, it's specified how to handle strings, so the user just has to know that that's the case, and that it'll be treated as a URL :-).

14:02 bbloom: oinksoft: over here in clojureland, we do our data design before we do api design ;-)

14:03 oinksoft: justin_smith: i want to make my program easy to maintain but also easy for the code user. one way i see epeople doing this in clojure is with macros (like sqlkorma does this)

14:03 bbloom: go on ... :)

14:03 gtrak: but you can extend the IOFactory protocol to any object, then it'll be slurpable :-)

14:03 bbloom: oinksoft: take a look at datomic or the clojurescript analyzer or something like that. they are very narrow APIs

14:04 oinksoft: datomic has a handful of functions, the cljs analyzer is basically just one "analyze"

14:04 justin_smith: oinksoft: macros can make things easier / cleaner for a specific use, but can make other uses more tedious. Please provide a sensible function only path also.

14:04 bbloom: everything else about the public contract is part of the implicit schema of the data

14:04 tbaldridge: You should start with the data your system is working with, then write functions that manipulate that data, then configure the execution of those functions with more data, and finally (and only if needed) write an actual API/DSL

14:05 oinksoft: tbaldridge: that's really good advice. it's easy to dwell on the API design. you know, fancy paint and stickers on the car :)

14:07 or maybe the steering wheel... b ut you can't steer something that doesn't drive, or uses the wrong gas

14:07 technomancy: hm; only ~300 responses on the leiningen survey. we had more last year.

14:07 mdrogalis: technomancy: I wasn't aware it was even out.

14:07 * technomancy points folks to https://lein-survey-2014.herokuapp.com/

14:08 technomancy: vote early; vote often

14:08 no wait, that's something else

14:08 yotsov: technomancy: where was it announced? it seems I am missing some channels

14:08 mdrogalis: Wait! No, I took the survey a while ago. :P

14:08 Just forgot :)

14:09 Crisis averted.

14:09 technomancy: yotsov: I posted it to the leiningen and clojure mailing lists a week or two ago

14:09 also twitter

14:09 yotsov: technomancy: ok thanks

14:09 `szx: so i'm trying to understand the reasoning behind the choice of seq functions implemented in core.reducers - e.g. i *think* first isn't there since it offers no benefit over lazyseqs, though not sure why take-while but no drop-while, no map-indexed, etc.?

14:10 also, any idea why (into [] (r/map identity {:a 1 :b 2})) would work in clojure but not clojurescript?

14:11 justin_smith: `szx: maybe you need to explicitly call seq on the hashmap literal?

14:11 bbloom: clojurebot: working is what does "not working" mean?

14:11 clojurebot: Pardon?

14:11 bbloom: clojurebot: working |is| what does "not working" mean?

14:11 clojurebot: I don't understand.

14:12 bbloom: i dunno how to use clojurebot :-P

14:12 `szx: bbloom: Error: No protocol method IReduce.-reduce defined for type cljs.core/PersistentArrayMap: {:a 1, :b 2}

14:12 justin_smith: calling seq on the hashmap should fix that error, yeah

14:12 hiredman: bbloom: the question mark at the end trips it up

14:12 bbloom: clojurebot: working is please define "not working"

14:12 clojurebot: c'est bon!

14:12 bbloom: ~working

14:12 clojurebot: working is please define "not working"

14:13 `szx: justin_smith: yeah, it just looks like it should work fine - https://github.com/clojure/clojurescript/blob/master/src/cljs/clojure/core/reducers.cljs#L40

14:13 bbloom: `szx: might be a bug

14:15 `szx: bbloom: yeah, looks like to me

14:16 bbloom: `szx: can you put together a minimal repo case and report it on jira?

14:16 `szx: bbloom: sure. checking to make sure it hasn't already been reported

14:18 in the meantime, back to my other question - is there a reason some functions are missing from core.reducers or is it just because nobody got to it yet?

14:22 brainkim: Does anyone have a good example project with unit-tests for an http-kit server? I'm trying to figure out if I'm going to have to mock websocket requests.

14:25 mdrogalis: brainkim: Try introducing small, local queues with core.async to get around that.

14:26 amalloy: `szx: i think only one or two additional reducers have been added since the original release of reducers. having attempted to define a couple myself (and had them deferred indefinitely), i'd say there's some question about how to define a reducer rich finds acceptable

14:27 nickmbailey: fa

14:28 brainkim: mdrogalis: That's prboably what I should do. I'm having a lot of trouble creating small functions core.async but that would be really testable.

14:30 mdrogalis: brainkim: Yeah, it works out great because the processor of the request doesn't need to know which thread the request came from

14:33 rtl: gs

14:37 brainkim: mdrogalis: Thanks. That works great. I have a global channel because I don't really know how to structure the request-handlers and shit, but it's making repl-based testing a lot easier.

14:40 mdrogalis: brainkim: Glad to hear it :)

14:40 brainkim: Try using stuartsierra's Component framework in conjunction with that technique. I've used it more than once so far, and I'm really happy with how it turns out.

14:40 That way you can use smaller channels and control the lifecycle easier.

14:42 bbloom: ,(if-let [[x & y] []] "grumble grumble" "makes sense")

14:42 clojurebot: "grumble grumble"

14:43 justin_smith: ,(if-let [[x & y] nil] "grumble grumble" "makes sense")

14:43 clojurebot: "makes sense"

14:43 rasmusto: ,(if-let [[x & y] []] [x y "grumble grumble"] "makes sense")

14:43 clojurebot: [nil nil "grumble grumble"]

14:43 rasmusto: ,(first '())

14:43 clojurebot: nil

14:44 bbloom: ,(when-let [[x] [1 2 3]] x)

14:44 clojurebot: 1

14:44 bbloom: ,(when-let [[x & _] [1 2 3]] x) ; i'd rather write this

14:44 clojurebot: 1

14:44 justin_smith: ,(let [[x & y :as z] []] [x y z])

14:44 clojurebot: [nil nil []]

14:44 justin_smith: the :as is what if-let actually sees I think

14:44 even if you don't bind it

14:45 bbloom: *shrug* maybe... destructuring works great when unconditional, but the sematnics of if-let, when-let, etc are a little flakey and seem like impl-details exposed

14:45 rasmusto: I don't like if-let

14:45 * rasmusto proposes some-let for fixing destructuring of nil

14:45 justin_smith: why not expand on the principle of if-let - let-defn for example

14:46 amalloy: bbloom: you seem to be asking for nil-punning for empty vectors? like, [] is truthy, so if-let really has to treat it as such

14:47 it can't know whether the destructuring accomplished your goals - it's not pattern matching

14:47 rasmusto: is it that? I thought it was just ##(let [[a & b] nil] [a b]) ; that was the issue

14:47 lazybot: ⇒ [nil nil]

14:47 bbloom: amalloy: yeah, it's what justin_smith said about the :as

14:47 it makes sense, but it's kinda pattern-matchy & i forget it's not proper pattern matching sometimes

14:47 amalloy: bringing :as into it seems, to me, just to confuse the issue, but i guess if it helps...

14:48 bbloom: amalloy: logically speaking, it's testing the truthiness of the :as value... when i really wish it was testing match success/failure

14:48 amalloy: bbloom: no, it's testing the truthiness of the expression you gave it; it doesn't know anything about :as, because there isn't one

14:49 justin_smith: amalloy: kind of agreed, the rhs is what if-let sees and :as binds, but that rhs has no name or binding so it was a shortcut to just refer to the :as value

14:49 bbloom: amalloy: sure, call it "as" or call it "rhs", same thing

14:51 amalloy: bbloom: it'd be interesting to write a destructurer that returns whether or not each variable was bound successfully. or does that basically require writing most of core.match?

14:51 ghadishayban: Any good solution for lagginess in Emacs/Cider repls when the output is huge?

14:51 amalloy: ghadishayban: clear the output buffer?

14:52 bbloom: amalloy: the bulk of core.match is related to optimizing the decision tree

14:52 mdrogalis: ghadishayban: I think rkneufeld just tweeted about that lol

14:52 amalloy: if a single output is huge, then probably don't output it all at once

14:52 mdrogalis: https://twitter.com/rkneufeld/status/453230902542622720

14:52 ghadishayban: oh wow

14:52 so the solution is don't

14:52 rkneufeld: Yeppers, I've been using naked lein repl and/or inferior lisp instead.

14:52 amalloy: slime+swank for life

14:53 <- trouble-maker

14:53 rkneufeld: I don't know if there is something I'm not doing with Cider to make things better, but it has generally been a pain.

14:53 mdrogalis: I tried it and put it down, just wasn't cutting it for me.

14:54 bbloom: amalloy: you can make indepent design decisions regarding the pattern, the conditional behavior, and the binding behavior

14:54 amalloy: our pattern syntax & binding behavior are very simple/nice, but i dislike the conditional behavior

14:55 amalloy: bbloom: i'm not sure i follow. the conditional behavior, if i understand what you mean, is not connected to patterns/bindings at all: if-let is an ordinary if, followed by a pattern-match/binding

14:56 you could write one that's a pattern-match/binding followed by some decision based on that, but it's not close to if-let, it's close to core.match

14:56 bbloom: amalloy: yeah, that's a design decision (and a reasonable one)... consider what happens when destructuring fails

14:57 ,(let [[x] 5] x)

14:57 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Long>

14:57 bbloom: in theory, the destructuring could return success or failure instead of just crashing

14:57 it's a relatively small change, actually

14:58 amalloy: i'm not sure it's *that* small, but i agree it'd be an interesting feature (as i did say above)

14:59 bbloom: small impl change, big impact to all code, of course

14:59 a naive impl would be pretty slow too compared to the existing approach

15:12 root__: can someone explain recursion ? (defn is-even? [n] (if (= n 0)

15:12 true

15:12 amalloy: root__: www.refheap.com

15:14 root__: https://www.refheap.com/73072 what does "not" do in this case ?

15:15 `szx: ,(not true)

15:15 clojurebot: false

15:15 `szx: ,(not false)

15:15 clojurebot: true

15:15 cbp: teletubs: it negates the value returned from (is-even? (dec n))

15:16 teletubs: cbp: I am lost, this code work but I don't know why ?

15:17 amalloy: teletubs: think of it in words, as a definition of even: "a number N is even if it is zero, or if N-1 is not even"

15:17 now try it on a few samples, by hand: 0, 1, 2, and 3 should be enough to see how it works

15:17 teletubs: amolloy: I did

15:18 amalloy: i mean like on paper or in your head, not typing it into the repl

15:18 doing that should help you understand *why* it works

15:27 trap_exit: consider a url of the form http://localhost:8080/?blah=foo

15:27 how do I read out the "blah=foo" part in clojurescript ?

15:29 dnolen_: (.. js/window -location -search) if you're trying to do this on the current url, or http://docs.closure-library.googlecode.com/git/class_goog_Uri.html

15:29 trap_exit: dnolen_: will read up on that, thanks!

15:33 miseria: "cuando la causa nos enloquece, el efecto nos destruye y el fin continuara siendo un sueño" bienvenidos: http://castroruben.com *temo_a_un_ser_sin_rival*

15:34 teletubs: amalloy: so its doing something along the lines of 2 -> not 1 -> not not 0 which is true right ?

15:34 amalloy: indeed it is

15:36 teletubs: haha THANKS. My head was begining to spin :)

15:39 Rakko: What's the best choice of text editor integration (especially in-editor REPL, syntax highlighting/indenting support, doc and symbol lookup) for a newbie to Clojure? I'm pretty comfortable with Vim, Emacs, and Eclipse.

15:40 justin_smith: Rakko: if you know all equally, Emacs has the best integration

15:40 Rakko: cool

15:40 bmabey: the others are decent too so you can't go wrong

15:40 Rakko: I have a tiny bit of experience with CL in SLIME

15:40 bmabey: emacs does have the most mindshare however

15:42 teletubs: How about big-integer recursion? https://www.refheap.com/73077

15:43 justin_smith: ,(dec (BigInteger. "1")) ; it should just work

15:43 clojurebot: 0N

15:44 cbp: teletubs: you don't need to distinguish between long and BigInteger in clojure

15:44 justin_smith: though really there are better ways to check even / odd status than iterating until you hit 0, that is merely a good way to demonstrate recursion, not a good way to do that task

15:44 $source even?

15:44 lazybot: even? is http://is.gd/LyGOJD

15:44 amalloy: &(inc Long/MAX_VALUE) ;; cbp

15:44 lazybot: java.lang.ArithmeticException: integer overflow

15:45 justin_smith: teletubs: see lazybot's link above for the right way

15:46 teletubs: though extending *that* to bigints (probably by doing modulus) would be interesting

15:47 or maybe a bigint bit-mask if such a thing exists

15:47 amalloy: justin_smith: it works fine for bigints, doesn't it?

15:47 an unchecked cast to long should just drop off the top N bits

15:48 cbp: Ok i mean you don't need to use the BigInteger methods when dealing with bigintegers, if your function gets passed a bigint it will work

15:48 justin_smith: ,(bit-and 1 (long (BigInteger. "11111111111111111111111111111111111111111111111111111111111")))

15:48 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for long: 11111111111111111111111111111111111111111111111111111111111>

15:48 justin_smith: amalloy: or what did you have in mind?

15:49 amalloy: ,(even? (BigInteger. "11111111111111111111111111111111111111111111111111111111111"))

15:49 clojurebot: false

15:49 amalloy: ,(unchecked-long (BigInteger. "11111111111111111111111111111111111111111111111111111111111"))

15:49 clojurebot: 1857484646311031239

15:49 justin_smith: oh, never mind then, thanks

15:50 cbp: you can just add N to the end to turn it into a bigint :-P

15:54 justin_smith: ,(= (BigInteger. (apply str (repeat 226 \1))) 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111N)

15:54 clojurebot: true

15:56 teletubs: amalloy: What is going on inside of that loop?

15:57 justin_smith: teletubs: do you mean the source to even? - if so, that is not a loop

15:57 amalloy: he means the refheap he pasted earlier

15:57 teletubs: justin_smith: https://www.refheap.com/73077

15:57 amalloy: tail-recursive even

16:08 tbaldridge: oh awesome....tools.cps is getting a re-work with tools.analyzer http://www.chrisfrisz.com/blog/2014/04/06/progress/?utm_source=dlvr.it&utm_medium=twitter

16:09 bbloom: tbaldridge: neat, but i've got my eyes locked on dynamic extent :-)

16:10 tuft_: ,(def foo.bar 2)

16:10 clojurebot: #'sandbox/foo.bar

16:10 tuft_: ,foo.bar

16:10 clojurebot: #<CompilerException java.lang.ClassNotFoundException: foo.bar, compiling:(NO_SOURCE_PATH:0:0)>

16:10 bbloom: tbaldridge: i'm definitely going to attempt what you suggested w/ JIT-compiling via clojure.core/eval

16:10 rasmusto: ,#'sandbox/foo.bar

16:10 clojurebot: #'sandbox/foo.bar

16:10 tuft_: ah ok, thanks

16:11 rasmusto: tuft_: I don't know what I just did

16:11 bbloom: tbaldridge: should be pretty doable to (clojure.core/eval `(fn [] ~(unparse ast)))

16:11 tuft_: tuft: er, actually yeah =)

16:11 rasmusto: ,(identity foo.bar)

16:11 clojurebot: #<CompilerException java.lang.ClassNotFoundException: foo.bar, compiling:(NO_SOURCE_PATH:0:0)>

16:11 tuft_: ,@#'foo.bar

16:11 clojurebot: 2

16:11 tuft_: gross but works

16:11 rasmusto: is it a clojurebot reader thing?

16:12 tuft_: i guess avoid dots in symbol names

16:12 amalloy: you're "not supposed to" use symbols with dots in them

16:12 rasmusto: oh, its looking for a class

16:12 justin_smith: rasmusto: all that will work the same in a repl

16:12 reader rules

16:12 amalloy: justin_smith: not reader, evaluator

16:12 rasmusto: ,(def -.-.-.- 2)

16:12 clojurebot: #'sandbox/-.-.-.-

16:12 justin_smith: oh, ok

16:12 amalloy: foo.bar reads as foo.bar

16:13 rasmusto: ,@#'-.-.-.-

16:13 clojurebot: 2

16:14 justin_smith: is there a matching trick in let?

16:14 sritchie_: justin_smith: what do you mean?

16:15 justin_smith: ,(let [... :silence] (apply str (repeat 2 (name ...))))

16:15 clojurebot: #<CompilerException java.lang.ClassFormatError: Illegal field name "..." in class sandbox$eval186, compiling:(NO_SOURCE_PATH:0:0)>

16:15 justin_smith: #' will not work there clearly

16:15 it's just a weird corner case of course

16:16 michaniskin: is there something like :refer-clojure that i can use in a ns declaration to exclude java mappings? like java.lang.Error is mapped to Error, for instance

16:17 amalloy: michaniskin: no, you're stuck with java.lang afaik

16:17 clojurenewb: hi, anyone know how to group a bunch of selector/transformer pairs to be able to re-use them with laser ?

16:18 michaniskin: amalloy: thanks :/

16:21 justin_smith: clojurenewb: I think you can make a map with selectors as keys and transformers as vals, then use apply

16:21 hmm... that could require a mapcat also

16:21 amalloy: clojurenewb: tell Raynes to release 2.0.0 - it turns those pairs into just vectors, so that you can hang onto them and combine them with just like (list pair1 pair2 pair2)

16:22 he's apparently been on 2.0.0-SNAPSHOT for nine months

16:22 Raynes: And decreases performance by about 400%.

16:22 Haven't had time to figure that out yet.

16:22 amalloy: feh, performance is for chumps

16:22 Raynes: Apologies.

16:23 clojurenewb: so is the plan for now this map idea ?

16:23 Raynes: Either way, selector and transformers are just functions. I'm pretty sure you can compose them in a reusable way in any version of laser.

16:23 justin_smith: based on an example, maybe something like this: (apply laser/document (laser/parse html) (apply concat {(laser/id= "hi") (laser/content "omg") (laser/class= "meow") (laser/content "omg)}))

16:23 technomancy`: clojurebot: it?

16:23 clojurebot: it is &env and &form

16:24 amalloy: a map sounds like a terrible idea, because you'd lose ordering

16:24 technomancy`: hm; I was hoping for "it is just a function"

16:24 justin_smith: though in practice the map would not be defined inline with the call of course

16:24 technomancy`: which I'm sure is buried in there somewhere

16:24 Raynes: I guess you can compose selectors and transformers individually, but not together.

16:24 That blows.

16:24 amalloy: well yeah, Raynes, that's why you made the changes in 2.0.0 :P

16:25 Raynes: I thought the reason was "this fundamentally makes more sense"

16:25 I never realized that it was actually adding features.

16:25 justin_smith: amalloy: fair point, so the map could be replaced by a vec of alternating selector / transformer, or a vec of two element selector / transformer vecs

16:25 clojurenewb: my only idea now is to combine then in some other element and re-write that… not a great idea

16:25 Raynes: Anyways, there are a few bugs in the 2.0.0 snapshot and the changes are woefully undocumented as such, but it works for the most part. It's slow as hell.

16:26 vendethiel: what'd be the clojure community "framework of choice" for clojure (and maybe clojurescript)?

16:26 Raynes: If all of those things are okay with you for now, then you can use that.

16:26 vendethiel: luminus?

16:26 justin_smith: another try: (apply laser/document (laser/parse html) [(laser/id= "hi") (laser/content "omg") (laser/class= "meow") (laser/content "omg)])

16:26 Bronsa: michaniskin: you can use ns-unmap though

16:26 Raynes: I think the Clojure community is too large for there to be any one canonical anything, vendethiel.

16:27 Luminus is a great way to start.

16:27 vendethiel: Raynes: that's the idea :)

16:27 Raynes: Some folks like Pedestal.

16:27 I'm a compojure guy.

16:27 I support luminus, if that matters to you at all.

16:27 yogthos gets stuff done.

16:27 I pretend to help.

16:28 vendethiel: well, I'm certainly interested at something that shows clojure's best parts, not something that "gets stuff done" but is hacky (if that's what you meant)

16:28 clojurenewb: justin_smith: I don’t think thats what I am looking for, that is one selector and multiple transformations

16:28 mynomoto: vendethiel: I think Hoplon is a good framework.

16:29 justin_smith: clojurenewb: really? it should bbe taking them pairwise

16:29 vendethiel: mynomoto: thanks, noted

16:29 justin_smith: clojurenewb: so two selectors in the example I adapted above

16:30 clojurenewb: justin_smith: I will see if I can get it to work, thanks

16:31 justin_smith: I assume laser/document takes any number of alternating selectors and transformers, if so that would be the usage pattern for reusing some set of selectors / transformers repeatedly

16:31 s/the/a

16:34 clojurenewb: justin_smith: oh.. ‘Don't know how to create ISeq’ when I pulled in a function that used ‘apply’ over a few pairs of selector/transformer (pulled in to a defdocument)...

16:35 yogthos: @Raynes I just mostly glue stuff together and document it :P

16:36 Raynes: clojurenewb: I really don't think you can do this without digging into the 2.0.0 snapshots.

16:36 That whole branch of development is adding the feature you want.

16:36 It's very similar to compojure's middleware.

16:37 Compiles all selectors and transformations into functions calling functions calling functions (yo dawg).

16:37 And gives you the power to do that.

16:37 justin_smith: clojurenewb: they should be all in a flat list, not pairs

16:37 clojurenewb: Raynes: ok thanks… I probably can’t use it yet though as you mentioned the preformance difference… its to go into production :-)

16:37 justin_smith: list/vector/whatever

16:37 clojurenewb: justin_smith: I’ll try again

16:38 Raynes: clojurenewb: Well, the version you're using probably isn't bleeding fast fwiw. Enlive is inevitably much faster as Christophe put a lot of effort into making that be the case.

16:38 michaniskin: Bronsa: ns-unmap was just the thing. thanks!

16:38 Raynes: I put a lot of effort into keeping the code base as small and trivial as possible.

16:39 clojurenewb: Raynes: I think laser is awesome by the way… did not mean to sound negative, thanks for a cool library

16:40 Raynes: Of course! Feel free to yell at it or me at any time. I've dug myself this hole by letting 2.0.0 go unworked on for so long despite squeeling for two months about how laser was going to be better maintained than enlive.

16:40 It certainly isn't abandoned though. I just need to spend a weekend or so on it.

16:41 clojurenewb: I know the feeling… so much to work on, so little time

16:45 blake__: Trying to comprehend this function definition, specifically the meaning/purpose of the "->": (defn func->func-info [func]

16:46 bbloom: blake__: it's just part of the name

16:46 ,(symbol "foo-><-bar")

16:46 clojurebot: foo-><-bar

16:46 bbloom: ,'<><><><>---<><<><---,

16:46 clojurebot: <><><><>---<><<><---

16:47 blake__: oh...huh...not used to all the punctuation yet...just got accustomed to minus signs not being minus signs =P

16:47 rasmusto: ,(let [map->vec (fn [m] (mapv vec m))] (map->vec {:a 1 :b 2}))

16:47 clojurebot: [[:b 2] [:a 1]]

16:47 tuft_: blake__: even the minus sign is just a symbol name in clojure =)

16:47 rasmusto: (bad example, just showing the naming) :P

16:47 justin_smith: blake__: rule of thumb, anything but ()[]{}#. will be part of a name unless separated by some space

16:48 bbloom: justin_smith: eh... or ~ or @ or , or a lot of things

16:48 blake__: Right...that's another one that gets me--significant spaces.

16:48 bbloom: blake__: the AMOUNT of space isn't significant. just the fact that it exists...

16:48 justin_smith: even in c ab isn't the same as a b

16:48 * rasmusto thinksthatspaceissignificant

16:49 * bbloom parse error: unknown symbol: thinksthatspaceissignificant

16:49 rasmusto: quantity of space shouldn't matter though :)

16:49 bbloom: blake__: while we're at it... commas are whitespace in clojure

16:49 blake__: right...significant space...well, punctuation not used a separator...not complaining, just retraining the brain...

16:49 bbloom: ,(+ 5 ,,,,,,,,,,,,,,,,,,, 10)

16:49 clojurebot: 15

16:50 blake__: bbloom: That I knew and adapted to quickly. For whatever reason.

16:50 rasmusto: ,(,,+,,5,,,,,,,,,,,,,,,,,,,10,,)

16:50 clojurebot: 15

16:51 bbloom: commas as whitespace is one of those awesome ideas i could have never though of in a million years

16:51 jcromartie: trying to figure out how to render (╯°□°)╯︵ ┻━┻ as a symbol

16:51 I mean usable

16:51 bbloom: ,(symbol "(╯°□°)╯︵ ┻━┻")

16:51 clojurebot: (?�?�??? ???

16:51 bbloom: heh

16:51 rasmusto: AHhaha

16:51 blake__: heh

16:51 justin_smith: &(symbol "(╯°□°)╯︵ ┻━┻")

16:51 lazybot: ⇒ (╯°□°)╯︵ ┻━┻

16:51 jcromartie: well aside from that

16:51 justin_smith: (inc lazybot)

16:51 lazybot: ⇒ 24

16:51 jcromartie: :P

16:51 bbloom: no, don't reward lazybot for unicode support!

16:52 it's fucking 2014

16:52 (dec clojurebot)

16:52 lazybot: ⇒ 39

16:52 justin_smith: hah

16:53 amalloy: truly we are in the future, where computers can recognize, like any sane person, that ┻━┻ is text

16:54 rasmusto: ^I disagree

16:55 technomancy: clojurebot: ┻━┻ is text.

16:55 clojurebot: c'est bon!

16:55 hiredman: ring and the servlet api defaults to iso whatever

16:57 technomancy: technically the IRC RFC states the encoding of messages is "unspecified"

16:58 clojurebot: ┻━┻?

16:58 clojurebot: ┻━┻ is text.

16:58 technomancy: the you have it

16:58 there

16:58 AmandaC: Most of the english-speaking world has settled on UTF-8 for IRC though.

16:58 justin_smith: ,(let [(╯°□°)╯︵┻━┻ (fn [WTF] (throw WTF))] ((╯°□°)╯︵┻━┻ (Exception. "TABLE"))

16:58 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

16:58 justin_smith: hmph

16:59 technomancy: AmandaC: sure; being pedantic

16:59 AmandaC: :p

16:59 technomancy: "You are technically correct." / "Which is the best kind of correct; amirite?"

16:59 justin_smith: ,(let [(╯°□°)╯︵┻━┻ (fn [WTF] (throw WTF))] ((╯°□°)╯︵┻━┻ (Exception. "TABLE")))

16:59 clojurebot: #<Exception java.lang.Exception: TABLE>

17:01 modulus: Hi, I'm having an odd issue with korma, I think related to macros. Say I have a db table called widgets. I can't do this:

17:01 (select wiedgets (if true (where {:id 1})))

17:01 I get a wrong number of args for where

17:02 though (select widgets (where {:id 1})) works fine

17:02 justin_smith: modulus: macros are weird

17:02 modulus: i need to be able to build conditional where clauses, so any clues how to go about it instead?

17:03 justin_smith: modulus: to programmatically interface with code that is a macro, you should make another macro

17:03 (or find a non-macro-using way to do it, of course)

17:03 modulus: that sounds like an awful idea....

17:03 justin_smith: remember that if is a macro

17:03 scape_: I'm having trouble with gen-class and creating my own class, I mocked up an example to show what I mean. #<CompilerException java.lang.ClassNotFoundException: cljtest.core.Test, compiling:(cljtest/main.clj:4:1)>

17:03 justin_smith: (if true (select widgets (where {:id 1})))

17:03 scape_: https://www.refheap.com/73085

17:05 justin_smith: modulus: since a macro represents a changed syntax, it often won't do what you want with arbitrary inline values, which is why the solution is usually use yet another macro, or don't use macros in the first place

17:06 modulus: nwjsmith___: yeah but the problem is i need to build quite a few different where conditions, depending on several things, so if i have to put the select in the if i'm pretty screwed.

17:06 er wrong completion, apologies.

17:07 justin_smith: np. Yeah, I would check if korma has a layer that just uses vanilla data as input. If not, construct the call in your own macro or don't use korma?

17:08 modulus: hmm maybe the starred forms will work, I'm going to try that

17:08 hiredman: ,(symbol "(╯°□°)╯︵ ┻━┻")

17:08 clojurebot: (╯°□°)╯︵ ┻━┻

17:09 justin_smith: ,'(╯°□°)╯︵┻━┻

17:09 clojurebot: (╯°□°)╯︵┻━┻

17:09 justin_smith: sweet

17:09 scape_: Why do I receive a classnotfound when compiling my code? am I using gen-class wrong? what am I missing?

17:10 justin_smith: scape_: maybe try putting the constructor in a function so it is not called at load time, but can be delayed until after everything else is loaded and compiled?

17:11 scape_: since classes can have side effects at creation time, putting a constructor at the top level is probably a bad idea anyway

17:11 (otherwise loading the namespace has sideeffects, which is bad)

17:12 scape_: i'll try that

17:12 justin_smith: also, I am not totally sure what that ^:skip-aot does, but it is suspicious

17:13 scape_: it shipped with my lein new app, I removed it and tried aot it also received same error

17:15 modulus: heh starred forms don't ... quite ... do it

17:15 scape_: justin_smith: I got the idea from here https://github.com/libgdx/libgdx/wiki/Using-libgdx-with-Clojure

17:15 where they use a class to initiate the game

17:15 i'll try another way, thanks :)

17:16 justin_smith: scape_: yeah, but they do the right thing and make the instance inside -main

17:16 that is different from the top level, -main should actually have side effects

17:17 and you should probably similarly create the class inside -main - or restructure things and not use classes, since usually that pattern of usage is for when you are using some lib that is from java, and there is no need if the defining code is clojure

17:19 scape_: this is true, i also couldn't get their code to compile :-\ but the lib is from java hence the class thing. I probably have an alternative i'll check out

17:20 modulus: hmm so

17:20 (-> (select* widgets) (where {:id 1}) (select)) works

17:20 but again, using if breaks it

17:20 i don't understand what's going on with the macros here which is confusing me

17:21 justin_smith: scape_: if you have something that should always be a singleton, you can just have a namespace with an init function and some vars for "fields" and defns for "methods" (if the fields are not immutible the var should hold a ref or atom). Otherwise there are things like a defn that returns a map plus some functions that expect that map as an arg.

17:21 rasmusto: ,(macroexpand (-> (select* widgets) (where {:id 1}) (select)))

17:21 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: select in this context, compiling:(NO_SOURCE_PATH:0:0)>

17:21 rasmusto: ,(macroexpand '(-> (select* widgets) (where {:id 1}) (select)))

17:21 clojurebot: (select (where (select* widgets) {:id 1}))

17:24 modulus: how do i see the expansion of a macro?

17:24 justin_smith: modulus: same way rasmusto did

17:24 modulus: quote the form, and call macroexpand on it

17:25 modulus: hmm

17:25 i forgot to quote

17:29 tuft: was using this handy datomic-schema lib, but the side-effecting defs bit me https://github.com/Yuppiechef/datomic-schema/blob/master/src/datomic_schema/schema.clj

17:29 modulus: heh, some weird transform

17:29 (macroexpand '(-> (select* widgets) (if true (where {:id 1}))))

17:29 (if (select* widgets) true (where {:id 1}))

17:29 I've no idea how the first becomes the second

17:29 tuft: were i to refactor, is the clojure test approach the way to go? i.e. use (ns-interns) instead of what this is doing with atoms?

17:29 justin_smith: modulus: -> is a macro, it just inserts each form into the next

17:31 ,(macroexpand '(-> long (very and boring) (a story)))

17:31 clojurebot: (a (very long and boring) story)

17:31 modulus: ahh, i see now, so the problem is the if is being threaded

17:31 justin_smith: well, a form is being threaded into if, but yeah

17:32 modulus: i thought if would execute first for some reason

17:32 rasmusto: modulus: yeah, stuff like that gets messy, and can be worked around (messily) with #(if blah % somethingelse)

17:32 justin_smith: ~macros

17:32 clojurebot: Barking spiders!

17:32 rasmusto: ~macro

17:32 amalloy: not sure whether to inc or dec clojurebot for that...

17:32 clojurebot: Holy Crap.

17:38 modulus: Well, thanks; I still don't know how to do conditional wheres but I'll think about it.

17:39 justin_smith: You could make a function that constructs the form to be called at compile time. What could go wrong with that?

17:44 tuft: need to stop programming clojure. python code getting hard to look at. =)

17:44 bohford: hard to go back isnt it

17:44 tuft: i keep trying to do structural editing, too

17:45 rasmusto: map(lambda x: x + 1, [1, 2, 3])

17:46 justin_smith: there are also things like the runtime that will gladly let libraries write outside array bounds

17:46 (that whole "reading a utf7 web page corrupts your couchdb instance" bug for example)

17:47 rasmusto: map(lambda x: x.append("foo"), [[1, 2] ["a", "b"]])

17:47 whoops, missed a comma

17:49 amalloy: i just looked up utf-7. who would ever use that?

17:49 justin_smith: amalloy: no idea? but if a webpage says it is utf7, one should parse as utf7 or fail I guess

17:50 bbloom: isn't that for like MIME headers or something?

17:50 yeah, imap uses it b/c email headers have to be in ascii

17:51 so basically no one would ever use it... if they could help it

17:51 justin_smith: http://rspeer.github.io/blog/2014/03/30/unicode-deadbeef/ title is funny (they blame text encodings rather than the insecure architecture of their runtime)

17:59 tbaldridge: unicode in Python is a mess anyways

18:00 justin_smith: I am tempted to generalize that statement

18:00 tbaldridge: true

18:00 but there are times where python obeys the encoding of the terminal the interpreter is started in

18:02 justin_smith: you could generalize over "unicode" or "Python" actually

18:02 the intersection is of course a little quagmire

18:33 scape_: justin_smith: got my test class to compile, I threw it in a main and then put :aot :all in project file. now i'll try fixing my actual issue with the java lib i'm using. thanks for the ideas

18:34 justin_smith: scape_: glad you worked it out

18:34 it should suffice to only aot the :genclass ns

18:35 scape_: yea, i figured but wanted to make sure :)

18:35 justin_smith: yeah, easier to have something that works and refine from there, to be sure

18:38 NicoArg: hello :) im from argentina

18:38 justin_smith: hello

18:39 NicoArg: chat me.. i dont kwnow write in english so much haha

18:39 i want learn more

18:40 rasmusto: NicoArg: http://www.clojurebook.com/ http://joyofclojure.com/

19:04 amalloy: huh, another function i didn't know was in clojure.core: find-var

19:04 i've always seen resolve used instead

19:05 `szx: amalloy: just saw your response re: the missing reducers - so you're saying in principle you don't see any reason why one shouldn't use r/drop-while, r/map-indexed, etc.?

19:05 tuft: ,(find-var `str)

19:05 clojurebot: #'clojure.core/str

19:05 tuft: cool

19:05 bbloom: huh, how does it differ from ns-resolve? it only does namespace qualified vars?

19:06 `szx: s/use/implement i guess

19:06 amalloy: `szx: implementing transformers like that isn't too bad - it's implementing new sources entirely, like range or repeat, that's fraught with problems

19:08 bbloom: well, ns-resolve uses the current namespace (including ns aliases), and also lets you resolve in a different namespace

19:08 it looks like find-var only accepts canonical names

19:08 bbloom: amalloy: makes sense

19:11 justin_smith: yeah, seems like find-var reduces the complexity and removes a potential failure point if you know the full ns and don't care about aliases

19:15 gtrak: if you tap into a mult, and that target channel is closed, seems like we need to untap it from the mult, too? What's the expected effect if you don't? also, if one of the taps of the mult has a full queue, does that also block the mult, and consequently all other taps?

19:19 justin_smith: I am trying to figure out how to use cemerick/friend - is there some simple example of using a :credential-fn (or replacement for one?) that does not require a map with an entry for every user?

19:19 I already have users in a db, and having to update some map every time I update the db seems like the wrong thing

19:21 hiredman: justin_smith: https://github.com/hiredman/ideapad/blob/master/src/com/thelastcitadel/ideapad.clj has a lot of moving parts, but it uses friend to do basic auth, authenticating a user against another service with a rest api

19:21 justin_smith: hiredman: awesome, thanks

19:22 hiredman: justin_smith: I think the thing you are missing is it doesn't have to be a map, it can be any function that takes a username and returns whatever friend wants

19:22 for :credential-fn

19:22 justin_smith: ah, that is much better, and totally compatible with my setup

19:24 (inc hiredman)

19:24 lazybot: ⇒ 39

19:27 bbloom: amalloy: what i really need is ns-resolve that doesn't find java classes...

19:28 oinksoft: bbloom, why?

19:29 bbloom: oinksoft: crazy esoteric experiment bootstrapping reasons

19:32 oinksoft: bbloom, i see, just curious :)

19:38 kenrestivo: X-In-Like-Flynn? o_0

19:39 hiredman: I needed to add an extra header for some reason which I no longer recall

19:39 technomancy: flynn from tron?

19:40 justin_smith: errol flynn's autobio is a rollicking tale, btw

19:41 hiredman: it rhymed *shrug*

19:46 bbloom: how do people feel about the distinctions between clojure.core and cljs.core ?

19:46 iirc, one gets re-routed to the other, right?

19:48 oinksoft: is it normal to design a clojure program around records/protocols?

19:48 justin_smith: oinksoft: in my experience program no, but library yes

19:49 oinksoft: justin_smith, this is a logging library

19:49 justin_smith: then yes, please do it that way

19:49 bbloom: i just replaced about 15 record types with two record types. my program got simpler AND faster

19:49 justin_smith: awesome

19:50 oinksoft: bbloom, i didn't bring it up yet, but performance was once concern i had about using a bunch of protocols. do i pay for that at compile time or runtime?

19:50 bbloom: yes

19:50 oinksoft: haha

19:50 ok

19:50 hiredman: megamorphic calls not fast, news at 11

19:51 bbloom: oinksoft: seriously though, start with a multimethod if you only have one generic function.

19:51 only define a protocol if you need it

19:51 only define a record or deftype if you need it

19:51 basically, use plain old data unless you need to dispatch on type a lot

19:52 oinksoft: bbloom, OK that was what i was wondering about. as i was designing i could see how most parts of it could be described through protocols

19:52 bbloom: oinksoft: that *might* be true for your problem or it could be brain damage from past languages

19:52 oinksoft: bbloom, in erlang it's normal to use a record /-type for anything because you only pay for that at compile time

19:52 sdegutis: How do you usually distribute a .jar file created with `lein uberjar` but from another project than your own? I'm trying to distribute REPLy to my remote server.

19:52 bbloom: oinksoft: i couldn't tell you unless i tried to implement whatever you're implementing ;-)

19:52 oinksoft: bbloom, so i didn't just want to go headlong into doing it in the erlang way :P

19:53 bbloom, sure, let me provide a concrete example

19:53 bbloom: oinksoft: i dunno much erlang, but it's probably better to go erlang -> clojure style than to go java -> clojure style :-P

19:53 technomancy: erlang uses records in a lot of places simply because proplists are ugly and maps are too new

19:53 clojure luckily has had maps since the start =)

19:54 gtrak: maps, fancy

19:54 oinksoft: bbloom, as i typed out the concrete example i got my answer, this was not a place for a record/protocol

19:54 technomancy: gtrak: http://thisotplife.tumblr.com/post/81168432835/when-i-heard-erlang-now-has-maps

19:54 bbloom: ha

19:54 sdegutis: It seems wrong to just compile the jar and stick it into my git repo..

19:55 bbloom: sdegutis: it is

19:55 oinksoft: technomancy, heh i have no problem w/ records, keep programs simple

19:55 gtrak: hah

19:55 sdegutis: I could clone REPLy and create an uberjar on-demand, and use that..

19:55 oinksoft: technomancy, proplists are mostly *slow*

19:55 sdegutis: It seems equally wrong to make REPLy a submodule of my repo.

19:55 gtrak: sdegutis: that IS wrong

19:55 sdegutis: gtrak: which one

19:55 gtrak: the first

19:55 sdegutis: Okay yea.

19:55 technomancy: oinksoft: maybe they don't seem as ugly if you aren't accustomed to maps =)

19:56 oinksoft: technomancy, probably more like stockholm syndrome

19:56 gtrak: sdegutis: is reply pure clojure? just eval it :-)

19:56 bbloom: oinksoft: fast immutable maps are LIFE CHANGING

19:56 oinksoft: bbloom, ah well those i havent used yet, except now in clojure

19:57 sdegutis: gtrak: I don't want Leiningen on the remote server, just Java.

19:57 technomancy: gtrak: also http://thisotplife.tumblr.com/post/76346999236/other-peoples-reaction-when-i-say-erlang-is-about-to

19:57 sdegutis: gtrak: REPLy is only gonna be there for debugging etc.

19:57 gtrak: well, the normal clojure repl is always there, if it's a clojure app.

19:57 you can eval arbitrary strings in there, which can include full libraries if you're trying hard enough :-)

19:58 * gtrak has done this before

19:58 gtrak: gotta run though, later

19:58 sdegutis: Alternatively maybe I can compile REPLy into my app, and just run it through my app...

19:59 That seems the easiest but maybe not the cleanest route.

20:03 oinksoft: what does it mean if i see (def fn (partial fn* unbound-thing)) ? where does unbound-thing come from?

20:04 if it matters, unbound-thing is also the name of a protocol method

20:05 hiredman: protocols don't have methods

20:05 they are collections of functions

20:05 oinksoft: wasn't sure of the terminology

20:05 *function

20:06 hiredman: that name is the name of a function, just like (defn foo ...) and foo names a function (it actually names a var which holds a function but whatever)

20:08 oinksoft: but there is no (defn unbound-thing) in this source file or imported

20:08 hiredman: oinksoft: you said it is part of a protocol

20:09 oinksoft: hiredman, it is, (defprotocol Proto (unbound-thing [arg] ....))

20:09 hiredman, this defines unbound-thing, unqualified, globally to my source file?

20:10 hiredman, that seems weird, what if i define two protocols that happen to share a function name

20:10 hiredman: oinksoft: they have to go in different namespaces

20:11 bbloom: oinksoft: what happens if you name two functions the same thing?

20:11 hiredman: ^-

20:12 bbloom: oinksoft: by "unbound" do you mean "unqualified"

20:12 oinksoft: oh!

20:12 Warning: protocol #'user/P is overwriting function f

20:12 this is surprising but now i know what is happening

20:12 bbloom: why is this surprising?

20:12 oinksoft: bbloom, well typically if i don't spend jack shit to study something i just understand it, you know? ;)

20:13 bbloom: *shrug*

20:13 oinksoft: bbloom, if a protocol is just a collection of functions that can operate on a record type, it makes a lot more sense

20:13 bbloom, i was thinking about this inside-out

20:13 bbloom: they can operate on any JVM type

20:13 plus nil, which isn't really a type :-P

20:13 oinksoft: yea, this is very nice

20:15 bbloom, hiredman, thanks for the help

20:20 tadni-: Are there any introductory (as in near to complete beginner) to programming text, in Clojure? All I can find assumes prior knowledge.

20:20 technomancy: tadni-: I don't think anything like that exists. clojure is not a great language to learn programming in.

20:21 bob2: suspect you'd be better off starting with python or ruby

20:21 technomancy: heavens no

20:21 start with racket

20:21 I mean, unless you are looking to use it professionally with little delay

20:22 amalloy: guys i found an amazing feature slime/swank has that's not present in cider: swank.core/read-from-emacs-minibuffer

20:22 technomancy: amalloy: I implemented that in nrepl-discover =P

20:22 amalloy: there's y-or-n-p support in there as well, although it's hidden

20:24 tadni-: I've been looking into elisp, for a practical skillset I could learn. Pretty sure they have an introductory text.

20:24 Bronsa: amalloy: woah

20:25 technomancy: tadni-: elisp is certainly more practical than racket. unfortunately it is very imperative. but the built-in intro is good, and the first half of Practical Common Lisp is very relevant too.

20:25 amalloy: i don't know how i would use that, technomancy. even reading through the docs and the source for nrepl-discover

20:25 technomancy: nrepl-discover has docs??

20:25 lazybot: technomancy: Uh, no. Why would you even ask?

20:25 Bronsa: now I need to find a way to use that

20:25 amalloy: well it has a readme

20:25 technomancy: yeah

20:25 it's pretty half-baked ATM

20:25 amalloy: Bronsa: i actually discovered it because i had a way to use it!

20:25 technomancy: but it's a lot nicer to extend than swank

20:26 scape_: is it possible with leiningen to have it include certain dependencies based on something specific when running lein?

20:26 amalloy: writing a program for work that prompts the user to fill in the blanks in some auto-generated data; i was giving it swappable ui bits, for gui/cli, and discovered i could add a slime/swank backend for myself as well

20:26 Bronsa: I feel a bit bad not using nrepl/cider but everytime I tried moving from slime/swank I ended up switching back after less than a day :(

20:27 technomancy: scape_: sure, as long as "something specific" is "which profiles are active"

20:27 scape_: okay, so it's profiles I should look into? thanks technomancy

20:29 amalloy: Bronsa: see also (#'swank/send-slime-command-to-emacs-and-wait :y-or-n-p prompt)

20:29 sadly that's a bit fragile - if you C-g out of it, clojure gets really sad

20:30 technomancy: amalloy: in nrepl-discover you just attach metadata to a function that says it's a command that should be invokeable from the editor

20:30 you can even provide various completion options

20:30 amalloy: technomancy: how does that help?

20:30 the goal is to go the other direction: let clojure call y-or-n-p

20:30 or, anyway, the goal of this feature in swank

20:30 technomancy: oh, but you can't prompt in the middle of an existing function call; never mind

20:31 amalloy: i have like (when (y-or-n-p "dude this looks bad, are you sure?") (jdbc/delete-everything-forever))

20:32 technomancy: yeah, nrepl is request/response

20:32 no SSE

20:38 tadni-: Ok

20:38 Well, thanks for the advice tech.

20:38 I'll look into racket more in-depth.

20:38 Peace people.

20:40 technomancy: oh he left before I could recommend HDTP =(

20:40 HTDP rather

20:41 cespare: What's the general convention for naming your deftest? I've been browsing some popular projects and it seems like a common choice is either just the name of the general thing/concept (e.g. 'deftest serialization') or to suffix with -test if it's a unit test for a function ('deftest conj-service-test')

20:41 amalloy: i was in the middle of telling him he could use tab-completion instead of calling you tech

20:41 cespare: some folks use test- as a prefix instead

20:42 amalloy: naming of tests is the wild west. stake your claim

20:42 cespare: amalloy: I'm coming up with a recommendation to replace the insano practice we seem to have here of calling it foo-bar-works-as-expected

20:42 :)

20:44 kras: can I control the number of threads spawned by pmap/pcall?

20:44 Emulating a thread pool

20:45 hiredman: you don't, so use a thread pool

20:45 ~pmap

20:45 clojurebot: pmap is not what you want

20:45 `szx: kras: again, https://github.com/TheClimateCorporation/claypoole

20:49 kras: `szx: this seemed like a basic usage and I thought the language ought to have some built-in

20:49 sorry for the repetition

20:50 `szx: kras: no worries. nothing built-in afaik

20:51 kras: so when I say (pmap inc [1 2 3 4 5]) it spawns 5 threads?

20:51 hiredman: no

20:51 it is much more annoyingly complicated

20:52 kras: :-(

20:52 hiredman: right, it is a gimmick, looks good in demos, is bad

20:56 ,(doc pmap)

20:56 clojurebot: "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."

20:57 gfredericks: "... and where function execution times have a low variance."

21:01 hiredman: "... and watch out for chunked seqs"

21:02 gfredericks: really?

21:02 is pmap implemented in ignorance of chunking?

21:04 amalloy: yes

21:04 pmap is implemented in ignorance of everything

21:04 gfredericks: ,(->> (range 10) (pmap print) (first))

21:04 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

21:05 gfredericks: that's exciting

21:06 amalloy: i wrote like a mediocre pdorun earlier: https://www.refheap.com/feee08c4a29bbd104005e5240

21:08 hiredman: we have a pdoseq at work, which I like, because I wrote it, but no one else has ever used it

21:08 gfredericks: there's a library that wraps all the executor stuff

21:08 has its own pmap & such

21:08 amalloy: executors are fine though

21:09 gfredericks: a little bit noisy if you use them a lot

21:09 amalloy: and pmap using wrapped executors doesn't sound likely to be much better than clojure.core/pmap anyway?

21:09 gfredericks: I haven't jumped to using said library though so apparently I'm on your side of it

21:10 well if you do it eagerly you're at least not subject to variance issues

21:10 amalloy: like, for my do-jobs, i was able to run job n+100, even if job n takes a really long time

21:10 (because i don't care about order)

21:10 gfredericks: sure; but executors can do that

21:11 amalloy: pmap needs to be eager to make that possible

21:11 gfredericks: sure

21:11 (like I said)

21:11 amalloy: right. it's just, you were saying it offhand, like "and pmap has to be eager". but that's a big deal

21:11 gfredericks: I say all my big deals offhand

21:12 hiredman: I really want some like (pipeline [queue-size threadpool-size some-function] [queue-size threadpool-size next-function] [" " "] ...)

21:12 gfredericks: I guess my hunch is that most people who jump to pmap care a lot more about parallelizing than they do about laziness

21:20 hiredman: clojure.core really doesn't have anything good for organizing multithreaded io stuff

21:22 bob2: may want claypoole

21:22 gfredericks: I think that's the library I was mentioning

21:32 noprompt: dnolen_: yeah, we have no idea what's causing the random errors. they're generally weird occasionally related to a ^@ character which we have idea what it's about.

21:32 java.lang.Error: Not a valid base 64 digit:

21:32 it could be a library but it's hard to say.

21:34 it still seems to be source-map related though. that last error comes from cljs.source-map.base64/decode.

21:57 kenrestivo: i feel bad for the guy who made gorilla. great idea, but now he's likely to get mired in browser incompatibility hell.

21:57 s/gorilla/any web app/g

22:23 scottj: kenrestivo: I felt bad for him because right after gorilla was released session was released and had a clojure/west talk and since they looked similar to me on first glance I thought gorilla would get overshadowed, but it appears that they have roughly the same number of github stars so I guess they're both doing fine.

22:34 zanes: Has anyone had issues AOT-compiling core.match :or expressions?

22:34 I think I may have found a regression.

23:16 Jaood: is there a function to get only the values that have been realized in a lazy-seq?

23:18 amalloy: Jaood: see: (doc take-while), (doc realized?)

23:18 mercwithamouth: o_O i'm looking at zippers and wow am i 'comfused'

23:25 amalloy: mercwithamouth: i suggest you don't worry about it - you don't need zippers, whatever your problem is

23:26 Jaood: amalloy: thanks

23:26 mercwithamouth: amalloy: good to know. i'll add them to my todo list and come back

23:27 amalloy: i guess the exception is "help someone gave me a zipper how do i use it"

23:27 mercwithamouth: definitely something i'd like to have a strong hold on but right now they're making my head hurt

23:27 i'm just going through 'clojure programming'

23:28 Jaood: mercwithamouth: what page?

23:28 mercwithamouth: Jaood: 152

23:29 skipping to concurrency and parallism...

23:29 Jaood: hah

23:29 you are ahead of me, page 95 still

23:31 amalloy now me wonder if I should skip that part too

23:33 +made

23:33 mercwithamouth: =P i have a few days off from work. I spent around 7 hours the other night going through it

23:33 after Part II i'll jump to the web programming in clojure book

23:35 Jaood: same, although some parts of chapter 8 are really useful to know

23:36 for daily clojure

23:36 mercwithamouth: true...i've done a bit of tinkering on the side so i'm getting pretty comfortable with namespaces and organization in general. i'll take a look over it though

23:45 Jaood: amalloy: so is there are pattern to replace zippers? or is a just don't do it that way?

23:46 amalloy: Jaood: you just don't need them. like, in certain esoteric scenarios, they are handy to have for sure. but if you are learning clojure, and think "i need zippers for this", you are wrong

23:46 and all you need is a recursive function, usually

23:47 they're pretty good for working with xml, i guess, if you have a reason to do that

23:51 Jaood: amalloy: got it

23:53 oinksoft: i'm having a hard time writing recursive functions in clojure, i am used to processing off the head of a list in erlang ... how do i recursively process a list in clojure?

23:53 i couldn't even find a function to take all but the head

23:55 sjy: oinksoft: use 'rest'

23:57 bob2: you may want map or filter or reduce instead though

23:58 mercwithamouth: any tutorials out there that go over building a compojure webapp 100% without hiccup?

23:58 bob2: what do you want to use instead?

23:59 Jaood: mercwithamouth: do you already know ring well?

23:59 oinksoft: bob2, i just want the first non-nil value of a list of functions when applied

23:59 bob2, if-let looks promising if i knew what it did, the examples are not very clear to me

23:59 Jaood: mercwithamouth: the book you mentioned covers that I think, the show how to use selmer too

23:59 mercwithamouth: Jaood: well..no but i've toyed a little with it along with both enfocus and om

23:59 beamso: mercwithamouth: http://www.luminusweb.net/

Logging service provided by n01se.net