#clojure log - Apr 10 2015

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

3:12 magnars: Turning on source-maps in my clojurescript profile, makes it basically just hang there for several minutes now - could it be taking so long? (I am including core.async) Any idea what could make it hang otherwise?

3:34 Guest72028: is the excuse , we have too many change requests valid for not using unit tests and version control?

3:35 magnars: there is no excuse to not use version control

3:35 Guest72028: :-), ok and the unit tests?

3:35 the project is very big btw

3:35 a payroll application

3:38 magnars: automated testing is a huge advantage when done right, but it might be prohibitively expensive to shoehorn into an existing huge codebase

3:39 but too many change requests sounds to me like a rather weak argument

3:39 Guest72028: oh, ok, i see

3:39 what if they implement unit tests gradually?

3:41 magnars: one good way of introducing unit tests is to write tests when reproducing bugs, and them keeping them around to avoid those known bugs to creep up again - that is probably easiest done with some sort of feature tests tho.

3:43 Guest72028: thanks, that seems like a clever idea

3:43 sveri: And adding tests for new features obv.

3:45 TEttinger: gfredericks made a pretty amazing regex tester for use in clojure tests

3:46 https://github.com/gfredericks/test.chuck/blob/master/src/com/gfredericks/test/chuck/regexes.clj#L501

3:46 Guest72028: part of the frustration i guess is that management want a feature and they want it like yesterday

3:47 TEttinger: if you want to make sure your input validation actually only lets in valid input, that tester util may be especially handy

3:48 oddcully: Guest72028: test are written to make change/refactoring easy. if every little change breaks half your testbase, then there are problems with the architecture

3:48 magnars: Guest72028: the only way to go fast is to go clean

3:49 Guest72028: ah, ok, so you have to tell the requester be reasonable, you can't build a house in 1 day

3:49 oddcully: Guest72028: you can't have a kid in 1 month with 9 wifes

3:49 Guest72028: :-)

3:50 magnars: software development is a marathon, not a sprint

3:50 Guest72028: i guess im the only one here, using git with feature branches running unit tests after new feature then merging back to develop branch

3:51 i mean only one in my company

3:51 oddcully: also i bet the most expensive part of testing right now are the poor sods that test the app before release by hand (hopefully be protocol); start with automated tests there. granted it can be hard, but at least it tests the stuff that faces customer

3:51 slipset: oddcully: wouln't mind trying though

3:52 oddcully: haha

3:52 Guest72028: oddcully: they're the typical cowboy coder, the users tests the features ,hehe

3:52 magnars: slipset: sounds exhausting ;)

3:52 if your users are doing all the testing, and they are still your customers, that might be a deliberate strategy that is currently working ;-)

3:53 Guest72028: the users have no choice, the software is enforced by the company

3:53 oddcully: sure. and management likes it because the devs can bring up new stuff every minute

3:54 Guest72028: yip

3:54 oh, looky here i have this button when i press it features magically appear

3:55 oddcully: and unless they are eastwook-level cowboys this pile of next-age-spaghetti will explode in at least a year

3:55 wook... s/wook/wood/

3:55 Guest72028: strange enough, i got a hold of the source code, they don't do oop in c++, theyre using c structs.. etc (atoi), software been running for 10 years

3:56 no inheretance, they use if statements for that

3:56 oddcully: inheritance is the root of all evil anyway

3:56 Guest72028: ok, so composition better?

3:57 magnars: separating data and functions is better :)

3:57 oddcully: (inc magnars)

3:57 lazybot: ⇒ 4

3:58 Guest72028: magnars: do you have an example?

4:01 magnars: Guest72028: wish I could come up with a brilliant example, but it is one of the core tenets of Clojure, in that "It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." - Alan J. Perlis

4:02 Guest72028: maybe i'm strange but i prefer the functional style of code

4:03 TEttinger: clojure is rather strongly opposed to defining new data structures when existing ones can be used, it's interesting

4:04 one of the few data structures that you do sorta need an external lib for are insertion-ordered collections.

4:04 $google clojure ordered collections

4:04 lazybot: [Data Structures - Clojure] http://clojure.org/data_structures

4:04 TEttinger: hm

4:04 $google clojure ordered collections flatland

4:04 lazybot: [amalloy/ordered · GitHub] https://github.com/amalloy/ordered

4:04 TEttinger: there we go

4:04 Guest72028: recently got interested with data science, incanter seems to be great tool for this

4:05 sorry for the bad grammar, my english can improve (2nd language)

4:06 TEttinger: I wouldn't have guessed, your grammar seems fine

4:08 Guest72028: ok, cool. feel free to correct if needed , hehe

4:09 i think i'd enjoy doing clojure programming as a job, don't see a market for it in our country at the moment

4:22 magnars: why is inheritence evil, just curious

4:23 ok, i see overcomplication of things

4:24 http://learnpythonthehardway.org/book/ex44.html

4:25 if clojure uses the jvm, is the limits of concurrency due to underlaying jvm, could it be as highly concurrent as say erlang?

4:27 slipset: Guest72028:what

4:27 is your country?

4:27 Guest72028: south africa

4:28 slipset: so, no clojure in south africa either :(

4:31 Guest72028: i found 3 jobs on a job searching app

4:31 dstockton: slipset: there's clojure in ZA

4:32 https://github.com/ptaoussanis wrote a load of popular libraries, is South African

4:34 oddcully: Guest72028: if inheritance is used to save you typing (as a cheap macro system) and not for reflecting the domain, this builds up bad code

4:34 Guest72028: the quote was from http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil

4:34 (and i quoted wrong ;p)

4:35 jonathanj: oh hey, more saffers ;P

4:40 Guest72028: dstockton: interesting

4:40 dstockton: i don't know about jobs, but there's definitely a community/interest

5:17 acron^: in David's enlive tutorial, he uses the following syntax: (def ^:dynamic *story-selector*

5:17 a) what is the "dynamic" metadata?

5:18 b) idiomatically, what do the asterisk' indicate?

5:20 kungi: acron^: dynamic means you can change *story-selector* through with-redefs (for example) by using clojures dynamic scoping.

5:21 acron^: the asterisk' or earmuffs are a remnant of lisp inidcating a "special variable" that's not lexically scoped.

5:22 acron^: Have a look here: https://stackoverflow.com/questions/1986961/how-is-the-var-name-naming-convention-used-in-clojure

5:22 acron^: Thanks kungi

5:22 (inc kungi)

5:22 lazybot: ⇒ 2

5:22 acron^: ;)

5:22 magnars: kungi acron^ - the idiomatic way to bind dynamic vars is with `binding`

5:24 kungi: magnars: I dont't see the difference between `binding` and `with-redefs` (just had a look at the docs)

5:26 magnars: kungi: `with-redefs` is global, `binding` is thread-local

5:26 kungi: magnars: I see thank you

5:27 Why are new bindings made in parallel? This introduced a bug in my code lately and I had to nest binding forms.

5:33 dysfun: i can't say i'm terribly impressed with cljs compile times. it's just taken 18 seconds with no optimisations to build effectively "hello, world"

5:34 Empperi: you have an issue in your compilation settings

5:34 dysfun: howso?

5:34 Empperi: I have compilation times of 0.1-0.8 secs here and this is definetly way more complex than "hello world"

5:34 a real reagent based webapp

5:35 dysfun: i'm generating a source-map. is that somehow mega slow?

5:35 Empperi: no if you have your settings correct

5:35 you're using cljsbuild plugin for leiningen I assume?

5:35 dysfun: my settings are source map, no opts

5:35 no, i'm using the boot cljs plugin

5:35 Empperi: ok

5:35 do you get one big "main.js" or gazillion smaller files?

5:36 if you get one main.js then you do have simple optimizations on which will slow down compilation considerably

5:36 with no optimizations clojurescript compilation will generate one .js file per .cljs

5:36 dysfun: i have optimisations disabled

5:37 Empperi: so you get tons of js files as on output?

5:37 dysfun: and yes, i have one js file per cljs

5:37 Empperi: then you do *not* have optimizations disabled

5:37 but you may think you have

5:37 ah fuck

5:37 sorry

5:37 misread

5:37 my bad

5:37 shit, need more coffee

5:38 dysfun: i'm looking at the generated js file

5:38 Empperi: anyway, sourcemap generation will slow it down somewhat, but those numbers I'm seeing is with sourcemaps on

5:38 dysfun: there are 4 lines of code that actually do something

5:38 it's all very human readable

5:38 Empperi: the main.js file should pretty much contain very little

5:38 with no optimizations

5:39 here we have 4 lines with fourth line being empty

5:39 it just inserts some stuff to DOM to allow google closure dependency management to kick in

5:39 and then it'll dynamically load all required js files one by one

5:40 dysfun: https://www.refheap.com/99457

5:40 Empperi: so that's your core.js I take it

5:40 dysfun: yes

5:40 Empperi: is that your output target file?

5:41 for cljs compiler

5:41 I'm guessing not

5:41 dysfun: i haven't explicitly specified one

5:42 (cljs :source-map true :optimisations :none) ;; my boot config

5:42 Empperi: this is leiningen config but... https://www.refheap.com/4e6ee2a346dfbe075c35c7417

5:42 you might want to enable :compiler-stats true and :verbose true to see what's really happening under the hood

5:43 you'll most likely end up seeing some kind of optimization happening even if you say you shouldn't have any optimizations

5:43 and oh

5:43 dysfun: optimiZations, not optimiSations

5:43 dysfun: aha

5:43 Empperi: clojurescript compiler reads :optimizations keyword

5:44 I'd guess boot plugin passes the parameters as-is to the cljs compiler like leiningen plugin does

5:44 dysfun: the one major benefit i've found of type systems is that it prevents locale-related spelling errors

5:44 Empperi: there are several others

5:44 dysfun: which is pretty niche i'll grant :)

5:44 Empperi: but then again dynamic typing gives you other perks

5:44 there is no silver bullet :)

5:45 dysfun: of course

5:45 Empperi: but I'm guessing you'll see a dramatic speedup in compile times if you change that 's' to 'z'

5:45 dysfun: it's theoretically possible to get the benefits of both, and yet it's sufficiently difficult we haven't done it yet

5:45 Empperi: of course we have

5:45 dysfun: ah, my fans are going full pelt. i must have started a jvm...

5:45 Empperi: check Google's Dart for instance

5:45 it has optional typing

5:46 pretty nice implementation of static typing on top of dynamic typing

5:46 dysfun: core.typed is a bit like that i suppose

5:46 Elapsed time: 24.063 sec

5:46 Empperi: dysfun: make a change to your file

5:47 it had to compile everything from scratch since you changed optimization level

5:47 dysfun: ah, 3.187, that's better

5:47 Empperi: which means clojure.core etc

5:47 still really slow

5:47 but better

5:47 "Successfully compiled "resources/private/generated/main.js" in 0.643 seconds."

5:47 dysfun: yeah, but it's fast enough to not make me want to give up clojurescript :)

5:47 Empperi: speed I'm seeing here

5:47 dysfun: this laptop is a bit slow

5:47 Empperi: we have something like 2k lines of clojurescript in this app

5:47 dysfun: and i have firefox running with $many tabs

5:48 it takes on a good day about 15 seconds to get to a boot repl

5:49 Empperi: geesh, you have something seriously funky going on there :D

5:49 but anyway, with this ~3 year old windows desktop I'm seeing compilation times like that

5:49 dysfun: this is a three year old macbook air

5:50 it flies when i kill firefox

5:50 Empperi: my ~year old mbp gives me similar compilation times as this desktop

5:50 kill the firefox and try to change a file then

5:50 what's the compilation time then?

5:51 dysfun: yes, of course firefox has just hung when i tried to quit it from within itself

5:51 Empperi: just kill it :)

5:51 dysfun: i did

5:51 Empperi: and if it kills your performance that bad then I'd change to Chrome

5:51 dysfun: 2.805

5:51 Empperi: not much of a difference there

5:51 strangely slow

5:52 dysfun: yes, kernel_task has spun up now

5:52 Empperi: oh well, might be air's slow I/O

5:52 dysfun: i'll wait for it to die down and report back

5:52 Empperi: but anyway, the speed I'm getting is what you're supposed to see too

5:52 and you definetly shouldn't think that kind of compilation times are normal

5:52 dysfun: and i've killed my VM too

5:52 Empperi: and dump cljs due to that

5:53 you'd regret it, I postponed getting familiar with cljs for quite some time

5:53 dysfun: oh great, spotlight is running an index too. it's not my day to actually try and compile stuff fast

5:53 Empperi: and now I've been using it for over a month

5:53 and shit I feel so stupid not going for it earlier

5:53 dysfun: well i've played with om a bit before

5:53 it's just that clojure is really fun and compiling isn't

5:54 0.992

5:54 hooray

5:54 Empperi: well, these days if you do frontend stuff you'll have some kind of compilation phase anyway

5:54 well that looks more like it :)

5:54 clojurebot: Excuse me?

5:54 dysfun: i try not to do frontend stuff for the most part

5:54 Empperi: clojurebot: you're excused

5:54 clojurebot: Cool story bro.

5:55 dysfun: and when i was doing it last, i didn't precompile css or js actually

5:55 Empperi: you can do that these days too but that's stupid way to do things :)

5:55 if you're writing raw javascript then you'll most likely have something like browserify or similar

5:55 dysfun: it's less stupid than you might think

5:55 Empperi: and css is written via less or sass

5:56 sure, if you're app is small then it's not a problem

5:56 dysfun: for example i checked out a competitor's app last year (it's open source!) and got fed up when the build process broke

5:56 Empperi: but with 10kloc and larger it gets really hairy

5:56 I've written a javascript frontend which had nearly 40kloc of javascript code

5:56 dysfun: yes, i *like* sass. i just don't care enough about the reduced code size enough

5:57 Empperi: without any kind of compilation

5:57 I tell you, that was pain :)

5:57 dysfun: however, now that boot seems to be doing a good enough job, it should be fairly easy for me to set it up and have it all managed by boot

5:57 which means no build tool hell

5:57 Empperi: happy to help

5:57 gotta do some work now :)

5:57 dysfun: frankly maintaining 40klo javascript is anybody's idea of hell

5:57 sobel: once i understood google's js closure compiler and why it's necessary, i realized the hand-written web is over

5:58 dunderproto: have any of you read Paul Graham's On Lisp?

5:58 dysfun: the hand written web has been dead for a while, but the corpse is still twitching

5:58 dunderproto: the book really piqued my interest but I wasn't sure how much of it would be applicable to clojure

5:58 sobel: sure, but let's not confuse the throes of death with viability ;)

5:59 dysfun: :)

5:59 Empperi: javascript is the new assembly

5:59 you see ppl writing raw assembly code too

5:59 :)

5:59 dysfun: dunderproto: it's been a long time since i read it. i'm happy to help you with specific questions

5:59 sobel: Empperi: yup, and there will always be people getting in deep to tweak things. i mean, someone implemented the logic gates that execute the machine code, right?

6:00 someone had to smelt the silicon and actually touch pre-hardware

6:00 dunderproto: dysfun: do you think it'd be worth reading? I was looking for a book that would teach me how to write macros for clojure. I saw some folks recommend On Lisp

6:00 sobel: (yuck!)

6:00 dysfun: dunderproto: frankly i'm a bit down on paul graham these days. and i really wouldn't recommend reading how to write macros in the wrong lisp in order to learn them in clojure

6:01 reading *about* macros in lisps, sure, but if you want to learn how to write macros, no, i wouldn't say it's a good idea

6:02 sobel: is there a koans chapter just on macros? :)

6:02 dunderproto: dysfun: ah. I appreciate the advice. Maybe I will keep looking.

6:02 dysfun: i forget which lisp graham favours. clojure macros are a bit like hygienic macros in scheme

6:02 we have different (imo better) syntax

6:03 sobel: i'm also useless at macros so far and figure i should eventually get introduced

6:03 dunderproto: Graham used common lisp I think

6:03 dysfun: yeah, common lisp macros are a bit special imo

6:04 dunderproto: dysfun: what book would you recommend for clojure?

6:04 dysfun: but hey, they look like function definitions. except your arguments are all the code between the parens instead of the values they represent

6:05 and you return some code.

6:05 book choice is highly personal. do you want a practical book or a theoretical one?

6:05 dunderproto: practical :)

6:05 dysfun: how quickly do you need to feel you've done something to keep going?

6:05 kris_: In Clojure(Script) how do I dereference an atom which is a different namespace?

6:06 dysfun: kris_: the same way? @other-ns/atom ?

6:06 dunderproto: I have a lot of patience

6:07 slipset: dunderproto: why do you want to learn how to write macros?

6:07 dysfun: in that case, have a look at one of the o'reilly's. i think there's a roughly 50/50 split on preference. read up about them both

6:07 slipset: It seems to me that the clojure community favors data over functions over macros

6:07 dunderproto: dysfun: thanks, will check it out

6:08 I was mostly drawn to lisps because of PG's essay about "beating the averages"

6:08 dysfun: slipset: well it's more about not using a hammer to crack a nut

6:08 slipset: the further down the chain you go, the more you lose in terms of composability

6:08 so "if you can do without a macro, do" is a good guideline

6:08 dunderproto: but yeah, I do understand that some of the techniques may not be as ideal or idiomatic for clojure

6:08 slipset: dunderproto: same thing for me, but I've yet to figure out the macros are great thingy

6:09 dysfun: macros are pretty great

6:09 oddcully: dysfun: that's how i usually do it. well last time i used a big skrewdriver for the chestnuts

6:09 Empperi: "the first rule of macro-club is that you don't write macros"

6:09 slipset: But I can see that in 1995, when there was little support for web programming, you could probably do a lot with macros to help that situation

6:10 dysfun: for example, how many times have you been tidying up code and thought "i wish i could generate the try/catch" ?

6:10 Empperi: "the second rule of macro-club is you'll still avoid writing that macro"

6:10 ddellacosta: dunderproto, if you're not familiar with macros and want to learn how to write them in Clojure, take a look at the chapters in Clojure Programming and Joy of Clojure

6:10 Empperi: "the third rule of macro-club is you should write that macro since you got this far in the rules"

6:10 kris_: @dysfun thanks, I was doing other-ns/atom (no @)

6:10 slipset: Empperi: sounds like Knuths optimization rules.

6:10 dysfun: i see macros largely as "the last stage of boilerplate removal"

6:10 Empperi: pretty much

6:10 macros give you insane power but they come with a cost

6:10 dunderproto: thanks dysfun and everyone else

6:11 dysfun: but you know what the real thing is?

6:11 slipset: dunderproto also remember, you cannot pass macros around

6:11 dysfun: it's that you're writing programs that read and write programs. and it's not that hard

6:11 slipset: (map some-macro myvec) will not work

6:11 dysfun: i can write a macro without a second thought to do what i need because it's easy when you've done it for a while

6:11 Empperi: there are some clojure.core macros which are macros for a good reason and still they bite me in my arse time to time

6:12 my favourite two are 'and' and 'or' macros

6:12 dysfun: anyone who's ever written macros for a non-lisp will know what i mean here

6:12 Empperi: wish I could sometimes do: (apply and list-of-predicates)

6:13 but you can't

6:13 not with 'and'

6:13 dysfun: however, every-pred does that

6:13 Empperi: yes

6:13 there are other cases too though

6:14 but anyway, a good example of one of the prices to be paid when you go the macro-way

6:14 dysfun: you should go read up about f-expressions. slightly different than macros, but pretty equivalent

6:14 and yes, not being able to use macros in higher order stuff is a bit of a pain

6:15 slipset: But back to Graham, I still fail to see how my writing macros make my life so much easier.

6:16 I can see the value of eg the go-macro, but it would not be for me to write.

6:17 And so, to me the go-macro could just as well be a feature of the compiler

6:17 I can also see that as a designer of libraries, macros can be nice, but I'm just a lowly consumer of such.

6:19 dysfun: well for example, i've got a simple macro 'safely' that wraps something in a try/catch

6:19 it's just a nice little touch to tidy it up

6:20 Empperi: I use macros especially with tests

6:20 (with-clear-database ....) etc

6:23 dysfun: right, now to see how well boot-reload works with a custom ring handler

6:23 sobel: so, how long until i'm one learning all the basic functions like every-pred?

6:24 dysfun: never?

6:24 sobel: one=done

6:24 dysfun: keep https://clojure.org/cheatsheet/ open in a tab

6:24 sobel: fair

6:24 it's already up

6:24 hadda ask

6:24 dysfun: :)

6:25 it's quite pleasing when you realise you have a useful working set of them in memory

6:36 sobel: i'm close but i still write more code than i have to, just because i don't always have the right ones yet

6:37 stian: it's a lisp, there will always exist a shorter way of expressing your forms - no matter your level ;)

6:40 TEttinger: yep

6:41 I can still probably code-golf some of my one-liners further

6:41 but clojure is an amazingly good language for code golf

6:47 dysfun: yes, except that unlike golfing e.g. perl, your code tends to become cleaner because golfing is more about figuring out how to do the same thing with better use of builtins

6:52 TEttinger: dysfun, excuse me, but my golf game must be on another level, since my clojure golf code starts out getting more readable and then gets much, much less readable once I start treating strings as sequences of chars and other useful but confusing tricks

6:52 :)

6:56 ,(map partition [1 2 3] (repeat "The Quick Brown Fox"))

6:56 clojurebot: (((\T) (\h) (\e) (\space) (\Q) ...) ((\T \h) (\e \space) (\Q \u) (\i \c) (\k \space) ...) ((\T \h \e) (\space \Q \u) (\i \c \k) (\space \B \r) (\o \w \n) ...))

6:56 dysfun: your output is unreadable, but that's a different thing :)

6:56 TEttinger: heehee

6:57 still, clojure is loaded with really handy features for golf that turn out to be useful in many more cases

6:57 dysfun: heh

6:57 Foxboron: o20aføsldkfjsadx20

6:57 wops

6:57 TEttinger: though I doubt myself that golf is an intended goal, some other lisp users have suggested that

6:58 dysfun: Foxboron: you might want to change that ;)

6:58 TEttinger: Foxboron, especially since this channel is publically logged

6:58 Foxboron: Not a password actually

6:58 me typing randomly as irssi hung up a few sec

6:59 TEttinger: haha

6:59 stian: or just golfing :)

7:00 dysfun: i think he missed if that was golf :)

7:00 oddcully: i find codegolfing a good way to actually learn about all that fancy functions

7:15 borkdude: I have a problem that I would like to discuss. I have a form with a rich text editing field in which users can upload pictures. I want to use a uuid to keep track of which form post the pictures belong to. The pictures are posted before the form. Is this a good approach?

7:15 dysfun: it's not an unreasonable approach. why uuids though?

7:16 borkdude: dysfun because I need some identifier

7:16 dysfun: you can create one of those by obtaining the next sequence id for the post

7:16 or by inserting a partial record with some flag

7:18 borkdude: dysfun the first option: this can pose a race condition. the second option seems ok to me, but more complex than using a uuid, because I won't have to clean up records if users decide not to finish their submission

7:18 dysfun: actually, you're going to have to clean out the images table

7:19 borkdude: dysfun true

7:20 dysfun: there are merits to both approaches

7:20 i'm not going to pretend to know more about your code than you :)

7:21 borkdude: dysfun well, I bet I'm not the first dealing with this specific problem :) Maybe other just upload the pictures and leave them lingering without even touching upon this problem?

7:21 dysfun: i expect in most cases they insert a partial record and then never clean up

7:22 borkdude: ok

7:25 mavbozo: borkdude, that's a good idea. btw, what db do you use?

7:25 borkdude: mavbozo mysql (legacy choice)

7:26 mavbozo: borkdude, and the uuid is just a standard uuid without indexing on the table?

7:26 borkdude: mavbozo yeah

7:27 mavbozo: borkdude, don't you a little a bit worried about the query performance?

7:27 zot: i'm trying to use a cljx-based project and run lein install to test the jar locally with another package, but the actual source files never make it into the jar. project file is here: https://github.com/benfleis/datascript/blob/feature/clojure-port-v2/project.clj . anybody see where i'm going wrong?

7:28 borkdude: mavbozo well, the uuid is just to prevent garbage. For example I could check if there are pictures with an unknown uuid on S3 and clean then. in the database I use an integer id also.

7:28 mavbozo in other words, there won't be a query using the uuid

7:29 zot: and at the moment, i don't even care whether the cljs makes it in, just the clj would be enough

7:30 acron^: I have an atom set, which holds hashmaps. Is there any way for me to alter a single hashmap in the set without swap! disj, swap! conj combo ?

7:32 zot: acron^: you mean you have sth like (atom #{ { … } { … } })? if so, how do you match elements of the set? (or is it a sorted set and you do some range matching or sth?)

7:32 acron^: zot: each hm has an :id

7:33 mavbozo: borkdude, well, for once then, i thought you use uuid as primary key, or index on the table.

7:33 acron^: (atom #{ { :id 4 … } { :id 6 … } etc })

7:33 it's not sorted, the ids are uids

7:33 zot: acron^: in your shoes i would mod it to be hm -> hm, with the id being the key, and do swap! update-in … (or assoc-in …)

7:34 borkdude: mavbozo well no. I would generate a uuid client side. Upload pictures in the rich text editor with the uuid as an extra parameter to keep track. The pictures would end up on S3. Then the user submits the form. The uuid is just an extra field, so I know which picture belongs to which form post.

7:34 zot: unreferrable data inside the atom just sounds needlessly tricky to me

7:34 borkdude: Another option is just to analyse the html and generate a list of used and unused pictures.

7:34 zot: err, un-path-map-able

7:34 acron^: so you mean i shouldn't use a set?

7:35 zot: meaning that there's no obvious sequence of keys that tells you what's what. even a vector would be an improvement, where you could do update-in with the vector index.

7:35 acron^: imho

7:35 if you're updating those things, are you expecting it to keep uniqueness for you as you make changes? that would be the only reason i can imagine, but that sounds unlikely to me

7:37 acron^: ok, i am a novice clojure users so my motive for using a set is flaky

7:37 lets say I change it to vec

7:38 dysfun: borkdude: there's another option. you could embed the image directly in the html with src="data://"

7:38 acron^: is there still no better way than removing and re-adding an element to the atom? (swap! disj, swap! conj)

7:38 dysfun: then when the user posts it, strip them out and save them properly

7:39 oddcully: swap! #(conj (disj %)) ish

7:40 acron^: :o

7:41 zot: acron^: if your structure looks like [ {:k1 1, :k2 2}, {:k3 3, :k4 4} ], (swap! <thing> assoc-in [0 k3] 1000) will work

7:41 oops, s/0/1/

7:41 for the array index

7:41 although in my example k3 would be added to the 0th element with a new val of 1000

7:42 using 1 would update k3 in the second

7:42 acron^: zot

7:42 that's perfect, thank you

7:43 (inc zot)

7:43 lazybot: ⇒ 1

7:43 zot: yw

7:43 oddcully: ,(doc replace) maybe then

7:43 clojurebot: "([smap] [smap coll]); Given a map of replacement pairs and a vector/collection, returns a vector/seq with any elements = a key in smap replaced with the corresponding val in smap. Returns a transducer when no collection is provided."

7:46 oddcully: ,(into #{} (replace {{:id 1} {:id 42}} #{{:id 1}}))

7:46 clojurebot: #{{:id 42}}

8:06 hellofunk: anyone have first-hand experience with the first and second editions of Joy of Clojure and can comment on the significance of their differences?

8:33 nicferrier: if I use a gensym in a macro it's compiled to the evaled name right?

8:33 it won't gensym in the byte code... it'll be the name.

8:33 I've written a macro to wrap a function in a child process

8:34 so it starts the process and then calls the function that you specify in the child process.

8:34 justin_smith: nicferrier: like future but in a new vm?

8:34 nicferrier: it does that by calling the same clojure program you are running ... but with an argument.

8:34 yeah. similar.

8:34 it's just to protect code that crashes.

8:35 you could use a bash while loop... but trust me... there are reasons why not.

8:35 it's just the basic supervisor pattern

8:35 justin_smith: I'm all too familiar with craziness from bash while loops

8:35 nicferrier: anyway, I'm using a gensym for this arg

8:35 justin_smith: well, it's more the organization I'm in. but anyway.

8:36 and it appears the gensym is different on either side of the child process.

8:36 justin_smith: gensym is not deterministic

8:36 blashyrk: hi! is there a way to do something like a "case-let" ? in terms of regular java it would be some thing like int x; if(something) x = someFunction() else x = someOtherFunction();

8:36 justin_smith: ,(gensym "hello")

8:36 clojurebot: hello27

8:36 justin_smith: ,(gensym "hello")

8:36 clojurebot: hello52

8:36 justin_smith: ,(gensym "hello")

8:36 clojurebot: hello77

8:37 nicferrier: justin_smith: yeah. but surely if I make a macro with the gensym it'll be gen'd at compile time and the gen'd value will be used in the bytecode?

8:37 justin_smith: blashyrk: ##(let [a (if (> (rand) 0.49) 42 :else)] a)

8:37 lazybot: ⇒ :else

8:39 justin_smith: nicferrier: I'm less sure of that

8:39 blashyrk: @justin_smith I know I could do it that way I was just checking if there was a shorter way, macro or something. thanks :)

8:39 nicferrier: justin_smith: yy. it's tricky enough at the best of times.

8:39 justin_smith: blashyrk: I can't think of anything that would be more concise than if

8:40 blashyrk: something like

8:40 (case-let [foo condition set-if-true set-if-false])

8:41 it's not that big of a deal really, I am just constantly trying to learn the tricks and was wondering if something like this was implemented

8:41 justin_smith: (let [foo (if condition set-if-true set-if-false)]) has exactly the same character count

8:41 it's literally the same number of symbols

8:42 blashyrk: but if you really want that syntax, it would be a relatively easy macro to write

9:44 hellofunk: anyone have first-hand experience with the first and second editions of Joy of Clojure and can comment on the significance of their differences?

9:49 not-much-io: Has anyone had indentation problems with Clojure in the graphical variant of emacs? (24.4.1) It *displays* that the indentation is off although opening in emacs in the terminal or another text editors shows the indentation is correct.

9:51 f3ew: not-much-io: tabs vs spaces?

9:53 borkdude: nice that this works: (assoc nil :foo "bar") ;;=> {:foo "bar"}

9:53 clojure is so forgiving

9:54 mavbozo: ,(get get get get)

9:54 clojurebot: #object[clojure.core$get "clojure.core$get@bb699c8"]

9:54 not-much-io: f3ew: I've never understood the tabs vs. spaces debate, I've used tabs. In the recent Stackoverflow survey there was a almost 50/50 split... What's the deal? Some press tab others click space multiple times?? :D

9:55 nicferrier: not-much-io: no. their editors press space multiple times.

9:55 justin_smith: not-much-io: sounds like you have a bad default font (maybe not a fixed width)

9:55 nicferrier: not-much-io: tabs are "bad" because you can vary what the tab is and that might change how the file looks.

9:56 not-much-io: justin_smith: the font is the same in both the terminal and GUI

9:56 mavbozo: ,(get get nil get)

9:56 clojurebot: #object[clojure.core$get "clojure.core$get@bb699c8"]

9:56 justin_smith: ,(get (gensym) (gensym) 42)

9:56 clojurebot: 42

9:56 not-much-io: nicferrier: If their editors press space for them, then how many times it presses can also vary right?

9:57 justin_smith: not-much-io: the difference is varying on creation vs. varying on display

9:57 when it varies on creation, the author can fix any errors

9:57 when it varies on display, the author just looks like they are incompetent because the indentation is broken

9:58 mavbozo: ,(get nil nil 42)

9:58 clojurebot: 42

9:58 nicferrier: but some people say "but then I can adjust the indentation"

9:58 justin_smith: clearly we need code editors with css support

9:58 not-much-io: justin_smith: Ahso, okei, well that makes sense. I have to re-evaluate my life now. Spaces it should be then?

9:58 mavbozo: wait til you see clojure's java source code

9:58 nicferrier: not-much-io it really should, yes.

9:59 not-much-io: Is there some easy step to switch from tab to space in emacs or should I just start googling?

9:59 tomjack: https://books.google.com/books?id=n8AOBwAAQBAJ

9:59 kind of frightening

9:59 justin_smith: not-much-io: untabify-region

10:00 tomjack: yuck

10:00 tomjack: that look-inside is so terrible

10:01 oddcully: is it me not allowing google executing javascript or is this just MD-ish code printed as book?

10:01 justin_smith: tomjack: and the authors who make crap books like that do review spam too

10:01 to make the books look popular

10:02 tomjack: :(

10:02 justin_smith: oddcully: MD-ish?

10:02 tomjack: maybe before long the books will actually be valuable

10:02 justin_smith: oddcully: it's a terribe book, probably written by a crappy mail-merge macro in microsoft word

10:02 oddcully: section 3 -> `* Groovy (programming language)|Groovy`

10:02 justin_smith: yeah

10:03 macro-generated

10:03 put on the store in the hopes they can trick someone into buying it

10:03 I bet every single book they publish uses the same stupid template

10:03 oddcully: should have used TeX ;P

10:03 borkdude: is this an autogenerated bok?

10:03 *book

10:03 justin_smith: yeah - it's a whole genre of crap

10:03 not-much-io: justin_smith: I think it might have fixed it but, configuring the space to indent like tab did?

10:03 oddcully: section 4 -> headline on page end

10:03 borkdude: it indeed looks like crap

10:04 oddcully: that looks like what my firefox generates when i generate a pdf

10:04 justin_smith: they generate books, make it look like something that might be valuable, and hope someone buys it. They use sockpuppet accounts to make fake reviews to make the books look popular.

10:04 huge scam

10:04 I mean, if it was just a formatting issue, you would find some content in the book

10:05 but no, it's not just badly formatted, it has no useful information

10:05 there are literally people who generate books with markov chains, then combine randomized keywords to generate a title

10:06 there's no cost to publishing the stuff, and if anyone is stupid enough to buy, jackpot

10:06 tomjack: sorry, hope I didn't ruin your morning :)

10:06 justin_smith: haha no, I'm sorry for the rant

10:06 I just really hate people that do that

10:06 oddcully: rant away

10:07 clears the system

10:10 tomjack: I found the book in my search for a solution to this hilarious problem: https://www.refheap.com/2ab934158d7df2615f7bdf6fb

10:10 oddcully: did it help?

10:11 tomjack: (org.eclipse.jdt.core)

10:11 justin_smith: tomjack: wait, is that a thing that actually works?

10:11 tomjack: why on earth would someone make a .java -> AST library where the AST nodes print _as .java source_??

10:11 lazybot: tomjack: Uh, no. Why would you even ask?

10:11 justin_smith: oh yeah, eclipse basically has its own java parser, huh

10:11 tomjack: java brain poisoning I guess

10:11 justin_smith: haha

10:12 but you can still access the ast data, right?

10:12 tomjack: yeah, but I have to apparently write a library which converts their AST into data, which just makes me "ugh"

10:14 justin_smith: tomjack: just because the printed form is java source doesn't neccessarily make the data harder to access though does it?

10:14 tomjack: AFAICT it means you have to go to the javadoc or inspector to see what's available, instead of just printing

10:15 justin_smith: tomjack: but most printed forms for java objects are totally useless

10:15 tomjack: yes, I guess I should not be surprised :(

10:29 not-much-io: I am confused with how to switch from using tabs to using spaces in Emacs. From here -> http://emacsblog.org/2007/09/30/quick-tip-spaces-instead-of-tabs/ It says just use '(setq-default indent-tabs-mode nil) but for me tabs keeps working and space is still a single space. Is there no easy way to pretty much keep using space just let it use spaces?

10:29 keep using the tab button *

10:30 dysfun: is there a clojurescript equivalent of http://www.clojure-toolbox.com/ yet?

10:35 justin_smith: not-much-io: after you do that, the tab key should insert multiple spaces

10:35 as apropriate for your mode's indentation

10:36 not-much-io: something very helpful is M-x whitespace-mode

10:37 not-much-io: justin_smith: That is very helpful, I now see that thespaces in the GUI emacs are shorter than the spacen in the CLI

10:38 justin_smith: yeah, like I was saying, proportional font

10:38 even in a terminal, a proportional font will display as fixed-width, it's a limitation of the CLI

10:40 not-much-io: justin_smith: If I look really close, they might really be different, but really similar. Alright thanks, I'll experiment with the font.

10:40 Have I understood correctly that if someone helps you out you '(inc that-user) for clojurebot? :)

10:41 justin_smith: without the quote, and it's lazybot that does it

10:41 but yeah

10:41 not-much-io: I quoted to not trigger the inc :D

10:41 (inc justin_smith)

10:41 lazybot: ⇒ 237

11:34 tomjack: ,(:foo #{:foo}) ; whoa

11:34 clojurebot: :foo

11:38 calvinfroedge: Can anyone tell me if something like this is possible? (defn foo [a & [b c :as args & d]](prn d))

11:39 I want to bind b and c to :args, but also have d

11:45 mavbozo: ,(defn foo [a & [b c :as args & d]](prn d))

11:45 clojurebot: #error{:cause "Unable to resolve symbol: d in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: d in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: d in this context", :at [clojure.lang.Ut...

11:47 calvinfroedge: mavbozo: See = ) Great mystery.

11:49 justin_smith: ,(defn foo [a & rst] (let [[a b & d] rst args [a b]] d)

11:49 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

11:50 justin_smith: ,(defn foo [a & rst] (let [[b c & d] rst args [b c]] {:a a :b b :c c :args args :rst rst}))

11:50 clojurebot: #'sandbox/foo

11:50 justin_smith: ,(foo (range 10))

11:50 clojurebot: {:a (0 1 2 3 4 ...), :b nil, :c nil, :args [nil nil], :rst nil}

11:50 justin_smith: ,(apply foo (range 10))

11:50 clojurebot: {:a 0, :b 1, :c 2, :args [1 2], :rst (1 2 3 4 5 ...)}

11:52 calvinfroedge: justin_smith: Nice work! Thanks a lot.

12:17 borkdude: ordnungswidrig I'm using :handle-request-entity-too-large (fn [ctx] {:error "My error"}) and I get this error: No method in multimethod 'render-map-generic' for dispatch value: null. What could it be?

12:19 ordnungswidrig I'm reading this https://github.com/clojure-liberator/liberator/issues/94

12:40 favetelinguis: what am i not understanding with features: http://lpaste.net/130495 why is this code not printing anything 4sec?

12:40 futures that is :)

12:48 justin_smith: favetelinguis: "I will print after 4 sec" is not a function

12:48 favetelinguis: if you deref the future, you'll see the exception thrown

12:48 favetelinguis: hehe i saw it now, thanks

13:27 does core.reducers support trancducers? if not will they in the future?

13:48 zanes: Is there any reason why `(go (<! (async/timeout 1000)))` should behave differently than merely `(async/timeout 1000)`?

13:53 whodidthis: not sure if im using splice correctly but if i run #?@(:clj [(def a 1) (def b 2)]) how come only a gets defined

13:54 Bruce_Wayne: does anyone know how to render a link in reagent?

13:56 Bronsa: whodidthis: wrap it in a (do)

14:00 dnolen: zanes: those those don't mean the same things

14:01 zanes: dnolen: Sorry, (<!! (async/timeout 1000)) and (<!! (go (<! (async/timeout 1000))).

14:02 dnolen: zanes: what do you mean by "behave differently" then?

14:03 zanes: Yeah, let me get you a more complete example.

14:07 dnolen: False alarm.

14:08 I’m writing a test and one of the go blocks was using Thread/sleep.

14:16 I thought the test was deadlocking with `(<!! (go (timeout…` and not with `(<!! (timeout`, but I was wrong.

14:19 ncthom91: hi all. When I use a `go` block in the middle of my function body, does the go block execute in a separate thread while the execution of the remainder of my function continues?

14:19 or does the remainder of my function wait for that go-block to finish

14:19 I think it's probably the former, yea? Cause the go block immediately returns a channel

14:22 zanes: ncthom91: The former.

14:22 ncthom91: zanes cool, thanks

14:22 zanes: If you want to block until it’s finished you can call `<!!` on the channel returned by `go`.

14:23 ncthom91: zanes i took a slightly similar, but essentially equivalent (i think?), approach by removing the (go) block and changing my >! call inside the go block to a >!!

14:23 zanes: Yeah, that works!

14:24 saik0: having some trouble improrting clojure.data.priority-map https://gist.github.com/anonymous/cc6ffaa0c58442890f95

14:24 ncthom91: sweet. zanes my other question is, this function itself actually runs inside a go block from the calling function, so all of this happens in a separate thread right?

14:25 zanes: ncthom91: So, like, `(f (go ((fn [] (>!! c :thing)))))`?

14:25 Something like that?

14:25 ncthom91: Well I have a function `update` and inside update I make my >!! call

14:26 But `update` gets called from a different function with (go (update x y))

14:26 zanes: But regardless: Yes. If a function calls another function inside a go block the called function is executing in one of the go threads.

14:26 Yes, totally. That’s happening in one of the go threads.

14:26 ncthom91: sweet.

14:26 What happens if my `update` function does IO?

14:27 in terms of what code runs in what threads?

14:35 mavbozo: saik0, priority-map function call should've been (clojure.data.priority-map/priority-map :a 1 :b 2)

14:36 saik0: mavbozo ah, got it. thanks

14:38 mavbozo: saik0, because the namespace is too long, you might want to alias it (:require [clojure.data.priority-map :as pm])

14:38 saik0, might help the eye spotting what's wrong

15:09 lemonodor: if you’re into gorilla (or planespotting), this has been a fun worksheet I’ve been working on: http://viewer.gorilla-repl.org/view.html?source=github&user=wiseman&repo=orbital-detector&path=stats.cljw

15:17 kwladyka: what is the right architecture in functional language like clojure? i am talking about things like MVC, Enitity, Boundary, Interactor etc. What is the right way to separate UI, use cases and DB? How to do that right in Clojure?

15:19 It will be greate if somebody can give some real example of project like web app where the UI is undepended code, and the core is the core, and DB is independed, easy to change.

15:19 pbx: kwladyka, what do you mean by "undepended" and "independed"?

15:20 (not that i have an example handy)

15:20 ecelis: kwladyka: check luminus

15:21 http://www.luminusweb.net/

15:21 there is no such thing as "right way"

15:22 aaelony: how does luminus facilitate transfer of dat structures from clojure to clojurescript?

15:22 kwladyka: pbx, sorry, it should be "independent"

15:24 mavbozo: kwladyka, see http://modularity.org/index.html. malcolm sparks is in the process of writing a book which i think would be a good answer to your question. It's still a draft for now but there are some ready-made leiningen templates.

15:24 kwladyka: ecelis hmm so another quesion is: should use web framework in Clojure or just ring+compojure? What more gives thing like luminus? I am sorry about that question but i am learning Clojure and it is my first functional language, so i am confuse sometimes.

15:26 mavbozo thx

15:27 mavbozo: kwladyka, you wrote Interactor, that's interesting choice of term. Where did you know about that term?

15:27 kwladyka, i only heard it from uncle bob videos

15:27 kwladyka: mavbozo clean code, episode 07 about architecture

15:27 :)

15:29 i feel how i am doing this now it is bad... and i am looking solution everywhere... and the worst thing i don't understand how to write in functional language yet. but i am pretty sure how i did this in OOP it was bad and i never liked that :)

15:29 i feel myself all should be divded as much as possible

15:29 mavbozo: kwladyka, ah, so you have previous experience building webapps. If that's the case, then I recommend you to dive straight in making website in clojure.

15:30 kwladyka: the on thing is use for example AngularJS, Clojure to write backend, and DB. It is good step. But... how to do that without AngularJS? I am not sure how to do right architecture then.

15:30 mavbozo: kwladyka, yogthos's book Web Development in clojure will guide you https://pragprog.com/book/dswdcloj/web-development-with-clojure

15:33 kwladyka: Adding things liek AngularJS makes this easier, because i have separated UI in natural way and i can communicate by JSON. But how to do that if i will use static pages?

15:33 this book will answer for that question?

15:34 and even if i use AngularJS or static pages... details about core are important too.... is there any conception like MVC, but for functional language?

15:35 mavbozo: kwladyka, the book will help you get real experience creating websites in clojure. besides, the book starts with a familiar MVC pattern.

15:36 kwladyka: mmm but i feel MVC is really bad way to do projects. I need solution for architecture now, not how to use tools in Clojure.

15:36 mavbozo: kwladyka, i think it helps having some practical coding with clojure first before continuing on with answering your question

15:37 kwladyka: i will start do some web app anyway to learn, this process of learning is obviously. But i am not sure how to learn creating of good architecture.

15:38 my main think is: architecture should be true image of business model, easy to read, easy to write, extermly elastic - it has to be done in some way.

15:38 especially with Clojure :)

15:41 mavbozo: kwladyka, there are good books-- https://leanpub.com/building-a-system-in-clojure and this https://pragprog.com/book/vmclojeco/clojure-applied, and video presentations to help you answer your question about architecture in clojure application such as

15:41 web application

15:41 bacon1989: I've been meaning to grab that book

15:41 kwladyka: thx, added to read :)

15:41 mavbozo: or business model

15:41 bacon1989: but I like physical books :(

15:41 mavbozo: but i don't think it's not for clojure beginners

15:42 bacon1989: do you know if it's coming out to paperback anytime soon?

15:42 mavbozo double negative

15:42 mavbozo: correction, i think it's not for clojure beginners

15:42 bacon1989: ;)

15:44 kwladyka: mavbozo there is only one way to not be beginner, i has to read things like that and try to understand :)

15:44 mavbozo: kwladyka, i still think you learn creating good architecture by studying -> doing -> review -> discuss

15:44 bacon1989: ah, the paperback release is at the end of the year

15:44 mavbozo: kwladyka, you discuss it here

15:44 bacon1989: I might get it

15:45 kwladyka: mavbozo yes but i don't want research whole wheel again.

15:47 ecelis: kwladyka: luminus includes bootstrap for the front end, but its my guess it can be easily changed to use angular

15:47 or any other front end framework for that matter

15:48 but you can also choose to use bare compojure or ring, it depends on your needs really

15:48 kwladyka: ok so another question is: what should use for web apps? In the Internet it is a lof of informations but out of date. Use rings+compojure? Or lumius or something else? Mayby right question should looks: when use which one? Example if i want write e-store app as independent core and connect with that web intefrace or mayby later even mobile phone interface. Which tools should i use?

15:48 ecelis: kwladyka: try yourself, there is no absolute answer of what tools to use

15:49 bacon1989: kwladyka: most people use compojure+ring

15:49 ecelis: it depends on programmers needs, taste, background, etc

15:49 weavejes_: kwladyka: Luminus is a project template, rather than a framework in the same sense of Rails or Django.

15:50 saik0: i have a collection of infite seqs, I'd like to "make" str print something like '((first seq) "LazySeq@xxxxxx"), it would be handy for experimenting.

15:50 kwladyka: weavejes_ what do you mean "project template"? I should understand that like get other libraries as dependency but zero lumius code?

15:51 mavbozo: kwladyka, starts with instructions from yogthos's book web development with clojure. It makes you focus building your web app quickly without overwhelmed by various ways and toolings in clojure.

15:51 kwladyka, and then you can review it based on your previous knowledge about building good architecture.

15:51 kwladyka: mavbozo but tools are very important, i don't really want miss that

15:51 weavejes_: kwladyka: If you run "lein new luminus foo", then Luminus will generate a new project for you called "foo". It'll include a number of dependencies, such as Compojure and Ring.

15:52 kwladyka: i want do this in 80% or something like that and later finish that research :)

15:52 mavbozo: kwladyka, we can not hope to understand everything in this world.

15:52 kwladyka, if you want to learn good architecture, then focus on that.

15:54 kwladyka: just i have to start with something, so i am doing quick research about tools and architecture to decide which tools i will use first and in what way :)

15:54 weavejes_: kwladyka: Luminus is essentially a way of getting started. It's not really a framework, since it doesn't include its own code in the template, as far as I'm aware.

15:54 mavbozo: kwladyka, agree with weavejes_

15:55 kwladyka, luminus is a good way to start

15:56 kwladyka: i did lein new luminus foo and looking on code now :)

15:56 mavbozo: kwladyka, great!

15:56 kwladyka: is ther more tool wich i should be interested in?

15:57 ecelis: besides leiningen and your text editor, I don't think you need any other tool :)

15:57 mavbozo: kwladyka, git as scm and heroku to deploy your webapp

15:59 kwladyka: Do you think Light Table is good? Or is it not ready yet?

15:59 mavbozo: kwladyka, Light Table is good for clojure beginners

16:00 kwladyka: mavbozo but not for clojure pro?

16:00 justin_smith: kwladyka: it has some cool features that can definitely help you figure out clojure, but eventually most people move to a more normal editor or ide

16:00 kwladyka: no reason not to try it

16:01 mavbozo: kwladyka, Light Table is used as editor in yogthos's instructions in web development with clojure

16:02 kwladyka, i dont' want you get distracted from your architecture focus

16:03 kwladyka: mavbozo yes, anyway i think i will use light table for a while, becuase too many things too learn

16:04 bacon1989: kwladyka: no no no, you should jump right into emacs

16:04 mavbozo: and ends up studying emacs architecture instead

16:04 arohner: bwhaha! leinception! https://github.com/arohner/lein-docker#lein

16:05 kwladyka: ok, i checked how luminus build start architecture but still i don't have answer about how to build architecture to be image of business model, not technical separation. I think it is really hard issue :)

16:05 mavbozo: kwladyka, try put all your business model code in separate namespaces first.

16:06 kwladyka: mavbozo i will try but... it will be glad to see how sombody did this

16:06 from my live experience it is always better to first look how other did things :)

16:15 ok, i am tired today, its time to a little rest and play bloodborne game :) thank you for your time and see you later! :)

16:17 dfinninger: Gah, 2 hours left until I can get back to Bloodborne!

16:21 bacon1989: is bloodborne like dark souls?

16:21 I don't know anything about that franchise

16:29 already i'm enjoying this applied clojure book

16:29 I didn't know about the map->record function

16:30 it was kind of why I shyed away from using records that were more than 3-4 parameters

16:57 brainproxy: any examples of a (relatively) simple transducer stack that terminates early via (reduced ...)

17:00 dfinninger: bacon1989: yup, basically a more action-heavy dark souls

17:12 sidhartha: anyone have a nice clojure based web user registration and cookie system they'd like to share knowledge about ?

17:17 ya know.. i'm looking at mozillas' persona ...

18:11 danielglauser: In Emacs I have a handy piece that highlights an expr when I'm on the open or close of it. Works for (, [, {, etc. Is there anything similar in Intellij/Cursive land?

18:13 cfleming: danielglauser: You mean it highlights the whole expr?

18:13 danielglauser: Yes

18:14 cfleming: danielglauser: Cursive will highlight the matching paren, and show the extent in the left gutter, but I don't think there's anything that will highlight the expr. Could you file an issue for that?

18:15 danielglauser: I've actually been considering something similar for if forms, that would highlight the then and else clauses slightly differently, perhaps in subtle green/red

18:16 danielglauser: cfleming: Funny you mention that, this question was born out of that complaint, folks would like an easier way to see the else part of an if

18:16 cfleming: danielglauser: Which I'm hoping will catch some of my stupid "used when instead of if" bugs

18:16 danielglauser: Oh nice

18:16 danielglauser: cfleming: Link to place to file an issue? Google is not my friend.

18:17 cfleming: danielglauser: https://github.com/cursiveclojure/cursive/issues

18:17 danielglauser: Oh cool, it's on Github. Sweet.

18:17 cfleming: danielglauser: Just the issues, not the source, sorry

18:17 danielglauser: Got it

18:19 cfleming: Some of the source will be up there sometime soon when I get the extension API out there

18:28 danielglauser: Thanks

18:29 danielglauser: cfleming: np

18:29 cfleming: danielglauser: Nice github profile pic too :)

18:30 danielglauser: Thanks! Back when California still had water in it.

18:30 cfleming: Hehe

18:31 I'm in New Zealand, kayaking is pretty huge here - I did some white water stuff a long time ago, but nothing like that

18:33 danielglauser: cfleming: Well, it has been a while since I've done drops like that. New Zealand is awesome for paddling, I've seem some great footage from there.

18:38 cfleming: danielglauser: Yeah, lots of nice spots. Lots of sea kayaking around where I am.

18:39 danielglauser: cfleming: Nice! I'm sure hiredman would enjoy that too.

18:55 wei: what’s an idiomatic way to update one element in a vector into two elements? e.g. [1 2 3 4 5] => [1 2 :a :b 4 5]

18:55 (flatten (assoc-in [1 2 3 4 5] [2] [:a :b])) is one solution, but I’d rather not use flatten

18:58 TimMc: I think a general-purpose splice fn (as in JS) is called-for.

19:07 rukor: hi, pls how can one disable source maps for advanced compilation

19:14 dnolen: rukor: source maps are not enabled by default for advance compilation, also there is a :clojurescript channel

19:14 er #clojurescript channel

19:16 justin_smith: wei: ##(mapcat (fn [[i x]] (if (= i 2) [:a :b] [x])) (map-indexed list [1 2 3 4 5]))

19:16 lazybot: ⇒ (1 2 :a :b 4 5)

19:16 justin_smith: wei: with a helper function or maybe a macro that can be made a bit more comprehensible, of course

19:17 maybe this is better ## (mapcat (fn [i x] (if (= i 2) [:a :b] [x])) (range) [1 2 3 4 5])

19:17 lazybot: ⇒ (1 2 :a :b 4 5)

19:19 rukor: dnolen: thanks, i actually thought i was typing in #clojurescript

19:20 wei: ##((fn [i x coll] (concat (take i coll) x (drop (inc i) coll))) 2 [:a :b] [1 2 3 4 5])

19:20 lazybot: ⇒ (1 2 :a :b 4 5)

21:30 Lewix: whats the meaning of seq can be infinite?

21:32 justin_smith: Lewix: a lazy-seq is represented so that you don't realize all the items, you just have a function that you know will get the next item

21:32 so for example iterate returns a seq that doesn't end

21:32 or cycle

21:33 ,(nth (cycle [1 2 3]) 1000000)

21:33 clojurebot: 2

21:33 Lewix: justin_smith: If I understand correctly seq that are operations such as map, filter, reduce, some , replace are lazy and infinite

21:34 justin_smith: Lewix: iterate is always infinite, cycle is always infinite, map filter and replace are all as long as their input, or shorter

21:34 reduce is not infinite except in very special circumstances

21:35 I've yet to use an indefinite return value from a reduce

21:36 Lewix: justin_smith: Are sequence backed by functions infinite?

21:36 justin_smith: they can be

21:36 lazy-seqs are backed by functions, they are not always infinite

21:36 reduce is not lazy, the others you mentioned are

21:36 Lewix: why is (def a-range (range 1 4)) considered infinite?

21:36 justin_smith: it isn't

21:36 but (range) is

21:37 Lewix: why is reduce not lazy while the others are?

21:37 justin_smith: because the point of reduce is to get a single value from a collection

21:38 if you put your mind to it, you could ensure that single value is actually an infinite sequence, but I haven't seen that in practice, and it wouldn't be derived 1->1 from the inputs like the other higher level transforming functions are

21:39 Lewix: (def a-range (range 1 4)) as opposed to (range 1 4) doesn't get created until it's called

21:39 justin_smith: that's false

21:39 both are equally lazy

21:39 neither are realized until the values are accessed

21:39 in the repl, def returns nil so you don't access the value at first

21:40 Lewix: ,(range 1 4)

21:40 clojurebot: (1 2 3)

21:40 justin_smith: the side effect of printing is why that gets realized

21:40 ,(do (range 1 4) nil)

21:40 clojurebot: nil

21:40 Lewix: ,(def a-range (range 1 4))

21:40 clojurebot: #'sandbox/a-range

21:40 justin_smith: that sequence cannot ever get realized ^

21:40 the one in the do that is

21:41 Lewix: ok

21:41 justin_smith: better example: ##(do (map println (range)) nil)

21:41 lazybot: ⇒ nil

21:41 Lewix: (second (range 1 4)) is different from (second a-range) - the former is invoked once while the other twice

21:41 justin_smith: no

21:41 that's wrong

21:42 Lewix: How?

21:42 justin_smith: lazy-seqs store their realized values

21:42 and def does not invoke any of the values

21:42 nor does using seq directly

21:43 it's only consuming values (eg with second, nth, print, count) that anything is realized

21:43 and the values are guaranteed to be realized exactly once

21:43 ,(def foo (map println (range)))

21:43 clojurebot: #'sandbox/foo

21:43 justin_smith: ,foo

21:43 clojurebot: (0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\nnil nil nil nil nil ...)

21:43 justin_smith: ,foo

21:43 clojurebot: (nil nil nil nil nil ...)

21:44 justin_smith: see, the println only happens once

21:44 it's only invoked once

21:44 Lewix: justin_smith: so Alan Dipert got it wrong

21:44 justin_smith: I'd more likely believe you are misreading

21:44 but possibly

21:45 Lewix: justin_smith: thanks I'll go over it again

21:47 justin_smith: so you're arguing that (second a-range) is invoked once

21:48 just like (range 1 4)

21:48 just like (second (range 1 4) )

21:49 *

21:49 justin_smith: wait, what exactly do you mean by "invoked" here?

21:49 as in the thunks being realized? yes, in both cases invoked exactly once

21:50 Lewix: ok thanks

22:09 justin_smith:

22:10 justin_smith: "instead of being backed by data like linked lists are clojure sequences are backed by functions so they can be lazy and infinite" - this is a verbatim copy of what I heard

22:11 justin_smith: right

22:11 but the results of those functions are cached

22:11 so it's true, but perhaps incomplete

22:13 and they can be lazy and they can be infinite, but some seqs are neither

22:23 Lewix: justin_smith: that means that sequences are invoked twice

22:23 justin_smith: (second (range 1 4))

22:23 justin_smith: I literally have no idea what you are talking about

22:23 where is the second invocation you are talking about here?

22:24 Lewix: in linked list you have to pass through the first item to get to the second

22:24 justin_smith: yes

22:24 so calling second realizes two elements

22:24 Lewix: invoked once for first the a second time for the second item

22:25 justin_smith: range is chunked, you would need to consume at least 33 items iirc for two distinc invocations to happen

22:25 Lewix: I meant that it's invoked twice in that specific case

22:25 justin_smith: no

22:25 it isn't

22:25 because range realizes 32 items at a time

22:25 Lewix: it what the same guy is saying ^^

22:25 it got me thinking

22:25 justin_smith: it's an implementation detail

22:25 OK

22:25 ,(first (map print (range)))

22:25 clojurebot: 012345678910111213141516171819202122232425262728293031

22:26 justin_smith: note that it gave us the first item, but it realized 32 items

22:26 tomjack: whew. looks like I was a bit unfair to eclipse jdt: https://www.refheap.com/29f0551b9dab5c11bd8299f2f

22:26 Lewix: ,(set! *print-length* 1000000000000)

22:26 clojurebot: 1000000000000

22:26 Lewix: ,(first (map print (range)))

22:26 clojurebot: 012345678910111213141516171819202122232425262728293031

22:26 justin_smith: it's going to be 32 every time

22:27 like I said, it's an implementation detail, but unless you use anything beyond the 32nd item, there is exactly one invocation that happens

22:27 but if you rely on stuff like that you're doing it wrong anyway

22:27 Lewix: right justin_smith - i care about details though , so you're sayin gthat the 32 items are cached

22:28 justin_smith: right, there's exactly 1 invocation that realizes 32 items, in that case

22:28 Lewix: buok thanks

22:28 for clarifying

22:28 justin_smith: which is one reason why laziness and side effects don't mix, and if your code relies on a specific number of items from some lazy-seq being realized, it's going to be buggy code

22:29 tomjack: user> (first (map print (range)))

22:29 0

22:30 user> *clojure-version*

22:30 {:major 1, :minor 7, :incremental 0, :qualifier "beta1"}

22:30

22:30 justin_smith: tomjack: yeah, I was careful to say "implementation detail" for a reason :)

22:30 tomjack: this was merely a counterexample to the assertion that you invoked a lazy-seq twice if you get the second item

22:31 if clojurebot was using beta1, I would pick a different example :)

22:31 tomjack: my point was, 'if you rely on it, your code may break' is not just a warning now

22:31 it just broke! :)

22:31 justin_smith: oh, yeah

22:31 haha

22:31 true!~

22:31 tomjack: (also, I didn't know what the result was going to be..)

22:31 justin_smith: heh

22:32 tomjack: now try ##(first (map print [:a :b :c :d :e :f :g]))

22:32 lazybot: ⇒ :a:b:c:d:e:f:gnil

22:33 justin_smith: gnil

22:33 gnil is a new nil that takes extra arguments including the standard --help command line flag

22:35 tomjack: same result

22:35 justin_smith: interesting

22:35 the purge of chunks

22:35 tomjack: no, I mean, same result as before 1.7

22:35 justin_smith: ahh

22:40 fitz: Normal Java interop can't see private fields, can it?

22:40 justin_smith: fitz: you can see them via reflection

22:42 fitz: justin_smith: that's different than just Classname/staticField, right?

22:42 justin_smith: right

22:42 it's trickier (and you can do the same thing in java too)

22:43 Lewix: juancate: tomjack ;i guess previous versions didn't have that constrain if I may call it so

22:45 ,*clojure-version*

22:45 clojurebot: {:major 1, :minor 7, :incremental 0, :qualifier "master", :interim true}

22:45 tomjack: ah, interesting

22:46 user> (first (map print (range 100)))

22:46 012345678910111213141516171819202122232425262728293031

22:46

22:46 (still 1.7.0-beta1)

22:46 justin_smith: oh, so (range) is special cased, but (range 100) is not

22:46 tomjack: (range) is now (iterate inc' 0)

22:47 justin_smith: aha

22:47 that explains it

22:49 Lewix: user=> (first (map print (range)))

22:49 012345678910111213141516171819202122232425262728293031nil

22:49 {:major 1, :minor 6, :incremental 0, :qualifier nil}

22:57 justin_smith: what if i want to print 44 items with range

22:58 justin_smith: then it would realize 64 of them

22:58 well, depending on clojure version etc. of course

22:59 Lewix: justin_smith: I mean how do i do that since it's set to 32 and (set! *print-length* 1000000000000) wouldnt work

22:59 justin_smith: Lewix: clojurebot has weird settings

22:59 Lewix: I see

22:59 TEttinger: &(doseq [n (range 44)] (print n " "))

22:59 lazybot: ⇒ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 nil

23:00 TEttinger: lazybot has no print length

23:00 &(doseq [n (range 444)] (print n " "))

23:00 lazybot: ⇒ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 6... https://www.refheap.com/99487

23:00 TEttinger: lazybot also has no def, a tradeoff

23:12 tomjack: (inc cgrand)

23:12 lazybot: ⇒ 2

23:13 tomjack: http://stackoverflow.com/questions/15013458/clojure-zipper-of-nested-maps-repressing-a-trie/15020649#15020649

23:53 Lewix: I'm looking for a benchmark of programming languages - slowest to fastest

23:54 and any advantages/disadvantage of each programming languages. i would have thought that in 2015 we could easily find such a study ^^

23:55 justin_smith: there's the alioth.debian.org benchmarks game

Logging service provided by n01se.net