#clojure log - Aug 18 2015

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

0:00 sdegutis: The connection is stored in a simple var, so basically yeah.

0:02 rhg135: ,(do (def a 1) (alter-var-root #'a inc) a)

0:02 clojurebot: 2

0:02 sdegutis: justin_smith: back

0:03 justin_smith: sdegutis: rhg135 has a good point, you could just use alter-var-root or def

0:03 Bronsa: ew

0:04 rhg135: I never said it was a good idea

0:04 sdegutis: Won't that be slower?

0:04 rhg135: just that it existed

0:04 sdegutis: Also Compojure, thus threads.

0:04 rhg135: exactly

0:05 ,(meta *ns*)

0:05 clojurebot: nil

0:05 justin_smith: ,(meta (the-ns *ns*))

0:05 clojurebot: nil

0:05 Bronsa: ,*ns*

0:05 clojurebot: #object[clojure.lang.Namespace 0x62eb0ba1 "sandbox"]

0:05 justin_smith: ,(meta #'meta)

0:05 clojurebot: {:arglists ([obj]), :doc "Returns the metadata of obj, returns nil if there is no metadata.", :added "1.0", :static true, :line 202, ...}

0:06 rhg135: ,(alter-meta! *ns* assoc ::store-stuff-here-and confuse-people)

0:06 clojurebot: #error {\n :cause "Unable to resolve symbol: confuse-people in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: confuse-people in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve sym...

0:06 rhg135: ,(alter-meta! *ns* assoc ::store-stuff-here-and-confuse-people)

0:06 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: core/assoc--4130"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/assoc--4130"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 427]\n [clojure.lang.AFn applyToHelper "AFn.java" 156]\n...

0:06 justin_smith: rhg135: assoc needs two values

0:06 rhg135: eh, I probably shouldn't be writing code

0:06 justin_smith: and they both need to be things that exist...

0:06 rhg135: ,(alter-meta! *ns* assoc ::store-stuff-here-and-confuse-people true)

0:06 clojurebot: {:sandbox/store-stuff-here-and-confuse-people true}

0:07 justin_smith: rhg135: heh, I know that feel, I had a large helping of whiskey before leaving work

0:07 hit a major milestone and had to celebrate

0:07 rhg135: sad thing is, i'm sober

0:07 justin_smith: finally moved the major foundation of our app into onyx for distributed computation - it's like "hey app, welcome to the 21st century"

0:08 onyx is cool

0:08 rhg135: I'm just going to update my lazybot fork. that way when I mess up other people can debug for me

0:08 justin_smith: (inc mdrogalis)

0:08 lazybot: ⇒ 9

0:08 rhg135: via IRC

0:09 justin_smith: I did a bunch of lazybot hacking earlier this year

0:09 but did not fix the *one thing* that actually needed fixing, somehow

0:09 rhg135: I a few years ago

0:09 I was meaning to excise mongo, but lazy

0:10 I'd have to rewrite half the plugins

0:10 Bronsa: justin_smith: the connection issues?

0:10 justin_smith: you should totally hook in a dotomic based karma system

0:10 Bronsa: yeah

0:10 rhg135: I wanted to

0:10 justin_smith: Bronsa: the way it will think it is connected and really be in a void connected to nobody/nothing

0:10 rhg135: instead I will finish my text generator plugin

0:10 Bronsa: just immagine how sad and lonely it must feel

0:11 rhg135: you can call, but nobody replies

0:11 justin_smith: Bronsa: lazybot bugs are how I truly feel inside :(

0:12 anyway, yeah, never did find a fix for that issue

0:12 rhg135: my workaround was ping me until I get off my a** and restart it

0:13 eventually I just took it offline

0:14 crocket: Why does it take a lot longer to start an uberjar than to start a single script via clojure.jar?

0:14 rhg135: justin_smith: actually, that datomic idea isn't bad. It'd reminded me I could leave in mongo and move stuff to datomic in time

0:15 no clue

0:28 Seylerius: ,(defn fibber [n] (take n (map first (iterate (fn [[a b]] [b (a + b)]) [0 1]))))

0:28 clojurebot: #'sandbox/fibber

0:28 Seylerius: ,(fibber 6)

0:28 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

0:29 Seylerius: Oi.

0:29 I really made that mistake?

0:29 ,(defn fibber [n] (take n (map first (iterate (fn [[a b]] [b

0:29 (+ a b)]) [0 1]))))

0:29 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

0:30 Seylerius: ,(defn fibber [n] (take n (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))

0:30 clojurebot: #'sandbox/fibber

0:30 Seylerius: ,(fibber 6)

0:30 clojurebot: (0 1 1 2 3 ...)

0:30 Seylerius: ,(defn fibber [n] (take n (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1]))))

0:30 clojurebot: #'sandbox/fibber

0:31 Seylerius: ,(fibber 6)

0:31 clojurebot: (1 1 2 3 5 ...)

0:31 Seylerius: There we go.

0:32 crocket: Hell

0:35 If I compiled a clojure library for java users, is it tied to a specific clojure version?

0:35 Seylerius: crocket: Pretty sure it compiles the clojure it needs into the jar, so yes.

0:37 crocket: Ewww

0:37 It's going to become large

0:38 Seylerius: crocket: If you're compiling for use by non-clojurists, expect to have to carry around some deps.

0:44 rhg135: clojure isn't that large anyway

0:45 sdegutis: So, swapping out a value for another value inside insert-into-database and update-entity don't sound like terrible ideas performance-wise?

0:46 crocket: Clojure 1.7.0 3.8MB

0:47 rhg135: that's relatively small

1:53 Olajyd: Hi, justin_smith

1:57 Hi, TEttinger :)

2:00 Tettinger, I want to implement a perl regex pattern in clojure, is this possible?

2:00 TEttinger: probably, perl uses a subtly different regex engine, but it's mostly compatible

2:00 what is it in perl?

2:01 also, http://www.regular-expressions.info/tutorial.html is an amazing resource

2:04 Olajyd: there's some further confusion possible because perl 6 (which is kinda in alpha or beta or some prerelease state) potentially can use really really crazy regexes.

2:04 Olajyd: TEttinger, I tried the following: given a perl regex : s/^[PH]*// for the string “hPPHp123hp” i figured a way of doing it in clojur as (clojure.string/replace “hPPHp123hp” (re-pattern “[Pp]|[Hh]”)) :=> “123”

2:06 TEttinger: do you want it to ignore case?

2:06 Olajyd: Tettinger, yes sure

2:06 TEttinger: ,(clojure.string/replace "hPPHp123hp" #"^[PpHh]*" "")

2:06 clojurebot: "123hp"

2:06 TEttinger: if you want it to remove all h and p

2:06 ,(clojure.string/replace "hPPHp123hp" #"[PpHh]" "")

2:06 clojurebot: "123"

2:06 Olajyd: oh great

2:07 another use case that seems to confuse me is to replace any possible occurrence with the string “000”

2:09 TEttinger: so in regexes, which are pretty much their own language, not related to clojure at all (and clojure's regexes are the same as java's), the character ^ means start of string usually. square brackets with some characters inside mean any of those characters will match, once. ^ inside square brackets means anything that ISN'T the characters after ^ in the brackets will match

2:09 Olajyd: so say (clojure.string/replace "hPPHp123hp" #"[PpHh]" “000”) I need it to return ;=> “000123000”

2:09 TEttinger: * means repetition, 0 or more

2:09 Olajyd: ok

2:09 TEttinger: + means repetition, 1 or more

2:09 ah ok

2:10 ,(clojure.string/replace "hPPHp123hp" #"[PpHh]+" "000")

2:10 clojurebot: "000123000"

2:10 Olajyd: Great

2:10 Thanks,

2:11 Will go over the resource you just shared

2:11 I owe u another drink.. :)

2:11 TEttinger: no prob! regexes are something that I wish they taught whole classes on in colleges, they are extremely useful even to non-programmers (some text editors and even word processors allow regex find/replace, huge timesaver)

2:13 Olajyd: hmm, thanks

2:17 TEttinger: some of the better tricks with regexes cover stuff that's very difficult with character-by-character processing of a string. within a regex (not a normal string), \b can be very very handy to find word boundaries, and \p{Lu} will find all upper case letters, even ones that aren't in English

2:17 MasseR: \p? Shouldn't it be \w?

2:18 Or maybe even, what's the difference between them

2:18 TEttinger: MasseR: \w I believe is the same as [A-Za-z0-9_]

2:19 MasseR: TEttinger: Hmm.. alphanumeric yes, but outside of ascii range

2:19 grep -E "\w+" --color=always seems to match for both foo0 and föö0

2:19 TEttinger: &(let [latin1 (apply str (range 32 255))] (apply str (re-seq "\w")))

2:19 lazybot: java.lang.RuntimeException: Unsupported escape character: \w

2:19 TEttinger: &(let [latin1 (apply str (range 32 255))] (apply str (re-seq #"\w" latin1)))

2:20 lazybot: ⇒ "3233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142... https://www.refheap.com/108397

2:20 TEttinger: oh stupid me

2:20 MasseR: :)

2:20 TEttinger: &(let [latin1 (apply str (map char (range 32 255)))] (apply str (re-seq #"\w" latin1)))

2:20 lazybot: ⇒ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"

2:20 TEttinger: yep, ascii only for \w in java

2:20 &(let [latin1 (apply str (map char (range 32 255)))] (apply str (re-seq #"\p{Lu}" latin1)))


2:20 TEttinger: &(let [latin1 (apply str (map char (range 32 255)))] (apply str (re-seq #"\p{L}" latin1)))

2:20 lazybot: ⇒ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ"

2:21 TEttinger: &(let [latin1 (apply str (map char (range 32 255)))] (apply str (re-seq #"\p{Ll}" latin1)))

2:21 lazybot: ⇒ "abcdefghijklmnopqrstuvwxyzªµºßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ"

2:21 MasseR: grep -E doesn't seem to match anything with \p. I like regex, but too many variations of it :/

2:22 TEttinger: yeah. \p takes a unicode category code after it in curly bracees

2:22 L is letters, Lu is upper case letters, Ll is lower case letters

2:22 not all regex engines implement it, and they all do different unicode versions.

2:23 java 9 will support unicode 7.0 sometime next year

2:23 perl 6 (on one of the VMs it can run on) supports Unicode 8.0

2:23 perl 6 also has some really really weird and useful extensions

2:24 IIRC, \c[APOSTROPHE] is another way of matching the ' character, and it's especially useful when your editor thinks any ' is a string starting

2:25 \c[SIGN OF THE HORNS] is the metal fingers gesture introduced as an emoji in unicode 8

3:09 varnie: good day.

3:11 I have a question about reduce. suppose I have a function which recursively traverses directory, finds specific files and calculates, the count of lines in them. this function returns total count of lines in files. My question is - wouldn't (reduce + ...) produce a lot of "thunks" and, thus, gobble up a lot of memory?

3:13 I can show my code snippet to clarify what I mean.

3:30 luxbock: gfredericks: sorry if you my question earlier was unclear, I'll try to describe my use case

3:31 my program deals with trees that are "drawn" from rules and a root-node

3:31 and I'd like to use test.check to test properties of the trees

3:32 so to generate them, I need two generators, one for the rules and one for the root-nodes

3:33 however these trees can grow quite large depending on the rules and the root-node

3:33 justin_smith: varnie: reduce doesn't need to build thunks, because all it needs is the accumulator

3:33 varnie: and in the case of reduce + the accumulator takes up very little RAM

3:34 varnie: nothing is executed out of order, so there are no thunks to keep around

3:34 varnie: justin_smith, I want to understand what happens when the depth of execution is big enough.

3:34 justin_smith: varnie: reduce doesnt do "deep"

3:35 varnie: at each step, the execution so far is cleaned up and replaced by the accumulator

3:35 varnie: we enter the directory which contains N subdirectories, in order to perform outermost reduce + we need to traverse all of them and calculate their output "result value".

3:35 luxbock: so in order for my tests to fail early, I'd like to generate the properties of the rules and the root-nodes so that they result in smaller trees at the beginning, and then grow larger and larger

3:35 i.e. that's what I meant with shrinking

3:36 varnie: and only when we have a list of result values, say (100, 200, 0, 20, etc), the outermost reduce + will fire. or am I wrong?

3:36 justin_smith: varnie: there is never a list of results

3:36 varnie: + is applied at every step

3:36 varnie: justin_smith, can you have a look at my code?

3:36 justin_smith: varnie: it's late and I'm just having a bit of insomnia but I'll give it a try

3:37 luxbock: this would be really easy to do if I can define a generator that chooses elements from a collection, choosing the earlier elements more frequently at the beginning

3:37 varnie: justin_smith, thank you. one moment please...

3:37 luxbock: does `gen/one-of` already do that?

3:37 justin_smith: varnie: but reduce does not hold onto the individual results before applying its accumulation - it's appled and the input is forgotten at every step

3:37 varnie: justin_smith, here it is: http://pastebin.com/Nja2D7xe

3:38 justin_smith, as you already know, I am a newbie, so... ;)

3:39 justin_smith: varnie: at line 14 the "reduce +

3:39 sorry

3:39 at line 14, the reduce + realizes one item of your map at a time

3:40 the map returns a number and all other information from that call realizing that item is thrown away

3:40 varnie: okay. can you say, what are the drawbacks of my approach? what could be done better in other words?

3:40 justin_smith: the number is added to the total you have so far, and the previous total is thrown away

3:40 varnie: I see.

3:41 justin_smith: varnie: I think it's easy to be confused by "reduce +" because + can take more than two args, and in that case it calls reduce

3:41 varnie: but when you use "reduce +" you only call + with two args each time

3:42 varnie: will it be better to rewrite it using loop/recur and accumulating an atom value during each step?

3:43 justin_smith: ,(reduce (fn [acc i] (print "element " i " ") (+ i acc)) 0 [1 2 3 4 5])

3:43 clojurebot: element 1 element 2 element 3 element 4 element 5 15

3:43 justin_smith: varnie: does the above help?

3:43 varnie: I know what it does. you mean that I might rewrite my program in that way?

3:44 justin_smith: varnie: regarding loop + atom, absolutely not. First off you don't need loop for this, second off if you are using a loop you don't need an atom - you would just pass the updated value to recur

3:44 varnie: I was just demonstrating that at each call reduce gives two numbers to +

3:44 varnie: and all previous steps are gone

3:44 varnie: ah, that's right.

3:46 justin_smith: varnie: and just a couple of style things - you can use import and that way you don't need to type out the full package to use a method

3:47 varnie: justin_smith, yes, but as for "org.apache. ...." it doesn't work from "lein repl" if I do "(load-file my-app.clj"). (currently I don't have a project for it)

3:47 justin_smith: and you might want to reduce your repetition by binding something like "file-object (io/file file)" in the let block

3:47 varnie: sure, but import doesn't change this at all

3:48 varnie: you need to set up your classpath, whether you use import is orthogonal to that

3:48 varnie: justin_smith, I'll check it out.

3:48 justin_smith: varnie: you'll find that in clojure not having a project is the hard way to do things, as soon as you have deps

3:49 varnie: haha, correct

3:49 I decided to start from something simple, but it turned out it is not *that* simple.

3:49 having a project would be way better.

3:50 justin_smith: varnie: yeah, the simple thing is to define a project (unless you know classpath building like the back of your hand)

3:50 varnie: justin_smith, what are the other ways to rewrite my program?

3:52 justin_smith: varnie: on line 24, where you look at "last s" this is O(n), here I am sure this does not matter because it's not like you'll have paths thousands of letters long, but since a string is counted it is much faster to use .charAt based on the count

3:52 which is O(1) rather than O(n)

3:53 varnie: in general, be suspicious of "last" unless the argument is a lazy sequence (in which case O(n) is your best / only option)

3:53 varnie: I see. but this function execute 1 times only.

3:53 in my current program, I mean.

3:53 justin_smith: yeah, like I said, it likely does not matter here

3:53 since the strings are probably very short too

3:53 just something to note in general, last is usually not the right thing for anything counted

3:54 ,(counted? "hello")

3:54 clojurebot: false

3:54 justin_smith: oh wait, I should have remembered that bit of silliness

3:54 anyway, a string is effectively counted, heh

3:54 varnie: counted? : ""Returns true if coll implements count in constant time""

3:54 justin_smith: right

3:54 in other words we know the count without counting the items by hand

3:55 which means we can probably look up an item without going through them one by one

3:55 varnie: yup, I got it.

3:57 justin_smith: varnie: also, "remove-last-slash" is not needed - you might like it for aesthetic reasons, but /usr/foo/////bar is a valid path, and is equal to /usr/foo/bar

3:57 unless commons.io is applying restrictions beyond that of the system

3:59 ,(require '[clojure.java.io :as io])

3:59 clojurebot: nil

3:59 justin_smith: ,(io/file "/////user//////bin///////////ls")

3:59 clojurebot: #object[java.io.File 0x573cf76b "/user/bin/ls"]

4:00 varnie: okay. I agree.

4:02 justin_smith: varnie: otherwise, modulo camelCase naming (we usually do kebab-case instead), looks fine

4:02 one pragmatic reason for kebab-case for clojure bindings, is that if we see camelCase we know it's a method of some Object we are using

4:03 makes code easier to read

4:03 varnie: one more question - here I used "isString" which is "(string? path)". I use it to be sure that "(.is Directory (io/file path))" doesn't throw an exception.

4:03 I wonder what is a proper way of handling wrong input? say, I execute (count-lines "php", 123)

4:04 where 123 is "path"

4:04 justin_smith: you already have a :pre block

4:04 varnie: yes, that too. but is it ok?

4:04 justin_smith: {:pre [(not (clojure.string/blank? extension)) (string? path)]}

4:05 you can have as many conditions as you like in there, and since the code doesn't work if path is not a string, you may as well make it a pre-condition

4:06 just remember that pre-conditions are assertions, and like all other assertions can be turned off at runtime, so use them to detect programmer errors and not exceptional runtime conditions

4:06 varnie: so, I remove my (let [isString ....]) and leave only pre-condition

4:07 one more pointer - I suspect that my count-lines-in-file function might throw some exception if the passed file couldn't be open.

4:08 justin_smith: varnie: yeah - whether you want to leave that as an exception for the caller (they asked for information that couldn't be given) or just return 0 for files you can't open via a try/catch is up to you

4:09 varnie: and, possibly, not only this particular exception ;)

4:09 justin_smith: sure, you could even try/catch/throw if you want a more specific error in that case

4:13 varnie: justin_smith, thanks for your help

4:13 justin_smith: np, glad I could be of assistance

4:14 TEttinger: (inc justin_smith)

4:14 lazybot: ⇒ 284

4:14 justin_smith: (identity amalloy)

4:14 lazybot: amalloy has karma 293.

4:16 luxbock: when I implement a protocol from another namespace, am I supposed to use the of the class or the var of the protocol in the spec declaration?

4:18 justin_smith: (ns foo (:require [bar.baz :as baz])) (defrecord quux [] baz/SomeProto ...)

4:18 so really as neither

4:18 as the protocol :)

4:19 but yeah, expect it to be resolved the same way any symbol pointing to a var would

4:20 luxbock: alright, I'm having some issues with defining the protocol as a schema, to avoid the issue of circular namespace definitions, if you still remember me asking about that earlier

4:21 so trying to track that down

4:21 justin_smith: oh, yeah. I'm not as familiar with using protocols in schemas (but I'd expect it would work...)

4:21 luxbock: it works, sometimes, which is why this is so annoying

4:24 justin_smith: luxbock: what about defining a schema for the protocol, that validates whether the item implements said protocol? https://github.com/Prismatic/schema/wiki/Defining-New-Schema-Types

4:25 luxbock: justin_smith: thanks for the idea, I said schema but I'm actually using https://github.com/roomkey/annotate which is very similar

4:25 but I said schema since I figured more people would know of it

4:25 justin_smith: oh - well at that point I'm even less helpful

4:26 luxbock: fwiw I think your suggestion is how annotate attempts to use it

4:26 I'm guessing the issue is related to the order in which the namespaces are loaded

4:27 justin_smith: luxbock: also, looks like the trick with annotate would be to make a "type" for your protocol, that extends Typeable, and returns true if the arg implements said protocol?

4:27 luxbock: all of my other namespaces use my schemas namespace, so it gets required there, but my test namespaces don't

4:27 justin_smith: http://roomkey.github.io/annotate/annotate.core.html#var-Typeable

4:29 luxbock: or it looks like you could use (Pred (partial satisfies? MyProto))

4:29 luxbock: justin_smith: I think annotate already does that for me

4:29 like I said, it works sometimes :)

4:30 justin_smith: luxbock: OK, I made that suggestion based on the fact that their documentation made no mention of supporting protocols

4:31 but if it only sometimes works automatically, it couldn't hurt to try doing it by hand, no?

4:32 luxbock: yeah, I'll give that a try next, I'm currently investigating if requiring my schemas-namespace in my generators namespace would do the trick

4:37 yeah the problem is that for some reason the records that I define are not implementing the protocol

4:39 but they do so when I define them in the namespace where the record-type is defined

5:15 fdija: Hi! Is it possible to start a NREPL session from lein run? I want to start my app in a terminal, have it init it's UI there, and then connect my editor (emacs) to it with nrepl (Cider). Is that possible?

5:16 phillord: "lein repl :headless" ?

5:17 or you can launch nrepl from within the application. I do that here...https://github.com/phillord/protege-nrepl

5:18 but in this case, it's because I couldn't work out how to launch the application in any other way

5:18 schmir: fdija: and then M-X cider-connect

5:19 phillord: or you could launch the nrepl in the normal way with leiningen, then launch the application directly either by calling it's main method, or doing App a = new App() depending on how your application initializes

5:21 In your case, you have a clojure app I guess. So, why not start nrepl in the normal way (i.e. let cider do it) then call launch the app from inside the REPL

5:24 fdija: Thank you all! I can connect now. What seems to be working is to in my terminal run `lein repl :headless`, and in my repl run (-main). I'm writing a terminal-based text editor, and am writing the side-effect-heavy rendering code. So nice to not be running blind.

6:32 Olajyd: ,(clojure.string/replace "hPPHp123hPHp" #"^[PH]+" "")

6:32 clojurebot: "hPPHp123hPHp"

6:39 Olajyd: can somebody help me with this (clojure.string/replace "hPPHp123hPHp" #"^[PH]+" "") I want the result to be “hp123hPHp”

6:40 nickenchuggets: hi

6:42 jeaye: Olajyd: Seems like you want #"PPH"

6:44 oddcully: jeaye: no i think OP wants the first occurance of any [PH]-chain removed

6:47 ,(.replaceFirst "hPPHp123hPHp" "[PH]+" "")

6:47 clojurebot: "hp123hPHp"

7:23 nickenchuggets: hmm

7:23 having some trouble accessing a dependency

7:23 I got lein set up

7:23 ran lein classpath, and it looks as though the dependency I've specified is on the classpath, as a jar file

7:24 I'm a clojure newb btw

7:25 I wonder if I need to lein javac

7:25 this is what I'm trying to do: https://gist.github.com/brlafreniere/abee9b5fa78babf5902f

7:26 this is the library I'm trying to use: https://github.com/Raynes/irclj

7:30 hmm, clojure is funky :P

7:32 vijaykiran: nickenchuggets: may be a bit more context will help - where's your clj code ?

7:32 nickenchuggets: I used lein to generate an 'app' structure

7:32 so it's in the standard places mostly

7:33 src/cljbot/core.clj

7:33 I see "Hello World" when I do lein run

7:33 so I think for the most part things seem to be working

7:33 but I can't seem to load that library, irclj

7:34 in the lein repl or in my src/cljbot/core.clj file

7:34 and I do have it listed in my project dependencies

7:34 and it appears to have installed when I run lein run

7:35 hmm, yeah, tried lein deps... all dependencies appear to be installed

7:36 can't (require '[irclj.core :as irc]) in lein repl

7:36 hmm, I have an idea

7:36 haha

7:37 * nickenchuggets checks clojars.org

7:37 nickenchuggets: hooray!

7:37 I fixed the problem

7:38 I looked up the library on clojars.org

7:38 and saw that it suggested a different version

7:38 instead of the version I was using

7:38 so I used the version suggested on clojars.org for that library, and it appears to be working now

7:39 :)

8:36 TMA: (inc rubberduck)

8:36 lazybot: ⇒ 5

8:41 nickenchuggets: hehe

8:41 so I'm new to clojure, and it's kinda neat

8:44 gfredericks: luxbock: there are a couple issues you're hitting I think

8:46 1) is that gen/one-of and gen/elements do not grow from the beginning of the collection, which is because they both use gen/choose (which doesn't grow). I have in test.chuck an alternative to choose that *does* grow, so you could use it in your own version of gen/elements and gen/one-of if you wanted https://github.com/gfredericks/test.chuck/blob/5ed96e279334dfe47df9c9646b060d7fecf73ebf/src/com/gfredericks/test/chuck/generators.clj#L197

8:47 2) is that it sounds like you're making a recursive generator, which can be tricky w.r.t. sizing. have you looked at the built-in helper for recursive generators?

8:56 neurostorm: I have a vector with ["123" "#234" "#232" "324" "232" "#23"] and need to join lines starting with # with the prev line, so the result should be ["123#234#232" "324" "232#23"] , how can this be done?

9:07 hyPiRion: neurostorm: https://www.refheap.com/108426

9:08 neurostorm: Thx!

9:13 dabd: what are the advantages of clj's PersistentVector implementation over an implementation based on skew binary random access lists?

9:14 I was reading this post http://cstheory.stackexchange.com/questions/27820/is-there-a-purely-functional-vector-with-o1-access-to-the-front-and-back-but-o and the poster mentions it can be faster than the clj's implemention.

9:15 neurostorm: '(reduce

9:15 (fn [col i]

9:15 (let [last-idx (- (count col) 1)]

9:15 (if (= (first i) \#)

9:15 (assoc col last-idx (str (nth col last-idx) i))

9:15 (conj col i)))) [] ["a" "b" "#c" "d" "#e" "#f" "g"])

9:20 hyPiRion: dabd: cache and linear type utilisation mostly. PersistentVector has O(1) for last, and transients provide way faster batch modifications.

9:22 dabd: does the latest PersistentVector implementation use RRB-trees?

9:24 hyPiRion: dabd: core.rrb-vector gives you concatenation functions -- see https://github.com/clojure/core.rrb-vector

9:29 dabd: hyPiRion: I was wondering if those improvements made it into the PersistentVector implementation

9:31 but I see it is interoperable with the original PersistentVector implementation

9:32 hyPiRion: yeah, it's essentially just a set of functions that works over PVecs and RRBs without any (notable) penalty

9:33 Diabolik: does anyone have any suggestions for projects for a complete newbie to do as a first project?

9:33 im a rails dev by trade if that helps

9:44 gilliard: Diabolik: I would think you could get a good feel for the language by trying some of the problems at http://4clojure.com

9:46 magnars: I made a screencast making a game with Clojure and ClojureScript: http://parens-of-the-dead.com Hopefully it'll show how quick and fun it can be to use our language of choice. :-)

9:50 stain: nice!

9:50 you put some effort into this

9:51 what is that funny unicode-shell, btw?

9:51 wasamasa: lol, mutations ahead

9:51 that does indeed sound scary

9:52 magnars: stain: the shell is zshell with oh-my-zshell

9:52 gotta stay away from those mutations :)

10:08 stain: magnars: so when you first did this.. did you actually do the static HTML/CSS first and then write all the cljs afterwards, or is that just for the screencast?

10:09 magnars: yeah, I created some dummy HTML in an index.html file, and wrote the CSS and images for that.

10:11 stain: yeah, so you could prototype the view without thinking too much about the logic yet

10:11 magnars: exactly

11:02 jaaqo: #join WordPress

11:04 rhg135: I see

11:06 noncom: in clojure seesaw, there is the bind concept which allows controlling canges of values in atoms and such through gui, ok. but is there any concept for the reverse? i.e. if i change the value of the atom - can i make it so that the gui automatically reflects the change?

11:07 matthavener: noncom: check out 'add-watch'

11:07 noncom: oh, ok, so atom watches are the way..

11:08 matthavener: other that wrapping the atom update in your own abstraction to coordinate handling changes.. yep, as far as i know :)

11:09 noncom: i see... sadly this implies much manual work.. unless i write some automation macros for that..

11:09 i hoped there is something inside seesaw to make it work already..

11:09 but okey, i can manage :)

11:09 phillord: I am trying to add tools.nrepl to an existing maven build without changing the pom (i.e. as a per user setting). Anyone know if this is possible?

11:10 noncom: phillord: ummm not sure, but maybe pomegranate is what you need?

11:10 * phillord nods

11:11 noncom: but it will require to have it itself in the deps..

11:11 phillord: if pomengranate were in the pom.xml then yes, it would be, but it isn't. And if I knew how to add pomengranate without changing the pom, then I could just do the same with tools.nrepl

11:11 noncom: well, you could extend the classpath for the jar on launch

11:11 phillord: how?

11:11 clojurebot: with style and grace

11:12 noncom: either via java standard method or..

11:12 phillord: I've thought about settings.xml but that only allows you to changes I don't want to change

11:12 noncom: https://clojuredocs.org/clojure.core/add-classpath

11:12 but that's deprecated, idk if it works

11:12 phillord: parent projects seem a way forward

11:13 oh, sorry, I don't have Clojure either

11:13 noncom: ?

11:13 phillord: I want to add a clojure repl to an existing Java app

11:13 noncom: ah

11:13 phillord: or rather Java build

11:13 noncom: oh

11:13 well, i would do it the other way around

11:13 add the java app as a lib to to clojure

11:14 phillord: I could create a maven plugin that would do this, but then I can't add that either, since maven does not allow me to change that either.

11:14 noncom: just start the clojure as usual, but linking the java app jar to it via the classpath (see java cli options for that)

11:14 * phillord thinks

11:14 noncom: then you can start clojure and import all your java stuff

11:15 phillord: yes, I guess that is possible, although I have to create a new clojure project for every maven project to which I want to connect

11:15 * phillord does not really like maven very much

11:15 noncom: not sure. you're saying you already have the java app jar?

11:16 why not just create a .bat or .sh for every java jar? (or even all of them)

11:17 java -cp clojure.jar clojure.main file.clj

11:17 thi sis the default command to launch clojure throught cli

11:17 phillord: no, I have a maven project with Java in it. Maven lets me run it, no worries. I want to run a clojure nrepl with maven, so that the clojure nrepl process has the environment of the Java project. Then I can use the nrepl to introspect over the java project.

11:18 noncom: you could do something like "java -cp java-app.jar nrepl.jar clojure.jar clojure.main file.clj"

11:18 not sure for the exact syntax of -cp though

11:18 phillord: I'm trying to add interactivity to a java development environment for Emacs

11:18 noncom: yes, i understand...

11:18 phillord: nrepl seemed like a nice option -- all working but I have to change the pom

11:19 * ellis

11:19 noncom: why not 1) launch clojure project with nrepl 2) link your java app ?

11:19 think of your java app as a library...

11:19 phillord: because I don't want to build the Java project to jar every time, and anyway, the java app will be in a set of libraries.

11:20 I need to be able to recompile the Java and update the repl

11:20 noncom: recompile java with a running nrepl without restarting jvm?

11:20 phillord: yes -- that's been done (vinyasa does it)

11:21 noncom: ok, was going to suggest vinyasa :)

11:21 phillord: my roadblock is just getting maven to add nrepl (and my middleware) to the project

11:21 noncom: hmmmm and your java project also epends on loads of libraries, right?

11:21 * phillord nods

11:21 phillord: exactly

11:22 noncom: uh..

11:22 phillord: although if pomengranate can add a "live" dependency -- i.e. a project directory rather than a fully build maven artifecact it might work.

11:23 it's very frustrating -- although that is a common emotion when working with maven

11:23 rhg135: You can do so through the class path option

11:24 phillord: rhg135 I can add a directory in this way, but I need to add a project with all of it's dependencies also

11:25 noncom: look at this: https://github.com/cemerick/pomegranate/blob/master/src/main/clojure/cemerick/pomegranate/aether.clj

11:25 does it look like it could work for you?

11:26 rhg135: Is there a way to get the class path from maven?

11:26 gilliard: https://maven.apache.org/plugins/maven-dependency-plugin/build-classpath-mojo.html

11:29 phillord: gillard: again, same chicken and egg -- only works if the dependency plugin is installed.

11:29 noncom: yes, it may be possible -- launch clojure then fix it up so that it looks like the project.

11:29 gilliard: you can just run mvn dependency:build-classpath without changing the pom.

11:33 phillord: gillard: okay, that might help. I run clojure with nrepl, then run maven to get build classpath, then add all of these to the clojure repl with pomengranate. Messy, but doable.

11:34 noncom: if you do not change the libraries too often, maybe you can formulate the project.clj deps out from the java app pom

11:34 but that is not a very functional approach.. rather it could save time, but i am not sure..

11:35 hey, you could also make a whole tool out of that. i am sure that could be useful to other people too

11:35 phillord: I've been the route before of trying to understand the maven pom. It's a terrible mess with no defined semantics and things never work as you expect.

11:36 blkcat: xml, barf.

11:37 noncom: well, maven helps completing some really complex tasks..

11:37 i am sure if anyone could come up with something more simple, it would have been adopted already worldwide..

11:37 phillord: XML is just a syntax -- it's the total absence of clear meaning that is problem. If maven had documentation that were, well, comprehensible it would be okay.

11:37 noncom: they say gradle is not that bad for interfacing with maven

11:38 phillord: noncom: I agree -- the only worse thing than using maven for building java is managing java dependencies without maven.

11:39 gilliard: ha. nicely put.

11:39 noncom: yeah

11:39 which is really strange because in reality, the dependencies are just a simple tree

11:41 phillord: not really, noncom

11:42 noncom: yeah, there are goals and conditions and stuff..

11:42 but..

11:42 phillord: you are forgetting time -- so, a dependency on "Clojure 1.2" is actually a dependency on 1.2 *or later*.

11:43 I will have a think on the awful ness of getting maven to report it's dependencies

11:43 might be easier.

11:43 gilliard: The dependency plugin has a few goals which might be useful.

11:43 Olajyd: how can I convert a string in to a verctor of strings given “ig” => [“i” “g”]?

11:43 * gilliard has drunk quite a bit of maven-aid.

11:43 justin_smith: phillord: it's not even as simple as that - because it won't look for "or later" unless some other dep demands it

11:44 Olajyd: what's the separation rule?

11:44 ,(mapv str "ig") ; if the rule is "one string per letter"

11:44 clojurebot: ["i" "g"]

11:44 phillord: justin_smith: that's my point -- it's actually a named directed graph, not a tree.

11:45 Olajyd: justin_smith yea sure

11:45 noncom: wtf.. http://joxi.ru/V2VnD95s5anW2v

11:45 justin_smith: phillord: right, agreed 100%

11:45 Olajyd: justin smith I have a problem in clojure and wish you could help me out?

11:45 justin_smith: noncom: wow, your client doesn't handle smart quotes at all :)

11:45 Olajyd: you can go ahead and answer the question, and I am sure someone will try to answer

11:46 noncom: seems so :) idk even what that means

11:46 Olajyd: ok

11:46 phillord: anyway, thanks for all the help -- I will consider the options.

11:47 justin_smith: noncom: http://i.imgur.com/FKwOTwk.png

11:47 "smart" quotes

11:47 noncom: wow, haha )

11:47 creepy

11:47 justin_smith: infamously inserted by some osx irc clients

11:47 and of course totally breaking code examples

11:48 Olajyd: oh where I said "you can go ahead and answer the question" that's weird and I meant "you can go ahead and ask the question" - you don't need to ask permission to speak on IRC

11:48 Olajyd: hahhaa

11:48 gotcha

11:50 implement a function that transforms a string by applying a regular expression to it. The first match is replaced by the replacement string. Replacing all matches can be achieved by using the 'g' (global) qualifier. This function allows virtually any perl-syntax regular expression to be applied

11:50 use cases:

11:51 To remove all occurrences of a 'P' or an 'H' at the beginning given a string “PH123p” => “123p”

11:52 oddcully: ,(.replaceFirst "hPPHp123hPHp" "[PH]+" "")

11:52 clojurebot: "hp123hPHp"

11:52 Olajyd: Use case 2: To do the same as above but to catch both uppercase and lowercase P's and H's at the beginning and replace them with 000: given a string “PHpp123p” => “000123p”

11:53 justin_smith: Olajyd: I'd look at the various regex functions (they are grouped in one section on http://conj.io ) - with the right combo of them I am sure you can make some progress

11:53 Olajyd: aite thanks

11:54 justin_smith: Olajyd: also you could look at cond for handling the command switches like "g"

11:55 Olajyd: oddcully, the use of P and H actually mean all capital letters and not necessarily P and H

11:55 oddcully: i just mentioned it again on your previous question, since it was lost in disconnection

11:56 Olajyd: justin_smith does that also apply for the use of the “i” flag in the regex?

11:56 oddcully I’m sorry I didnt see it

11:56 justin_smith: Olajyd: yeah, I would use a regex to pull out the flags/options from your command, then use cond to figure out how to process the string given the flags

11:56 Olajyd: oh great

11:57 so I would create someting like isGobal? predicates right

11:57 justin_smith: I assume you also know how to use "let"

11:57 Olajyd: yeah, something like that

11:57 Olajyd: or something like isCaseSensitive? predicates too

11:57 ok

11:59 justin_smith I’m sorry but what exactly is the differene between [A-z]+ and [A-z]+

12:00 oddcully: looks the same to me

12:00 justin_smith: ,(= "[A-z]+" "[A-z]+") ; a typo I am sure

12:00 clojurebot: true

12:01 noncom: when using grid layout, is there a way to force column width with seesaw?

12:04 Olajyd: justin_smith so exactly how can I check if an element exist in a vector?

12:05 using the ‘’some” method

12:06 oddcully: Olajyd: when i don't know if there is something around for my case, i consult http://conj.io/ and try a few "words" that might match my usecase

12:06 Olajyd: oddcully thanks buddie

12:51 shiranaihito: "halp." .. i'm having mysterious trouble with protocols / records - "class not found" or something, and now i'm trying to ":aot :all" in my lein project because i have no fucking clue what's wrong, but that's not working either: Compiling c2d.db.entity

12:51 java.io.FileNotFoundException: Could not locate c2d/db/entity__init.class or c2d/db/entity.clj on classpath

12:51 why does compiling a namespace require some sort of already-compiled thing for the namespace being compiled?

13:00 Olajyd: Hi, justin_smith

13:01 Hi, oddcully

13:05 shiranaihito: any educated guesses as to what the fuck is wrong with my code? (yes, i'm a bit irate.. :p) .. what's the most common "mistake" people make with protocols and records that would lead to a class not being found?

13:07 rhg135: aot

13:09 shiranaihito: rhg135: you'll have to be a bit more specific.. consider that i have no clue about the low-level details related to aot compilation and its relationship to protocols and records etc, and i don't even care.. i just want to get stuff done

13:10 justin_smith: shiranaihito: the most common problem is code being reloaded

13:10 shiranaihito: you'll end up with two classes with the same name, that are not the same class

13:10 shiranaihito: for example, apparently now i have a record that gets instantiated (potentially just fine), but when its used in a call to a protocol it implements.. nothing happens.. and now i'm not even getting any error messages anywhere

13:10 Olajyd: justin_smith help me optimize this code please..

13:11 justin_smith, (defn apply-regex

13:11 "Function to transforms the contents of a column by applying a regular expression to it"

13:11 [ row input ]

13:11 rhg135: usually aot compilation (or stale classes) messes it up

13:11 Olajyd: (let [{:keys [ col replacement qualifier]} input

13:11 isCaseSensitive? (some #(= "i" %) (mapv str qualifier))

13:11 shiranaihito: justin_smith: i'm not using a REPL though.. can something get reloaded in a problematic way anyway?

13:11 Olajyd: isGlobal? (some #(= "g" %) (mapv str qualifier))

13:11 justin_smith: Olajyd: if you just ask your question someone can probably help, I'm in the middle of trying to help shiranaihito at the moment

13:11 Olajyd: val (if (and isGlobal? isCaseSensitive?)

13:11 (clojure.string/replace (get row col) (re-pattern "[A-z]+") replacement)

13:11 (if (and (false? isGlobal?) isCaseSensitive?)

13:11 (clojure.string/replace-first (get row col) (re-pattern "[A-z]+") replacement)

13:11 (if (and (false? isGlobal?) (false? isCaseSensitive?))

13:11 (clojure.string/replace-first (get row col) (re-pattern "[A-Z]+") replacement)

13:11 (clojure.string/replace (get row col) (re-pattern "[A-Z]+") replacement))))]

13:11 (assoc row col val)))

13:11 ok gotcha

13:11 justin_smith: Olajyd: please don't paste multiple lines of code into IRC

13:12 oddcully: please don't paste large code snippets in here

13:12 justin_smith: use a pastebin site

13:12 refheap.com is good

13:12 shiranaihito: Olajyd: try www.refheap.com

13:12 rhg135: refheap ftw

13:12 Olajyd: Ok let me try that

13:12 justin_smith: shiranaihito: yes, bad things can happen if protocol definitions are reloaded and you have objects around that implement the older version of the protocol - even if the definition did not change

13:13 shiranaihito: justin_smith: how/why would the definitions get reloaded?

13:13 justin_smith: shiranaihito: what happens is then when compiling the namespace, a class is generated, and a new class is generated when you reload the namespace

13:14 Olajyd: so after pasting in pastebin do I post the link here or how will you get to see the code?

13:14 shiranaihito: justin_smith: do you mean at runtime.. ? i'm not using a repl.. ? what kind of situation are we talking about

13:14 justin_smith: shiranaihito: ring projects are set to auto-reload. If nothing is reloading your namespaces there is also the issue of AOT - where you can have some objects using the AOTd protocol and some using another definition loaded at runtime

13:14 shiranaihito: I'm trying to describe the common case, but there are a few ways this can bite you

13:14 shiranaihito: justin_smith: i'm actually not using ring - i've set up my own cute little web framework on top of an embedded Jetty

13:14 justin_smith: OK

13:14 oddcully: Olajyd: yes, paste the link

13:15 Olajyd: https://www.refheap.com/108436

13:15 justin_smith: Olajyd: the reason I suggested cond earlier is because it works out better than having if inside if inside if

13:16 Olajyd: ok

13:17 oddcully: Olajyd: that mapv in the let is copy-and-paste; use a let for it. but if you are just interested if there is a letter in the string you might as well just use .indexOf

13:18 justin_smith: Olajyd: instead of (if a b (if c d (if e f g))) you can have (cond a b c d e f :else g)

13:18 the transformation is pretty simple

13:19 shiranaihito: justin_smith: so what's a typical problem with protocols and records when no reloading is involved?

13:19 Olajyd: oddcully this is how I plan to call the function (apply-regex ["PPP123p" "1"] {:col 0 :replacement "000" :qualifier "ig”})

13:19 justin_smith: shiranaihito: the protocol is redefined, but the record is still extended to the older protocol (pre-redefinition), and this breaks the protocol mechanism

13:20 shiranaihito: since protocols have an interplay between ns/var level stuff and classes

13:20 shiranaihito: justin_smith: i've run into something before, but not like this.. at some point, i think the solution to some protocol-related problem was to require the related namespace .. but this is different

13:20 justin_smith: shiranaihito: OK

13:20 shiranaihito: justin_smith: damn you read fast.. :x

13:21 justin_smith: how would i end up in a situation like you described?

13:22 justin_smith: shiranaihito: if you had a definition of the protocol visible thanks to AOT, then you had a namespace that used the protocol but did not require the protocol's namespace, so it used the AOT generated class, then another ns required the protocol namespace, causing a new class to be generated

13:22 shiranaihito: by any chance do you extend the protocol in any namespaces that do not require the ns implementing the protocol?

13:23 shiranaihito: justin_smith: and just to be clear, we're not talking about anything related to reloading code now.. ? :P

13:23 (runtime etc)

13:23 justin_smith: at this point, no, not at all

13:23 shiranaihito: ok, cool

13:23 oddcully: Olajyd: i am talking about things, that are used over and over in the code (like (mapv str qualifier) and (get row col))

13:23 justin_smith: this is an interaction between the AOTd protocol class and the version created when the namespace is loaded at runtime

13:24 oddcully: Olajyd: don't copy that down. if it's used twice its a candidate for a let

13:24 Olajyd: oddcull gotcha

13:24 oddcully gotcha

13:24 shiranaihito: justin_smith: i only extend the protocol in the namespace it's defined in.. i'm just using it from another Lein project, where the lib containing the protocol is a dependency

13:26 justin_smith: shiranaihito: hmm, that should just work then

13:26 shiranaihito: justin_smith: yeah.. this is the most mysterious situation i've been in with Clojure.. and most of my troubles have been related to protocols.. :X

13:35 Olajyd: oddcully can you help me check out if this is ok https://www.refheap.com/108438

13:36 justin_smith if you are not in the middle of something can youalso help me check https://www.refheap.com/108438 out too :)

13:37 justin_smith: Olajyd: in general, it's good to use not instead of false? unless you know that your input is always a boolean

13:37 Olajyd: because in most things in clojure, both nil and false are considered "falsey"

13:37 ,(false? nil)

13:37 clojurebot: false

13:37 justin_smith: ,(if nil :huh? :OK)

13:37 clojurebot: :OK

13:38 justin_smith: it acts like false even though it is not false? - so it's usually better to use not instead of false?

13:38 shiranaihito: ,(false? nil)

13:38 clojurebot: false

13:38 justin_smith: ,(not nil)

13:38 clojurebot: true

13:39 Olajyd: justin_smith was thinking the isCaseSensitive ans isGlobal will always return a boolean

13:39 shiranaihito: so false? only evaluates to true for the actual "false" value, but not nil even though both are falsey?

13:39 justin_smith: yeah

13:39 shiranaihito: hmhm.. that's kind of unintuitive

13:39 justin_smith: Olajyd: oh, right, that's true. But "not" is still more idiomatic than "false?" generally

13:39 Olajyd: ok

13:40 justin_smith and more additions or subtractions ;)

13:40 justin_smith: ,(some #(= \i %) "hi")

13:40 clojurebot: true

13:40 justin_smith: that way you don't need qailifier-vec

13:40 *qualifier-vec

13:41 Olajyd: justin_smith thanks… more corrections please :)

13:41 snowell: shiranaihito: false? is the same as (= false). It's not a test for (not true)

13:41 That would be not :)

13:41 shiranaihito: snowell: i get that it works the way it's intended to work.. i just said it's kind of unintuitive :p

13:43 snowell: Well I was used to Oracle PL-SQL, where (nil == nil) and (nil != nil) both return false. So I guess after that anything can make sense

13:44 justin_smith: shiranaihito: yeah, which is why "false?" should almost always be pre-emptively replaced with not

13:44 shiranaihito: justin_smith: yyep :p

13:44 justin_smith: shiranaihito: we should keep a community blacklist

13:44 flatten, false?, partition

13:44 I am sure there are others

13:45 shiranaihito: justin_smith: oh :p .. i didn't know flatten and partition were Bad somehow

13:45 justin_smith: ~flatten

13:45 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.

13:45 shiranaihito: what's the problem?

13:45 oddcully: ,(some #{\i} "ho")

13:45 justin_smith: ~partition

13:45 clojurebot: nil

13:45 partition is probably not what you want; see partition-all.

13:45 oddcully: ,(some #{\i} "hi")

13:45 clojurebot: \i

13:45 justin_smith: oddcully: that's fancy, but slower than the = check

13:46 oddcully: i suggested indexOf above ;P

13:46 justin_smith: :)

13:46 (inc oddcully)

13:46 shiranaihito: justin_smith: ok but what's wrong with using flatten instead of concat, for example, even if you only need to flatten one level?

13:46 justin_smith: shiranaihito: ##(flatten {:a 0})

13:47 ,(flatten {:a 0})

13:47 clojurebot: ()

13:47 justin_smith: ,(flatten "hello")

13:47 clojurebot: ()

13:47 shiranaihito: wtf

13:47 justin_smith: ,(apply concat {:a 0})

13:47 clojurebot: (:a 0)

13:48 shiranaihito: justin_smith: so why does stuff disappear?

13:48 justin_smith: shiranaihito: also only the end user of a function knows whether "you only need to flatten one level" - so if you are writing a function someone else might use, you are severely restricting their data representation if you use flatten

13:48 shiranaihito: as the factoid mentions, imagine if your base case is a list or vector

13:49 shiranaihito: stuff disappears because flatten "takes a nested combination of sequential things" and I guess {:a 0} and "hello" are not sequential things

13:50 shiranaihito: justin_smith: alright, but i wasn't thinking about it from a library author's viewpoint.. just some random situation where you personally have a choice between flatten and whatever.. but it does look weird when stuff disappears like in your examples

13:50 justin_smith: shiranaihito: which is why concat is almost always the better choice

13:50 it's more controlled too, which means it is more flexible

13:57 sdegutis: What's a noble alternative to select-keys that includes nil keys?

13:58 justin_smith: ,(select-keys {nil "OK" :a 0 :b 1} [:b nil])

13:58 clojurebot: {:b 1, nil "OK"}

13:58 sdegutis: My current solution is just ##(select-keys (merge {:a nil :b nil :c nil} {:a 1 :b 2}) [:a :b :c])

13:58 justin_smith: Sorry I meant absent keys.

13:59 justin_smith: ,(let [wanted [:a :b]] (merge (zipmap wanted (repeat nil)) (select-keys {:a 0} wanted)))

13:59 clojurebot: {:a 0, :b nil}

14:00 sdegutis: So you'd use the same basic technique?

14:00 justin_smith: with less manual repitition, yeah

14:00 sdegutis: Right.

14:00 I wasn't sure how to manually create a map of nils for all given keys.

14:00 justin_smith: I mean that version could easily become select-all-keys or something

14:01 yeah, zipmap is probably the best bet for making that map

14:01 sdegutis: Well I only need it in one function so far.

14:01 Thanks bro.

14:01 justin_smith: np

14:03 sdegutis: Oh wow. Turns out that's what I was already using too.

14:03 justin_smith: hah, figures

14:03 sdegutis: I had this: (defn- entity-equals [a b] (let [a (merge (zipmap (keys b) (repeat nil)) (select-keys a (keys b)))] (= a b)))

14:04 Yours is way better tho.

14:04 Closer to the metal.

14:04 justin_smith: uh... if you say so

14:05 sdegutis: Yours being this: (defn- select-all-keys [m ks] (merge (zipmap ks (repeat nil)) (select-keys m ks)))

14:05 justin_smith: right

14:05 sdegutis: I'm totally using yours now, it's simpler.

14:06 Okay, I had two idiotic functions scattered in my tests: entity-matches? and entities-match? ... the former is completely removed from all my code!

14:06 Now to finish the latter... :D

14:26 gfrederi`: tcrawley-away: ping

14:31 sdegutis: IT WORKED!!!!!!

14:38 Finally got rid of functions that have been bugging me for 2 years.

14:39 Tons of them too.

15:26 crazydiamond: Hi. What do I need to use cljc files? I'm trying to include ns from cljc file in cljs file, but got an error "No such namespace"

15:34 gfredericks: crazydiamond: you have to be using clojure 1.7

15:35 crazydiamond: gfredericks, and I'm doing so

15:36 gfredericks: that's the only requirement I know of; you might check your cljsbuild configuration for source paths

15:36 crazydiamond: oh you might also need a recent version of cljs

15:36 crazydiamond: aha

15:39 gfredericks, thanks, I'll check cljs version too. I'm using boot instead of lein, but it operates much the same

15:40 gfredericks: boot can build it!

15:40 ~boot

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

15:40 gfredericks: ~boot |can build| it!

15:40 clojurebot: In Ordnung

15:42 TEttinger: clojurebot: boot is where you hide the bodies... of Maven POMs, before you bury them forever.

15:42 clojurebot: Ok.

15:42 justin_smith: ~boot

15:42 clojurebot: boot is where you hide the bodies... of Maven POMs, before you bury them forever.

15:43 TEttinger: I've not had the best experience with maven

15:44 snowell: Gradle makes maven a little more palatable

15:44 Then again, so does lein

15:45 TEttinger: I really have not liked gradle in the time I've had to use it with certain java libs

15:45 it's much much slower than maven

15:45 snowell: Hmm, not sure I've really seen that

15:46 Then again the only non-trivial migration I've done to gradle was from ant

15:46 So basically anything was better

15:48 justin_smith: if boot wants to take off, some sci-fi author needs to write a sequel to Leiningen vs. the Ants culminating in Boot wearing aliens that defeat Leiningen in a battle of wits.

15:48 TEttinger: also at least when this particular library switched to gradle (because android was moving that way, really), the IDE integration was really abysmal

15:48 every other IDE update would break gradle integration, no matter what IDE

16:15 tcrawley: gfredericks: pong

16:24 sveri1: TEttinger gradle 2 has sped up a lot of things and agreed the IDE support is bad, as long as the console does not count as IDE where it shines :-)

16:25 TEttinger: yep. it's definitely gotten better, I just wish lein or boot had something that was similarly succinct in the java-world

16:28 oddcully: it got "better" with recent intellij - if you generate some xmlblobs for intellij to tell it: you don't have a clue whats going on, right? better keep out of it - ymmv

16:30 TEttinger: yeah, that's what I always do now.

16:31 it's a pain when you need to change gradle and IDE settings to do certain things and project file regen is needed

16:33 oddcully: if its vital i extract the fragments from the .ipr file and inject them in the idea task

16:35 sveri1: hm, we encountered problems with eclipse, but all of them were solvable

16:38 mostly related to target platforms

17:27 gfredericks: tcrawley-away: is it possible to use immutant.messaging w/o using jboss?

17:42 jcrossley3: gfredericks: sure

17:42 depending on your definition of 'jboss' :)

17:46 gfredericks: everything here (and more) works standalone, i.e. not deployed to wildfly (formerly known as jboss): https://github.com/immutant/feature-demo/blob/master/src/demo/messaging.clj

17:46 you can check that project out and just 'lein run'

17:47 or more specifically, 'lein run -m demo.messaging'

18:11 jborden: good afternoon.

18:13 I was wondering if there is a library for modifying your source code (clj,cljs) using a lein exec script or other method. e.g. I have a user.clj file which will send out an email when a new user is added to the system. I want to comment out the line that sends out the email for development and testing purposes but leave it in production.

18:14 basically, I want to be able to modify the source code and have different versions for 'development' and 'production'. Does anyone know of a library or lein plugin that does that?

18:21 eriktjacobsen: jborden Why do you want to modify the source code, instead of the more standard approach of using an environment variable or filesystem config?

18:22 put a file in “/etc/jborden.config” for instance that has either “production” or “development” inside (or perhaps even email specific settings?) and have the program read from that at run-time to determine behavior

18:27 jborden: eriktjacobsen: So have an environment variables, say 'send-email?' , and a bunch of if statements in the code that (if (send-email?) (send-email args)) ?

18:28 eriktjacobsen: You could, or simply have an environment variable that sets things either to “dev” or “prod”. Here is some code from a project:

18:28 http://pastebin.com/5F1iZAR3

18:29 set-env! sets an atom, so rest of program can just do a check on (if (= @env :prod))

18:29 but basically, yes

18:31 if you want finer grain stuff than simply “dev/prod”, I’d recommend you use a filesystem config file that contains a map of variables, either serialized clojure (pr-str) or json, and then you load that as a map so you can pull out specific stuff and don’t have to juggle multiple environment variables

18:33 jborden: so I would basically keep my environment variables in a map and just set the environment I am in with a System/setProperty ?

18:35 { :dev {:param1 "value"} :prod {:param1 "different-value"}} (System/setProperty "environment" ":dev")

18:37 OK I will do that if it is the more standard way of doing things, makes more sense than modifying the entire source tree because you can see what is going on

18:38 thanks eriktjacobsen

18:40 eriktjacobsen: jborden: multiple situations so going to restate for clarity…. the System/getenv is reading environment variables, so for instance you wouldn’t set that in the code, but you’d do something like “export PARAM=prod;java -jar asdf.jar (or lein run)” and then once that env is read into an atom (or whatever), all your conditional statements would be checking against either dev / prod. The second situation would be where

18:40 you’d want finer grain control over stuff, in which case you would skip the environment variable and not care if you are in dev / prod at all, but rather have specific things like email in the config file (on the filesystem, separate from your deployed jar), then the conditionals inside code would work off that config map

18:54 rhg135: well, now my lazybot has datomic backed karma semi-working

18:55 etting the schemas from the plugins was a pain

19:20 justin_smith: rhg135: I can't think of the last time someone took a joke I made that seriously

19:20 rhg135: I seriously was meaning to go to datomic

19:20 justin_smith: oh, OK

19:42 sotrhRaven: hello everyone

20:07 gfredericks: jcrossley3: okay, good to know, thanks!

20:14 rhg135: https://github.com/rhg/flutterbot/tree/datomic I was serious

21:07 justin_smith: ,(whither)

21:07 clojurebot:

21:07 justin_smith: ,(whither)

21:07 clojurebot:

21:07 justin_smith: ,(repeatedly whither)

21:07 clojurebot: (⤉ ⬆ ⇍ ⇃ ➱ ...)

21:17 justin_smith: I should have named it ddr

21:54 TEttinger: ,(defn ddr [] ((comp symbol str char) (rand-nth (concat (range 0x2190 0x2200) (range 0x27f0 0x2800) (range 0x2900 0x2980)))))

21:54 clojurebot: #'sandbox/ddr

21:54 TEttinger: ,(repeatedly ddr)

21:54 clojurebot: (⇐ ⟷ ⥹ ⇓ ⇞ ...)

21:55 justin_smith: (inc TEttinger)

21:55 (ddr)

21:56 ,(ddr)

21:56 clojurebot:

21:56 TEttinger: ,(ddr)

21:56 clojurebot:

21:56 TEttinger: how'd you do yours, justin_smith?

21:56 justin_smith: I really don't know how to do some of these dance moves

21:56 TEttinger: haha

21:56 justin_smith: TEttinger: much stupider

21:56 ,(ddr)

21:56 clojurebot:

21:56 TEttinger: yours can do some symbols mine can't

21:56 justin_smith: TEttinger: I had found a page with every unicode arrow like thing, and just made a string

21:56 TEttinger: oh yes

21:56 that is an option I considered

21:57 justin_smith: TEttinger: http://copypastecharacter.com/arrows

21:57 TEttinger: the best version would condense all the ranges on that page, of course

21:57 TEttinger: there are many arrows in weird unicode categories that aren't arrows, supplemental arrows A, or supplemental arrows B

21:58 ,"\u27ac"

21:58 clojurebot: "➬"

21:59 TEttinger: ,"\u2b90"

21:59 clojurebot: "⮐"

21:59 TEttinger: that's a tricky ddr move

21:59 "slip and fall"

23:57 justin_smith: ,(->>[[8592 8703][9027 9032][9036 9037][9039 9040][9043 9044][9046 9047][9166][9650][9654][9660][9664][9735 9736][10132][10136 10159][10161 10174][10224 10239][10496 10538][10541 10569][10578 10619][11008 11025]](mapcat #(apply(fn([x][x])([x y](range x (inc y))))%))(map char)(apply str))

23:57 clojurebot: "←↑→↓↔↕↖↗↘↙↚↛↜↝↞↟↠↡↢↣↤↥↦↧↨↩↪↫↬↭↮↯↰↱↲↳↴↵↶↷↸↹↺↻↼↽↾↿⇀⇁⇂⇃⇄⇅⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥⇦⇧⇨⇩⇪⇫⇬⇭⇮⇯⇰⇱⇲⇳⇴⇵⇶⇷⇸⇹⇺⇻⇼⇽⇾⇿⍃⍄⍅⍆⍇⍈⍌⍍⍏⍐⍓⍔⍖⍗⏎▲▶▼◀☇☈➔➘➙➚➛➜➝➞➟➠➡➢�

23:57 justin_smith: TEttinger: ^

23:57 TEttinger: I used a sort / reduce to generate those number ranges of course

23:58 TEttinger: ah nice

23:58 ,(char 11025)

23:58 clojurebot: \⬑

23:59 TEttinger: ,(map int "➢�")

23:59 clojurebot: (10146 65533)

23:59 TEttinger: ah, you got cut off and utf-8 took over

23:59 justin_smith: oh yeah that must have happened somewhere

Logging service provided by n01se.net