#clojure log - Jul 27 2013

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

0:01 futile: having two reverses just for the sake of destructuring seems dumb. i like #54 the best.

0:03 isaacbw: futile: oh man, that's clever. It took me a while to grock

0:03 futile: isaacbw: thats a sign that its stupid :)

0:03 isaacbw: lol

0:04 I just haven't seen the -> macro before

0:04 futile: isaacbw: the last tweak i would make is to use doseq instead of map to make it more explicit whats happening.

0:04 https://www.refheap.com/16956

0:04 isaacbw: oh ->, yeah thats a good thing. i thought you meant the destructuring and reversing.

0:07 isaacbw: and for the sake of separation-of-concerns i'd split it into two functions: https://www.refheap.com/16957

0:08 plus that makes the two parts more re-usable and easily maintainable.

0:08 and testable

0:09 isaacbw: yay testing

0:10 futile: actually you dont even need to name "lines" in (let) ... https://www.refheap.com/16958

0:11 isaacbw: i guess this has been a whirlwind tour of how my mind tries to make clojure code "more idiomatic"

0:12 isaacbw: :P

0:12 it's been very helpful. Thank you

0:12 futile: but i recommend having someone else in here write it too

0:12 ... if there is anyone else in here?

0:12 chouser_log: lookin' good. I'd use 'when' instead of 'if'. Or maybe cond->

0:13 futile: chouser: hmm

0:13 ,(doc cond->)

0:13 clojurebot: "([expr & clauses]); Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression."

0:14 futile: chouser: i dont know why but it seems like 'when' implies side-effects

0:14 chouser: so (-> data ... (cond-> last-line-complete? (concat [""])) ...)

0:14 futile: chouser: ah! yes, i see now! thats perfect

0:14 is that what cond-> was designed for?

0:15 chouser: I believe so, yes.

0:15 futile: sweet

0:15 (inc chouser)

0:15 lazybot: ⇒ 14

0:15 chouser: Also what synthread was designed for, but you don't have to go there. https://github.com/LonoCloud/synthread

0:16 futile: Your observation about 'when' is fair.

0:16 The fact that it allows multiple "then" clauses makes it useful for side-effects, like 'do'.

0:17 But it also makes it absolutely clear up front that you're not going to provide an "else" clause, so that's why I like to use it.

0:18 futile: isaacbw: with chouser's edit it's https://www.refheap.com/16959 although im on the fence about cond-> when first learning clojure

0:18 chouser: That's also fair. :-)

0:18 futile: chouser: hmm yeah good point.

0:18 chouser: cond-> is quite new and not yet widely used, I think.

0:19 futile: it seems like maybe 'when' should be split into two forms, one implying side-effects and one thats just 'if' but without any else clause.

0:19 not sure what itd be named though.

0:19 (iff) ?

0:21 chouser: my reasoning about cond-> is that it requires a firm grasp of imagining clojure macro-transformations, which i think beginners dont have yet

0:21 chouser: yep, perfectly fair. Even -> is often a stretch.

0:21 futile: although the same might be said about ->, but that one seems simpler and probably easy.

0:22 ,(iff foo (println "yep, its a foo alright")

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

0:22 futile: ,(iff foo (println "yep, its a foo alright"))

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

0:22 futile: clojurebot: *yet*.

0:22 clojurebot: Cool story bro.

0:22 chouser: you can always use let instead of ->

0:23 futile: chouser: actually the more i think about it, the more i think beginners should get used to -> right up front

0:23 chouser: at work we've had some (let) blocks that continuously rebind the same name on each line, and it makes it really easy to do bad stuff

0:24 chouser: yeah? what about ->> ? and doto ? and cond-> and when-> :-)

0:24 futile: i think using -> and ->> makes it easier to avoid bad practices. cant say for sure what they were though, this was a few months ago when we were new to clojure

0:24 when-> !?

0:25 ,(doc when->)

0:25 clojurebot: Pardon?

0:25 chouser: hm... The names changed a couple times right before they were released.

0:25 futile: maybe as-> ?

0:25 ,(doc as->)

0:25 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

0:26 futile: thats useful for when you want to mix -> and ->> but cant really

0:26 chouser: oh, I was thinking some->

0:26 futile: oh yeah, i still dont know what thats there for

0:26 ,(doc some->)

0:26 clojurebot: "([expr & forms]); When expr is not nil, threads it into the first form (via ->), and when that result is not nil, through the next etc"

0:27 futile: oh, so its just a short-circuiting ->

0:27 ,(doc some->>)

0:27 clojurebot: "([expr & forms]); When expr is not nil, threads it into the first form (via ->>), and when that result is not nil, through the next etc"

0:27 futile: neat

0:27 chouser: People were asking for that for ages. Often named -?>

0:27 futile: heh, naming is getting harder now that its a pretty rounded out core lib

0:27 i dont see how it relates to 'some'

0:28 but im sure they settled on some-> for good reason

0:28 i mean.. for *some* good reason :D

0:28 chouser: heh

0:28 some stops as soon as it gets a non-nil, some-> stops as soon as it gets a nil, so ... umm ...

0:29 yeah, I guess I don't know either.

0:29 futile: ,(doc some)

0:29 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

0:29 futile: logical true means non-nil-or-false

0:30 meh, whatever.

0:30 so.. isaacbw, got any more fun exercises like that one?

0:34 chouser: futile: http://clojure-log.n01se.net/date/2012-11-29.html#10:15

0:35 isaacbw: futile: hah, none at the moment

0:35 futile: chouser: ahh

0:35 isaacbw: aww

0:35 isaacbw: :P

0:36 chouser: Doesn't look like it got resolved there.

0:36 oh well. :-)

0:36 sdegutis: heh

0:36 chouser: interesting nonetheless

0:37 hmm, i dont think i can change nicks like this, callen will yell at me for it

0:38 i still like test-> better

0:40 as-> seems right

0:41 isaacbw: I'm trying to write an LMTP server with clojure, but I'm starting to realize that this may not be the best learning project

0:41 lol

0:41 futile: heh

0:41 isaacbw: considering how stateful that kind of thing can be

0:41 futile: how about hangman?

0:41 for cmdline

0:42 isaacbw: oh, that would be cool actually

0:42 futile: ok

0:42 if i write it too, want me to not show it to you?

0:43 (it sounds like fun)

0:43 chouser: ooh i get some-> now.. it threads through "some" of the expressions, but maybe not all

0:44 seems like it should be (while->) or something

0:44 but not while-> because its unrelated to while

0:44 maybe iff->

0:45 :D

0:45 oh who cares what callen thinks

0:45 sdegutis: there.

0:56 Raynes: sdegutis: FWIW, Jose was already gone by time you joined #elixir-lang. It's a pretty active channel during some hours of the day.

0:56 sdegutis: Raynes: ah

0:56 i want to be interested in it, its just so.. infixy

0:56 Raynes: :P

0:56 sdegutis: extra rules for my poor brain to memorize

0:56 and special cases and edge cases

1:14 chouser_log: thx for the tips

1:14 chouser_log, isaacbw nite.

1:28 akurilin: Quick dumb question, is there a list literal in clojure? As in, can I do '(1 2 3) as opposed to (list 1 2 3)? Hasn't worked too great for me, hence the question.

1:29 alandipert: akurilin: what about it hasn't worked for you? '(1 2 3) and (list 1 2 3) are both legit

1:38 akurilin: alambert, I'm using (fn [id] '(ks1 ks2)) in a with-redefs where ks1 and 2 are two maps I deffed earlier. My UTs don't pass when I use the literal approach.

1:39 actually let me repl this for a sec, see if I can repro by hand.

1:40 alandipert: akurilin sounds like you're running into the fact that '(..) => (quote ...) and anything inside the quote form isn't evaluated (such as the elements of a list)

1:40 akurilin: alambert, yes

1:41 alandipert: akurilin: `(~ks1 ~ks2) is one option, as syntax-quote allows for selective evaluation of forms via ~ (unquote)

1:42 akurilin: but i would prefer just [ks1 ks2] which relies on the fact that literal vectors do evaluate their constituent elements, which is the best bet if you're not relying on listiness particularly

1:42 ,`(1 ~(+ 1 1) 3)

1:42 clojurebot: (1 2 3)

1:43 akurilin: alandipert, I don't think I am. I'm trying to have my with-redefs stubs for clojure.jdbc return whatever data structure the form returns, which is probably just a sequence.

1:43 I was hoping a list would be more legit than a vector, but I might not really need this at all

1:43 alandipert: akurilin: i think returning a vector is a safe bet, esp. since vectors are also sequential

1:44 akurilin: alandipert, yeah that's a good point.

1:45 alandipert, thanks for clarifying, I learned something new today :)

1:45 Raynes: alandipert: Ohai. How's things?

1:45 alandipert: np! happy computing

1:45 Raynes: good, and thyself?

1:46 Raynes: I'm fantastic enough.

2:14 SegFaultAX: Pi is a weird movie.

2:40 rattboi: good one though

2:40 easier to follow than Primer

3:29 speedwagon: Hi! beginner question: The nrepl i started in emacs does not seem to know clojure.contrib. duck-streams . How can i fix this or am i using an outdated tutorial ?

3:31 supersym: duck-streams If a clojure.contrib namespace is not listed here, it is most likely an old namespace that was either migrated somewhere else or deprecated as part of Clojure 1.2 (e.g., clojure.contrib.duck-streams mostly migrated to clojure.java.io

3:31 http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

3:37 speedwagon: Thanks, I will read that.

3:41 I should probably look for a different tutorial/book.

5:01 tomjack: (memoize (fn [& args] (Object.)))

6:16 noncom: if, when i am in repl, *ns* is the current namespace then what is *ns* when a clojure program is executed from a jar?

8:07 squidz: how would you normally translate this into clojuresciprt? https://www.refheap.com/16961

8:07 it is only a couple of lines of javascript

8:35 patrkris: hi. i'm pretty new to Java interop in Clojure, and wrote the following code to try out netty: https://www.refheap.com/16962

8:36 noncom: squidz: do you know how to translate this to clojure?

8:36 (i mean not clojurescript)

8:36 patrkris: I've set *warn-on-reflection* to true, and Clojure now warns me that the call to .option can't be resolved

8:37 how do I get Clojure not to use reflection in this case?

8:37 (.channel and .childHandler can't be resolved either, but curioulsy it doesn't complain about the call to .group)

8:40 noncom: patkris: why do need warn-on-reflection?

8:40 squidz: noncom: no i'm guessing I would use an atom, but i've never done so

8:40 noncom: squidz: gimme a sec, i'll give it a try

8:41 squidz: okay thanks

8:42 i've tried avoiding atoms and state for as long as possible, but it seems like the time has come where I can't get around it again

8:42 patrkris: noncom: I don't need it per se

8:43 noncom: patrkris: i am no pro, but i think that if you need it (coz it is needed to know if speed-critical places ose reflection), i would enable and disable it when required

8:43 and created a macros to do that for me

8:44 patrkris: you may be right, but I'm still curious to know how to avoid reflection in this case :)

8:46 noncom: patrkris: try using explicit type hints maybe?

8:47 squidz: tell me what do yo want to get with that code?

8:48 squidz: you want to get a set of objects which have x and y properties set depending on passed value?

8:48 patrkris: noncom: I tried annotating b with ^ServerBootstrap, but it didn't help... :-(

8:49 squidz: yeah I want the nodes variable to contain x and y properties dependent on an index

8:52 noncom: patrkris: huh i look in the javadoc and it contains plenty on generics and stuff. are you sure that the java version of these methods itself does not use reflection?

8:53 patrkris: noncom: I don't know. I would've thought that a simple method call to a newly instantiated object wouldn't involve reflection (like the call to .option does)

8:54 noncom: patrkris: i think it uses some reflection here: http://netty.io/4.0/api/io/netty/channel/ChannelOption.html

8:56 patrkris: but it warns explicitly that it is the call to .option on ServerBootstrap that can't be resolved

9:04 noncom: squidz: smth lik htis? https://www.refheap.com/16963

9:05 squidz:threr is also a protocol way, like http://stackoverflow.com/questions/9018326/how-do-i-create-an-js-object-with-methods-and-constructor-in-clojurescript

9:06 patrkris: noncom: aaah, I am starting to see what you mean about generics now

9:06 noncom: patrkris: yeah, it looks a convoluted type-inference work there in java

9:07 my best guess really... what else..

9:09 squidz: i did not test, though, but should work if you call mk-objs.. and yeah,this could be written far more compact, but just for the sake of explicitness...

9:11 squidz: yes I see what you did there. My main problem is modifying the objects once they are created and I see that you pulled the indexing out into a separate function. I will try something similar out

9:16 noncom: squidz: further fun: https://www.refheap.com/16965

9:16 oh forgot (into {})

9:18 oh crap, no it wont work

9:19 squidz: as a good advice: try always to separate you single object creation logic from you sequence-of-objects creation logic. you get benefits then. soon you find how you can use same code in many places then

9:20 squidz: noncom: check out this solution that somebody else recommended https://www.refheap.com/16964

9:24 noncom: squidz: very nice! this enlightens me since i too a newb in clj and cljs. but note that this approach is less modular. in real projects, when you have big objects, you will want to break this one up (not always). i would make the main function separate, and the body looks a bit cryptic at first glance..

9:25 i would not choose this kind of creating values for x and y since it is hardly readable (for me :))

9:25 clojurebot: In Ordnung

9:26 squidz: yeah maybe pull out the logic with the adding and bit-wise operations and keep the threading creating as a general function and be able to push in different logic

9:27 noncom: yes. threading is a good idea here... my two concerns are modularity and reading this breaks my eyes: (+ (:y o 0) (if (= (bit-and 1 i) 1) 42 -42))

9:28 squidz: yes that logic can be pushed in on the fly

9:29 noncom: here is the actual javascript that i'm trying to translate: http://bl.ocks.org/mbostock/1021841

9:29 because the simplified snippet i posted may give false impresssion

9:29 noncom: but irl i kill people that i meet who use ternary operators too :D

9:30 squidz: yes I don't like it but if you look at the link that is what they use in the javascript

9:30 noncom: nice!

9:30 nice example, i also first time hear of d3

9:30 squidz: down below in the force.on("tick" ...)

9:31 noncom: how is your experience on d3? you like it?

9:34 squidz: noncom: yeah it's good, but I hate the mutability of everything

9:35 that is why i'm trying to switch over to clojurescript, but i'm trying to wrap my head around how I will do things the clojurescript way, which is why i have the problem code I pasted

9:36 noncom: squidz: ahahah :D. so you don't like mutability from your personal preference and you seek functional immutable approaches? what is your main languages of like?

9:39 squidz: well I love clojure but I have mostly done java. Now I have to dig into javascript and so i thought what better opportunity than to use clojurescript. I am hoping that if I can understand how to translate that the benefits of using clojurescript should outweigh the difficulties but a conclusion hasn't been made

9:39 this translation of the link I pasted is kind of a test-run to see if I can get this working. If i feel confident afterwards I am going to switch and use clojurescript at work

9:44 noncom: squidz: i see, much like me. well, my transition was first to clj than cljs, and when i finally made it, now i simply can't think of coding in another language.. besides other lisps maybe and C when things come to what C is great for.

9:53 squidz: i find myself fine building a full-scale gui framework based on kineticjs, although, still i'm learning things. also, note that when in clojure, you code backend with clojure and front end with cljs, which are like one language (not exactly, but still, where else you saw smth alike?), and you can call backend functions seemlesly from the frontend with shoreleave rpc mechanism

10:01 squidz: noncom: yeah in the end it's really aweesome. The only downside is that everything is still relatively new and not as mature as a lot of java and javascript libraries, but it is getting there for sure

10:11 noncom: Yeah I am also wanting to play around with clojurescripts async

11:14 dotemacs: hi, silly question: how do you search clojars from the CLI ? Or better: what's the recommended way to see what packages are available via the CLI ?

11:18 hyPiRion: $latest leiningen.core

11:18 lazybot: No project by this name exists on clojars.

11:19 hyPiRion: I know there's a `lein search`, command. You could look at its help info through `lein help search`.

11:22 dotemacs: hyPiRion: OK, so I wanted to see whats the latest package for postgresql, so i ran: lein search postgresql, it showed a list of packages with the first one at version 9.0-801.jdbc4. But when I do a search on postgresql on clojars.org, the first result is: 9.1-901.jdbc4. How come ?

11:27 hyPiRion: dotemacs: Not sure. Perhaps clojars' cache is a bit old, or there's a bug somewhere. You should probably ask in the #leiningen channel, there are people in there knowing how the internals of how `search` works better than what I do.

11:31 dotemacs: hyPiRion: thanks, will do

12:03 ToBeReplaced: If you have a .clj file that is compatible with both clojure and clojurescript, how can you deploy it to clojars for use on either platform?

12:21 dotemacs: Is there a way to "disable" a deftest from the test suite? For example you have 10 deftests and you only want to run 9 of them, would there be a way to prefix deftest with a ... to not have it run? Rather than just commenting it out and running the tests.

12:25 seangrov`: dotemacs: You can add metadata to them, might be one approach

12:31 dotemacs: seangrov`: sorry, not sure how, any pointers/URLs ? :)

12:36 hyPiRion: dotemacs: have a look at the sample.project.clj in the Leiningen repo on Github

12:37 dotemacs: hyPiRion: thanks :)

12:41 rlb: What am I missing? The javadocs say that (.indexOf this s fromIndex) returns k such that "k >= Math.min(fromIndex, s.length()) && this.startsWith(s, k)", or -1.

12:41 However (.indexOf "xyz" "" 10) returns 3.

12:42 According to my math Math.min(10, ...) can't be less than 10.

12:42 Ok, now that was stupid.

12:43 nevermind

12:47 ...was overlooking the edge case where "" matches at the end of the string and satisfies the predicate.

12:59 noncom: in ccw if i load a file into a repl, and it depends on other files and those other files fail to compile, the loading is stopped. and it becomes broken, since i can't restart or continue it without restarting repl. is there a way to re-load all without restarting repl?

13:00 Bronsa: (let [x 1] (defn x [] x)) returns 1, I wonder if that's the desired behaviour

13:01 dnolen: Bronsa: in CLJS?

13:01 Bronsa: dnolen: clj

13:02 dnolen: Bronsa: I just tried that w/ 1.5.1, I don't see that behavior

13:02 alandipert: noncom: not sure about ccw, but you can reload a namespace and its dependencies from the repl with: (require 'foo.bar :reload-all)

13:02 Bronsa: dnolen: I meant when invoking (x)

13:02 noncom: alandipert: gonna try it

13:02 thanks!

13:03 dnolen: Bronsa: hrm, there may be a reason for that ... I vaguely recall something

13:03 noncom: Bronsa: so it creates a closure i think

13:04 hyPiRion: Bronsa: It expands to (let* [foo 1] (def foo (fn* ([] foo)))), go figure

13:04 dnolen: Bronsa: CLJS doesn't preserve that behavior, it returns the self reference

13:04 Bronsa: yeah, if only it expanded into (fn* foo ([] foo)) there would be no problem

13:05 hyPiRion: yup.

13:05 dnolen: Bronsa: would break redef

13:06 Bronsa: hm?

13:06 clojurebot: benchmarking is https://github.com/hugoduncan/criterium

13:06 dnolen: Bronsa: oh right I guess not

13:08 Bronsa: hm

13:08 hyPiRion: dnolen: actually, I think you're on the right track.

13:08 Bronsa: actually

13:08 yeah.

13:08 see: http://sprunge.us/OLDM

13:09 dnolen: Bronsa: hyPiRion: ok yeah

13:11 Bronsa: I think this is treated as special case in the CLJS compiler.

13:15 hyPiRion: Bronsa: also, recursive functions through alter-var-root https://www.refheap.com/16976

13:15 Bronsa: dnolen: I see, the var name gets passed around and https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj#L386-L387

13:15 dnolen: Bronsa: yeah

13:16 Bronsa: hyPiRion: right

14:04 squidz: noncom: I posted the results of the code you were helping me with earlier. Here it is in it's glory. I still want to improve it though since the cljourescript is pretty much a 1-to-1 translation from the javascript http://s.trokes.org/beandipper/6095600

14:07 noncom: squidz: cool! well, i would avoid using (set!) and use (cljs->js) instead...

14:07 also using forEach is anti-pattern since clojure is all about sequences and it should be used here

14:09 squidz: yeah just not sure how to use doseq here with an index while being able to modify the structures in place

14:13 bbloom: dnolen: why are you deleting tickets, rather than closing them?

14:20 noncom: squidz: just try smth like (js/Object. (cljs->js {:x 2 :y 4}))

14:21 squidz: but! on coord modification i would certainly use (set!) because immutability is very natural to game-like processes

14:21 squidz: oh i meant MUTABILITY not immutability

14:22 squidz: noncom: i'm not sure that it will work because the nodes objects that i am setting are custom structures from the library I believe

14:22 noncom: i will look more into your code on monday, now i'm finishing my work and have to go.. if i find something i can think can be improved, i'll let you know and ask you if you found something too, since i'm intereted coz i learn too

14:23 squidz: okay

14:23 noncom: squidz: see, you create them with native js/Object. and they take json i think

14:23 you could try

14:23 it worked for me with kineticjs

14:23 looks much finer that way

14:23 squidz: yeah I can try it out later, but I am going to work on something else for now. That was mostly a test project

14:24 noncom: tests are life :D

14:40 whee: for someone just getting into clojure and web applications, are ring and compojure a safe start?

14:40 gfredericks: yep

14:41 onr: what about Java EE Servlets? :)

14:43 noncom: whee: maybe luminus will be a good start. it uses ring and compojure

14:43 they have nice docs too

14:46 dnolen: bbloom: I'm deleting them, cloning them now

14:47 bbloom: I'm tired of seeing crap in the year 2020

14:48 bbloom: dnolen: heh ok, just wanted to make sure you weren't accidentally bulk deleting stuff. b/c i got an email about a ticket being deleted

14:48 dnolen: bbloom: only applies to tickets from the initial import

14:48 bbloom: ah ok

14:48 dnolen: are you able to carry over watchers too?

14:49 dnolen: bbloom: I don't think it carries over everything but again it only applies to the initial tickets, I think we can live with that.

14:49 bbloom: ok

14:50 dnolen: bbloom: up to CLJS-23

14:50 so not many tickest

14:50 bbloom: yup

15:05 dnolen: k CLJS JIRA cleaned up no more stuff from 2020

15:06 squidz: is there a way to refer to map entries while defining that same map. For example {:first 1 :second (inc (:first this))} producing {:first 1 :second 2} ?

15:07 dnolen: squidz: there is not

15:08 squidz: okay thanks

15:16 fbernier: How would you indent the word-count function? Would you indent it at all?

15:16 https://gist.github.com/fbernier/6095820

15:16 bbloom: fbernier: try -> and ->>

15:16 s/and/or

15:17 fbernier: oh right thanks

15:20 bamford_: People, if there is a patient soul in here, can you explain to me how the (atom {}) can leave the scope of the (let) in the memoize function at this address? http://clojure.org/atoms

15:20 still learning ... :/

15:21 gfredericks: bamford_: what languages are you familiar with?

15:21 bamford_: gfredericks: Java, Python, Perl, Vim script, ...

15:21 bbloom: bamford_: it's not leaving the scope

15:22 bamford_: think of the fn as defining an instance of a Function class

15:22 gfredericks: bamford_: any language with closures will do; I think that includes python?

15:22 * gfredericks knows very little about perl

15:22 bbloom: bamford_: but if it uses somethign above it, it creates a Closure class which is a Function and map of variables

15:22 bamford_: gfredericks: I believe I understand simple closures well enough ... :?

15:22 bbloom: so fn is basically something like new Closure(new Function(…), new HashMap(…))

15:23 bamford_: ok

15:23 gfredericks: bamford_: so the fn includes a reference to the atom, in somewhat the manner than bbloom is suggesting

15:23 that*

15:23 bamford_: bbloom: ok, but where is the atom mem stored? is it inside the fn closure?

15:23 bbloom: bamford_: precisely

15:23 inside the hashmap

15:23 bamford_: oh boy

15:24 gfredericks: otherwise it would get GC'd

15:24 isaacbw: can anonymous functions be passed from clojure to a java class, and then called from java?

15:24 bamford_: very cool, but puzzling for an unenlightened soul

15:24 isaacbw: *object

15:24 bbloom: bamford_: enlightenment takes time :-)

15:24 gfredericks: isaacbw: yes

15:24 bamford_: bbloom: :)

15:24 gfredericks: isaacbw: they're both Runnable and Callable

15:24 isaacbw: gfredericks: oh, awesome

15:25 gfredericks: if you want to pass args you might need to treat it as an IFn

15:25 bamford_: bbloom: last question: so if multiple threads call the memoized fib, they will all see the same mem atom

15:25 gfredericks: bamford_: yep

15:25 bamford_: ... actually yes, that must be it

15:25 gfredericks: thankx

15:26 bbloom: bamford_: if you want different threads to see different values, you can use (doc binding)

15:27 bamford_: bbloom: yes, Vars, Refs, Atoms I can tick off, now over to Agents ... :)

15:28 bbloom: bamford_: 90% of clojure code only ever needs a very small number (preferably zero) dyamic vars and like ONE atom

15:29 bamford_: bbloom: heh, ok, so which one is your basic workhorse for concurrency stuff, Refs? (or "it depends", I know)

15:29 bbloom: bamford_: in 1.5 years of clojure, i've used refs ONCE and nobody believed me that i actually needed them for my use case until after an hour of explaining myself in IRC

15:30 bamford_: ?! but they look so cool! I want to use them

15:30 gfredericks: I have also used refs jutsifiably 1 time.

15:30 bbloom: but atoms are simpler :-)

15:30 gfredericks: justifiably*

15:31 bamford_: clojure has a lot of cool features that you don't usually need, which is itself kind of a cool feature

15:31 bamford_: no but seriously, what do you use then? (Thread.) ?

15:31 gfredericks: for what?

15:31 srruby: I can create an anonymous function that always returns the number 1. (fn [] "always return 1" 1) How do I do the same with #() form ?

15:31 bbloom: bamford_: i didn't even really need refs for concurrency (although they gave me that) i really needed them for independent garbage collection. i could have stuck a map in an atom, but then i'd need to manage lifetime manually :-P

15:32 gfredericks: srruby: returning literals with #() isn't worth doing

15:32 srruby: #(do 1), #(identity 1) (constantly 1)...

15:32 the first two are distracting I think

15:32 the third communicates your intent

15:33 srruby: Thanks!

15:35 bamford_: gfredericks: actually I don't know, all this clojure has me stoked for concurrency, but I should probably put my head in ice water for a bit and see what I want to use it for :)

15:36 gfredericks: bamford_: yeah I know the feeling.

15:36 bbloom: bamford_: yeah, it's sorta unfortunate that concurrency gets so much airtime, since it means that people come to clojure & try really hard to run before they can walk or crawl

15:39 fbernier: bamford_: I've also been stoked about concurrency in clojure, but up to now I've done close to none. I really enjoy learning the language right now!

15:40 bamford_: bbloom, gfredericks: thanks for your insights. I actually spent some time looking into Haskell some time ago, which is also very functional, but the community and docs have much less emphasis on concurrency

15:49 isaacbw: gfredericks: using IFn worked perfectly!

15:49 gfredericks: nice

15:50 isaacbw: man, this stuff is making me so happy. I can wrap existing java libraries into functional clojure APIs

15:51 java's got two things going for it: the jvm and the ecosystem

16:00 rhg135: hello, i would be grateful for any advice on how to make https://www.refheap.com/16979 more "idiomatic"

16:00 bugrum: Hi, new Clojure programmer here. I was wondering if anyone can point me to a library that implements the dataflow model, similar to that of Cells on Common Lisp

16:01 gfredericks: rhg135: any use/only can be replaced with require/refer

16:01 rhg135: ok

16:02 but im pretty sure that's why :only exists

16:04 Bronsa: if only there was a way to group different dispatch values in a single defmethod :(

16:04 gfredericks: rhg135: require/refer was added so that :use isn't needed anymore

16:04 rhg135: hmm i guess

16:04 idk the order lol

16:06 i had this working, but after some minor changes it broke, i guess i need some good tests, but i've never written a test

16:07 gfredericks: clojure.test is pretty easy to use

16:07 Bronsa: gfredericks: it's tests that are difficult to write

16:08 rhg135: i know HOW to use it, but don't know how to TEST it

16:08 gfredericks: you're testing downloading some stuffs?

16:08 rhg135: it's a scraper lib

16:08 gfredericks: you could stub your download function

16:08 or use a vcr lib to record the things you're scraping

16:09 for high-level tests

16:09 rhg135: stub? vcr?

16:09 gfredericks: (binding [*download* (constantly {:some :data})] (test the other functions))

16:10 rhg135: true but what'd be the point of testing it on arbitrary data

16:10 i guess I need intergration tests

16:10 gfredericks: to make sure it doesn't blow up. if you have something more specific in mind, test that too at a lower level maybe

16:11 high level tests with recorded data can go nicely with pre/postconditions and other assertions/contracts

16:11 rhg135: yeah, im gonna bactrack to a working revision and add testing

16:12 or just add now and hax it till it works

16:14 also I'm wondering, in Haskell (which I last used) it's common to use the type system to ensure functions take and return the proper type would pre/post conditions be the best alternative

16:16 gfredericks: yeah I think so.

16:17 rhg135: ok I'm going to add some testing

16:17 gfredericks: should java.jdbc change its default :result-set-fn from doall to vec, so that processing can be chunked?

16:26 bbloom: dnolen: shesh, your jira attach has generated a ton of email for me :-P

16:26 attack*

16:35 functionform: is this the appropriate channel for newbie questions?

16:35 gfredericks: totally

16:36 functionform: assuming a vector of words, i want to use string/replace on each of them

16:36 noonian: and get a vector of words back that have had replacements made?

16:36 functionform: exactly!

16:37 why does this return a quoted string?

16:37 (-> words (str/replace "i" "b"))

16:38 or is my approach totally wrong

16:38 gfredericks: ,(doc map)

16:38 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

16:38 Bronsa: ,(mapv #(clojure.string/replace % #"a" "b") ["aa" "ab"])

16:38 clojurebot: ["bb" "bb"]

16:39 functionform: ok so function is required

16:39 i was trying to figure something out with threading etc

16:39 noonian: ,(map (fn [word] (clojure.string/replace word "foo" "bar")) ["blargfooey" "bardom"])

16:39 clojurebot: ("blargbarey" "bardom")

16:39 arcatan: functionform: that converts words to a string first and then replaces i with b - that's why you get a quoted string

16:40 functionform: bizarre, i wouldn't have expected that conversion to take place

16:40 arcatan: ,(str ["this" "will" "be" "quoted"])

16:40 clojurebot: "[\"this\" \"will\" \"be\" \"quoted\"]"

16:40 noonian: ,(->> ["blargfooey" "bardom"] (map (fn [word] (clojure.string/replace word "foo" "bar"))))

16:40 clojurebot: ("blargbarey" "bardom")

16:41 functionform: ooooooh now i see what iw as doing

16:41 ok

16:41 right

16:41 thanks!

16:42 oh its so beautfil

16:42 when i get it working... loving this language.

16:43 jpreston: Anyone fancy giving a newbie a hand? :)

16:44 bbloom: ~anyone

16:44 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

16:44 jpreston: When I try to use the function in here: http://codepad.org/RViLS8Kf

16:44 I keep getting "Wrong number of args"

16:45 This is in a lein repl, and that file lives in overtone_workspace/controls/slipderpanel.clj in the lein project's src/ dir.

16:45 gfredericks: what function does it say the wrong number of args were passed to?

16:45 jpreston: sliderpanel

16:46 But AFAIK [& opts] would make it completely variadic.

16:46 gfredericks: yep

16:46 maybe your repl has some stale code?

16:47 jpreston: lets see

16:47 haha that was it

16:47 cheers! :D

16:58 RuralClojurer: are there any resources to explain how aot compilation affects macro evaluation?

16:59 gfredericks: RuralClojurer: presumably the macros still happen at compile-time

17:01 RuralClojurer: occasionally i hear someone mention vaguely that their macro may not work in aot-compiled code

17:01 i'm just wondering what this means

17:02 gfredericks: hmmm; I can imagine macros with side effects might have that problem?

17:02 RuralClojurer: ok, mb it's not something i need to worry about then

17:03 gfredericks: afaik

17:03 why do you need AOT?

17:03 RuralClojurer: i'm writing a library that someone might choose to compile

17:03 gfredericks: ah

17:04 RuralClojurer: thanks gfredericks, i'll stop worrying then!

17:07 gfredericks: omg this is the weirdest stack overflow I've ever seen. (f (doall (map (constantly nil) coll))) throws a SO, but (f (repeat (count coll) nil)) does not.

17:07 I have no idea what the difference between those two is

17:07 the (doall ...) is not the part throwing the SO, f is.

17:08 and coll is not chunked.

17:08 dnolen: bbloom: yep, still got another 150 issues to close

17:08 bbloom: dnolen: fun times

17:09 dnolen: bbloom: will be careful to close resolved tickets in the future

17:09 bbloom: dnolen: can't just bulk update them?

17:09 dnolen: bbloom: not sure how to do that?

17:09 bbloom: i'm quite confident it's in there somewhere :-P

17:11 dnolen: "tools" menu in top right

17:11 go to the issues tab

17:11 jira's UI is atrociously bad

17:12 also, if that just saved you 150*nMinutes, you owe me a beer :-)

17:12 dnolen: bbloom: sweet done!

17:12 and no emails :)

17:12 bbloom: haha even better!

17:13 dnolen: bbloom: beer owed

17:13 bbloom: pleasure doing business with you

17:35 scape: Hi all, I come with a question :) I am working with libgdx in clojure and am curious how I am to properly call the Mesh class that exists in graphics. When I call something like: (Mesh. true 4 4 attrs) I get UnsatisfiedLinkError com.badlogic.gdx.utils.BufferUtils.newDisposableByteBuffer(I)Ljava/nio/ByteBuffer; com.badlogic.gdx.utils.BufferUtils.newDisposableByteBuffer (BufferUtils.java:-2)

17:36 However I have this (:import (com.badlogic.gdx ApplicationListener Gdx) (com.badlogic.gdx.graphics GL20 Mesh VertexAttribute Color) (com.badlogic.gdx.utils BufferUtils))

17:37 So if anyone may know what I am doing wrong, I'd appreciate help.

17:37 avishai: a question about promises

17:37 is there a function which "breaks" a promise?

17:37 or do i have to deliver some magic keyword to mark the promise as broken

17:38 hyPiRion: scape: I have no idea how that library work, but UnsatisfiedLinkError is thrown by the JVM whenever one tries to call a native method, but is unable to find it. I guess you need to include some native DLL or SO or something.

17:39 scape: interesting, ok. if i nest the call in (proxy [ApplicationListener] [] ) then it will work, this is strange to me since the class exists in a different interface, graphics

17:39 i'll see if there is a native library i'm missing

17:45 lpetit: greetings

17:46 scape: avishai, you could break the promise as you suggest with some flag you recognize

17:47 noonian: avishai: to me, the promise is that you will deliver a value. I think instead of breaking it you want to return a different value than normal, often nil, so that the receiver isn't stuck blocking if it dereferences the promise

17:51 AtKaaZ: ,(contains? [1] 1)

17:51 clojurebot: false

17:51 AtKaaZ: ,(contains? [1,2] 1)

17:51 clojurebot: true

17:51 AtKaaZ: what am I missing here?

17:52 oh that's right

17:52 ,(contains? [1] 0)

17:52 clojurebot: true

17:52 AtKaaZ: i don't even want to know, something about indexes

17:53 hyPiRion: ,(doc contains?)

17:53 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

17:53 hyPiRion: emphasis on key, there.

17:53 lpetit: technomancy: ping

18:02 clj_newb_2345: anyone know of a good tutorial on _implementing/writing_ PEG parsers in Clojure?

18:02 I don't want to use use a PEG parser; I wnat to understand how to implement one.

18:04 bbloom: clj_newb_2345: check out the source code to instaparse. it's not a PEG parser, it's a full CFG parser, so the algorithm will be different, but the clojure code will give you the right idea

18:04 from there, you can try reading the original paper about PEGs to see how the algorithm differs :-)

18:05 dbushenko: hi all!

18:05 which is the best unit-tesing library/framework for clojure&

18:06 clj_newb_2345: bbloom: isn't the only difference "CFG = can be ambigious" "PEG = removes ambiguity by always taking the first"

18:06 bbloom: clj_newb_2345: that's the only difference in their semantics, but deterministic choice can allow a dramatically different implementation strategy

18:06 hyPiRion: dbushenko: some are satisfied with clojure.test, others prefer a tool named Midje.

18:07 bbloom: the purpose of PEG is the be 1) fast and 2) un-ambiguous after composition

18:07 hyPiRion: Well, a library, rather.

18:07 dbushenko: hyPiRion: thanks!

18:07 bbloom: clj_newb_2345: where by composition, i mean union

18:21 gfredericks: &(->> (repeat 30000 (cons :x [:y])) (apply concat) (reduce (constantly nil)))

18:21 lazybot: java.lang.StackOverflowError

18:21 gfredericks: ^ trying to figure out if that's a bug

18:22 we have a sequence that you can do just about anything with with no problems except for reduce it

18:22 as far as I can tell

18:23 hyPiRion: that's a lazy seq, though.

18:23 gfredericks: sure

18:23 amalloy: gfredericks: i actually think i know what's up with that

18:23 gfredericks: amalloy: it's bouncing between different reduce impls no?

18:23 amalloy: yes

18:23 gfredericks: this seems avoidable

18:23 given I can wrap the thing in (take 1000000000 ...) and it's okay

18:24 hyPiRion: gfredericks: yeah, then this is obviously a bug

18:24 gfredericks: this is not contrived btw. came up at work and I spent several hours wittling it down to this

18:25 amalloy: I don't imagine you have a fix in your head?

18:26 amalloy: gfredericks: well, wait for java 9+ and get TCO :P

18:26 gfredericks: w00t

18:27 * gfredericks starts to browse the protocols.clj code

18:27 hyPiRion: not sure why it jumps from IChunkedSeq to Object and back again.

18:27 but that's what it does

18:28 gfredericks: because the seq is an alternation of chunked seqs and regular seqs

18:28 amalloy: hyPiRion: because (cons:x [:y]) is a two-element sequence, where (seq thing) is non-chunked, and (next thing) is chunked

18:29 and he concats a zillion of them together

18:29 rboyd_: is ob-clojure meant to have support for code blocks with arguments? doesn't seem to work for me.

18:29 hyPiRion: shh

18:30 kristof: Is the Reducers library part of standard Clojure?

18:30 hyPiRion: that's stupid, although I can see the rationale for bouncing down to a faster one.

18:30 lpetit: Are there Counterclockwise users there ?

18:31 hyPiRion: Would be better if if could jump up instead of down the stack there.

18:32 kristof: Because if it's not, I'm wondering what the rationale is in that.

18:32 hyPiRion: kristof: it is

18:32 gfredericks: I guess I'll file a ticket

18:32 no fix to protocols.clj is coming to mind

18:32 kristof: hyPiRion: So why don't they just reduce map and reduce?

18:33 hyPiRion: I mean replace.

18:33 gfredericks: kristof: reducers are a little trickier to use

18:33 and only work on special data structures

18:33 kristof: Well, they work on collections

18:33 gfredericks: not seqs

18:33 kristof: Oh, I see

18:34 And so you don't want to use a reducer in a place where order is important?

18:34 gfredericks: that's also true

18:34 in any case it'd be a backwards incompatible change

18:34 hyPiRion: kristof: because their semantics are different. reduce is single-threaded, map is lazy. Reducers may be multi-threaded, mappings is eager

18:34 gfredericks: which is not something that rich does just for funs

18:34 kristof: Ah, I see

18:34 So different tools for different jobs.

18:35 hyPiRion: yeah

18:35 kristof: Cool, that makes sense. Thanks hyPiRion and gfredericks. =)

18:35 gfredericks: I need a good word to describe my sequence

18:36 I have something on the tip of my tongue, like "edge case" but stronger

18:36 kristof: extrema

18:36 outlier

18:36 gfredericks: it refers to the fact that the sequence is exactly the worse thing given the code that's running

18:37 hyPiRion: gfredericks: a "sequence with oscillating chunkedness"?

18:37 gfredericks: worst*

18:37 hyPiRion: too long for the ticket title :)

18:37 pathological

18:37 that's it

18:38 it seriously weirded me out that (map (constantly nil) coll) was bad but (take 100000000 coll) was okay

18:38 kristof: I was going to say a Murphy. :P

18:38 gfredericks: makes sense now though

18:38 hyPiRion: gfredericks: map or reduce?

18:38 gfredericks: hyPiRion: I'm talking about passing the results of those to reduce

18:39 hyPiRion: oh, right

18:39 gfredericks: map preserves the alternating chunkiness but take masks it

18:39 hyPiRion: chunky/funky

18:46 gfredericks: CLJ-1237 it is: http://dev.clojure.org/jira/browse/CLJ-1237

18:49 hyPiRion: watched

18:49 Now I'll get an email about the fix in 1.5 years

18:50 wooho

19:10 gfredericks: I guess we could trampoline the whole thing, but that seems lame

19:10 maybe not a deal-breaker for perf though?

19:10 it'd probably be constant-time overhead for most uses

20:47 te: I'm trying to make System/getenv a bit friendlier since its a java.util.Collections$UnmodifiableMap

20:48 I'd like to do (:foo (System/getenv)) as well as (get (System/getenv) :foo 33)

20:48 I'd also like to treat the map from System/getenv as a map with indifferent access

20:49 so I can use :foo, even if the map itself has a key of "FOO".

20:51 also, i always wonder why clojure.walk doesn't have a more generic hash-map walker/modifier

20:53 in addition to keywordize-keys and stringify-keys it'd be nice to see a form which takes takes a pred and form, pred checks whether key meets pred, if so, apply form, same for keys

21:08 https://gist.github.com/devn/6096924

21:08 Does anyone see why that couldn't be included in clojure.walk? After all, there postwalk-demo lives in there.

21:19 amalloy: te: (a) clojure.walk is dead and buried; (b) that doesn't really walk over a generic data structure recursively like everything else in clojure.walk

21:20 te: amalloy: im confused -- stringify-keys and keywordize-keys do the exact same thing as those fns, they just dont expose pred and f as args.

21:20 amalloy: i wasn't aware that clojure.walk was dead -- why do you say that? what took its place?

21:22 amalloy: oh, you're using postwalk. i thought you used map, ie nonrecursively

21:23 mostly what's taken the place of clojure.walk is a realization that it is slow, unwieldy, and doesn't work very well with several data types (eg, records), so that it's better to just start from scratch than use a not-quite-right lib as a starting point

21:26 bbloom: amalloy: stuart recently published this: https://github.com/stuartsierra/clojure.walk2

21:26 based on protocols, supports records :-)

21:27 te: there's no refuting that it doesn't work with some data types, but i often wind up pulling in clojure.walk simply for keywordize-keys or stringify-keys. I don't see why adding some more general versions of those functions would be a terrible addition.

21:27 * te forks and submit PR

21:28 bbloom: good call :-)

21:28 stuart might require you have a clojure contributor license, in case he plans to get this integrated back into clojure proper

21:33 te: i have one

22:05 vraid: how does "frame.getContentPane().add(canvas)" translate into clojure?

22:06 i can't seem to fit the 'add' in there

22:06 bbloom: (doc ..)

22:06 clojurebot: "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand."

22:11 amalloy: (-> frame (.getContentPane) (.add canvas))

22:12 or, if you prefer, (.add (.getContentPane frame) canvas)

22:15 thm_prover: does peg == packrat parsing, or are they different things?

22:15 bbloom: one is a formalism, the other is a possible algorithm for implementing it

22:16 vraid: amalloy: the last one worked, thanks

22:17 thm_prover: so it's like binary search tree :: red-black tree ?

22:17 Raynes: vraid: Pretty sure they both worked, right?

22:17 bbloom: thm_prover: eh, close enough

22:18 thm_prover: bbloom: why are you so knowledgable ?

22:18 bbloom: thm_prover: abstraction & concrete implementation is one way to look at it, yeah

22:18 te: I'm trying to make System/getenv a bit friendlier since its a java.util.Collections$UnmodifiableMap and I want to have indifferent access to keys so I can say (:foo (System/getenv)), (get (System/getenv) :foo) even though k/v pairs in the result are {"FOO" "BAR", "BAR" "BAZ"}.

22:19 bbloom: thm_prover: b/c i spend more time reading doing a pruning search across a citation graph, than i do reading the top N items on hacker news ;-)

22:19 vraid: Raynes: ah, right, i missed the ->

22:19 thm_prover: bbloom: ouch :-)

22:19 te: im currently doing this: https://gist.github.com/devn/46b4f7a871e1ac0d5b9a

22:20 pretty sure im doing it wrong

22:20 bbloom: thm_prover: wasn't intended as an insult to either you or HN

22:20 tos9: te: Why's that friendlier, the environment is case sensitive

22:20 thm_prover: bbloom: no, it's so true though

22:20 bbloom: HN provides the drug-like-feeling as if I;m learning somethig new

22:20 bbloom: but it's one thing to know that X exists; it's another thing to have a formal definition of X; and it's entirely different to be able to use X understand how X is implemented

22:20 te: tos9: okay then, throw out the case insensitivity -- i'd like indifferent access

22:21 bbloom: thm_prover: my understanding comes from implementation. go make things!

22:22 fake it until you make it, it works

22:22 thm_prover: i recall this other statement

22:23 the best performance improvement is not "exp time to linear time", it's "not working to exp time

22:23 justin_smith: te: for one thing, it seems that you are keywordizing-keys, but using the name of the key to do the lookup

22:23 one of those should probably be skipped

22:23 on one side making keyword out of string, while on the other making string out of keyword - like two ships in the night

22:24 te: justin_smith: pay no attention to that impl. -- the question is still about indifferent access

22:25 namely the (:foo {"FOO" "BAR"}) case

22:32 (:term (System/getenv)), for instance, throws: ClassCastException clojure.lang.Keyword cannot be cast to java.lang.String java.lang.ProcessEnvironment$Variable.valueOfQueryOnly (ProcessEnvironment.java:144)

22:32 is there any way around that or no?

22:32 justin_smith: also, see updated gist https://gist.github.com/devn/46b4f7a871e1ac0d5b9a

22:40 justin_smith: te: is the "get" that you are referencing in EnvMap actually the same "get" that :keyword uses when called?

22:40 when I run your code in a repl I get warnings that the new get is repacing the previous core/get

22:41 I think :keyword is still using the previous core/get, and user/get isn't even coming into play with (:term (System/getenv))

22:42 user> (get (System/getenv) :term) => "dumb"


22:42 that totally works with your code

22:45 yeah, (clojure.core/get (System/getenv) :term) throws the same error (:term (System/getenv)) does; I am not sure how you would redefine/extend what a keyword does when called, but just defining get in a new namespace definitely won't do it

22:46 clj_newb_2345: is there a clojure builtin that mimics the "shift" on US keyboards? i.e. a -> A, b -> B, 1 -> !, 2 -> @, ..., [ -> {

22:48 justin_smith: clj_newb_2345: you could define it, it would be a little tedious - {\a \A \b \B ...} etc.

22:48 clj_newb_2345: yeah, the berst I have is to define all but a-Z

22:48 and then use to upper case for a-z

22:49 justin_smith: clj_newb_2345: I would be tempted to just use a map, but then you can't use upper-case

22:49 clj_newb_2345: union + map

22:50 justin_smith: ,(apply str (map {\a \A \b \B} "ababab))

22:50 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

22:50 justin_smith: oops

22:50 ,(apply str (map {\a \A \b \B} "ababab"))

22:50 clojurebot: "ABABAB"

22:53 justin_smith: the reason I would always be inclined to use a map rather than a function with conditionals is it makes code much easier to read, and fewer moving parts leads to more solid code

22:55 though of course a 101 key keyboard is a pretty big map

23:00 ,(into {} (map (fn [c] [(char c) (-> c (- 32) char)]) (range (int \a) (int \z))))

23:00 clojurebot: {\a \A, \b \B, \c \C, \d \D, \e \E, ...}

23:05 justin_smith: https://www.refheap.com/16989

23:06 clj_newb_2345: that link has something that should work

23:06 clj_newb_2345: justin_smith don't we need: (+ (int \z) 1) ?

23:07 justin_smith: why?

23:07 clojurebot: why not?

23:07 justin_smith: ahh

23:07 clj_newb_2345: , (range 1 10)

23:07 clojurebot: (1 2 3 4 5 ...)

23:07 clj_newb_2345: , (range 1 3)

23:07 clojurebot: (1 2)

23:07 justin_smith: yeah, you are right

23:08 ,(range (int \a) (inc (int \c)))

23:08 clojurebot: (97 98 99)

23:13 clj_newb_2345: justin-smith: https://gist.github.com/anonymous/6097177 not as elegant as your code; but avoids lots of \'s

23:15 justin_smith: you don't like \?

23:19 I, on the other hand, prefer to avoid #

23:19 heh

23:25 clj_newb_2345: justin_smith: nah, inputting 1! is "1 shift 1", whereas \1 \! is "\ 1 \ shift 1"

23:26 in the context of core.async, how does >!! and >! differ?

23:26 gfredericks: >! is only allowed in a go block

23:26 >!! does actual blocking

23:27 justin_smith: clj_newb_2345: what I am trying to minimize is the (human) read overhead

23:28 I tend to read things many times for every once I write them

23:28 clj_newb_2345: !! <-- blocks a real Java thread; ! <- blocks a "light weight go thread" ?

23:28 gfredericks: is the above interpreation correct?

23:31 gfredericks: clj_newb_2345: sounds right

23:31 the translation to cljs is !! is not allowed

23:33 (def unchunk (partial take Double/POSTIVE_INFINITY))

23:35 justin_smith: gfredericks: what would that do that doall would not?

23:35 clj_newb_2345: (create a channel, write one msg to it, read from it) * 1000 = 342 milliseconds <-- is this timing about right fore core.async?

23:35 gfredericks: justin_smith: return a sequence that isn't chunked

23:36 justin_smith: also it would not realize the sequence

23:36 so it has very little in common with doall

23:36 justin_smith: ahh

23:36 cool, thanks

Logging service provided by n01se.net