#clojure log - Jul 29 2014

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

0:02 danielcompton: Seeking to simplify the JMX api, I have made something far more terrible

0:05 justin_smith: danielcompton: beware, those who would look into the JMX API, for the JMX API also looks into you

0:05 danielcompton: (inc justin_smith)

0:05 lazybot: ⇒ 54

0:06 arrdem: (inc justin_smith)

0:06 lazybot: ⇒ 55

0:06 arrdem: they dug too deep and too greedily and awakened some ancient evil...

0:06 Balveda: (defn deffer [x] (println "heyo " x))

0:07 no defns huh

0:07 (deffer "e")

0:07 justin_smith: Balveda: clojurebot uses ,

0:07 Balveda: ,?

0:07 justin_smith: the (inc person) syntax is a pseudo-clojure command for karma tracking

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

0:07 rpaulo: I installed ac-nrepl and now I get: which-func-ff-hook error: (scan-error "Containing expression ends prematurely" 8 9)

0:07 whenever I open a clojure file in emacs

0:07 danielcompton: JMX will ins​tantly transport a programmer's consciousness into a world of ceaseless screaming, he comes, the pestilent slithy regex-infection wil​l devour your JMX parser, application and existence for all time like Java only worse he comes he comes do not fi​ght he com̡e̶s, ̕h̵i​s un̨ho͞ly radiańcé destro҉ying all enli̍̈́̂̈́ghtenment, MBeans lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain, the song of JMX

0:07 parsing will exti​nguish the voices of mor​tal man from the sp​here I can see it can you see ̲͚̖͔̙î̩́t̲͎̩̱͔́̋̀ it is beautiful t​he final snuffing of the lie​s of Man ALL IS LOŚ͖̩͇̗̪̏̈́T ALL I​S LOST the pon̷y he comes he c̶̮omes he comes the ich​or permeates all MY FACE MY FACE ᵒh god no NO NOO̼O​O NΘ stop the an​*̶͑̾̾​̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑

0:07 rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚​N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ

0:08 arrdem: ahahahahaha



0:08 (inc danielcompton)

0:08 lazybot: ⇒ 2

0:08 danielcompton: Mbeans leaking from your eyes

0:08 arrdem: I love that regex parsing thread

0:09 technomancy: clojurebot: batty?

0:09 clojurebot: Excuse me?

0:09 justin_smith: rpaulo: try M-x toggle-debug-on-error - that should drop you into the elisp debugger

0:09 technomancy: aw shucks

0:09 justin_smith: rpaulo: you can run M-x top-level to get out of the debugger

0:09 or interact with the debugger and look for what went wrong

0:10 rpaulo: that is to say, debug-on-error should cause *future errors to drop you into the elisp debugger

0:10 technomancy: clojurebot: batty is <reply>I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

0:10 clojurebot: Huh?

0:10 justin_smith: so you can figure out the source file for the code, and the file where a variable was defined

0:10 rpaulo: justin_smith: didn't work :(

0:10 technomancy: clojurebot: come on man

0:10 clojurebot: Cool story bro.

0:10 technomancy: clojurebot: batty is <reply> I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

0:10 clojurebot: Excuse me?

0:10 arrdem: technomancy: batty |is| ...

0:10 justin_smith: rpaulo: it didn't pop up the debugger on your next error?

0:11 technomancy: clojurebot: batty |is| <reply> I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

0:11 clojurebot: Cool story bro.

0:11 rpaulo: justin_smith: nop

0:11 technomancy: clojurebot: inventory

0:11 clojurebot: I am carrying 0) a poorly-calibrated inference engine, currently leaking 1) a well-worn copy of clojure 1.2 tucked deep away inside a classloader 2) the last shreds of what was once my sanity

0:11 rpaulo: I'm using Cask to install everything.

0:11 and leiningen to install nrepl

0:11 justin_smith: rpaulo: http://www.emacswiki.org/emacs/WhichFuncMode

0:11 technomancy: cask? "the bundler of elisp"?

0:11 arrdem: ~technomancy

0:12 ,1

0:12 clojurebot: eval service is offline

0:12 technomancy: ~batty |is| <reply> I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

0:12 clojurebot: Cool story bro.

0:12 rpaulo: technomancy: yeah, better than cloning git repos by hand

0:12 justin_smith: OH

0:12 * arrdem mutters darkly

0:13 justin_smith: rpaulo: found that by googling part of your error message

0:13 rpaulo: ok, that took care of the error, but ag-nrepl still doesn't work

0:13 justin_smith: ac-nrepl is finicky

0:13 technomancy: porting the whole "why is it broken in mysterious ways" concept straight from ruby to elisp

0:13 justin_smith: often I find it slowing down my clojure mode buffers significantly, until I just shut it off

0:14 rpaulo: ah, it works fine after jack-in

0:14 but, yes, it's too slow :(

0:14 arrdem: justin_smith: ac-nrepl is abandoned. company-mode has replaced ac.

0:14 justin_smith: arrdem: good to know, thanks

0:15 rpaulo: you catch that? time to get rid of ac-nrepl and use company mode

0:15 rpaulo: arrdem: I should try that one instead

0:15 arrdem: rpaulo: only if you use cider rather than nrepl.el

0:15 rpaulo: nrepl.el has ac support, cider has made the company leap

0:15 justin_smith: technomancy: they even use the L word in their introduction docs http://cask.readthedocs.org/en/latest/guide/introduction.html

0:15 rpaulo: I'm actually using ac-nrepl with cider, so no problem there

0:16 arrdem: rly?

0:16 * arrdem never had good luck with cider's auto complete of any kind

0:16 arrdem: rpaulo: for my entertainment, can you refheap the relevant config bits?

0:17 technomancy: justin_smith: aw man; what the heck

0:17 justin_smith: technomancy: at least they have admirable goals, even if they don't hit them

0:17 rpaulo: arrdem: http://paste.lisp.org/display/143252

0:18 arrdem: rpaulo: remapping {} is brave given how much map crap Clojure uses :P

0:18 technomancy: justin_smith: wow, that readme is incredibly arrogant

0:19 "all projects that don't use cask aren't worth using"

0:19 justin_smith: technomancy: and poorly written, yeah

0:19 rpaulo: heh, I thought exactly the same

0:20 arrdem: am I the only one here who build a modular .emacs.d system?

0:20 * arrdem mutters about heathens with huge .emacs files

0:20 Balveda: i just use emacs live. should i be shot?

0:20 justin_smith: arrdem: I decompose my .emacs.d/init.el into separate el files, so I can toggle loading for different hosts / emacs versions / whatever more easily

0:21 rpaulo: I haven't used Emacs much in the past. Dare I say I'm a vi person? The truth is Clojure is much better with Emacs...

0:21 justin_smith: one file for clojure stuff, one file for javascript, one for custom keybindings, etc. etc.

0:21 arrdem: https://www.refheap.com/88672

0:21 justin_smith: and when / if I switch from nrepl to cider, I will make a second version of my clojure-stuff.el

0:22 rpaulo: arrdem: that's neat

0:22 hiredman: much like cider the only thing I've seen cask do is break emacs

0:22 Balveda: I wish I had dipped my feet in the wonderful world of lisp earlier

0:23 Lisps rather since I'm barely getting started with the channel's namesake

0:24 justin_smith: arrdem: https://www.refheap.com/88673

0:25 those customizations at the top of the file should be in their own file maybe

0:25 arrdem: justin_smith: interesting. a better approach to ignoring config files than my system offers.

0:25 possibly... all I can do is move stuff off the autoload path.

0:26 justin_smith: yeah, I wanted to be able to have arbitrary predicates for each one (copying the behavior of built in stuff where (foo -1) means no foo)

0:28 arrdem: http://gigasquidsoftware.com/blog/2014/07/28/the-proper-pronunciation-of-clojures-assoc/

0:28 * arrdem cracks up

0:28 justin_smith: lol, "jeremy"

0:30 rpaulo: hmm, company is indeed much better.

0:32 jeremyheiler: i, for one, thing "jeremy" is the correct answer.

0:32 think*

0:33 arrdem: I DETECT BIAS

0:33 talios: assoc is a word, not an abbreviation, therefor - a-sock.

0:33 eggsby: assokiate

0:33 arrdem: $google dilbert assok intern

0:33 lazybot: [Intern on Dilbert.com] http://search.dilbert.com/comic/Intern

0:33 justin_smith: talios: "associate"

0:34 talios: justin_smith - and? (assoc) is a function. It may be _derived_ from the abbreviation of the word associate. But the symbol/function itself?

0:35 * brehaut goes to look at gifs of cats till this blows over

0:35 talios: same reasoning why you should never use URL or JDBC, but rather Jdbc or Url.

0:35 jeremyheiler: officialy statistically analaysing didn't remove it from the results. no bias!

0:35 arrdem: where's tbaldridge with his popcorn...

0:35 I want some

0:35 talios: 'lo brehaut

0:35 brehaut: hi talios

0:36 talios: brehaut - move to auckland, work here, join danielcompton as we subsume anyone doing clojure

0:36 brehaut: talios: not going to move to auckland, but happy to do some work

0:36 danielcompton: brehaut: don't believe them, they force me to do Scala and Java

0:36 talios: danielcompton - hey, you did that willingly.

0:37 brehaut: danielcompton: ive done VBScript for money. nothing will be worse than that

0:41 talios: brehaut - doing it for fun? :)

0:42 brehaut: talios: who are you kidding? nobody does that for fun :P

1:12 TEttinger: ,(def jeremy assoc)

1:12 clojurebot: #'sandbox/jeremy

1:13 TEttinger: ,(jeremy {} :a 1 :b 2)

1:13 clojurebot: {:b 2, :a 1}

1:13 TEttinger: ,(def ass-sock assoc)

1:13 clojurebot: #'sandbox/ass-sock

1:13 TEttinger: ,(ass-sock {} :a 1 :b 2)

1:13 clojurebot: {:b 2, :a 1}

1:13 rpaulo: ,(def assok assoc)

1:13 clojurebot: #'sandbox/assok

1:45 Raynes: Clojars is nice and broken

1:47 arrdem: Raynes: how so?

1:47 Raynes: As in it does not appear to function as intended.

1:47 It doesn't load.

1:47 Blasted cache and everything

1:47 arrdem: erm...

1:47 clojars works for me

1:48 gws: clojars.org

1:48 Raynes: Two different browsers.

1:48 No wory

1:48 No worky*

1:49 pyrtsa: The frontpage appears completely empty for me too. But I was able to jump to https://clojars.org/search via a Google search.

1:49 Raynes: arrdem: Roommates can't load it either.

1:49 What he aaid.

1:49 said*

1:49 pyrtsa: It was like this 1.5 weeks ago already.

1:49 (Haven't tried in the meantime.)

1:49 Raynes: technomancy: Can we go back to the old but working UI? :P

1:50 arrdem: Raynes: interesting. If I log out clojars.org is indeed horked

1:51 pyrtsa: https://clojars.org returns "HTTP/1.1 500 Server Error" with an empty body.

2:15 Bronsa: Raynes: there have been reports of clojars returning a blank page on this channel for weeks now

2:16 Raynes: That's usually what happens when you do flashy website makeovers :p.

3:41 Glenjamin: i get a blank page also

3:50 hyPiRion: I get blank page as well from the front.

3:51 But I didn't know it was like that for so long, I'm pretty sure I've been at the frontpage without problems in the last 2 weeks.

3:59 Bronsa: well I've opened an issue on clojar's github page

4:11 danielcompton: I'm working on a library to provide sorted set operations over lazy-seqs/core.async channels.

4:11 I'm tossing up between an abstract name like rummy

4:12 And a more straightforward one like seq-set or chan-set. Any opinions?

4:18 Is clojars down for everyone or just me?

4:19 I'm just getting a white page

4:23 __daniel__: danielcompton: yes, everyone is saying the same

4:26 mbac_: what's the equivalent of map but without creating a sequence as a return value?

4:26 that is, i simply want to iterate over a collection and do side-effecty things

4:27 Glenjamin: ,(doc doseq)

4:27 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

4:32 mbac_: sweet

4:35 H4ns: is there a way to automatically use certain name spaces in all other namespaces, but only in the repl? i usually use clojure.tools.trace and clojure.pprint, but having to manually do it in every namespace gets old quickly.

4:37 Glenjamin: H4ns: https://github.com/gfredericks/dot-slash is an option

4:37 H4ns: ah, nice hack, thanks!

4:41 and another cider question: i've recently updated cider and now i see no backtraces anymore, just the exception message. how can i get backtraces back?

4:43 mbac_: mmmm, cider

4:45 vijaykiran: H4ns: (setq cider-show-error-buffer 'only-in-repl)

4:45 H4ns: check the README on cider gh - https://github.com/clojure-emacs/cider for other options

4:46 H4ns: vijaykiran: thanks! it seems that i also forgot to install my profiles.clj on the machine that i'm working on, so that will probably help as well.

4:48 vijaykiran: danielcompton: regarding the naming - personally I prefer having descriptive names, and easy to remember as "that library with core.async set ops"

5:13 H4ns: Glenjamin: is there a way to import complete namespaces in dot-slash, or do i need to spell out all symbols that i want to import into the dot namespace? i'm not yet completely able to read the code.

5:14 Glenjamin: no idea, gfredericks might have some input

5:27 vijaykiran: H4ns: Doesn't look like it has ns mapping

5:28 https://github.com/gfredericks/dot-slash/blob/master/src/dot_slash/plugin.clj#L6

5:28 H4ns: vijaykiran: i suspected so, but i was not sure. thanks for confirming.

5:29 vijaykiran: H4ns: I use :repl-options btw in profiles, btw

5:31 H4ns: vijaykiran: but that does not auto-import debugging namespaces into your application namespaces, or does it?

5:34 vijaykiran: H4ns: true - not in other namespaces, but only in the default/starter namespace

5:36 H4ns: i think the dot-slash hack is quite nice, and if i really want the debuggin stuff to be accessible without prefixing, i can (use '.)

5:44 mbac_: i love/hate how clojure automatically turns my map into a thunk that's never executed because it appears in the middle of a doseq

5:44 er, in the middle of a do

5:44 and i need to change the map to doseq to get the hot side-effect action

5:45 is lazy evaluation really that much of an advantage in exchange for the surprising behavior?

5:45 H4ns: once you got used to it, it is no longer surprising :)

5:46 mbac_: except until i make a mistake somewhere because i've trained my brain through 20 years of programming to expect things to happen in order from top to bottom

5:46 H4ns: you _do_ need to adjust your expectations, of course.

5:47 but the fact that you've been doing it "wrong" for 20 years should not stop you from getting used to it.

5:47 note the quotes. :)

5:47 blunte: Hi guys. I'm missing something (simple)? Trying to get a list of strings from map keys: (map #(apply name %) (keys m))

5:47 mbac_: it feels good spiritually that stuff that's not needed won't be evaluated, but i doubt this is something that will improve clarity in the long run

5:48 llasram: blunte: (map name (keys m))

5:48 mbac_: that is, i doubt lazy evaluation will become that much less surprising in the long run

5:48 H4ns: mbac_: i think that in the long run, code clarity wins over expectations from the pasdt.

5:49 mbac_: and lazy evaluation does help with code clarity. that certainly is arguable and you may as well decide that you want to stay with imperative programming. nothing wrong with it, really.

5:49 mbac_: i disagree. making everything lazy by default can only confuse and the win *might* be optimization

5:49 blunte: llasram: thanks. I'm still not clear on when I need (map #(apply ...) data) vs (map foo data)

5:49 H4ns: mbac_: you are free to not program in clojure if you like it. common lisp is a nice lisp without all the crazy lazy stuff :)

5:50 mbac_: the opposite of lazy evaluation for everything is not go back to imperative programming

5:50 you can have functional programming without lazy evaluation

5:50 H4ns: mbac_: sure. lazy is just the next logical step.

5:50 mbac_: functional programming is where the clarity wins come from

5:50 llasram: blunte: `apply` is itself a function, which "applies" another function to a sequence, turning a collection into positional arguments

5:50 &(doc apply)

5:50 lazybot: ⇒ "([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args]); Applies fn f to the argument list formed by prepending intervening arguments to args."

5:51 mbac_: *shrug*

5:51 llasram: blunte: So (apply f [a b c]) <=> (f a b c)

5:51 blunte: Ah ha, thank you

5:57 nathan7: mbac: being able to work with infinite sequences increases clarity a lot often

5:57 mbac: you can take the space of all possible solutions and filter over it and take the first few, etc

5:58 a lot of sequence-handling pipelines work thanks to laziness

6:21 wizzo: does nil work the same as false in an if statement condition? or should i always check with (not (nil? ...))?

6:21 SagiCZ1: wizzo: it works the same way

6:22 mbac: nathan7, i agree and in those cases i'd definitely like to be able to opt into having lazy/infinite sequences

6:22 wizzo: cool thanks

6:22 mbac: i'm just don't agree that making EVERYTHING lazy by default is a compelling argument

6:22 nathan7: I do

6:23 but then again, I think Haskell is pretty sweet

6:23 Glenjamin: opt-out is sufficient

6:23 mbac: i disagree. probably most of the time laziness is of no advantage.

6:23 Glenjamin: and no disadvantage

6:24 mbac: except for the surprising behavior

6:24 H4ns: mbac: really, what is it that you're looking for? do you want us to convince you? then maybe you should get used to it, no convincing required. or do you want to change the way clojure works? then you're probably out of luck. just saying.

6:24 Glenjamin: there's only surprises if you try and iterate with side-effects

6:25 well, there's only surprises if you want side effects but don't consume, which isn't often

6:25 mbac: i was actually wondering if there was a button i could press that would tell me my pipeline relies on side-effects somewhere

6:25 SagiCZ1: mbac: I am new to Clojure, programmed in Java for 4 years.. I have no problems getting used to the laziness.. it bit me exactly once. It is actually pretty simple concept.

6:25 mbac: or to turn the lazy evaluation off unless i'm doing something obviously lazy like iterating an infinite sequence

6:26 babilen: http://blog.ontoillogical.com/blog/2014/07/28/how-to-take-over-any-java-developer/ ← why it is a bad idea for every language community to invent their own package management system

6:26 (sorry for OT)

6:26 mbac: i'm sure the actual arguments for/against laziness by default has been hashed to death

6:26 Glenjamin: babilen: as opposed to?

6:27 babilen: Glenjamin: Using established methods that are OS/distribution specific and have been tested for years/decades

6:29 It's amazing how you see the same mistakes pop up whenever it is done which is just unnecessary and exposes many services to risks that could have been avoided.

6:29 Anyway, it was just a nice PoC that I thought should be shared.

6:30 piranha: is there something like pr-str, but that dumps metadata as well?

6:31 ah, *print-meta* :)

6:32 SagiCZ1: babilen: could we throw away leiningen and use maven instead in clojure?

6:32 H4ns: SagiCZ1: you can, but i won't :)

6:33 wizzo: hi H4ns my lisp friend

6:33 Glenjamin: babilen: there's a trade-off in allowing ease of sharing that OS-based package management tools don't provide

6:33 not to mention how to deal with apps wanting different versions of a lib on the same box

6:33 wizzo: babilen: what package managers would you say are tested for decades?

6:33 Glenjamin: but yeah, better security would be nice

6:35 SagiCZ1: wizzo: ant?

6:36 Glenjamin: i believe the comparison is things like apt

6:36 SagiCZ1: Glenjamin: ofc sorry

6:37 wizzo: i haven't used clojure enough to say but my experience with python packages is a lot of them simply don't exist in the distro package manager

6:40 clgv: babilen: just use encryption for sensitive tasks^^

6:40 hyPiRion: babilen: I agree -- It should be some sort of requirement to read up on already existing and well-developed package managers before you end up developing one yourself.

6:41 clgv: well it's not as if they hadn't cared. it's their business model to provide https only after a donation...

6:41 in this caste the people hosting their stuff there are to blame, I'd say

6:41 *case

6:42 blunte: Is there a more concise way to (cons "a" (cons "b" ["c" "d"]))?

6:42 so you end up with one list of all elements?

6:42 clgv: is the leiningen and clojars.org combination using encryption as default?

6:42 SagiCZ1: ,(cons "a" (cons "b" ["c" "d"]))

6:42 clojurebot: ("a" "b" "c" "d")

6:42 Bronsa: (list* "a" "b" ["c" "d"])

6:42 ,(list* "a" "b" ["c" "d"])

6:42 clojurebot: ("a" "b" "c" "d")

6:42 hyPiRion: blunte: ##(list* "a" "b" ["c" "d"])

6:42 lazybot: ⇒ ("a" "b" "c" "d")

6:42 clgv: list* ^^

6:42 blunte: Ahh, super. thanks.

6:42 SagiCZ1: (doc list*)

6:42 clojurebot: "([args] [a args] [a b args] [a b c args] [a b c d & ...]); Creates a new list containing the items prepended to the rest, the last of which will be treated as a sequence."

6:43 blunte: perfect

6:43 hyPiRion: clojurebot: yes, but we check in maven central as well.

6:43 clojurebot: I don't understand.

6:43 hyPiRion: clgv*

6:43 clgv: $findfn :a :b [:c :d] [:a :b :c :d]

6:43 SagiCZ1: clojurebot: How are you today?

6:43 clojurebot: Excuse me?

6:43 clgv: lazybot: ?

6:44 :(

6:44 lazybot: [clojure.core/list*]

6:44 SagiCZ1: aww :(

6:44 clgv: ah well :D

6:44 he get's slower as he ages ;)

6:46 by the way: how do you force a signature check with leiningen?

6:46 hyPiRion: `lein deps :verify`

6:47 not sure what you mean with force though

6:57 clgv: usually it doesnt do that right?

6:58 hyPiRion: no. You want it to fail if it cannot verify a signature?

6:58 clgv: lein deps :veriy was what I wanted to know :D

6:58 hyPiRion: ah, good :)

6:59 clgv: but it cant know the correct public key to check the signature right?

7:00 so checking authenticity is not really possible?

7:02 justin_smith: clgv: hypothetically, you can integrate with a separate keyserver, and have a list of name to package mappings acquired via ssl

7:03 clgv: justin_smith: that seems to be the long term goal with clojars.org right?

7:03 justin_smith: not sure

7:03 clgv: lol which currently is just "blank" from here

7:04 clojars.org just gives me a blank page... :(

8:48 ChouLin: I have trouble print unicode (Chinese) in Mac terminal.

8:48 (println "你好") is good.

8:48 (seq "你好") -> (\ä \½ \  \å \¥ \½)

8:48 (count "你好") -> 6

8:48 I'm using OSX mavericks, clojure-1.6. I think it's encoding problem 'cause same code work fine in a Debian machine.

8:48 any hint ? thank you everyone.

8:50 justin_smith: ChouLin: (count "你好") is 2 on my machine

8:50 i-blis: ChouLin: 1) what Terminal are you using? 2) is it in lein repl?

8:51 ChouLin: it's not a lein repl. I use system default terminal.

8:51 justin_smith: yeah, I would check if your terminal is using utf8

8:51 vijaykiran: ChouLin: same here Java 1.7 though (count "你好") => 2

8:51 justin_smith: ChouLin: so you are running clojure.jar directly?

8:52 i-blis: ChouLin: in Emacs with cider no issue? no issue either in iTerm2

8:52 ChouLin: no, I'm using 'java -cp clojure-1.6.jar clojure.main' to start a repl

8:53 I don't have iTerm2, in emacs , I start a eshell , then 'java -cp clojure-1.6.jar clojure.main', same error. I'm not using cider right now.

8:53 i-blis: I meant: no issue in emacs with cider, no issue in iTerm2 (OS 10.9 too)

8:53 what is your locale in the term?

8:54 clgv: $seen lpetit

8:54 lazybot: lpetit was last seen quitting 13 weeks and 4 days ago.

8:54 clgv: $seen laurentpetit

8:54 lazybot: laurentpetit was last seen quitting 22 weeks and 5 days ago.

8:54 clgv: $seen laurent

8:54 lazybot: I have never seen laurent.

8:55 vijaykiran: ChouLin: I think the problem is with emacs/eshell

8:55 ChouLin: you need to set it to use UTF-8, I think

8:55 ChouLin: @ i-blis: LC_CTYPE="C"; LC_ALL=''

8:55 clgv: ChouLin: encoding or font issue

8:56 i-blis: ChouLin: then set it

8:56 clgv: ChouLin: your terminal uses a UTF-8 capable font?

8:56 ChouLin: @vijaykiran, same error in system's terminal outside Emacs.

8:56 i-blis: ChouLin: to en_US.UTF-8, for instance

8:57 ChouLin: it's en_US.UTF-8 outside Emacs,yes

8:57 LANG="en_US.UTF-8"

8:57 vijaykiran: ChouLin: strange - on terminal its fine for me, but in eshell I get count => 6

9:00 i-blis: ChouLin: what output do you get for (seq "你好") outside emacs?

9:00 ChouLin: I wish there's a way to make this simple code strong in both Debian and Mac. I decode string to unicode inside my Python programe then encode to 'UTF-8' before output. Is there's similiar paradigm in Clojure ? or best practice ?

9:01 TimMc: Python has a strange notion of character encoding that I still don't fully understand.

9:01 ChouLin: encoding is classical bitter in every language I think.

9:02 i-blis: Python and Ruby inherited custom character encoding from Perl I guess

9:03 ChouLin: @i-blis: I got this outside Emacs: (seq "你好") -> (\\? \? \\? \?)

9:03 i-blis: never has any issue with non-ASCII stuff in Clojure

9:03 ChouLin: qusstion marks

9:03 TimMc: There are only three problems I know of with character encodings in the JVM: It uses UTF-16 internally, it exposes this when you ask for string length, and it defaults to the system character encoding for input/output (instead of UTF-8.)

9:03 justin_smith: ChouLin: you can encode a string to byte array, and byte array back into string, and specify encoding (def raw (.getBytes "你好" "UTF-8")) (String. raw "UTF-8")

9:04 i-blis: ChouLin: this is not good. did you set both LC_CTYPE and LC_ALL?

9:05 justin_smith: ChouLin: I guess the extra step along with the above is opening a file as raw bytes, then manually specifying the correct encoding

9:05 ChouLin: I didn't se LC_ALL, LC_CTYPE is 'C' in eshell, 'en_US.UTF-8' in system shell.

9:06 justin_smith: ChouLin: what if you setenv LC_CTYPE properly in eshell?

9:06 (properly meaning, setting it to a UTF-8 encoding)

9:07 ChouLin: @justin_smith: that makes simple problem hard. what if I want make a word count for each word ? I split the string with #"" then every Chinese word become a triple ?

9:07 TimMc: ChouLin: (By the way, in IRC it is not customary to use an "@" prefix when you're using when addressing people. It may interfere with people's nick-highlighting.)

9:08 justin_smith: ChouLin: the place where the error happens is input / output. Once it is in your program the vm does the right thing.

9:08 if it was input properly

9:09 ChouLin: Thank you TimMc , I feel like a fool, both with IRC and Clojure.

9:09 justin_smith: this isn't a bug in how the vm handles characters, its a bug in character input

9:09 TimMc: No worries.

9:10 ChouLin: you're right justin_smith, real world's complexity. I do asia language text analysis, encoding is my big pain.

9:11 deathknight: I've been stuck at creating a barebones webapp with oauth2 functionality for weeks...is there a tutorial out there that really explains it for dummies?

9:11 ChouLin: I'm so jealous people deal with plain ascci only.

9:11 deathknight: all of the literature out there is just a bit above my skill level

9:11 justin_smith: ChouLin: I think if you put your text into files of known encoding, and ensure that they are read using the correct encoding, the jvm should handle the rest just fine

9:12 mpenet: ChouLin: did you try passing -Dfile.encoding=UTF-8 to java?

9:12 TimMc: ChouLin: In your REPL, try (seq (slurp "some-file.txt")) where some-file.txt consists of 你好.

9:12 justin_smith: deathknight: when I was trying to use it, my conclusion was more that oauth2 was *from* dummies

9:12 mpenet: same in :jvm-opts would work

9:12 TimMc: This may help distinguish between I/O problems in general and the terminal specifically.

9:12 ChouLin: sounds like python's way. I'm trying to figure out '.getBytes' & 'String.' , am I on rigth track ?

9:12 i-blis: ChouLin: I deal with all kind of strange non-ascii scripts all the time. after having set LC_CTPYE, check in Terminal options if UTF-8 is set btw

9:12 deathknight: justin_smith: lol

9:14 justin_smith: ChouLin: String. to go from bytes to chars, and .getBytes to get from String to bytes is what probably works in your running code (unless your planned UI is an eshell inside emacs) - but then there is also the eshell config, for actually being able to develop and use a repl

9:14 ChouLin: thank you i-blis TimMc justin_smith , thank you all. I'll let you know if it works.

9:15 TimMc: ChouLin: You shouldn't have to use .getBytes.

9:16 justin_smith: TimMc: I was suggesting that for the output side of things (for symmetry)

9:17 TimMc: also that combo of .getBytes / String. can be used to preserve chars but change encodings

9:21 TimMc: justin_smith: Are you suggesting this for debugging or for production use?

9:24 justin_smith: TimMc: as a general suggestion. Of course in production the real question is "what is the actual encoding of this input / what encoding do I need on this output" but String. / .getBytes provide the mechanism for making sure the right encoding is used on each side.

9:25 and can also be used while debugging (coercing a set of bytes to a different assumed encoding, and seeing if that results in the right characters)

9:29 ChouLin: Hi, I start from simple modification, 'java -Dfile.encoding=UTF-8 -cp clojure-1.6.jar clojure.main' did the trick. thank you friendly guys! thank you mpenet. I haven't modified LC_ALL yet.

9:30 justin_smith: glad that worked

9:31 mpenet: ChouLin: np, I had the same issue with files containing french text

9:34 ChouLin: I feel so good after 4 hours stucking here!!

9:35 Actully I've tried '-Dencoding=UTF-8' but it won't work.

9:37 justin_smith: also, most things from from clojure.java.io (which underlies ie. slurp) can take an optional :encoding keyword argument (which defaults to "UTF-8")

10:17 gfredericks: H4ns: yo

10:17 H4ns: gfredericks: hi!

10:17 gfredericks: thoughts?

10:19 gfredericks: I hadn't thought of the full-namespace idea; that kind of implicit stuff is usually avoided in clojure, but the whole thing is a dev hack anyhow so I don't think I would mind it

10:19 clojurebot: 'Sea, mhuise.

10:19 gfredericks: ~I hadn't thought of the full-namespace idea; that kind of implicit stuff

10:19 clojurebot: I hadn't thought of the full-namespace idea; that kind of implicit stuff is usually avoided in clojure, but the whole thing is a dev hack anyhow so I don't think I would mind it

10:19 Bronsa: har har

10:19 gfredericks: clojurebot: you |are| a weirdo

10:19 clojurebot: Ik begrijp

10:19 H4ns: gfredericks: yeah, i'm also in the "explicit" camp usually, but i like my tools handy on the repl.

10:19 gfredericks: the ./ idea is awesome :)

10:19 gfredericks: :D I'm enjoying it

10:20 H4ns: gfredericks: i'll send you a pull request when i'm annoyed enough by the lack of the feature

10:20 gfredericks: H4ns: any other comments/issues?

10:20 I'm adding whole namespaces to the list of future embetterments

10:21 H4ns: gfredericks: no. it is perfect, from what i can say :)

10:49 martinklepsch: is there a directory of leiningen templates?

11:01 jeremyheiler: martinklepsch: https://clojars.org/search?q=lein-template

11:02 martinklepsch: it's a start :-P

11:03 arrdem: oh good clojars is unhorked

11:04 hugod: that search seems incomplete (eg. mies is not listed)

11:05 Bronsa: arrdem: https://github.com/ato/clojars-web/issues/235#issuecomment-50472946

11:06 arrdem: Bronsa: interesting. thanks.

11:07 technomancy: wait he wasn't learning stuff last night

11:07 did clojurebot fix himself?

11:08 aeikenberry: how could i write a macro that takes one required argument and an infinite number of optional requirements?

11:08 technomancy: clojurebot: batty |is| <reply> I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

11:08 clojurebot: Pardon?

11:08 technomancy: clojurebot: batty |is| I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

11:08 clojurebot: Huh?

11:08 technomancy: dang it

11:08 p_l: lol

11:08 justin_smith: batty |is| I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

11:09 technomancy: gfredericks just has the magic touch

11:09 justin_smith: ¯\_(ツ)_/¯

11:09 __daniel__: aeikenberry: have it take two arguments, the second being a sequence

11:09 and walk the sequence?

11:09 i think there is a limit on the number of args

11:09 Bronsa: ~batty

11:09 clojurebot: Cool story bro.

11:09 __daniel__: @whatis batty

11:11 aeikenberry: <__daniel__>: thanks

11:11 __daniel__: thanks

11:11 justin_smith: you can use & in a macro argument list

11:11 if you want an optional unknown length number of extra args

11:11 aeikenberry: like [required & args] ?

11:12 justin_smith: yeah

11:12 aeikenberry: thanks kindly

11:12 justin_smith: that works the same way it does for functions, where args is a sequence of all arguments after required (and nil if only required was present)

11:12 aeikenberry: i'm very new

11:12 to clojure

11:13 justin_smith: aeikenberry: writing macros may not be a good place to start

11:13 aeikenberry: it

11:13 's a challenge

11:13 TimMc: ~macros

11:13 clojurebot: Holy Crap.

11:13 justin_smith: ~macros

11:13 TimMc: haha, was not expecting that

11:13 clojurebot: I added a ~' and it worked.

11:13 justin_smith: ~macros

11:13 clojurebot: macros are just a game with symbols

11:14 justin_smith: too many answers for that one

11:14 TimMc: ~macos

11:14 clojurebot: Huh?

11:14 TimMc: clojurebot, macos |is| <reply>x

11:14 clojurebot: Roger.

11:14 justin_smith: ~macos

11:14 clojurebot: x

11:15 justin_smith: clojurebot, batty |is| I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

11:15 clojurebot: Cool story bro.

11:15 justin_smith: ~batty

11:15 clojurebot: Titim gan éirí ort.

11:15 justin_smith: clojurebot, batty |is| <reply>I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain.

11:15 clojurebot: Titim gan éirí ort.

11:15 justin_smith: ~batty

11:15 clojurebot: excusez-moi

11:15 justin_smith: bleh

11:16 llasram: justin_smith: clojurebot*:* maybe?

11:16 justin_smith: llasram: TimMc made it work with the ,

11:16 TimMc: Weird. I usually expect it to accept the factoid and screw it up somehow -- but at least accept it.

11:16 llasram: Oh, nm

11:16 justin_smith: TimMc: yeah, I wonder why it hates that one

11:16 or maybe it hates me (and technomancy)

11:17 TimMc: I know it has trouble with \. but I thought that just truncated the factoid.

11:22 Conclusions from /query chat with clojurebot: The thing is bonkers.

11:23 justin_smith: clojurebot: |is| certified bonkers.

11:23 clojurebot: I don't understand.

11:23 justin_smith: you wouldn't

11:24 arrdem: clojurebot also ignores people at hiredman's whim... clearly lazybot's factoids functionality should become standard and clojurebot should be abandoned :P

11:24 TimMc: *nod*

11:25 !

11:25 It just said to me: "A nod, you know, is as good as a wink to a blind horse."

11:26 arrdem: gtrak: is there some special magic involved in getting cider/company to work?

11:27 I've gotten Company's autocomplete to work for me in REPL buffers but it's doing nothing in clojure-mode.

11:27 Bronsa: arrdem: slime+auto-complete works like a charm.

11:27 arrdem: Bronsa: quiet you

11:27 Bronsa: just sayin.

11:29 arrdem: yeah.. and auto-complete-mode "just works" as well

11:29 no friggin idea what's with company-mode

11:30 justin_smith: ¯\_(ツ)_/¯

11:31 gtrak: arrdem: basically, you just install company mode, don't install company-cider.

11:31 I think it just works.

11:31 arrdem: grrrrr

11:32 gtrak: though I found it a bit unintuitive and removed it for the default completion.

11:32 i like seeing the massive list of syms

11:33 arrdem: okay... cider, cider-tracing and cider-decompile

11:33 no cider-company

11:35 gtrak: https://github.com/clojure-emacs/company-cider#deprecation

11:35 cbp: company mode does just work

11:50 rpaulo: oh, I didn't know it was deprecated.

11:50 arrdem: weirdness...

11:50 looks like I managed to break company with the 13 other minor modes I had attached to clojure-mode..

11:51 if I throw all that out then company works fine.

12:12 gfredericks: arrdem: I choose to interpret these statements as referring to an actual commercial company

12:12 technomancy: initech-mode

12:13 arrdem: M-x umbrella-corp-mode

12:13 gfredericks: M-x IPO

12:14 arrdem: heh

12:14 justin_smith: M-x weyland-yutani-dispose-employees

12:14 {===c

12:56 slpsys: hah

13:25 ahoenigmann: Is it possible to get eclipse-like code completion for java.lang and other java packages in emacs while coding clojure? (I have emacs and cider setup now)

13:37 justin_smith: ahoenigmann: yeah, I have completion for java.lang using nrepl.el and autocomplete, so it should work in cider too

13:38 unless cider had a regression on that feature

13:39 ahoenigmann: so is it just <TAB>?

13:39 yup it is!

13:40 sjouke: what are the arguments against SOLID design? i remember hearing a guy from the functional programming community shuttering when he heard Kiskov substitution mentioned

13:41 justin_smith: sjouke: Liskov substitution?

13:43 teslanick: There are a few obvious-in-practice objections to Liskov substitution.

13:45 justin_smith: teslanick: you mean objecting to Liskov substitution, or objecting to the demand that subclass be Liskov-substitutable?

13:48 teslanick: Perhaps I've not seen a subtyping implementation that actually captures Liskov substitution correctly, but it seems like if type T is a subtype of type S, unless T and S are identical, Liskov substitution cannot hold for all possible provable attributes.

13:49 justin_smith: teslanick: liskov (and solid) are not rules about all programs, they are criteria for good programs

13:49 (or so they claim)

13:50 agarman: SOLID is good for making programs possible to reason about

13:50 justin_smith: of course working software can violate the constraints of solid, but the claim is that if you meet the criteria of solid, your code is more resiliant, better designed

13:51 teslanick: Well, it's supposed to be a "soft" correctness guarantee. Type S and T can be used interchangeably because they expose similar contracts (where S might be a superset of T). In practice for non-trivial problems, I've not found this to be the case.

13:51 Unless S and T are identical (or very nearly so)

13:51 justin_smith: agarman: do you have a good clojure example of something that violates SOLID but would be an improvement over the SOLID alternative? (legitimate question, not an argument)

13:53 teslanick: sure, but it is not an invariant, it is a criterion by which they claim some other goal can be attained. I have never seen a claim that liskov substitution was somehow a description of algorithms as-is.

13:55 teslanick: That's fair. I see enough dogma around type systems that aren't true in practice, that I'm probably too-skeptical of the claimed benefits.

14:01 prc: Anyone can give me a hand with this piece of code: http://pastebin.com/raw.php?i=0pgMdtmX ?

14:01 The problem is mentioned there, and as you can see I'm a beginner, so please bear that in mind.

14:02 amalloy: prc: rest returns a sequence, not a vector; and conj on a sequence adds to the front

14:03 i can't actually tell if you're conjing onto something you rest'ed, but there are a lot of conj and rest

14:03 llasram: THey do use `drop-last`, which has the same effect

14:03 teslanick: Is the goal to check if braces are correctly nested?

14:03 amalloy: yeah

14:03 llasram: You want `pop`

14:03 prc: amalloy: but until that point it was adding it at the very end, no?

14:04 teslanick: that's correct.

14:04 llasram: You also want `not` instead of `complement` (although you really want `(seq ...)` instead of `(not (empty? ...))`

14:04 teslanick: loop/recur is usually not what you want. You can express the problem more idiomatically

14:05 llasram: (inc teslanick)

14:05 lazybot: ⇒ 1

14:05 teslanick: my first karma <3

14:05 amalloy: teslanick: loop-recur is fine for paren checking. what else is much better?

14:05 teslanick: I wrote one that used reduce in JS

14:05 llasram: I'd use `reduce`

14:06 amalloy: llasram: okay, and on the input (cons \) (repeat \)), you go forever? you can use (reduced false), but that's just shoehorning into reduce when you don't really want to process the whole thing

14:08 the best way to shorten this is to create a map of open-delim to close-delim, rather than hard-coding all six cases

14:08 llasram: `reduce` already captures the pattern of eagerly iterating over collection to produce a result. `reduced` exists to support the optimization of short-circuiting

14:08 Seems like a good fit to me

14:08 teslanick: Yeah; when I wrote the JS version, I wished for `reduced` and resorted to throwing a specially-formed exception to break eagerly.

14:09 amalloy: reduce isn't *awful*, but it's not so much better than loop/recur that i'd suggest it to someone who's asking why his code doesn't work (given that messing up loop/recur was not his problem)

14:10 teslanick: I guess; usually when I resort to loop/recur I'm not thinking about the problem correctly and end up rewriting the function more tersely later.

14:15 llasram: Yeah, and actually, now that I've taken a swing at it, you want to short-circuit to a Boolean value when the `reduce` state is a vector

14:15 So loop/recur may make the most sense anyway

14:21 hyPiRion: llasram: It can go both ways. I feel reduce is easier to wrap my head around here.

14:22 https://www.refheap.com/88701 – although I shoehorn the (reduced [:nonempty]), I feel the reduction pattern matches better.

14:25 amalloy: hyPiRion: the indentation of your cond form is kinda disorienting

14:26 i keep trying to figure out what it's supposed to line up with

14:26 hyPiRion: amalloy: I know, and I fixed it now

14:26 amalloy: i remember someone (fogus?) innovating by using ,, instead of two spaces, to "indent" a cond form in a way that emacs won't revert and is obviously not meant to line up

14:27 arrdem: that's... disgusting and yet I may do so.

14:27 amalloy: i use that occasionally, for cond and for indenting multi-line let-expressions, but everyone hates it when i do

14:29 hyPiRion: I tend to use #_=> sometimes to make copy-pasteable repl examples

14:29 perhaps I should do it here as well, muahahah

14:30 * arrdem ponders hyPiRion's #_=> for Grimoire's examples

14:30 hyPiRion: probably not, it would be confusing for everyone, me including

14:30 arrdem: fair enough...

14:30 hyPiRion: arrdem: oh, I was talking about inside a cond

14:32 I do like #_=> though. Not sure if it's going to make docs easier to read, but at least you can copypaste all of it immediately

14:32 arrdem: although e.g. http://grimoire.arrdem.com/1.6.0/clojure.core/seq/ prints out output you can't copypaste anyway, so I'm not sure how much sense it would make

14:33 arrdem: yeah...

14:33 amalloy: what do you mean, hyPiRion, can't copy/paste? because it's not quoted?

14:34 hyPiRion: amalloy: yes

14:34 amalloy: but #_=> fixes that. and would fix it for seq as well as for whatever else. so i'm not sure how seq is relevant to the discussion of #_=>

14:35 hyPiRion: amalloy: oh, I thought it was meant as a replacement for user=>

14:36 amalloy: maybe so. i was thinking you meant it like in JoC, where they write (inc 1) ;=> 2

14:36 but i guess that doesn't actually make sense

14:37 hyPiRion: right, #_=> is just the same thing as whitespace

14:37 it wouldn't quote the (1) for example

14:38 amalloy: obviously we need the more advanced sigil #_=>#_

14:38 arrdem: wat

14:38 hyPiRion: amalloy: or just #_#_=>

14:38 sjouke: justin_smith: i'm not entirely sure what type systems have to do with SOLID design

14:43 justin_smith: sjouke: me neither, I guess inheritance assumes some kind of type system?

14:43 sjouke: but I definitely wasn't the one making that connection in the conversation here

14:44 Uranio: hi, how could I use slrup being behind a proxy?

14:46 justin_smith: Uranio: if you configure the jvm with the right proxy, slurp should "just work"™

14:46 http://stackoverflow.com/questions/120797/how-do-i-set-the-proxy-to-be-used-by-the-jvm

14:46 you can set the jvm flags in project.clj

14:46 Uranio: thanks

14:47 but I would prefer to us declare it in each script

14:47 justin_smith: actually, proxy is less a per-project thing and more per-user, so likely belongs in profiles.clj

14:47 script? what script?

14:48 Uranio: I have a only one .clj script with my very litle program

14:48 justin_smith: it's still not a clojure level config, it is a jvm config

14:49 Uranio: justin_smith: would be posible to declre it inside clojure?

14:50 like when using java from inside clojure?

14:50 TEttinger: I would guess yeah, but then your code wouldn't work for someone else?

14:50 justin_smith: I guess you can do (System/setProperty "http.proxyHost" "..." "http.proxyPort" "..." "http.nonProxyHosts" "")

14:50 but yeah, that would make your code non-portable

14:51 my bad, setProperty is not varargs, you would have to do each of those separately

14:51 Uranio: yep... seed

14:51 justin_smith: and you end up with code that only works on your computer

14:52 amalloy: i'm a little surprised the jvm doesn't just automatically use whatever proxy settings your OS wants

14:52 but i guess i don't know anything about proxy config

14:53 Uranio: amalloy: me too

14:53 it should work

14:53 justin_smith: amalloy: yeah, I thought it did, but I wasn't interested in going down the "which os are you using..." path

14:53 technomancy: amalloy: I think it depends on how it was packaged

14:53 Uranio: (set! (. Classname-symbol [...]

14:53 ^should work

14:54 justin_smith: for what? it uses properties for proxy setup

15:00 kitallis: could somebody explain to me this behaviour with (Long.)? – http://pastie.org/9429900

15:02 justin_smith: ,(long (or (count "ok") 2)) this works

15:02 clojurebot: 2

15:02 justin_smith: no idea why Long. does not work on that form

15:02 stuartsierra: kitallis: I suspect this is a subtle interaction of Java interop and primitive arithmetic in the Clojure compiler.

15:03 gfredericks: ,(Long. (or (count "ok") 2))

15:03 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Long>

15:03 gfredericks: ,(Long. (long (or (count "ok") 2)))

15:03 clojurebot: 2

15:03 kitallis: heh

15:03 gfredericks: ,(Long. ^long (or (count "ok") 2))

15:03 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Long>

15:03 amalloy: (or (count "ok") 2) returns an Integer, where (count "ok") returns an int

15:03 gfredericks: ,(Long. (int 2))

15:03 clojurebot: 2

15:03 amalloy: gfredericks: that ^long doesn't survive macroexpansion

15:04 kitallis: ,(type (count "ok))

15:04 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

15:04 kitallis: ,(type (count "ok"))

15:04 clojurebot: java.lang.Integer

15:04 gfredericks: ,(Long. (count "ok"))

15:04 clojurebot: 2

15:04 amalloy: ,(Long. (identity (count "ok")))

15:04 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Long>

15:04 amalloy: simpler than using or

15:05 clearly demonstrates that the issue is how (count "ok") is boxed

15:06 stuartsierra: ,(Long. (.longValue (identity (count "ok"))))

15:06 clojurebot: 2

15:06 stuartsierra: fun

15:06 gfredericks: why doesn't the compiler emit reflection after being unable to rule out that the expression returns a string?

15:06 stuartsierra: It is.

15:06 amalloy: gfredericks: it does

15:07 gfredericks: ooooh it's failing at runtime

15:07 of course

15:07 stuartsierra: java.lang.Long doesn't have a constructor that takes an Object.

15:07 gfredericks: okay so if it sees a constructor that takes a long and it has an Integer then it will not convert?

15:08 justin_smith: which is why we have "long" in clojure - which works with boxed numerics

15:09 kitallis: what's a boxed numeric?

15:09 justin_smith: Integer as opposed to int

15:10 it's in an object (its "box")

15:10 stuartsierra: Welcome to the JVM, where *almost* everything is an Object. :)

15:10 justin_smith: it can be the key in a hash-map

15:10 gfredericks: eh rubby is that way too a little differently. Fixnum is a fake object.

15:11 amalloy: gfredericks: it acts like an object in every observable way though, right? the fact that the interpreter does it with pointer tomfoolery doesn't matter afaik

15:11 gfredericks: no

15:11 you can't muck with its singleton class

15:11 same with Bignum it looks like

15:12 amalloy: er, what does that mean? you can't monkey-patch Fixnum?

15:12 gfredericks: you can't monkeypatch an instance of Fixnum

15:12 amalloy: ah

15:13 gfredericks: ruby is an enlightened language where you can monkeypatch individual objects

15:13 arrdem: "enlightened"

15:13 gfredericks: you _can_ monkeypatch a boolean

15:14 stuartsierra: Java boxed numbers aren't fixnums, though, they're real objects.

15:15 ,(identical? (Integer. 42) (Integer. 42))

15:15 clojurebot: false

15:15 stuartsierra: ^ That should be true in a runtime with real fixnums.

15:16 amalloy: stuartsierra: uhhhhhh, i don't think so. (identical? 42 42) maybe, but when you call a constructor, you get a new object, every time

15:16 ,(identical? 42 42) *is* actually true, but only because of trickery

15:16 clojurebot: true

15:16 gfredericks: stuartsierra: my point was that both runtimes have second-class [non-]objects

15:16 whether primitives on the jvm or fixnums in ruby

15:16 TEttinger: amalloy: only on account of villainy!

15:17 amalloy: ,(identical? 542 542)

15:17 clojurebot: false

15:18 gfredericks: ,(->> (map (fn [a b] [a (identical? a b)]) (range) (range)) (remove second) (ffirst))

15:18 clojurebot: 128

15:18 amalloy: gfredericks: from -128 to 127

15:22 aeikenberry: if i have a sequence like (:foo (println "bar") (println "barbar") :bar (println "foo"))

15:22 how could i make a hash-map using those keywords as the keys, and what's between them (in :foo's case) as the value?

15:22 or is a hash-map what i want? i'm new

15:23 gfredericks: aeikenberry: those printlns will turn into nil, right?

15:23 aeikenberry: when i try to make that a hash-map is says "No value supplied for key"

15:24 justin_smith: aeikenberry: that's an odd number of forms

15:24 stuartsierra: amalloy_: I mean Lisp-style fixnums, where integers aren't allocated on the heap at all. Can't remember if Ruby does that.

15:24 justin_smith: also, you probably don't want (println "bar") as a value in a hash map - that's just nil, with a one time printing side effect that dissapears after the assignment

15:25 TEttinger: ,(:foo #(do (println "bar") (println "barbar")) :bar #(println "foo"))

15:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo>

15:25 justin_smith: ,(hash-map :a (println "prints once") :b (println "not in the data structure"))

15:25 clojurebot: prints once\nnot in the data structure\n{:b nil, :a nil}

15:25 gfredericks: stuartsierra: I believe ruby does do that, and that's exactly what makes them second-class

15:25 TEttinger: ,{:foo #(do (println "bar") (println "barbar")) :bar #(println "foo")}

15:25 clojurebot: {:foo #<sandbox$eval77$fn__78 sandbox$eval77$fn__78@1ffdf86>, :bar #<sandbox$eval77$fn__80 sandbox$eval77$fn__80@1da817b>}

15:25 stuartsierra: thanks gfredericks

15:26 TEttinger: aeikenberry, it depends what you want to do

15:26 aeikenberry: i'm trying to build a macro for an assignment

15:27 stuartsierra: Of course, John Rose proposed fixnums for the JVM back in 2008 https://blogs.oracle.com/jrose/entry/fixnums_in_the_vm

15:27 TEttinger: they're covering macros before "hashmaps have an equal number of keys and values"???

15:27 lazybot: TEttinger: Oh, absolutely.

15:28 justin_smith: TEttinger: we should start teaching steeplechase racing in preschools

15:28 aeikenberry: it takes a truthy test, and then any number of arguments with the format (macro truthtest :iftrue 'this 'orthis (println 'this) :iffalse 'nottrue)

15:28 TEttinger: I've heard category theory as being easier to grasp than conventional math for kindergarteners

15:29 aeikenberry: my thought was to conver those arguments to a hash map

15:29 convert

15:29 TEttinger: (category theory being "box of kittens" and "box of apples and kittens" while math being all abstract)

15:30 aeikenberry: to be like if test do the stuff inf :iftrue part of the hash map

15:30 justin_smith: TEttinger: but as soon as you introduce arrows some poor kitty loses an eye

15:30 TEttinger: justin_smith, haha

15:31 what is 'orthis there, aeikenberry?

15:31 aeikenberry: print the string

15:32 (macro (> 3 1) :iftrue 'ok :iffalse 'notok)

15:32 TEttinger: no I mean, if it's an if statement, then you have "test is true" "test is false"

15:32 where is there an alternate truth?

15:32 aeikenberry: inside the macro

15:33 TEttinger: agh

15:33 aeikenberry: would test the truthiness of (> 3 1)

15:33 and if true, evaluate what's after :iftrue

15:33 TEttinger: oh ok

15:33 aeikenberry: passed into the macro

15:33 TEttinger: so it isn't an or, it's a continuous set of things to evaluate

15:34 aeikenberry: yeah, like (do 'ok 'true (println 'ok)) if the truth test passes

15:34 TEttinger: you want to evaluate everything in the iftrue block if and only if the test is true, and if the test is false, evaluate everything in the iffalse block?

15:35 aeikenberry: exactly

15:35 but i'm unsure how to parse the arguments properly

15:35 TEttinger: that makes sense

15:37 aeikenberry: if i have [test & args] in my macro, i'm not sure the best way to parse those args in a way to use them after the truth test

15:37 arohner: in pedestal, is there no public API for terminating a request during an interceptor?

15:37 aeikenberry: any hints or pro-tips welcome

15:37 arohner: the only one I see is in io.pedestal.impl.interceptor

15:38 rkneufeld: arohner: You should be able to return a response to terminate the chain, no?

15:38 arohner: rkneufeld: I don't know. The docs are unclear on what an interceptor should return

15:38 justin_smith: aeikenberry: if you really want to do macros before you know clojure (which is a painful way to do things), macroexpand and macroexpand-1 are really helpful

15:39 arohner: but they do say "Alternatively, an interceptor may call terminate", but then terminate is in impl

15:39 aeikenberry: it has been painful :/

15:39 rkneufeld: arohner: in honesty, there is a bunch of stuff in impl that should not be there.

15:39 terminate included.

15:39 TimMc: aeikenberry: If you like pain, go right ahead. But macros really are an advanced topic.

15:40 justin_smith: ,(macroexpand-1 '(or 1 2)) aeikenberry

15:40 clojurebot: (clojure.core/let [or__3975__auto__ 1] (if or__3975__auto__ or__3975__auto__ (clojure.core/or 2)))

15:40 arohner: rkneufeld: thanks. Just making sure I'm not doing something The Wrong Way

15:42 justin_smith: aeikenberry: but you can do everything interesting with regular functions and sequence operations, macros are mostly just needed for custom syntaxes, which is an odd first thing to try in a new language

15:42 regular functions, especially sequence operations, and the built in macros and special forms, that is

15:44 expez: The only way to get nil out of a core.async/chan is if someone closed! it, right? Is there some truly abject code out there that could cause a chan to return nil without someone calling close! on it?

15:45 I just grepped by code base for close! after by db barfed on a not null constraint

15:45 justin_smith: expez: well, writing nil to a chan closes it, right?

15:45 expez: but that throws an exception!

15:45 justin_smith: oh, it's been a while since I played with that stuff, sorry

15:46 expez: an exception in some thread somewhere, are you sure you would see it?

15:47 expez: I just tried putting nil to a chan, it does throw an exception and does not close it

15:47 so you can keep using it if that was somehow something you expected

15:48 but that totally could've been it :)

15:55 dnolen_: stuartsierra: if it's possible to do the Google Closure release sooner rather than later that would be ideal - I believe for a lot of people 2277 doesn't work w/o the patch to the Closure build script

15:56 stuartsierra: dnolen_: I doubt I'll have time before Friday. Code to build the JARs is in script/closure-library-release

15:57 dnolen_: stuartsierra: but I take it no button to click somewhere to release this a la ClojureScript?

15:57 stuartsierra: dnolen_: no

15:57 That's been on the queue for approximately forever

15:57 dnolen_: stuartsierra: k

15:58 stuartsierra: What's the thing with 2277? Does the release build need to change?

15:58 Sorry, just haven't been following anything with this.

15:58 dnolen_: it's not 2277 that's busted rather the Closure Library changed

15:58 they used to dupe dep.js in both Library & 3rd Party

15:59 now dep.js is a blank file in 3rd Party

15:59 so I think this causes problems

15:59 stuartsierra: OK, so the Closure Lib build will have to change then, because it patches deps.js

16:01 dnolen_: stuartsierra: http://dev.clojure.org/jira/browse/CLJS-826

16:01 stuartsierra: there's already a patch for this in master

16:01 but not resolved until we release new Closure JARs

16:02 stuartsierra: OK I'll push up some JARs to Sonatype as soon as I can.

16:13 We need to make me not the bottleneck for this.

16:15 dnolen_: OK, JARs are in staging at https://oss.sonatype.org/content/repositories/orgclojure-1312 and https://oss.sonatype.org/content/repositories/orgclojure-1311

16:15 dnolen_: stuartsierra: awesome thanks

16:16 stuartsierra: Just confirm that third-party stuff works and I'll release to Central.

16:17 dnolen_: stuartsierra: yeah sent out a message to mailing lists to get feedback and will try it myself as well

16:18 stuartsierra: Those are links to staging repositories, by the way.

16:18 dnolen_: stuartsierra: yes

16:24 arohner: (go-loop [] (<! (timeout 1000)) (foo) (recur)). Is there a better way to express 'run foo once a minute'?

16:24 s/minute/second/

16:24 ztellman: arohner: using core.async, or via any mechanism?

16:25 AeroNotix: arohner: there are timer classes and scheduler classes in the java stdlib

16:25 ztellman: scheduledthreadpoolexecutor

16:26 arohner: any reason to pick one of those over core.async?

16:26 AeroNotix: arohner: they're purpose built for that task

16:26 ztellman: arohner: your mechanism doesn't have a way to cancel, a way to specify the level of parallelism allowed, etc

16:27 amalloy: also what if foo takes half a second to run?

16:27 ztellman: also, yours doesn't run it once a minute, it runs it every minute + execution time

16:27 amalloy wins again

16:28 amalloy: my secret is keeping quiet until there's a point someone else is bound to make, and then sniping it

16:28 AeroNotix: point sniping

16:28 justin_smith: hah, help-camper

16:28 AeroNotix: :)

16:38 aeikenberry: justin_smith: I believe the reason this was supposed to be a macro was so that the arguments passed in aren't evaluated

16:39 justin_smith: it is very strange though, that this would be a task given to me knowing I'd never used Clojure before

16:39 justin_smith: aeikenberry: sure. you can also specify that the arguments supplied should be functions of no arguments, effectively gets you the same result, no new macros needed

16:41 aeikenberry: justin_smith: well thank you for the help.

16:42 justin_smith: i'll do my best, i guess

16:49 blunte: forgive me if this question was already answered. My connection dropped...

16:49 amalloy: aeikenberry: it sounded like building that hashmap is not actually part of your requirements, but just your implementation strategy? you don't really need to build a hashmap at all; you can just create two lists, one with the if-true expressions and one with the if-false expressions

16:50 blunte: Q: is it possible to pass a defrecord "type" as a parameter?

16:50 not an instance, but the class itself

16:50 aeikenberry: amalloy: how would i parse the argument to make the two lists though i was wondering?

16:51 justin_smith: blunte: (class my-record-instance) or your.ns.RecordName

16:51 aeikenberry: i have a SequenceArray of arguments, wondering the best way to parse that into the two lists or a hash map

16:51 two lists would be good, i'm sure

16:51 amalloy: (partition-by #{:iftrue :iffalse} args) would be a start

16:51 aeikenberry: ok

16:51 thanks. very helpful

16:51 amalloy: ,(partition-by #{:iftrue :iffalse} '(if x :iftrue a b :iffalse y))

16:52 clojurebot: ((if x) (:iftrue) (a b) (:iffalse) (y))

16:53 blunte: (defrecord R1 [a b])... can I pass R1 the type/class as an argument to a function?

16:56 justin_smith: blunte: yes, I just showed you how

16:56 aeikenberry: amalloy: what are a b in that line?

16:56 justin_smith: ,(do (defrecord R1 [a b]) (identity R1))

16:56 clojurebot: sandbox.R1

16:56 justin_smith: blunte: see above

16:57 amalloy: those are your printlns

17:04 aeikenberry: amalloy: (partition-by #{:then :else} (:then 'ok :else 'ok)) seems to throw an argumentException

17:06 wrong data type for partition-by i suppose

17:06 aperiodic: aeikenberry: you are calling :then as a function

17:07 sdegutis: aeikenberry: you want {} not () probably.

17:07 aeikenberry: or maybe []

17:15 gfredericks: ,(partition-by #{:then :else} [:then 'ok :else 'ok])

17:15 clojurebot: ((:then) (ok) (:else) (ok))

17:15 gfredericks: ,(partition-by #{:then :else} '(:then ok :else ok))

17:15 clojurebot: ((:then) (ok) (:else) (ok))

17:16 aeikenberry: ah

17:17 jjwatt: is there a way I can control how #insts are written to a file? i know that they're java.util.Dates, but when I use org.clojure/data.csv to write them, they're written in a human readable format, and I'd rather just write them as timestamps.

17:19 hiredman: ignore jjwatt

17:19 whoops

17:19 pardon me

17:20 sdegutis: awkward...

17:20 jcromartie: hahahaha

17:21 jjwatt: lol

17:22 jcromartie: jjwatt: just convert your data the hard way

17:22 data.csv has no facilities for customizing how values are printed or read back

17:22 it's not like clojure.edn

17:22 gfredericks: jjwatt: #inst does not exactly signify java.util.Date

17:22 jcromartie: or the reader in general

17:23 gfredericks: jcromartie: what does data.csv do? call #toString?

17:23 clojurebot: No entiendo

17:23 justin_smith: jcromartie: or cheshire, for that matter

17:24 jcromartie: data.csv just deals with strings

17:24 jjwatt: jcromartie: right, and i know that an #inst doesn't always signify a Date, but that the reader creates that object

17:24 jcromartie: and anything that isn't a string gets str'ed

17:24 every object written to CSV just gets str called on it, and then quotes get escaped if necessary

17:25 jjwatt: i was just wondering if there was a dynamic bind similar to *data-reader* that you could use when marshalling to strings.

17:25 I like the work it's doing with quotes and escaping

17:26 i'll just convert the data types before-hand in the pipeline

17:26 sdegutis: ~seen halgari

17:26 clojurebot: It's greek to me.

17:26 sdegutis: !seen halgari

17:26 erm...

17:28 gfredericks: str is customizable for IMeta

17:28 hyPiRion: $seen foo

17:28 lazybot: foo was last seen joining on #unavailable 2 weeks and 2 days ago.

17:28 stuartsierra: jjwatt: There's nothing bulit-in, but you can override print-method

17:28 gfredericks: as stuartsierra just explained

17:28 hyPiRion: sdegutis: but you're probably looking for tbaldridge?

17:29 gfredericks: I guess for any other specific type as well

17:29 tbaldridge: sdegutis: greetings

17:29 sdegutis: hyPiRion: oh, yeah..

17:29 tbaldridge: oh hi...

17:30 I should have worded this before pinging...

17:30 tbaldridge: oh wait, never mind.

17:30 amalloy: halgari is a pseudonym for tbaldridge?

17:31 sdegutis: Hey everyone: what's the general etiquette on naming one project the same as another project, when they're fundamentally different open source software projects?

17:31 arrdem: it's the name he uses everywhere but here...

17:31 sdegutis: For example, let's say one's a Ruby library, and another is a Qt application for Linux that lets you play DVDs or something.

17:31 jcromartie: sdegutis: is there ANY chance they could collide in some context?

17:31 amalloy: i guess i've never looked very closely at him anywhere but here or at a conference

17:31 sdegutis: jcromartie: they could both be used by the same user, but the user would clearly know they're different things.

17:31 * gfredericks imagines amalloy looking very closely at tbaldridge at a conference

17:32 sdegutis: gfredericks: LOL

17:32 justin_smith: sdegutis: would they be parallel packages in one package manager?

17:32 amalloy: hey, i have to look pretty closely to read nametags. dang tiny fonts

17:32 sdegutis: justin_smith: Never.

17:32 jcromartie: justin_smith: that sounds like a good rule of thumb

17:32 * tbaldridge getting uncomfortable

17:33 hyPiRion: heh

17:33 * arrdem popcorn

17:33 justin_smith: sdegutis: on my debian based system, I can pick ruby libraries and QT based video players in one big menu, and a naming conflict would force one of them to be renamed

17:34 amalloy: justin_smith: node is the worst-named package i remember seeing in debian

17:34 stuartsierra: This is what group IDs are for.

17:34 hyPiRion: yeah, exactly

17:34 sdegutis: tbaldridge: How would you feel if a completely unrelated open source app used the name "fafnir" also, and it happened to be completely unrelated to Clojure.. let's say it was some kind of instant messaging app for GKT+ or something...

17:35 I mean, just hypothetically.

17:35 tbaldridge: I really don't care

17:35 not like I have a copyright to the name or anything

17:35 sdegutis: tbaldridge: oh just wondering, thanks for your advice

17:35 amalloy: what if i named my cat fafnir?

17:36 tbaldridge: then no, in that case, the cat would be mine

17:36 sdegutis: ~lawyers

17:36 arrdem: amalloy: then you get sued by the BattleTech guys

17:36 clojurebot: Titim gan éirí ort.

17:36 justin_smith: amalloy: see also jack, chromium (just off the top of my head)

17:37 amalloy: maybe i'll change my name to chromium

17:37 that should make a lot of things mine

17:37 sdegutis: tbaldridge: so you wouldn't mind if I named my OS X program Mjolnir?

17:37 tbaldridge: I missed the part where it matters what I think

17:37 amalloy: i'd mind, but only because of the stunning lack of creativity

17:37 sdegutis: tbaldridge: just trying to use "etiquette" or something.

17:38 tbaldridge: im still not sure how this open source stuff works tbh

17:38 justin_smith: ,(java.util.UUID/randomUUID) I declare that the name of sdegutis's new library is:

17:38 clojurebot: #uuid "7ce21776-9109-49f1-94d9-6db44b70633f"

17:39 sdegutis: ha

17:39 tbaldridge: justin_smith: ah so we're using COM these days?

17:39 technomancy: doesn't gfredericks have a patent on a system and method for choosing library names by uuid in an internet chat system?

17:39 justin_smith: hey, no likely name clashes

17:39 hyPiRion: sdegutis: You could probably use Gungnir instead, if you really worry

17:39 gfredericks: &(format "lib-%04d" (rand-int 10000))

17:39 lazybot: ⇒ "lib-7816"

17:39 gfredericks: ^ hand-made

17:40 hiredman: getting a sweet domain name and use it as a group-id

17:40 technomancy: oh right

17:40 hiredman: get a

17:40 technomancy: non-infringing

17:40 justin_smith: but mine has "1776" embedded in it, which is way historically significant

17:41 gfredericks: murica

17:41 hyPiRion: justin_smith: well, 7816 is way more significant, you just don't know it yet.

17:42 justin_smith: heh

17:42 jcromartie: (ns org.afc85879-35ed-4cd7-b81f-1db66edb1950.ee10e10a-3c20-454b-974a-3371318568f7.core "Core functions for ee10e10a-3c20-454b-974a-3371318568f7" (:require [org.afc85879-35ed-4cd7-b81f-1db66edb1950.ee10e10a-3c20-454b-974a-3371318568f7.util :refer :all]))

17:42 justin_smith: lol

17:42 jcromartie: usage: (require '[org.afc85879-35ed-4cd7-b81f-1db66edb1950.ee10e10a-3c20-454b-974a-3371318568f7.core :as ee10])

17:42 simple

17:43 * aperiodic re-rolls until he gets an org UUID starting with `deadbeef-cafe`

17:44 gfredericks: ,(apply * (repeat 12 16))

17:44 clojurebot: 281474976710656

17:45 sdegutis: tbaldridge: cool thx

17:45 fwiw, this is the app in question: https://github.com/sdegutis/hydra/issues/332

17:47 celwell: Hello, any suggestions on making this more idiomatic and simple? https://gist.github.com/celwell/552318c5c08fc5a2bff2

17:48 sdegutis: celwell: can you show an example input and output?

17:50 justin_smith: celwell: #(list (:id %) (:prefill_config %)) should be (juxt :id :prefill_config)

17:50 (inc juxt)

17:50 lazybot: ⇒ 11

17:50 jcromartie: wouldn't this be exactly as valid as waiting for a "real" "deadbeef-" UUID? ,(str "deadbeef" (.substring (str (java.util.UUID/randomUUID)) 8))

17:50 justin_smith: and (map ...) flatten should be just (mapcat ...)

17:50 ~flatten

17:50 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.

17:51 amalloy: jcromartie: if you're counting sheep, you don't just say "a million" and fall right to sleep

17:51 celwell: sdegutis: I've just added input and output to the gist in the first comment.

17:51 aperiodic: jcromartie: what, you're just letting people make up their own now? madness! anarchy!

17:52 the system & method clearly specifies using the output of the random UUID generator in whole!

17:53 celwell: justin_smith: thanks for pointing out 'juxt' that's helpful


17:54 amalloy: celwell: (apply hash-map (mapcat (juxt f g) xs)) should just be (into {} (map (juxt f g) xs))

17:54 cbp: amalloy: I don't think that works

17:54 ,(into {} [:a 1])

17:55 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword>

17:55 cbp: er

17:55 hyPiRion: cbp: That's wrong though

17:55 amalloy: cbp: it does work

17:55 cbp: im an idiot

17:55 justin_smith: ,(= (mapcat #(list % %) (range 4)) (flatten (map #(list % %) (range 4))))

17:55 clojurebot: true

17:55 justin_smith: the function there is not the point, just noting the equivalence of mapcat to flatten on a non-nested input

17:56 amalloy: celwell: you're also doing a bunch of work to build a potentially-huge map, and then selecting out just the keys you actually wanted. could be better to pre-filter

17:56 gfredericks: to flatten variable depth structures, tree-seq is probably always preferable to flatten?

17:57 amalloy: gfredericks: honorable suicide is preferable to flatten

17:57 justin_smith: (inc amalloy)

17:57 lazybot: ⇒ 151

18:01 gfredericks: (->> (ns-publics 'clojure.core) keys (sort-by awefulness) (reverse) (take 5))

18:01 awfulness*

18:05 cbp: (take-last 5) imo

18:07 amalloy: gfredericks: (shuffle '(test == cast fnext newline)) is my back-of-the-envelope guess

18:08 justin_smith: => (flatten, pmap, defstruct, apropos, cast)

18:08 amalloy: thanks for the "cast" suggestion

18:09 I include apropos in that list because it gives you names of functions, but no namespace info

18:09 totally annoying

18:09 amalloy: to-array-2d looks about as pointless

18:11 man, what the heck is the deal with #'clojure.core/filter-key? how did that ever get included, or written the way it is?

18:12 eskatrem: I'm having a problem with Monger: running (mc/update db coll {:eng eng-message} {:fr message} :upsert true) gets me an error "Wrong number of args (6) passed to: collection/update"

18:13 amalloy: justin_smith: clojure.core/xml-seq

18:14 justin_smith: oh, that's another good one

18:14 cbp: wonder if anyone's ever used test

18:15 AeroNotix: amalloy: which version is that in?

18:15 cbp: it's private

18:15 justin_smith: cbp: I think I had a reason to use it once. I think, sort of like inot-array-2d, it's one of those things that is in there because rich hickey finds it useful, but most of the rest of the userbase will probably never touch it

18:16 amalloy: most of these functions i doubt rich actually finds useful. he was just starting with clojure and was like "what are some cool things i can build and/or might want someday"

18:16 justin_smith: like, any sane clojure user would just use a set with keywords in it, but some crazy person maybe tests if bits are set

18:17 oh, now I remember: I was building a quad tree data structure where the lookup of data mapped to the x / y bitwise representation of the coordinates

18:17 so I found it useful to check specific bits

18:17 it sped up my lookups immensely

18:17 amalloy: justin_smith: what function are you talking about?

18:18 justin_smith: test

18:18 amalloy: you seem to mean bit-test

18:18 justin_smith: ahh, yeah

18:18 amalloy: &(doc test)

18:18 lazybot: ⇒ "([v]); test [v] finds fn at key :test in var metadata and calls it, presuming failure will throw exception"

18:18 justin_smith: oh, never mind :P

18:19 yeah, some cruft from before clojure.test I guess

18:19 cbp: i was confused for a bit

18:19 gfredericks: ,(defn add {:test (fn [] :yep)} [x y] (+ x y))

18:19 clojurebot: #'sandbox/add

18:19 justin_smith: cbp: amalloy: in my defense, there is a link on the clojure cheatsheet page that says "test" and clicking it goes to bit-test (the tricky formatting fooled me)

18:19 gfredericks: ,(test #'add)

18:19 clojurebot: :ok

18:20 cbp: #badpuns

18:20 gfredericks: ,(defn add {:test (fn [] (/ 3 0))} [x y] (+ x y))

18:20 clojurebot: #'sandbox/add

18:20 gfredericks: ,(test #'add)

18:20 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Divide by zero>

18:20 AeroNotix: justin_smith: jeez I need to go to bed I thought you said "... on the clojure cottage cheese page .."

18:20 justin_smith: AeroNotix: that does not sound very appetizing at all

18:21 amalloy: set your homepage to clojure.org/cottagecheese - something exciting coming soon!

18:21 AeroNotix: justin_smith: :)

18:23 gfredericks: you gotta come to strange loop to see the talk that announces it

18:23 amalloy: now, amusingly, clojure.test/deftest actually puts the test into the var's metadata rather than the var itself, just in case someone calls clojure.core/test

18:23 justin_smith: oh, so not pre clojure.test cruft, but just an unused feature compatible with clojure.test

18:24 amalloy: i don't think you can draw that conclusion

18:24 it was probably around before clojure.test, and clojure.test structured to be compatible with it

18:24 justin_smith: OK - I guess it wouldn't respect any fixture definitions

18:24 gfredericks: clojure.core should start adding :weird? metadata to weird vars

18:25 arrdem: I'd take :pure as well because tracing side-effects is a royal pain..

18:25 justin_smith: gfredericks: each var should have a :karma metadata, dictated by the popularity of that definition on #clojure

18:26 amalloy: yeah, clojure.core/test was added a year before the first commit i can find clojure.test

18:27 gfredericks: (dec clojure.core/test)

18:27 lazybot: ⇒ -1

18:33 frankle: i know nothing about clojure, but thought that you guys touted something like this as more readable, right? (inc (last (take 2 (filter odd? [1 2 3 4 5]))))

18:34 if so, why is prismatic writing macros for clojurescript to do something like this instead: https://gist.github.com/davegolland/dd47281d1ef1e4a10f3b#file-threading-example-clj

18:34 AimHere: Umm, (last (take 2 foo)) is the same as (second foo)

18:35 frankle, that ->> macro is a clojure built-in

18:35 frankle: AimHere: thanks. didn't know that. what form is encouraged?

18:35 AimHere: Use that, or use the nested s-expressions, according to which you feel is more readable at the time

18:36 frankle: what about consistency?

18:36 AimHere: Consistently aim for readability

18:36 frankle: i like it

18:36 haha

18:37 gfredericks: amalloy elucidated an interesting rule of thumbs on that yesterday

18:38 i.e., a more specific definition of readable

18:38 frankle: what's that?

18:38 and do you have a link?

18:39 amalloy: frankle: search for "(= [1 2 2]" in http://logs.lazybot.org/irc.freenode.net/%23clojure/2014-07-28.txt, and then follow the conversation between me and gfredericks

18:40 gfredericks: lazybot: you need line anchors in your irc log pages

18:40 frankle: thanks

18:40 amalloy: feel free to read http://stackoverflow.com/questions/12715577/when-should-i-use-the-clojure-arrow-macro as well

18:42 the implementation of underive is bizarre. it starts with (declare flatten)

18:43 gfredericks: clojurebot: clojure is lisp4j

18:43 clojurebot: Roger.

18:47 aeikenberry: (partition-by #{:then :else} args)

18:47 pdk: clojurebot: you're my best friend

18:47 clojurebot: Titim gan éirí ort.

18:48 aeikenberry: what is the #{:then :else} doing exactly?

18:49 justin_smith: aeikenberry: when used as a function, a set returns nil if the argument is not present, or the argument if it is present in the set

18:49 ,(map #{:a :g} [:a :b :c :d :e :f :g])

18:49 clojurebot: (:a nil nil nil nil ...)

18:50 justin_smith: ,(keep #{:a :g} [:a :b :c :d :e :f :g])

18:50 clojurebot: (:a :g)

18:52 aeikenberry: after i run that partition-by, i get this: ((:then) ((quote ok)) (:else) ((quote notok)))

18:52 i'm trying to find the clojure way of grouping those by the keywords

18:53 justin_smith: aeikenberry: do you have a paste of your current code?

18:56 aeikenberry: justin_smith: https://dpaste.de/9UEU

18:56 this is what i was trying to do

18:57 (multi-if (= 1 0) :then (println "hi") :else 'ok)

18:57 justin_smith: aeikenberry: def is only for creating globals

18:58 aeikenberry: should be using let?

18:58 justin_smith: (hash-map chunks) should be (apply hash-map (cleanup-keys chunks))

18:58 cleanup-keys clearly has not been written yet :)

18:59 yeah, let

18:59 aeikenberry: what should cleanup-keys be doing there?

19:00 justin_smith: also, a macro needs to return that form that will run - so you may need to change (do ...) to (list 'do ...) (or maybe you need to construct your form by some other method)

19:00 aeikenberry: it would turn (:then) into :then and (:else) into :else

19:01 aeikenberry: hm. ok. thanks

19:01 justin_smith: or you could change (:then chunkmap) into (get chunkmap '(:then))

19:01 but that is weird

19:01 aeikenberry: i see. thanks a lot for taking a look

19:02 justin_smith: np

19:02 so now you are looking at something more like (defmacro multi-if [test & args] (let [chunks ...] ...))

19:03 you may or may not want to learn how to use ` and ~, they are helpful for selective evaluation and form building

19:03 most macros use them

19:03 but that may be more complexity than you need right now (since ` changes how you use let, etc.)

19:04 numberten: is there any difference between core/false? and core/not ?

19:04 justin_smith: ,((juxt false? not) nil)

19:04 clojurebot: [false true]

19:05 numberten: juxt is just comp but left to right?

19:05 not familiar with that function

19:06 justin_smith: (doc juxt)

19:06 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

19:06 numberten: oh no

19:06 yeah

19:06 justin_smith: ,((juxt inc dec) 0)

19:06 clojurebot: [1 -1]

19:06 numberten: it applied each to the value

19:06 wow that's really useful

19:06 justin_smith: also thanks for the example

19:06 for not and false?

19:06 justin_smith: right, it was a quick way to say "false? and not return different results when applied to nil"

19:06 np

19:09 technomancy: it's the best function

19:09 no other function is as good as juxt. objective fact.

19:09 arrdem: $karma juxt

19:09 lazybot: juxt has karma 11.

19:10 arrdem: Juxt is the 57th most referenced function in Grimoire

19:12 technomancy: (inc juxt)

19:12 lazybot: ⇒ 12

19:37 TimMc: (juxt inc)

19:37 justin_smith: ((juxt inc dec) TimMc)

19:38 though not implemented as a command, results in a logical outcome for said unimplemented command

19:38 technomancy: justin_smith: it's atomic too!

19:38 justin_smith: yup, no race conditions here

19:39 arrdem: Clearly lazybot should be extended to an sexpr interpreter supporting arbitrary combinations of inc, juxt, dec, doseq and usernames.

19:39 kelseygi_: what's the better (or even working) way to do this?

19:39 (swap! state

19:39 #(update-in % [:deletes]

19:39 #(concat (seq [1 12 13]) %)))

19:39 arrdem: kelseygi_: refheap.com

19:39 justin_smith: kelseygi_: please use refheap

19:39 kelseygi_: whoops sorry!

19:39 https://www.refheap.com/88703

19:40 arrdem: <3

19:40 gfredericks: (swap! state update-in [:deletes] #(list* 1 12 13 %))

19:40 justin_smith: (swap! state update-in [:deletes] #(conj % 1 12 13))

19:40 Raynes: (juxt inc inc inc inc inc inc inc inc inc inc inc inc inc inc dec #_ccccccccccombobreaker)

19:41 arrdem: (inc Raynes)

19:41 lazybot: ⇒ 47

19:42 justin_smith: (swap! state update-in [:deletes] #(conj % 13 12 1)) ; had it backwards

19:42 gfredericks: justin_smith: using conj assumes you have a seq; and if you do use conj, you don't need the anonymous fn

19:42 justin_smith: gfredericks: it was documented to take a seq

19:42 gfredericks: (swap! state update-in [:deletes] conj 13 12 1)

19:42 justin_smith: ahh, nice

19:43 gfredericks: in the future we will have update

19:43 and then it gets even prettier

19:43 kelseygi_: heh, learning clojure feels like a constant state of having it backwards

19:44 justin_smith: ,(swap! (atom {}) update-in [:deletes] conj 13 12 1) works, nice

19:44 clojurebot: {:deletes (1 12 13)}

19:44 justin_smith: kelseygi_: we are just very flexible about direction

19:45 amalloy: ,(swap! (atom {}) update-in [:deletes] (fnil conj []) 13 12 1) is even more exciting

19:45 clojurebot: {:deletes [13 12 1]}

19:45 kelseygi_: ,(apply update-in {} [:deletes] conj 13 12 1)

19:45 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

19:45 gfredericks: SO EXCITED

19:45 kelseygi_: see this is where i'm getting confused about what swap actually does

19:45 gfredericks: ,(update-in {} [:deletes] conj 13 12 1)

19:45 clojurebot: {:deletes (1 12 13)}

19:45 gfredericks: no need for apply

19:45 kelseygi_: yeah i know, i'm trying to work out what gets done with the args to swap!

19:46 "Atomically swaps the value of atom to be: (apply f current-value-of-atom args)"

19:46 amalloy: (swap! a f x y) => (swap! a #(f % x y))

19:47 kelseygi_: right, but that's why (swap! (atom {}) update-in [:deletes] conj 13 12 1) is confusing me

19:47 gfredericks: args in this case is [[:deletes] conj 13 12 1)

19:47 kelseygi_: isn't the map getting inserted before [:deletes]?

19:47 gfredericks: (swap! a f x y) => (swap! a #(apply f % [x y]))

19:48 kelseygi_: ,(apply update-in {} [[:deletes] conj 13 12 1])

19:48 clojurebot: {:deletes (1 12 13)}

19:48 kelseygi_: whooooaaaa, that's subtle

19:50 gfredericks: kelseygi_: have you used any other dynamically typed languages?

19:50 kelseygi_: javascript

19:50 gfredericks: javascript has this too

19:50 f(m,x,y) => f.apply([m,x,y]) // or so

19:51 I can't remember if you can f.apply(m,[x,y])

19:51 also there's probably a this arg I forgot?

19:51 I don't even want to think about it

19:51 kelseygi_: so i thought i got what apply was doing

19:51 tuft: there usually is

19:51 kelseygi_: but i'm a lil confused by what you pointed out, the f.apply(m,[x,y]) bit

19:52 gfredericks: compare these two

19:52 ,(apply update-in {} [[:deletes] conj 13 12 1])

19:52 clojurebot: {:deletes (1 12 13)}

19:52 amalloy: kelseygi_: (apply f x y [a b c]) => (f x y a b c)

19:52 gfredericks: ^ which is what you pasted

19:52 ,(apply update-in [{} [:deletes] conj 13 12 1])

19:52 clojurebot: {:deletes (1 12 13)}

19:52 gfredericks: ^ same thing but with first arg included in the list

19:54 kelseygi_: right, i follow there

19:54 i think i got led astray by the doc string "Atomically swaps the value of atom to be: (apply f current-value-of-atom args)"

19:55 gfredericks: yeah the docstring uses that form so as to be maximally generic

19:55 kelseygi_: yeah it's not *literally* that

19:55 gfredericks: well it might be

19:55 kelseygi_: well it is, but hte args are passed as an array

19:55 amalloy: kelseygi_: yes it is

19:55 kelseygi_: cause otherwise it does (f x y a b c) as amalloy pointed out

19:55 er i totally meant vector

19:55 gfredericks: it does both

19:56 apply does the (f x y a b c)

19:58 kelseygi_: i'm trying to understand the form apply gets called in when i call (swap! atom f x y a b c)

19:58 gfredericks: (apply f current-val [x y a b c])

19:58 according to the docstring

19:58 kelseygi_: yeah

19:58 gfredericks: and that is logically accurate

19:58 danielcompton: What's the reasoning behind clojure contrib projects having to use Jira patches? I understand that's how Clojure Core does it but it's not explained well at http://dev.clojure.org/display/community/Guidelines+for+Clojure+Contrib+committers

19:58 gfredericks: sometimes there are differences for performance, but logically you can ignore those

19:58 kelseygi_: i was trying it as (apply f current-val x y a b c) which is different

19:59 gfredericks: yes

19:59 amalloy: ,((fn [a f & args] (apply f a args)) 1 + 2)

19:59 clojurebot: 3

20:00 amalloy: here a is 1, f is +, and args is [2]

20:00 kelseygi_: yup, i see the difference, was trying to work back to where i got entangled in the swap

20:00 thanks!

20:01 aaelony: hmmm, trying to define a defrecord with 213 fields and getting "java.lang.RuntimeException: Method code too large!" ... sigh

20:02 gfredericks: I got a stack overflow

20:02 from: (eval (list 'defrecord 'Foo (vec (repeatedly 213 gensym))))

20:02 justin_smith: https://en.wikipedia.org/wiki/Potoooooooo another awesome namesake waiting to be claimed

20:03 aaelony: trying to determine what the max on my system is ...

20:03 gfredericks: I got method code too large for 163

20:04 hiredman: I suspect 0 or 1 will work

20:04 aaelony: seems about right where I'm at

20:04 gfredericks: 122 is my largest

20:04 * gfredericks did a manual binary search and feels pathetic as a result

20:04 aaelony: I guess I'll use a map instead.

20:05 amalloy: aaelony: what on earth. a record with 213 fields? there can't be any imaginable reason to use that instead of a map

20:05 it would perform abysmally

20:05 gfredericks: amalloy: why?

20:06 oh the copying?

20:06 amalloy: yes

20:06 aaelony: I've got a file with 213 columns. I like records, but in this case it'll be a map.

20:06 gfredericks: amalloy: but perform fine for writing amiwrite?

20:06 s/writing/reading/

20:06 s/amiwrite/amiread/

20:06 justin_smith: aaelony: what about nesting them? there must be some sub-categorization of the fields that simplifies the structure

20:07 amalloy: i dunno, maybe. (.foo ^MyRec x) would be fine, but (:foo x) might be quite poor

20:07 probably it'd be fine

20:08 gfredericks: clojurebot: probably it|'d be| fine

20:08 clojurebot: In Ordnung

20:08 gfredericks: ~probably it

20:08 clojurebot: probably it 'd be fine

20:08 gfredericks: aw

20:08 aaelony: justin_smith: I could. The idea was to read it in, then clean it up, add some business logic, transform things, then ultimately the output needs to be flat. I guess I'll just zipmap keyword labels onto it to make a big map...

20:08 amalloy: i wonder if (keys) is cached on records

20:09 i guess not, since keys is (map key (seq x))

20:10 aaelony: if I was evil I could create a defrecord for the first part and another for the second, I suppose as well

20:11 justin_smith: aaelony: if any of the fields could be collated into an array or vector, that could simplify things a lot during the intermediate pre-flattened processing

20:13 aaelony: justin_smith: agree. I'm thinking a simple map for now, but will noodle more on it. It surprised me that defrecords don't allow a lot more elements though.

20:14 I would think it's pretty common for a file to contain a lot of columns and a defrecord is nice for that

20:14 gfredericks: aaelony: why is it nice for that?

20:14 amalloy: they don't allow a ton of elements because all of the benefits of a defrecord are related to having a small, fixed/known number of keys

20:15 aaelony: if the premise is that it's like a map but faster, it's a nice idea

20:15 amalloy: it's not. if you gave it that many elements it would be slow

20:16 as i was discussing with gfredericks

20:16 aaelony: yeah, it's looking like a map is in order then

20:17 or a Java object....

20:24 gfredericks: deftype goes up to 254 on my machine

20:24 the error after that is "Too many arguments in method signature in class file compile__stub/user/Foo"

20:37 rritoch: Hi, does anyone know how to make a gen-interface with default arguments?

20:39 I tried using :methods [[get [String] Object] [get [String Object] Object]] with (defn get ([this k] ...) ([this k d] ...)) but I'm getting an aririty exception

20:40 aaelony: gfredericks: is deftype an option?

20:40 gfredericks: aaelony: depends on what you're doing?

20:41 aaelony: I'm sure it's a terrible option but I also think that about "a Java object"

20:41 aaelony: I tested a map, it works great. But curious, suppose this file got very large...

20:42 gfredericks: large rows or large columns?

20:42 aaelony: I think I'm lucky because a map might be good enough, but I can imagine a lot of other scenarios where it would be nice to have a performant thingy that feels like a map but also has the potential for polymorphism and oo stuff too...

20:43 gfredericks: that's way too squishy to analyze; maps can be polymorphic w/ multimethods

20:43 aaelony: large rows and large columns. I guess then a rethink would be in order, cascalog or something hadoopy

20:47 rhg135: rritoch, any reason you can't use protocols?

21:03 aaelony: rhg135: protocols for what?

21:04 rhg135: ahh, nevermind. question rescinded...

21:17 danielcompton: I'm wanting to flatten a nested map into a collection of maps like https://www.refheap.com/88706. I had a look around and I couldn't find anyone doing this kind of thing. What would be the right approach for this?

22:14 talios: is the depth constant?

22:43 danielcompton: talios: nope

22:44 talios: is the depth known?

22:44 * talios ponders

22:46 aeikenberry: i'm new. been working on this today for an assignment

22:46 https://dpaste.de/pg2d

22:47 it's real rough, but i don't really understand the error

22:51 sorry just learning clojure today

22:57 jeremyheiler: aeikenberry: the error implies that you're using a keyword as a function.

22:57 ,(:foo)

22:57 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo>

22:58 jeremyheiler: same error^

22:58 using a keyword as a function is fine, but calling it without any arguments is why this error occurs.

22:59 aeikenberry: thanks. that does make sense

23:00 is it line 5 that is having problems then?

23:01 gws: aeikenberry: try macroexpand-1 - possibly like this: (macroexpand-1 '(multi-if (= 1 0) :then (println "ok") :else notok))

23:03 jeremyheiler: aeikenberry: what gws suggested is exactly what i would do, too.

23:03 aeikenberry: thanks

23:06 seems to give me the same error

23:06 gws: did you quote the form like I had it?

23:06 that worked for me in a repl

23:08 aeikenberry: ah, i see

23:09 having (:then) as a key is certainly not the best way

23:09 jeremyheiler: aeikenberry: looking at the macroexpanded output, you have too many parens around things.

23:09 gws: ,(:then)

23:09 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :then>

23:09 gws: ,:then

23:09 clojurebot: :then

23:10 gws: ,(:then {:when "will" :then "be" :now? "soon"})

23:10 clojurebot: "be"

23:10 gws: aeikenberry: you can use keywords as functions in clojure

23:11 aeikenberry: when i do that partition-by, i get something like ((:then) ((println "ok")) (:else) (notok))

23:12 i thought making that into a map would make sense, but it's taking the whole (:then) rather than the :then

23:14 gws: ,(map first '((:then) ((println "ok"))))

23:14 clojurebot: (:then (println "ok"))

23:15 aeikenberry: oh wow

23:20 thanks guys. making progress!

23:21 gws: nice :)

23:29 aeikenberry: https://dpaste.de/VYTT

23:30 any idea why these both condition evaluates as if it were false?

23:30 macroexpand doesn't seem to help. just says (do 'notok)

23:36 gfredericks: ,(defmacro multi-if

23:36 [test & args]

23:36 (let [chunks (partition-by #{:then :else} args)]

23:36 (let [chunkmap (apply hash-map (map first chunks))]

23:36 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

23:36 gfredericks: (list 'cond 'test (list 'do (:then chunkmap)))

23:36 :else (list 'do (:else chunkmap)))))

23:36 welp

23:36 no defense for doing that.

23:37 aeikenberry: what the result of macroexpand tells you is that your problem is happening during macroexpansion

23:37 TEttinger: ,(defmacro multi-if [test & args] (let [chunks (partition-by #{:then :else} args)] (let [chunkmap (apply hash-map (map first chunks))] (list 'cond 'test (list 'do (:then chunkmap))) :else (list 'do (:else chunkmap)))))

23:37 clojurebot: #'sandbox/multi-if

23:38 gfredericks: aeikenberry: I don't think your parentheses are balanced the way you think they are

23:38 TEttinger: what were you going to do with that multi-if, gfredericks

23:38 gfredericks: ,(macroexpand-1 '(multi-if (= 1 1) :then (println "ok") :else 'notok))

23:38 clojurebot: (do (quote notok))

23:38 gfredericks: just that

23:39 aeikenberry: e.g., your line 5 is a complete NOOP

23:39 aeikenberry: sorry, what is NOOP

23:39 TEttinger: no operation

23:39 does nothing

23:40 also called dead code, or unreachable code

23:40 aeikenberry: i see

23:43 gfredericks: not unreachable in this case, just ignored

23:43 aeikenberry: why ignored though?

23:43 macro escaping?

23:43 gws: no, count parens

23:44 aeikenberry: ohhhh

23:45 all these parens!

23:45 gfredericks: it helps to have a text editor that indents based on the parens

23:46 your manual indentation is deceptive

23:47 aeikenberry: welp i fixed i thought but now i have the problem where only the truth evaluates...

23:48 (if test (do (println "ok")) (clojure.core/cond :else (do (quote notok))))

23:49 ah ha. if test rather than the exp

23:49 thanks a lot. you guys rule

23:50 gfredericks: :)

23:59 Balveda: (if (< 3 (count ["1" "2" "3" "4"]) (println "y") (println "n")))

Logging service provided by n01se.net