#clojure log - Sep 12 2015

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

0:17 kavkaz: justin_smith: Ah flyspell-popup is nice, I like it, thanks

0:18 good for the markdown side of my emacs usage

0:20 Is it okay to shadow the top-level parameter name with a parameter name in a letfn function definition? Given that they both refer to the same variable of course

0:27 mungojelly: is the clojure grammar too simple for anyone to have bothered saying it as BNF? i like BNF i'd like to see it just to make sure i'm not missing anything

0:35 here it is in ANTLR https://github.com/antlr/grammars-v4/blob/master/clojure/Clojure.g4 so i guess i'm satisfied :)

3:52 felipedvorak: So I have finally succeeded in answering Project Euler problem number 1 with Clojure, but now I was wondering if someone could read the code and criticize it for me. I'm worried if this is functional or not, and if the solution is too bizare.

3:52 http://pastebin.com/rYZb8mVT

3:53 You must get a sum of the numbers below 1000 that are divisible by 3 or 5.

3:53 sorry someo*one but you probably have alerts turned off anyway...

3:54 kungi: felipedvorak: I can help you a little

3:55 ,(reduce + [1 2 3 4])

3:55 clojurebot: 10

3:55 felipedvorak: kungi: thanks

3:55 kungi: felipedvorak: you can use + directly in your reduce

3:55 felipedvorak: wow, I tried that but somehow it didn't work :/

3:55 but I had some problems with paredit earlier, it may be that it was the culprit of the errors

3:56 kungi: felipedvorak: yes paredit can be a huge problem first

3:56 felipedvorak: why does create-range have to return a vector?

3:57 felipedvorak: kungi: don't know hauhauh

3:57 I'm with the impression vectors are more consistent

3:57 kungi: felipedvorak: consistent?

3:58 felipedvorak: instead of (reduce + [1 2 3]) you can also write (apply + [1 2 3])

3:58 felipedvorak: then you don't need the 0

3:58 felipedvorak: wow, apply is new to me!

3:58 kungi: ,(apply + [1 2 3])

3:58 clojurebot: 6

3:59 felipedvorak: the 0?

3:59 kungi: felipedvorak: (reduce + _0_ list)

3:59 felipedvorak: alright!

4:00 justin_smith: kungi: you don't need the 0 anyway

4:00 ,(reduce + [1 2 3])

4:00 clojurebot: 6

4:00 felipedvorak: justin_smith: Yeah, this is something I just realized, I'm always using reduce with an entry value when its not needed

4:01 justin_smith: felipedvorak: well, better to supply a non-needed initial value than not provide one when needed

4:01 kungi: I just found my first real world usage of `tree-seq`

4:03 felipedvorak: kungi: the overall code, you would call this usable in the real world? the structure? sorry, I'm new to programming AND to functional, so I'm a bit (lot) confused hehe

4:04 kungi: felipedvorak: I would extract the (if (or (mod ... into its own predicate function `mod-3-5?`

4:04 felipedvorak: hmm

4:05 very nice

4:05 kungi: felipedvorak: And I would use a precondition in add-all-odd to check for the vector instead of using a comment

4:05 felipedvorak: I still don't know how to do that :)

4:05 kungi: felipedvorak: And btw. It does not expect a vector.

4:06 felipedvorak: vector? perhaps hehe

4:06 kungi: I see, I'm removing this malformed mental constructo about vectors from my mind immediately.

4:06 kungi: felipedvorak: let me write it and show you my solution

4:07 felipedvorak: great

4:08 kungi: felipedvorak: solution is 233168?

4:08 felipedvorak: yeah

4:08 hehehe

4:09 kungi: (defn mod-3-5? [x] (or (= (mod x 3) 0)

4:09 (= (mod x 5) 0)))

4:09 (apply + (filter mod-3-5? (range 1000)))

4:09 * felipedvorak dies

4:09 felipedvorak: ok

4:10 hehe still a lot to learn :)

4:10 justin_smith: kungi: use (zero? (mod x y))

4:10 kungi: justin_smith: yes

4:10 stull a lot to learn :)

4:11 justin_smith: that's why we are all here, even me believe it or not

4:12 felipedvorak: thanks both of you! :) 5am, my clojure addiction must come to an end for today

4:13 kungi: felipedvorak: good night :-)

4:24 expez: (defn bar [baz] (foo!)), should bar really be bar!?

4:25 kungi: expez: What are you trying to communicate? -:)

4:25 expez: kungi: is the bang naming convention transitive?

4:26 kungi: expez: in my opinion yes it is

4:26 expez: Or rather, I often see in the wild that it is not, but should it be?

4:26 kungi: expez: Hmm no wait .... it depends

4:27 expez: If you properly hide your impurity in a function then ! may not be transitive

4:27 clojurebot: excusez-moi

4:28 justin_smith: kungi: except in clojure.core ! often means not safe in a transaction, and unless you do some intense defensive programming that will be transitive

4:28 eg. because it combines retries and side effects

4:38 (doc io!)

4:39 clojurebot: "([& body]); If an io! block occurs in a transaction, throws an IllegalStateException, else runs body in an implicit do. If the first expression in body is a literal string, will use that as the exception message."

4:55 amalloy: i don't think transitive is the right word for that

4:55 contagious would be my choice

4:58 justin_smith: "the flu is a transitive property of humans"

5:03 amalloy: yes indeed, for any three humans a, b, c, if a flu b and b flu c, then a flu c

5:04 today's achievements: make flu into a verb

5:04 justin_smith: heh

5:04 sobel: nomenclature question: if a function has a remote side-effect (e.g. sftp cwd) should it end in !

5:05 or is that more aimed at namespaced vars

5:05 justin_smith: sobel: I'd say it's safe to skip if it's idempotent, but usually yes it should

5:05 sobel: hmmm. i like that.

5:05 justin_smith: sobel: my rule of thumb is "what if someone used the function inside a swap! call and it was done 50 times in a row"

5:05 would that suck? if so, use !, if it wouldn't matter, no

5:06 sobel: seems sensible enough.

5:06 justin_smith: sobel: not that I always follow this advice (handler code is especially egregious here in my codebases)

5:06 sobel: it's side-effect grey area

5:07 justin_smith: the kind of bug that's been haunting us lately is double transmits on a websocket in a react app

5:07 like - sometimes the server gets two requests and it should have gotten one

5:08 not all our request handlers listening on the websocket are idempotent, so we get weird ass bugs (many coming from weirdness in react it seems (probably because misusing react))

5:08 I would just debounce server side, but that only handles the symptom (and increases latency)

5:08 sobel: i hear that

5:10 justin_smith: it appears one bug was being caused by a side-effecting button that was acting like an innocent link, so that a pop-up preview caused a double-trigger of the event (maybe)

5:10 or, I should say "css magic tried to make an innocent link be a side effecting button"

5:11 amalloy: debounce? is that a common term?

5:11 sobel: yes

5:12 justin_smith: amalloy: it is a way to turn sputtering event clusters into a single event, comes from analog electronics, where a switch will literally bounce

5:12 amalloy: i feel like i've heard it in a past life, and can infer meaning from context, but have no real idea how i would have learned it

5:12 justin_smith: rebound

5:12 sobel: yes, it is literally slew-rate limiting

5:12 amalloy: slew-rate! it's like i have suddenly forgotten how to understand english

5:13 justin_smith: it's also closely related to how things like double-click are possible (if not technically used)

5:13 second event during bounce period = this is a double click

5:14 (also check for confounding parameters like x/y motion that would counterindicate, of course)

5:15 sobel: so idempotent handlers would prevent the 'bouncing' in the first place

5:15 justin_smith: right, but some of our handlers create resources for the client, this isn't negotiable

5:15 also, some idempotent actions are CPU expensive, so triggering twice is bad

5:16 sobel: so, can't that still be faux-idempotent (create-or-ignore)

5:16 justin_smith: I was also tempted to invent a higher order function that would return "your function, but refuses to run a second time". I could even abuse memoize for this if I was feeling dirty. But this also only fixes the symptom.

5:16 sobel: yeah, i wasn't quite clear how memoize wouldn't work

5:16 TEttinger: runonce to parallel defonce, justin_smith?

5:17 both rhyming with Beyonce

5:17 justin_smith: sobel: they are allowed to create two resources with the same parameters, it's a time-dependent thing - it's just that if the amount of time is under 5 seconds they won't get an interesting result

5:17 TEttinger: haha, awesome idea

5:19 (defn runoncé [f] ...)

5:19 sobel: (inc justin_smith)

5:19 ,(inc justin_smith)

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

5:20 sobel: ok

5:20 justin_smith: sobel: the first one was right, but lazybot is on vacation I guess

5:20 sobel: clearly

5:21 i like the fn, defoncé

5:24 (def Brawndo™ [] (basically-mtn-dew) )

5:24 yes, unicode makes programming fun

5:26 🐙

5:44 TEttinger: sobel: unicode is fun

5:44 ,(def def "Pfft, can't take the value of a macro, eh?")

5:44 clojurebot: #'sandbox/def

5:45 TEttinger: ,def

5:45 clojurebot: "Pfft, can't take the value of a macro, eh?"

5:45 justin_smith: ,(macro? def)

5:45 clojurebot: #error {\n :cause "Unable to resolve symbol: macro? in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: macro? in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: macro? in t...

5:45 justin_smith: ,(:macro (meta #'def))

5:45 clojurebot: #error {\n :cause "Unable to resolve var: def in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve var: def in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve var: def in this context"\n ...

5:45 TEttinger: fine special form

5:45 justin_smith: haha

5:46 TEttinger: ,(map def '(a b c) [1 2 3])

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

6:25 noncom|2: i am thinking about hosting a webserver written in clojure with the frontend written in clojurescript somewhere. the service is a CRM-like thing, i am wondering, what minimal and what recommended machine specs are?

6:25 in particular, how much RAM do I need for that?

6:25 no huge load is planned, just some document office work

6:33 wink: noncom|2: I've successfully hosted a soup clone in pure clojure on a 5$ digitalocean box (incl. postgres)

6:34 noncom|2: sooo... I wouldn't go lower :) but should be enough for a first shot

6:34 noncom|2: very nice!

6:35 wink: I think it will depend on your concurrent users as well

6:35 noncom|2: well, for the moment there'll be no more than 100 users with occasional access to forms and documents, so should be ok. 512 or 1024 ram will do then

6:35 btw what is soup? :_

6:36 :)

6:36 wink: soup.io - a microblog with some social functions

6:36 mostly posting pictures

6:36 noncom|2: ah, i see

6:38 cool!

6:39 wink: btw, have you used hoplon?

6:39 wink: never even heard that

6:39 noncom|2: i'm just picking the framework for now

6:40 i worked with luminus, and there's also hoplon..

6:40 so will try hoplon too then

6:41 wink: I've also mostly used luminus

6:41 and somethin before that...

6:42 noir

6:42 noncom|2: yeah, noir is deprecated now. luminus builds on the best remaining parts of noir, compojure and stuff

6:42 hoplon is more innovative, but idk is it all good or bad or just different

6:43 for now it looks very cool, but different

6:43 sometimes it is hard to choose between two techologies esp if you see no clear difference between them unless you've made a big project to feel it all through

6:49 wink: hehe

6:49 sounds like our rewrite from ember to angular

6:50 I'm only playing around with clojure web apps, nothing serious

6:50 so far luminus was fine

6:50 noncom|2: yeah, me the same :D

6:50 wink: and unlike with noir (when it got deprecated) I don't see a good reason to change anything even if it might be a lot better

6:51 that said, the time will come when I am nosy enough to try my 30th web framework

6:51 still havent used a rust one for example :)

6:52 noncom|2: i did not use any rust even at all yet

6:52 tried go though, liked it, but i have no real tasks for that

6:52 besides, getting off a lisp is hard.. :/

6:52 wink: yeah I needed a small windows gui for ffmpeg

6:53 that's where I had my problem to solve

6:53 noncom|2: haha, i worked with ffmpeg through java-cv, so i was able to do it in clojure :D

6:53 java-cv is cool

6:54 thanks for the info! gotta go now, cheers! :)

6:54 wink: bye

7:45 crocket: hi

7:45 Is there an alternative to datomic?

7:48 ianhedoesit: https://github.com/tonsky/datascript

7:53 muhuk: it's in-memory only AFAIK.

7:56 msw: Is there a quick (clj) repl command to check in which protocol(s) a given method (say .. toString) is (potentially) defined?

7:57 Bronsa: msw: toString is not a protocol method

7:58 msw: for actual protocol methods, (:protocol (meta #'proto-method))

7:58 crocket: datascript is not an alternative to datomic.

7:59 ianhedoesit: that's the closest I'm aware of

8:01 msw: I see, thanks Bronsa.

8:09 Bronsa: woah datascript now supports clojure too, neat

8:25 crocket: What makes datomic special?

8:27 muhuk: crocket: special in what way?

8:27 crocket: I don't know

10:05 blucas: %n

10:23 tmtwd: how do I empty a whole channel in core async?

11:50 justin_smith: tmtwd: keep reading until you can't read any more in a loop?

11:52 mungojelly: is that really the idiom? i too was wondering if i should say like take-all or something

11:54 btw i'm running that ants.clj from rich's talk "clojure for java developers" or w/e that's one of the most popular talks on clojure, this is an awesome toy, someone should have linked me to this when i asked, this looks fun

12:08 expez: 1.7 is such a breaking change it's not even funny

12:08 Even library author now rewriting their libraries to use reader conditionals effectively forcing all consumers to also run 1.7 if they want patches

12:08 Every*

12:10 Bronsa: expez: 1.7 is a breaking change?

12:10 expez: Is there any reason at all to ship cljc files to the consumer over two platform specific files?

12:10 Bronsa: effectively yeah

12:11 Bronsa: expez: every release has had additional features over the previous ones, what's special about 1.7?

12:12 expez: Bronsa: I suppose the previous releases were nice to haves, but a lot of people seem to think cljc is essential.

12:13 I get the allure of only maintaining a single file, but that should be an implementation detail and I'd prefer if people still shipped clj and cljs files :/

12:14 Bronsa: cljc *is* essential if you want to use reader conditionals

12:15 expez: obviously?

12:16 You don't *have* to write your library with reader conditionals, though. And if you do I'd prefer if you processed those files as part of deployment and also shipped platform specific files so I don't have to upgrade to 1.7 to receive patches!

12:16 justin_smith: expez: why can't you use 1.7?

12:17 expez: justin_smith: *I* can, but I don't want to force everyone using CIDER and clj-refactor to use 1.7 :/

12:17 Bronsa: expez: oh come on, having to maintain both a clj and a cljs version of a library is *so much worse* than using reader conditionals

12:18 expez: Bronsa: Sure, but you can process those files and put the clj and cljs files in the jar along with the cljc file...

12:19 Bronsa: expez: that's what people did with cljx before clojure had native support for reader conditionals

12:20 expez: Guess I'm done here if nobody sees a problem

12:20 Just needed to vent

12:20 Bronsa: expez: why can't cider/clj-refactor just process the cljc files internally to strip the reader conditionals?

12:21 kavkaz: How come the REPL is not letting me do (map Integer/parseInt <some-seq>) but it lets me do (map #(Integer/parseInt %) <some-seq>)

12:21 ?

12:21 justin_smith: kavkaz: methods are not first class

12:23 kavkaz: justin_smith: So it's not a function object?

12:23 like (fn []), (defn [] ...) or #()

12:23 justin_smith: no, Integer/parseInt is a static method

12:24 another way to put it is that functions are objects, Integer/parseInt is not an object

12:24 kavkaz: justin_smith: Oh i see

12:24 Now that I think about it from a Java perspective

12:27 justin_smith: kavkaz: and since a static method is not itself a class, it isn't actually a thing that you can place on a call stack - in order to do so, clojure would have to implicitly create the anonymous function version for you

12:28 *not itself an object* - sorry

13:43 Narfinger: hiho, i am just starting out to learn clojure and i wonder if there is a similar library for xml parsing as hxt for haskell

13:43 for anybody who does not know, you basically define your structure of elements and it does the reading and writing according to the structure

13:53 justin_smith: Narfinger: we don't actually need something that strict, since we don't have Haskell's type system

13:53 Narfinger: not to say it doesn't exist - it might, but there is less motivation

14:06 Narfinger: if your data source is actual XML, clojure.data.xml might work (though it does have its limitations related to namespaces iirc)

14:14 noncom|2: justin_smith: once you said "i prefer websockets where available" - so, where are they not yet available?

14:14 Narfinger: ok i will look around thanks

14:17 justin_smith: noncom|2: some http servers / some clients, depends on what you are required to deploy to / support

14:18 noncom|2: though sente has a nice feature where it works with a post based fallback if websockets are not supported client side

14:19 noncom|2: but all general browsers do have support... i just wander, what a client today would not support it.. but i think i'm not gonna get in this situation...

14:19 justin_smith: noncom|2: http://caniuse.com/#feat=websockets

14:20 so unless you need to support android 4.3 or ie 9, you are probably good?

14:21 noncom|2: justin_smith: wow, that was exactly what i was looking for!

14:21 thanks!

14:33 mungojelly: -> and ->> are fun but also they seem random, it seems like semantics is given sometimes to the positions to try to unrandomify it with partial success, i thought of maybe something that threads through maps by key or something so it could be more explicitly semantic

14:34 noncom|2: mungojelly: they are not random in any degree

14:34 mungojelly: what is your original task?

14:34 mungojelly: maybe you're looking for get-in?

14:34 mungojelly: noncom|2: hm? i'm just learning clojure. what i mean is that you're threading through the first/last argument, which gives those positions special powers

14:35 justin_smith: mungojelly: you can use ->> inside ->

14:35 and if you need a position that isn't first or last, you can use as-> inside ->

14:35 mungojelly: which is almost like having a semantics, and then there's things like um, the sequences it said somewhere are all sequence last, so then that approaches semantic order to it so you can thread through the last which happens to be a sequence, yay

14:35 oh cool i don't know as-> yet what's that?

14:35 oddcully: ,(doc as->)

14:35 justin_smith: ,(-> 1 inc (-> as n (* n n)))

14:35 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."

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

14:36 justin_smith: ,(-> 1 inc (as-> n (* n n)))

14:36 clojurebot: 4

14:36 justin_smith: ,(-> 1 inc (as-> n (* n n) (inc n)))

14:36 clojurebot: 5

14:37 mungojelly: so -> threads at the beginning, ->> at the end, and as-> in the middle, it's beautiful, i'm not saying it's not beautiful

14:37 but also you're like manually building something, i'd rather they were more like magic magnetic connectors and you wave them at one another and they fall in line good

14:37 noncom|2: mungojelly: correction: -> threads at the second place

14:38 mungojelly: well, these are core macros and are intended to be very simple

14:38 oddcully: as-> with the varname/position as you like (not only once, not only in the middle)

14:38 noncom|2: mungojelly: also, take a look at the swiss arrows clojure library :)

14:39 mungojelly: the core functions/macros must not have magic. they all have very simple meanings. magic can be created in libraries

14:40 mungojelly: ha well this is all very magic to most programmers still but i do think i see what you mean

14:40 noncom|2: mungojelly: also, in most cases it is sufficient to use just -> or ->> or, rarely, their combination, as justin points out

14:41 mungojelly: are you saying you don't like my idea :p

14:41 noncom|2: mungojelly: if you find yourself in need of more, it can be a sign that you need a (let) form with clearly labeled subresults

14:41 mungojelly: nono, it's not that i don't like the idea

14:41 mungojelly: i want to thread semantically too, if the things i'm threading through have arguments with semantic names and i can say "thread through the :foo arguments" then i can take a random collection of stuff and throw it together more carelessly

14:43 or like you could take the same chains and thread them through various ways, like what are the chances a chain that works with -> is also going to work with ->> because it's haphazard but if they had semantically marked arguments they could easily happen to work with multiple ones

14:43 maybe i'm just talking about monads again idk

14:44 noncom|2: mungojelly: yes, this looks like modals, and you could have such functionality here, but really, it is far from basic

14:44 mungojelly: it is not always clear for the compiler, what do you really want to do and when it should signal you an error

14:45 mungojelly: with that much guessing it can quickly break things

14:45 since lisp is very fluid

14:45 mungojelly: here's what - why don't you try to write such a macros youself?

14:46 mungojelly: well because i just learned clojure's macros yesterday, i suppose. i made a few simple things and it went fine as soon as i got used to all this # business. ;)

14:47 noncom|2: mungojelly: actually, in the end you may come up with a pretty useful library, that's serious and a good excercise

14:47 congrats with learning the stuff :)

14:48 mungojelly: here's something i'm thinking of writing, i want an abstraction that's a grid of tiles, like the tiles each know how to draw themselves and there's a display context that asks the tiles in its field of view to draw themselves, etc

14:48 is there something like that already, a generic tiles interface?

14:50 it seems to me like that would be a friendly context for beginners to start making things in, because they just need to make a few tiles that know how to be tiles, and then ideally there'd be various pretty viewers and tools that they're compatible with

14:50 noncom|2: mungojelly: never heard of such a thing. how are you going to draw them, what graphics api to use? or you mean just data rendering of an n-dimensional grid?

14:50 mungojelly: there's a zillion games written with tiling systems but none of the ones i've read yet have the tiles written as a separate abstraction :(

14:51 noncom|2: weeeeeeeeell i could target a particular graphics api, or i could target some intermediate abstraction, what do you think would be useful??

14:51 like they could just say a list of polygons to paint on their tile, and then various viewers could translate that into various graphics apis

14:51 noncom|2: mungojelly: ah, i see. yep, you could very well do that. i would ofcourse decouple data rendering from the drawing api. and for the draving api in your particular case i'd pick the quil library that bases over processing

14:52 mungojelly: i saw something about quil and it looked awesome but i haven't tried it yet

14:53 one way i think would make sense to do it is to have tiles that know how to draw themselves in a zillion different ways, like they can make a tiny little version of themselves for zoomed out views, and say how to paint themselves as ascii, etc

14:54 noncom|2: quil is a very simple, friendly and powerful tool that will let you do things reaaaally quick without boring stuff. then, when you have your engine functional, you can plug in other renderers

14:54 mungojelly: then if you make a tile set that implements all the different ways of viewing it you can view the same game made with those tiles through all those lenses

14:54 noncom|2: mungojelly: interesting

14:57 mungojelly: with that idea you could create tiles described by a certain dsl with symbols that draw themselved in various ways

14:58 mungojelly: i'd think of implementing that like tiles are a map with :ascii goes to a function that paints the ascii, etc., so like {:ascii paint-ascii :polygons paint-polygons} is that clojurey

14:58 noncom|2: you mean ascii and polygons are two different renderers?

14:58 well, it's not about clojure i think, its about the concept more

14:59 i think more clojuric and functional would be to have a single language (a DSL) to describe a tile and then have interpreters of that DSL for every renderer

15:00 mungojelly: i was wondering earlier in general, is that what you do in clojure is fill data structures with functions you want to use, i thought of putting fields in my things and tucking functions into them but maybe i'm just messily recreating some object system i should use?

15:01 noncom|2: mungojelly: hm, you could have functions stored in datastructs if you need that. but i am not sure about your specific cases. when i started clojure i was constantly finding myself recreating OOP

15:01 after a period it gone, OOP and clojure (FP that it is) got separated completely, not i can use them independetly

15:02 s/not/now

15:02 mungojelly: well i mean the dsl is that there's tiles with attributes, so not much to it, {:name "I'm a happy tile!" :tiny-ascii "***\n*!*\n***\n"} etc, but then i think of tucking code(-like data) into them somewhere to make them pop

15:02 noncom|2: mungojelly: having fns in datastructs is perfectly fine if you really need this

15:03 mungojelly: if you're asking about having a function stored within it to render it like ((:renderer tile) (:data tile)) then that's recreating OOP :)

15:04 is this what you mean?

15:04 justin_smith: yeah, you don't need to recreate OOP in clojure, we've got protocols/records/multimethods for this

15:04 actual OOP!

15:05 noncom|2: yeah, and even going futher than justin is saying, i almost never use protocols/records/multimethods in my programs :D so i went even that far

15:05 mungojelly: i read that there's something called protocols, but i haven't understood yet how they go

15:06 noncom|2: not that it is a good example, many people use them, but that's just how it can possibly be too

15:06 mungojelly: so many facts about clojure are stirring my head and making it feel soupy

15:06 justin_smith: mungojelly: in pure clojure, the only way to have a method is to implement a method is to implement some protocol defining that method

15:06 mungojelly: clojure does seem to cohere though, there's some sense to it, the words are all somewhat memorable (a blessed rarity among lisps)

15:07 noncom|2: mungojelly: yeap, clojure is that type of soup that is used to make crystals

15:07 justin_smith: oh wow that was a mess

15:07 the only way to implement a method is to implement some protocol defining that method

15:08 mungojelly: it just turns into actual normal java method dispatch right? so i get to copy my intuitions from there. that's part of what makes this language so learnable.

15:08 it's so hard to tell because of course every language is easier to learn than the last but it really does feel like a very easy language to learn.

15:08 justin_smith: mungojelly: pretty much, aside the fact that we don't really do concrete inheretence (only interfaces)

15:09 mungojelly: it's an odd thing in computer science, that inheritance didn't turn out to be very useful. in theory it seemed like it was going to be useful. hm.

15:11 noncom|2: nah, inheritance is a very artificail concept, that's why it did not work

15:11 does not go well hand-in-hand with the rest of the type theory

15:11 well, it works, but in a much more limited application that many anticipated

15:12 mungojelly: clojure though scares me it's so much the other way, by which i mean nothing has any defined structure at all you're just biting at keywords in things :/

15:13 justin_smith: mungojelly: it's possible to have more structure - via things like defrecord, even deftype, protocols, prismatic/schema and core.typed

15:13 it's all optional though

15:13 noncom|2: well, it's just a lisp with unstrict typing

15:13 yeah and what justin says

15:14 there are ways to impose total control of your structures

15:14 turns out you don't need them most of the time though

15:14 but sometimes yeah

15:14 mungojelly: yeah of course it's possible, but i mean just in general as a habit it seems to be the code here just works with bare data structures and secretly understands the semantics of them

15:14 noncom|2: because in lisp there's actually not much semantics :)

15:15 mungojelly: of COURSE my thingamabob has a doohickey as its third whatzit, what else would it have

15:15 noncom|2: :)

15:17 my story was this: i wanted to learn a lisp for a very long time, but did not understand. then i became java, then, as a soft OOP->FP transition i was scala... was storming lisp walls several times never getting a grasp. i simply could not understand. then at one moment i understood that there's nothing to understand. it's just simple and it works.. was a revelation of sorts

15:18 mungojelly: i still don't understand common lisp, the concepts are fine but put them all together with that WEIRD VOCAB and i can't follow a thing. but i learned scheme from SICP, which is fantastic.

15:20 noncom|2: hmmm maybe :D

15:21 but there's just lambda and variable names..

15:25 mungojelly: so, if you're going to explore the tiling system or write the intellectual threading macro, cool! if you have some progress later, we're glad to witness and try it out :)

15:26 as i am programming games myself, i am especially excited about the tiling system excersise..

15:26 mungojelly: what are you up to? any code up i can read? i need to read a bunch of clojure

15:28 ugh if my tiles want to move should they request to move from a board manager or what sigh

15:29 i definitely feel like i'm not thinking clojure-y enough

15:29 justin_smith: IMHO unless you have a strong reason to do things otherwise, a tile should be pure data, and you should have a function that takes a board of tiles and returns a new board of tiles (including any moves needed)

15:30 noncom|2: mungojelly: well, actually lately i am using a game engine (JMonkeyEngine 3) to create software for audio-visual installations, mappings and stuff... unfortunately it is protected by my employers contract but i can share the wrapper for JME3, if you later come to it

15:30 justin_smith: so the board is a big container, tiles are smaller containers inside it, and the logic is in a function that transforms boards by moving tiles

15:31 noncom|2: mungojelly: yes, you have data and separately - functions that manipulate it

15:31 mungojelly: justin_smith: yes that's sorta what i was thinking but then.. do i ask every tile every time if they want to move? :/

15:31 noncom|2: mungojelly: but i also be happy to answer any game programming related questions you might have regarding clojure specific stuff... and other people here too do games

15:32 mungojelly: you just update the whole board at once

15:32 mungojelly: like push the board through the monad

15:32 mungojelly: well what i don't know is what you already have. do you have anything? is there anything i can play with? i mean like little abstractions, toys

15:32 justin_smith: mungojelly: it depends on what your ruleset is? if it's like chess, the "player" abstraction should decide what should move, if it's like conway's life, you should process one group of 9 at a time, each time determining the fate of the one in the middle...

15:33 mungojelly: justin_smith: i'm just making a general abstraction for building various toys and games and experiments on. maybe serious things too i suppose w/e.

15:34 it's like a toybox that comes with some generic empty boards and some sets of tiles and then you can build from there

15:34 take the alphabet tiles, make a word game

15:34 justin_smith: mungojelly: well, in that case you'll probably need to support both those models (plus others)

15:34 noncom|2: mungojelly: eh, sorry, no real functional code to play with :/ all is protected by the contract :/

15:37 justin_smith: mungojelly: one cool design which is very popular in the game world, and fixes a lot of the problems introduced by OO in games, is ECS

15:37 entity component systems

15:38 mungojelly: the whole time i've been learning to program i've been reading programs for games with tiles in them hoping for something i can pick up and play with but it's always, for row, for col, row * width * hope you got the rotation right, draw the imperative sequence of things :(

15:38 justin_smith: it's like you took the object graph, and made a normalized database out of it - you have a list of ids representing all entities in the game, and each property is actually a table mapping from an id to a value

15:38 mungojelly: justin_smith: everyone's saying ECS over and over but i don't understand what the big deal is. they weren't doing that already? wtf?

15:39 justin_smith: mungojelly: the difference is with ecs the player doesn't have a color

15:39 the game has a table of colors, that maps the player id to a color

15:39 so it's not OO at all in the layout

15:39 closer to sql

15:40 mungojelly: ..which they weren't already doing? every basic programming text tells you not to hardcode numbers. do we not understand that colors are numbers and you can't do that with colors either. hardcoded numbers everywhere.

15:40 justin_smith: mungojelly: the point is, there is no player object

15:40 and before ecs they were doing OO, where your entities are objects

15:41 mungojelly: i've been so irritated the whole time i've been learning by the lack of anything for me to play with and it's my theory there's no good reason for it at all, which i now will have to back up with some code, but i don't see what the problem is, i really don't, just give beginners any toys at all. :(

15:42 i want to give them some boards, like maybe finite boards and infinite boards, and then some tiles to put on the board

15:42 justin_smith: then do that

15:42 the problem with easy tools for beginners is that too often big systems are built with those tools, as if you had a temple made of tinker toys. What works in the small isn't the same as what works in the large.

15:43 mungojelly: and then there's an example game and what it says is, give me some tiles and arrange them like this, so then of course you can make a different program that arranges them differently, or different tiles to plug in

15:43 yeah like these incredible movies people have been making in scratch, have you seen those?!

15:44 i checked it out because TIOBE said that Scratch is one of the top languages so i checked out what people are making with it lately. give people any tools they can use at all, even if it's difficult, and they'll do it. they'll do difficult as long as they can observe incremental progress.

15:44 tmtwd: http://pastebin.com/qrvqc90E what is the .. in this function? and the -target and -value?

15:44 justin_smith: sure, and my job would be a living hell if I had to make things in scratch

15:45 but it's a great tool for learning, and a great toy

15:45 (doc ..)

15:45 mungojelly: unlike those users, you'd quickly add new blocks

15:45 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."

15:45 noncom|2: tmtwd: yes, one of the java interop things

15:46 justin_smith: tmtwd: .. is like -> but only for methods

15:46 tmtwd: oh

15:46 mungojelly: (doc ...)

15:46 clojurebot: Pardon?

15:46 mungojelly: just wondering

15:46 justin_smith: tmtwd: so -target is actually property access (.-target e)

15:46 tmtwd: oh I see

15:47 (.-target e) and (.-value )

15:47 right I get it

15:47 justin_smith: right, the whole form is actually (.-value (.-target e))

15:49 augustl: anyone else suddenly getting "error in process filter: Wrong number of arguments: (1 . 1), 0" in emacs for cider-jack-in?

15:49 justin_smith: mungojelly: I've done a lot of visual programming (mostly in puredata), and the biggest problem is that the number of relations between things that you can draw clearly is limited on a 2d surface, we can easily read text and infer a larger collection of relations with less ambiguity

15:49 augustl: sounds like you updated something in your cider ecosystem

15:50 augustl: I haven't touched it since I installed it but for some reason I have a -snapshot dependency

15:50 so perhaps it was updated automatically by leiningen

15:50 (in my ~/.lein/profiles.clj)

15:50 justin_smith: yup, snapshots are intended to update

15:50 but that's an elisp error

15:51 augustl: when I set this up a long time ago I had to use snapshots to make it work

15:51 doh, I did update all my packages in emacs too

15:52 justin_smith: augustl: in my experience when I update any packages that are in any way related to cider in emacs, I need to delete my elc files before things work again

15:52 mungojelly: justin_smith: one mistake i think all those systems make is they're ugly, or rather just boring looking. you're wiring up boxes, and they're all boxes. they need to be like candy cane striped and fluffy if they're this sort of thing, something that engages your visual perception of them.

15:52 justin_smith: augustl: emacs / cider should be smart enough to work this out itself, but somehow is not

15:52 noncom|2: mungojelly: btw, maybe nightcode by zach oakes is getting close to what you're saying

15:52 mungojelly: even scratch is just about being cute and silly and yet the blocks are all pretty much the same except they're color coded. boooooooring.

15:52 augustl: justin_smith: will try that, tnx :)

15:53 mungojelly: noncom|2: i tried to run it and it didn't work. :( nightcode, nightrun or something, i tried the one that makes games. but when i clicked to show the code it just showed a greyness. :(

15:54 noncom|2: hmmm.. should not be like that

15:54 mungojelly: i thought i'd see if i was doing anything obvious wrong and then write to the author

15:55 noncom|2: what could possibly be done wrong with a program that should work out-of-the-box?

15:56 augustl: hmm, deleting the elpa folder solved the problem. I'm this close to throwing out emacs.. Why do I have to waste time with mundane bugs in software that's at least a few centuries old

15:57 kavkaz: augustl: Personally I don't really have any alternative to emacs + CIDEr

15:58 CIDER*

15:58 I was using vim with the lein repl in a tmux session, but it wasn't the same

15:58 augustl: yeah, I'm addicted to its paredit too

15:58 justin_smith: ~justin_misth

15:58 clojurebot: Gabh mo leithscéal?

15:58 justin_smith: ~justin_smith

15:58 clojurebot: justin_smith is sits on a throne of lies

15:58 justin_smith: ~justin_smith

15:58 clojurebot: justin_smith is sits on a throne of lies

15:58 justin_smith: ugh keeps getting the wrong factoid

15:58 kavkaz: of course there's the eclipse plugin counterclockwise, but It's really not the same, because I'm too hooked on the vim bindings

15:59 justin_smith: anyway, I gave up on cider, and now code by banging parens with rocks

15:59 kavkaz: cursive is probably the most extensive integration right now

15:59 kavkaz: justin_smith: you mean emacs version 1.0

15:59 ?

15:59 justin_smith: kavkaz: I mean zero editor integration

15:59 kavkaz: they added pebbles and sticks in version 1.5

15:59 justin_smith: heh

16:00 augustl: all editors having "added paredit" in a relatively late changelog lose a lot of trust from me :P

16:01 kavkaz: justin_smith: do you use cursive?

16:01 justin_smith: kavkaz: I use emacs with no repl integration

16:01 kavkaz: justin_smith: Ah i see

16:01 justin_smith: kavkaz: I edit the code in emacs, save it, then reload it in my repl terminal

16:01 kavkaz: justin_smith: That's what I used to do with vim in tmux

16:01 but i need those rainbow parentheses lol

16:02 mungojelly: what is cursive, how do you extend it

16:02 oddcully: ~cursive

16:02 clojurebot: Gabh mo leithscéal?

16:02 noncom|2: its simply a clojure ide on top of jetbrains idea

16:02 mungojelly: i've gotten a vague impression that cursive is a cool thing so i have it on my list of things to try

16:02 augustl: kavkaz: I've found "highlight opposite parentheses" to be sufficient

16:03 noncom|2: many ppl say cursive is cool!

16:03 it is being actively developed

16:03 kavkaz: I'm gonna give it a shot with cursive, I have 240mb free space on my SSD lol

16:03 augustl: mungojelly: cursive is "oh god which editor do I hate the least whatever I'll throw money at the problem"

16:04 oddcully: i run vim-fireplace most of the time and check from time to time into cursive, what it complains about

16:06 kavkaz: Nah I'll stick with emacs

16:08 augustl: To me emacs just has been a better experience. But I understand the struggle of trying to get it to work the way you want it to

16:09 It's been said very well, vim is something that works right off the bat, emacs is something that you have to poke around with

16:12 augustl: emacs is my favorite so far as well

16:18 kavkaz: Honestly I think bbatsov's work on CIDER and Clojure mode makes emacs very sufficient for Clojure

16:21 Also all the other contributors for those projects, I know there's at least a couple here

16:21 and for other community projects as well

16:23 augustl: yeah that part is really nice, it's emacs itself I'm struggling with - it's so big!

16:25 Tagore: emacs can be kind of tricky- it kind of comes from a different time.

16:27 justin_smith: I don't know, I figured out emacs itself OK, but I'm too stupid to use cider properly

16:27 Tagore: It can also be very rewarding, especially if you want to do the kind of programming Slime and its alternatives allow.

16:31 Hmm- well I just joined this channel, so I'm missing context.

16:31 And I'm just starting to play with Cider- have used Slime a lot in the past though.

16:32 What's up with Cider?

16:32 And you?

16:33 kavkaz: Cider is honestly very minimal

16:33 justin_smith: Tagore: I used cider, it's features kind of worked, and every time any part of it was upgraded the whole thing would break

16:33 kavkaz: justin_smith: perhaps if you have an extensive emacs config as it is, many things will break

16:33 justin_smith: I got tired of fixing it all the time, and stopped using it. But clearly other people are productive with it.

16:33 kavkaz: when I started I only had evil mode on

16:34 justin_smith: kavkaz: being able to switch to evil mode was a bonus of leaving cider

16:34 kavkaz: augustl: check out braveclojure.com, he talks about emacs, I got a couple pointers from there

16:34 most of my proficiency with emacs comes from practice though... well, as with anything

16:35 justin_smith: Ah i see. I don't think evil mode broke too many bindings. Perhaps this is an earlier version of cider you're talking about?

16:35 Anyways I gotta go guys

16:35 augustl: I guess a core problem is my grumpyness.. I don't want to have to deal with weird errors after updating packages that are solved by basically a "clean' :)

16:35 justin_smith: kavkaz: versions 0.5 through 0.9, things broke all along the way

16:35 augustl: exactly

16:36 perhaps my fundamental problem was imagining a paradigm where packages could be updated

16:38 expez: Expecting software marked unstable to be stable isn't fair

16:39 CIDER uses semver so you should expect some stuff to break until it reaches 1.0

16:39 justin_smith: OK

16:40 expez: I guess I got used to clojure world, where I can use core.async 0.00001-ALPHA-asdlkfjasdklfj and then upgrade to 0.00002-ALPHA-joiasdf and things don't break

16:40 augustl: the problem seemed to be with emacs and how it compiles packages though

16:40 expez: Some people are even using the Melpa build while complaining about it being unstable. Melpa is like the development snapshot so unless you're willing to jump into the debugger every now and then you should definitely use melpa-stable

16:41 augustl: or I guess at least you could say emacs makes it possible for cider to update in a way that is broken unless you do a "clean" of already compiled elisp

16:41 justin_smith: expez: I wasn't using melpa, but you've concinced me to try cider if there's ever a 1.0

16:41 expez: justin_smith: the package manager gets better in emacs 25, but now you often have to manually delete packages after upgrading because emacs kept some of the old stuff around :/

16:42 justin_smith: expez: I guess cider was the only emacs thing I ever used that saw breaking abi changes, so it looked like a cider problem rather than an emacs one. But yeah, that sounds like a problem with emacs.

16:44 expez: also the nature of the projects I'm working on mean I expose some hairy edges UX wise. I have four clojure processes running at a time, juggling them is much easier when none of them are in my editor

16:44 expez: justin_smith: CIDER is 16k lines of Elisp now, and 4k lines of clojure. I doubt many other packages you use are of similar complexity.

16:46 justin_smith: yeah, that's very likely true

16:46 expez: justin_smith: you should check in every now and then to help find nasty edge cases :)

16:46 mungojelly: expez: huh that is big, what all does it do?

16:46 Tagore: Justin: do you have a way of interacting with a running program right now that works for you, or are you restarting it every time you change the code?

16:46 justin_smith: Tagore: I use (require my.ns :reload)

16:46 it's simple and it works

16:47 expez: mungojelly: check out the readme here https://github.com/clojure-emacs/cider for a list stuff

16:47 justin_smith: oops, (require 'my.ns :reload) of course

16:49 mungojelly: am i prematurely optimizing by thinking of having my tiles say what kind of tile they are and referring to one copy of how to draw them etc., will clojure make it ok if i just put the same thing over and over for the same tile. oh i guess it won't make it ok in serialized forms or whatever. so i should definitely just have the board be indirectly pointing to the tiles.

16:50 srbaker: heya folks.

16:50 i'm using enlive-html to do some scraping for my first clojure project.

16:50 mungojelly: i'm just going to have them indexed by a vector of [x y] i guess, indexing by vectors is pretty, or should i name them x and y like {x: 0, y: 0} hm

16:51 srbaker: first q: what's the easiest way to print out the value of a function so i can see what it's giving me? i think it's a map, but i'm not sure

16:51 i currently have just a println

16:51 Tagore: I haven't used that approach, so I have no idea what it's like to program using it. I have always found it very nicve to be able toi interact with a running Lisp image from my editor.

16:52 srbaker: http://pastebin.com/J9Q7bsyk that's what println gives me. but i'm having a hard time mapping over it

16:52 i don'tknow why

16:52 clojurebot: Cool story bro.

16:52 justin_smith: srbaker: there's prn if you want the output to be less ambiguous, or you could print the type of the thing

16:52 srbaker: aha, prn is what i wanted for now. thanks

16:53 justin_smith: srbaker: here's my trick (-> d type) followed by (-> d count) (-> d first type) (-> d first keys) (-> d first :attrs)...

16:53 srbaker: this is very quick if you are using the arrow keys in the repl, you can find your data quickly

16:53 srbaker: also, it helps to put a pprint at the end sometimes to get multi line printout

16:53 srbaker: okay i've updated the paste: http://pastebin.com/Rqrgv8D1

16:53 what type is that? and where do i get a list of functions i can use with it?

16:53 specifically, i want the string at the end.

16:54 justin_smith: it's a list which contains a number of things, including hash maps

16:54 srbaker: use the -> as I recommended above, you'll find a series of accessors that get the data you want

16:55 (where d is the var containing that whole big blob of data of course)

16:56 srbaker: i suppose i should probably set up emacs to be more helpful

16:57 justin_smith: srbaker: here's how to do it (I just used your paste as the starting data) you don't need emacs, this is just a regular repl https://www.refheap.com/109471

16:58 srbaker: nice. tanks

16:58 thanks

16:58 justin_smith: just fixed the formatting

16:59 srbaker: weird. so what's working in the repl is not working in my code

16:59 (defn vf-days [] (html/select (vf) [:p.p1]))

17:00 when i try to do first type on that, it complains that it can't convert it too ISeq

17:00 when when i prn it, and paste it into (def d on the repl, no problem

17:00 justin_smith: srbaker: OK, what does your code say the type is?

17:01 srbaker: LazySeq

17:01 er

17:01 justin_smith: then you should be able to get the first item of that

17:01 srbaker: whoops. missing parens

17:01 hah

17:02 i'm sure i'm not the first dude to run into that :P

17:02 justin_smith: the learning process never ends

17:18 srbaker: is there a has-key function?

17:18 justin_smith: srbaker: contains?

17:18 srbaker: i want to know if a map has a key :tag

17:18 justin_smith: ,(contains? {:tag "OK"} :tag)

17:18 clojurebot: true

17:18 srbaker: what's ,?

17:19 justin_smith: ,(contains? {:bag "OK"} :tag)

17:19 clojurebot: false

17:19 srbaker: ah, thanks

17:19 justin_smith: srbaker: it makes clojurebot evaluate things

17:19 srbaker: nice.

17:20 justin_smith: srbaker: also, in normal clojure code , is whitespace

17:20 _Bruno_: hey guys, does anyone know why (into {} [[:a 1] [:b 2]]) => {:a 1, :b 2} while (into {} ['(:a 1) '(:b 2)]) => throws ClassCastException??

17:20 justin_smith: ,,,,,(,,,,,+,,,,,,,,,,21,,,,,,,10,,,,,11,,,,),,,,,,,,,,,,,

17:20 clojurebot: 42

17:20 justin_smith: _Bruno_: because lists cannot be coerced to map-entries, but vectors can

17:21 _Bruno_: I came across this by trying to manipulating a sequence and turn it into a map, and I was curious to understand why the vector version works but it breaks with lists or sequences.

17:21 srbaker: (defn new-day [item] (if (contains? (item :content) :tag)) ...

17:21 i'm getting "unable to resolve item in this context" which is confusing :(

17:21 justin_smith: srbaker: too many parens

17:21 for starters...

17:22 or wait...

17:22 srbaker: are you sure that's what you have? because that should not complain about item - I mean if item is not callable it would complain about that

17:22 (:content item) would be more canonical

17:22 _Bruno_: justin_smith: is there any particular reason why would you not coerce a list into a map entry?

17:23 justin_smith: _Bruno_: I'm not totally certain of the reasoning, but I do know that clojure can use a vector as a map entry without creating a new data structure

17:23 or something like this...

17:23 but this can't be done with a list

17:24 _Bruno_: I guess the protocol need to be extended to lists as well.

17:25 justin_smith: well, lists aren't associative

17:25 so I don't know if extending the protocol even makes sense in that case

17:25 _Bruno_: MapEntry isn't either, it need just a tuple of two values

17:26 srbaker: it is complianing about item

17:26 justin_smith: _Bruno_: yes it is, all vectors are associative, and mapentry is a vector

17:26 ,(associative? [])

17:26 clojurebot: true

17:27 srbaker: it is definitely complaining about item :(

17:28 justin_smith: srbaker: can you use refheap.com to show us the whole function?

17:28 _Bruno_: justin_smith: vectors are but here you are trying to bridge Java's MapEntry which only cares about a key and a value which in turn can be extracted from a list with `first` and `second`

17:28 justin_smith: _Bruno_: no, this is clojure's map entry, which is a two element vector

17:28 luma: clojure's mapentry is a vector

17:29 justin_smith: _Bruno_: this isn't about the java data structures in hash maps at all

17:29 _Bruno_: justin_smith: it's java's one ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry

17:30 justin_smith: ,(into {} ['(:a :b)])

17:30 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.util.Map$Entry"\n :at [clojure.lang.ATransientMap conj "ATransientMap.java" 44]}]\n :trace\n [[clojure.lang.ATransientMap conj "ATransientMap.java" 44]\n [clojure.lang.ATransientMap conj "ATransientMap.java" 17]\n ...

17:30 justin_smith: oh, right, sorry

17:30 srbaker: hrm. not getting that error now. must've had some parens missing

17:30 justin_smith: anyway, the Map$Entry is a vector of two elements, regardless of provenance

17:30 srbaker: or too many at the bottom

17:31 _Bruno_: justin_smith: thx, i'll dig in the source code

17:31 justin_smith: _Bruno_: it's very unlikely you'll convice the core clojure team to change conj such that it would convert lists to map entries

17:32 though I guess it could be done hypothetically as a local extension

17:32 luma: clojure map's cons tries three different things: it checks if the object is a java.util.Map$Entry, then checks if it's a clojure.lang.MapEntry, then treats it as a sequence of java.util.Map$Entry without checking

17:32 justin_smith: luma: oh! I feel much less stupid now, thanks

17:32 luma: and it's conj not cons, of course

17:33 luma: in the java source, it's cons (but in clojure, conj obviously)

17:33 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java

17:33 justin_smith: oh, cool

17:33 srbaker: so the canonical form is (key map) for getting values from maps?

17:34 justin_smith: srbaker: if the map is not a literal but the key is, yes

17:34 srbaker: okay

17:34 justin_smith: srbaker: the idea being that you know what the key is because it's literal

17:34 whereas what happens if the map were a list instead? or nil?

17:43 luma: reading my comment again, the second check is actually for vector and not MapEntry

17:43 so that's why vector works but a list doesn't

17:45 _Bruno_: luma: looking at the code it looks like that lists or sequences are not accepted in order to be able to distinguish between the two following cases: (conj {} [:a 1] [:b 2]) and (conj {} {:a 1 :b 2})

17:45 luma: sounds reasonable

17:45 _Bruno_: the first one is a variadic parameter as seq of vectors

17:45 luma: since seqing a map results in a sequence of mapentries

17:45 _Bruno_: the second one is a seq of map.entry

17:46 justin_smith: I keep forgetting that (conj {} {}) works

17:52 srbaker: is there a pretty print function that will make these maps a bit easier to read when i print them?

17:52 justin_smith: clojure.pprint/pprint

17:52 srbaker: tack

17:52 justin_smith: it's automatically imported into your starting ns as pprint if you use nrepl

18:14 srbaker: ,(seq? "")

18:14 clojurebot: false

18:15 justin_smith: ,(map seq? [nil [] {} ()])

18:15 clojurebot: (false false false true)

18:36 srbaker: okay, this is a super weird error

18:37 https://www.refheap.com/109472

18:37 i'm sure it's someting to do with my expectionat of how the if works

18:37 in new-day

18:37 justin_smith: srbaker: line 10, (true)

18:37 ,(true)

18:37 clojurebot: #error {\n :cause "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java"...

18:37 TEttinger: ,true

18:37 clojurebot: true

18:37 justin_smith: srbaker: parens in clojure are not for grouping

18:38 they are for calling things

18:38 srbaker: oh

18:38 right, of course

18:38 and that shouldbe false :P

18:38 excellent. thanks

18:39 justin_smith: also, line 100 (= (:tag (first item))) will always return true

18:39 ,(= (:tag nil))

18:39 clojurebot: true

18:39 justin_smith: err, I mean line 11

18:39 srbaker: oh, right, i'm missing :strong

18:41 justin_smith: ,(map #(apply (first %) %&) (iterate #(conj % =) [= =]))

18:41 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/=>

18:42 srbaker: i'm getting a lot furhter when i switched to test-driving this.

18:42 justin_smith: srbaker: yeah, that can help a lot when it comes to keeping your steps organized

18:42 (and ensuring you don't break something as you fix something else)

18:42 srbaker: especially since i've practised TDD pretty much without exception since about 2001

18:44 justin_smith: ,(map #(apply (first %) (rest %)) (iterate #(conj % =) [= =]))

18:44 clojurebot: (true true true true true ...)

18:44 justin_smith: srbaker: that would help too!

18:45 srbaker: I'm a big fan of how you can make tests easy to implement in clojure by separating logic from side effects

18:45 well, I mean you can do that in other languages too, but clojure has some nice facilities for this sort of thing

18:46 amalloy: feature request: since (apply f x [y z]) is the same as (apply f [x y z]) already, (apply [f x y z]) should work too

18:47 * justin_smith votes amalloy to replace rhickey as bdfl.

18:47 giantwaffelcat: why do people think clojure is a lisp

18:47 dbasch: giantwaffelcat: because it plays one on the internet

18:47 amalloy: FR #2: replace all other characters in clojure source code with ( and )

18:47 justin_smith: giantwaffelcat: because they disagree with you about the definition of the word lisp

18:48 giantwaffelcat: heh

18:48 I'm just upset Clojure lacks cons

18:48 TEttinger: ,cons

18:48 clojurebot: #object[clojure.core$cons__4090 0x6db6d0a6 "clojure.core$cons__4090@6db6d0a6"]

18:48 justin_smith: ,(cons 'a nil)

18:48 clojurebot: (a)

18:48 giantwaffelcat: justin_smith: not proper cons

18:48 TEttinger: do you mean cons pairs?

18:48 giantwaffelcat: ,(cons 'a 'b)

18:48 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Symbol"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.lang.Symbol"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.lang.RT cons "RT.java" 655]\n [clojure.core$con...

18:48 giantwaffelcat: TEttinger: yes.

18:49 TEttinger: ,['a 'b]

18:49 clojurebot: [a b]

18:49 dbasch: giantwaffelcat: don’t focus on the cons, think of the pros

18:49 TEttinger: it is not that much different.

18:49 giantwaffelcat: also the fact nil isn't the (canon?) empty list is annoying

18:49 amalloy: anything you can do with improper lists you can do with real lists anyway

18:49 giantwaffelcat: dbasch: ...goddamnit

18:50 TEttinger: ,(seq (range 0))

18:50 clojurebot: nil

18:50 TEttinger: ,(seq [])

18:50 clojurebot: nil

18:51 TEttinger: if empty list was equivalent to nil, would appending to it result in a list or a vector?

18:51 conj can produce either

18:51 srbaker: aw shit, partition-by won't do what i want anyhow :(

18:51 TEttinger: ,(conj nil 1)

18:52 clojurebot: (1)

18:52 TEttinger: appears to be a seq anyway

18:52 srbaker: i was hoping that given a list of 1, 2, 1, 2, 1, 2; i could partitionon (= 1 1) and get three lists. whoops!

18:53 TEttinger: ,(partition-by (partial not= 1) [1, 2, 1, 2, 1, 2])

18:53 clojurebot: ((1) (2) (1) (2) (1) ...)

18:53 TEttinger: ,(partition-by (partial = 1) [1, 2, 1, 2, 1, 2])

18:53 clojurebot: ((1) (2) (1) (2) (1) ...)

18:53 TEttinger: ah!

18:53 you may want group-by, not sure

18:53 srbaker: oh

18:53 justin_smith: TEttinger: group-by returns a hash-map

18:53 TEttinger: err, no...

18:54 yeah I realized it was wrong after I said it

18:54 still waking up

18:54 srbaker: i basically want to iterate the list, and start a new sub-list every time (new-day) is true

18:54 justin_smith: srbaker: sounds like a good time to use reduce

18:55 srbaker: yeah.

18:56 justin_smith: ,(apply conj (reduce (fn [[done curr] el] (if (even? el) [(conj done curr) [el]] [done (conj curr el)])) [[][]] [1 2 1 1 2 1 1 1 2 1 1 1 1 2])

18:56 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:56 justin_smith: ,(apply conj (reduce (fn [[done curr] el] (if (even? el) [(conj done curr) [el]] [done (conj curr el)])) [[][]] [1 2 1 1 2 1 1 1 2 1 1 1 1 2]))

18:56 clojurebot: [[1] [2 1 1] [2 1 1 1] [2 1 1 1 1] [2]]

18:56 TEttinger: (inc justin_smith)

18:56 justin_smith: every instance of an even number starts a new vector

18:56 TEttinger: lazyboooooot!

18:56 justin_smith: KHAAAAAAAN

18:57 srbaker: ,(apply conj (reduce (fn [[done curr] el] (if (odd? el) [(conj

18:57 done curr) [el]] [done (conj curr el)])) [[][]] [1 2 1 1 2 1 1

18:57 1 2 1 1 1 1 2]))

18:57 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:57 srbaker: whoops

18:57 justin_smith: srbaker: yeah, one liners only with lazybot

18:57 srbaker: ,(apply conj (reduce (fn [[done curr] el] (if (even? el) [(conj done curr) [el]] [done (conj curr el)])) [[][]] [1 2 1 1 2 1 1 1 2 1 1 1 1 2]))

18:57 clojurebot: [[1] [2 1 1] [2 1 1 1] [2 1 1 1 1] [2]]

18:57 TEttinger: ,(apply conj (reduce (fn [[done curr] el] (if (odd? el) [(conj done curr) [el]] [done (conj curr el)])) [[][]] [1 2 1 1 2 1 1 1 2 1 1 1 1 2]))

18:57 clojurebot: [[] [1 2] [1] [1 2] [1] ...]

18:57 srbaker: i'm actually oversimplifying with 1 and 2

18:58 justin_smith: srbaker: I assumed, but I also figure you can do the mutatis mutandis to make it work with your code

18:58 srbaker: it's literally: a list of lists. the list is either a 1 element string; or a list of things where the first element is a hash with :tag => :strong

18:58 and it comes in, in order.

18:58 justin_smith: srbaker: do they always strictly alternate?

18:58 srbaker: i'm writing a bot to scrape and parse the lunch menus for the two restaurants near our office

18:58 so we can ask a slack bot what's for lunch.

18:59 justin_smith: srbaker: admirable plan

18:59 srbaker: justin_smith: yes, they always alternate. but the list elements mightbe varied

18:59 here's the menu: http://valfarden.nu/dagens-lunch/

18:59 justin_smith: in that case you can ditch the reduce and use partition-all 2

18:59 ,(partition-all 2 [:a :b :a :b :a :b :a :b])

18:59 srbaker: nope. while there are two options per day this week

18:59 clojurebot: ((:a :b) (:a :b) (:a :b) (:a :b))

18:59 srbaker: it's not always true

19:00 justin_smith: ahh, OK

19:00 srbaker: ii think reduce will do it

19:00 justin_smith: in that case a reduce to start new collections as you go should handle it then

19:00 yeah

19:00 srbaker: yep. it's a pattern i'm not familiar iwth, and it's 1am

19:00 so i'm probably going to give up for the night shortly

19:01 the solution is reduce, so i can start with that in the morning

19:01 i know how i'd do this with #inject in ruby, which is just reduce.

19:01 justin_smith: srbaker: do note that this is using a non-obvious idiom of making a collection of collections as the accumulator, and conditionally emptying an in-progress collection into the master collection at each step

19:02 s/emptying/putting oops

19:06 I should totally write a splits function that does what people keep expecting split-with to do

19:09 amalloy: flatland.seq has partition-between

19:09 er, flatland.useful.seq

19:10 _Bruno_: justin_smith: what do you think split-with should do?

19:12 justin_smith: _Bruno_: I'm fine with what split-with does, but what people keep expecting it to do is slice a collection based on a predicate

19:12 so that each item that is truthy for that predicate becomes the start of the next subsequence

19:12 (which is also useful and I think deserves to be its own function)

19:12 _Bruno_: justin_smith: isn't that partition-by ?

19:13 justin_smith: I think that's a special case of amalloy 's partition-between

19:13 _Bruno_: partition-by only splits once

19:13 oh wait,

19:13 you are right

19:13 amalloy: justin_smith: no, he's not

19:13 justin_smith: _Bruno_: it's almost partition by

19:14 _Bruno_: the one which split only once is split-at

19:14 justin_smith: but still not quite - that one starts a new coll every time the f returns a different value

19:14 amalloy: your predicate thing is different from partition-by, but not because of number of splits

19:14 right

19:15 justin_smith: what I am talking about is (splits #{:a} [:a :b :a :b :c :a :c]) => ((:a :b) (:a :b :c) (:a :c)))

19:16 amalloy: right. which is different fro partition-by

19:16 justin_smith: amalloy: yeah, and it can be done with partition-between just by testing the pred on the second item in the arg

19:17 _Bruno_: justin_smith: could be called split-when

19:17 justin_smith: _Bruno_: that's a good name for it

19:18 amalloy: the split- family of functions each split once, and the partition family split N times. if you were going to define this function i wouldn't call it split-X

19:18 _Bruno_: amalloy: partition-when then :-)

19:20 oddcully: partition-at

19:22 justin_smith: ,(defn partition-when ([p? [c & cs]] (partition-when p? cs [c])) ([p? [c & cs] acc] (cond (empty? cs) [acc] (p? c) (lazy-seq (cons acc (partition-when p? cs [c]))) :else (partition-when p? cs (conj acc c)))))

19:22 clojurebot: #'sandbox/partition-when

19:22 justin_smith: ,(partition-when #{1} [1 2 1 2 3 1 2 3 4 1 2 1])

19:22 clojurebot: ([1 2] [1 2 3] [1 2 3 4] [1 2])

19:23 justin_smith: oh it dropped the last part there...

19:23 oddcully: then do a partition-when-all

19:24 _Bruno_: (defn partition-when [p c] (->> c (partition-by p) (partition-all 2) (map (partial apply concat))))

19:24 justin_smith: ,(defn partition-when ([p? [c & cs]] (partition-when p? cs [c])) ([p? [c & cs :as coll] acc] (cond (empty? coll) [acc] (p? c) (lazy-seq (cons acc (partition-when p? cs [c]))) :else (partition-when p? cs (conj acc c)))))

19:24 clojurebot: #'sandbox/partition-when

19:24 justin_smith: oddcully: it was just a bug, I don't need the all version :P

19:25 ,(partition-when #{1} [1 2 1 2 3 1 2 3 4 1 2 1])

19:25 clojurebot: ([1 2] [1 2 3] [1 2 3 4] [1 2] [1])

19:25 justin_smith: _Bruno_: that's a nice way to do it too

19:28 noncom|2: i am using the latest version of tower and timbre from ptaoussanis and tower cannot be required because it does not find "timbre/logp", how can this be?

19:28 both are of the latest versions and from the same author

19:28 did anybody encounter such an issue?

19:30 justin_smith: noncom|2: have you checked lein deps :tree ? that should show potential conflicts or misversionings

19:31 amalloy: justin_smith: the lazy-seq is in an odd place there. i think you want to either write (lazy-seq (cond ...)) or, better, (cons acc (lazy-seq ...)). and the last clause can/should use recur

19:31 justin_smith: ahh

19:31 good point, thanks

19:31 *points

19:31 noncom|2: nope, did not check, will look at it now

19:37 justin_smith: heh, it does not show anything, but manually i have found out that the latest version of tower uses timbre 3.3.1 while the latest version of timbre is 4.1.1

19:37 weird

19:39 damn so i hate when projects do not compile of incompatible logging frameworks...

19:39 had this happening in java many times

19:39 thats why i really prefer println

19:40 justin_smith: noncom|2: I know, let's make a new logging framework api, that should fix this problem right?

19:40 noncom|2: yeah!

19:40 :D

19:41 emdashcomma: heh

19:41 crocket: What makes datomic attractive?

19:41 emdashcomma: strong, symmetrical features

19:41 crocket: Its EULA is unattractive, though.

19:43 oddcully: haha. and while you are at it also create a new linux distribution

19:45 noncom|2: sure! we'll get it integrated right into the core!

19:45 oddcully: a linux distro specialized in java logging

19:46 noncom|2: yeah!

19:46 and it will be very flexible, so the user will have to like, manually compile like 1000+ other libs

19:46 emdashcomma: infinitely configurable

19:46 crocket: Fuck

19:46 emdashcomma: make sure it doesn't do anything useful out of the box

19:46 better, have a team of consultants to offer

19:47 noncom|2: yeah! and we'll provide a script that does half of the setup for ubuntu 10.04 coz we care

19:47 oddcully: export EDITOR=nano sorted!

21:53 elvis4526: Is there a way to pass arguments to tests ?

21:53 Let's say for example when you're inside a fixture

21:53 justin_smith: no, fixtures don't pass data to tests

21:53 though they can use binding of special vars

21:54 elvis4526: but remember that you can call test/is inside a normal function, and then call that function from multiple tests

21:54 (or multiple times in one test)

21:54 and then, you absolutely can pass in eg. different test data to the same harness

21:55 Trioxin: what do ppl use for clojure on windows? intellij?

21:56 cursive..

21:57 cfleming: Trioxin: People use all sorts of things, but I try to make it easy with Cursive

21:57 Installing lein can be tricky so I bundle it, and you can do all your leiny things from the IDE

21:58 Which is useful for getting started - you'll want it working on the command line at some point though

21:58 elvis4526: justin_smith: okay thanks. Special vars are the same thing as normal vars, right?

21:58 Trioxin: cursive seems to not be out yet

21:58 justin_smith: elvis4526: not quite

21:58 ,(def *foo* 1) ; elvis4526 note the warning

21:58 clojurebot: #error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...

21:58 cfleming: Trioxin: It's not officially released but it works fine, it's as stable as anything else I think

21:59 justin_smith: elvis4526: anyway, in a real repl, if you try (def *foo* 1) it will warn you that the var is not declared dynamic, even though it has earmuffs

22:00 elvis4526: you make a special var with (def ^:dynamic *foo*)

22:00 elvis4526: Ah, right. I just tried with a non-special vars in the fixture and its still working

22:00 justin_smith: oh, you can use def too

22:01 but with a dynamic var you can use (binding [*foo* ...] ...) to rebind

22:02 elvis4526: the stackoverflow answer I read made it sound like the stars were just there to let know the programmer that the var was not dependant on lexical scope

22:02 justin_smith: the convention is that dynamic vars have ear-muffs

22:03 and yes, dynamic vars don't use lexical scope

22:03 elvis4526: okay - and what's exactly the difference between let and binding ?

22:04 Trioxin: Cursive > La Clojure?

22:04 both are intellij plugins

22:04 elvis4526: Trioxin: La Clojure is not maintained anymore AFAIk

22:04 Trioxin: kth

22:04 x

22:04 crocket:

22:04 justin_smith: elvis4526: let binds values to symbols that must be explicitly passed into a form to be used by that form

22:04 oddcully: i'd forget about ≠ cursive

22:05 it's all old

22:05 justin_smith: elvis4526: binding changes the value of a dynamic var, and this has effect until another binding form is reached, or the scope of the binding call is escaped

22:05 and this does not rely on passing values in, it changes the execution environments view of some var

22:06 the reason we make dynamic vars look weird is because the scope and value rules for binding can lead to programs that are hard to reason about

22:07 (but calling def inside runtime forms instead is even worse, mind you)

22:09 elvis4526: okay i get it - thanks

22:09 i'm not sure where dynamic vars would be that useful though

22:10 justin_smith: for situations where you need to change some code's execution environment. It's very useful for the UI of emacs, so much so that the default is for variables to have dynamic binding.

22:10 amalloy: they're easier to misuse than use correctly

22:10 justin_smith: very true

22:11 amalloy: the compiler and other tooling like emacs make use of a fair number of dynamic vars, but most user programs won't

22:11 justin_smith: elvis4526: another example, *out* is a dynamic var, because a repl user should be able to change where a subprogram sends its output without adding an extra arg to every output function

22:12 elvis4526: yeah it make sense - cool

22:20 Trioxin: so, I want to write my first clojure program (first lisp for that matter) and i have cursive and it's asking me what project type so I guess I should start with Java EE Application??

22:21 justin_smith: Trioxin: there should be a "lein project" option, or something like that

22:21 Trioxin: i dont see that

22:22 amalloy: you don't want a java application or a java ee application

22:22 Trioxin: http://screencast.com/t/xMMZ4ZVwffW

22:23 oddcully: Trioxin: for reasons unknow, it shows java ee... do a `lein new lerl` and open that project

22:23 crocket: Stay away from java ee

22:24 java ee involves application servers which you don't want to deal with.

22:24 justin_smith: Trioxin: that was the UI for "additional libraries and frameworks" and you don't need any of them - just a basic leiningen project

22:24 Trioxin: leiningen isn't under the clojure tab

22:24 crocket: Embed jetty in your web application. Don't embed your web application in a java-ee application server.

22:25 justin_smith: Trioxin: there's an option on the left to use Leiningen as the build / dependency manager

22:26 oddcully: Trioxin: do the `lein new` dance and then open/import from idea

22:26 Trioxin: so don't use the clojure tab to use clojure.. ok

22:26 justin_smith: cfleming: I think your further assistence might be required here

22:26 oddcully: he doesn't know lein yet I don't think, he was trying to do this via cursive (which I guess should be easier on windows?)

22:27 oddcully: justin_smith: then he has to learn. idea is just a borken editor

22:28 Trioxin: i've used other versions of this but not for java, for html5, php, C, C++, D

22:28 i mean not for lisp

22:30 choosing clojure as my first lisp

22:31 oddcully: Trioxin: i hate to bust the bubble, but idea is not the ``be all end all'' ide; cursive might lack right now the means to generate a project out of thin air. it's the same for "advanced" gradle, ...

22:32 Trioxin: guess I'll just find a clojure tutorial first and then i'll know how to do it all right

22:33 else I'll never cause the singularity

22:33 loljk

22:34 or am i?

22:34 cfleming: Trioxin: La Clojure is now officially deprecated in favour of Cursive

22:34 oddcully: no you are

22:34 all of them is depricated by not beeing useable

22:35 Trioxin: im not using la clojure

22:35 and i've done a lot of machine learning code

22:35 cfleming: Trioxin: In that screencast you sent, "Leiningen" appears on the left hand side as one of the project creation options.

22:35 Trioxin: yes

22:36 cfleming: That's the one you want

22:36 That will allow you to create a new lein project

22:36 oddcully: cfleming: not for me it doesn't

22:36 stuck at some java ee nonsense

22:37 cfleming: oddcully: What are you doing, exactly? File->New->Project..., select Leiningen from the left hand side list?

22:37 Trioxin: hold on updating my jdk first and then going back in there

22:37 cfleming, new project, then that yes

22:38 oddcully: meta-i -> ``Create New Project'' -> ``Leinigen''

22:38 Trioxin: well, I was under "Clojure"

22:38 and I checked out the other as well not knowing what it was then looked it up and about to open it again

22:39 idea

22:39 cfleming: oddcully: What do you have meta-i bound to?

22:39 oddcully: cfleming: start intellij

22:39 cfleming: Ok

22:39 oddcully: cfleming: that little window, with the "pick your project" stuff

22:40 cfleming: oddcully: So you select "Leiningen", and the next step is Project SDK and Additional Libraries and Frameworks

22:41 Trioxin: oh he's doing the same thing I am

22:41 oddcully: cfleming: yes. it's project sdk (1.8 here) and then it provides only java ee BS

22:41 cfleming: Right.

22:41 oddcully: this is on linux, if you mind

22:41 Trioxin: same on windows

22:41 cfleming: Where are you seeing the Java EE stuff?

22:41 Under "Additional Libraries and Frameworks"?

22:41 Trioxin: hold on ill screencast it again and try the leiningen

22:42 oddcully: cfleming: configure your idea to start up where the projects get picked

22:42 cfleming: oddcully: I don't understand what you mean

22:42 oddcully: iirc there is some switch that prevents loading the last project

22:42 cfleming: Oh, right

22:42 Ok

22:42 One sec

22:43 Trioxin: in my case there is no last project

22:43 oddcully: cfleming: isn't it way to early in the morning in jolly good england?

22:43 cfleming: Ok, let's go though this together

22:43 oddcully: It would be, but I'm in jolly good New Zealand

22:43 Trioxin: ok lol

22:44 oddcully: in that case... i'm way to early in the morning...

22:44 once you are at that

22:44 cfleming: Ok, so I'm on the "Welcome to IntelliJ" screen, previous project list on the left, IntelliJ logo on the right

22:44 oddcully: "idea startup screen thingy"

22:44 cfleming: Create New Project

22:44 oddcully: pick ``create new project''

22:44 cfleming: Leiningen

22:45 Choose your SDK

22:45 oddcully: for me there is regardless what i pick ``java ee''

22:45 cfleming: oddcully: Can you send a screenshot of what you're seeing?

22:45 oddcully: e.g. if i pick gradle, there is gradle stuff...

22:45 for leinigen there is only revolting java ee stuff

22:46 cfleming: oddcully: I need a screenshot to know what you're seeing

22:46 Trioxin: here's what he's doing

22:46 http://screencast.com/t/nEzBL05ONJ

22:46 cfleming: Trioxin: Thanks

22:47 Trioxin: ;)

22:47 cfleming: Ok, so that's all under additional libs and frameworks, you don't want any of that

22:47 It's all unselected by default

22:48 oddcully: well without a flash player i can not confirm it...

22:48 cfleming: Just press next after doing the SDK

22:48 You should see Project name: Project location: Template: Template options:

22:49 Trioxin: yes

22:49 cfleming: So if you just want a basic project, give it a name and location and press Finish

22:49 If you want to use a lein template, enter its name and any args it needs

22:51 Trioxin: eh. i used an uppercase char

22:51 there's an iml file

22:52 cfleming: The iml file is the IntelliJ module file

22:53 You don't care about that

22:53 Your namespaces will be under the src and test directories

22:53 Trioxin: oh wait

22:53 i did it without the uppercase erorr. now much more files

22:54 a project.clj file

22:54 src

22:54 core.clj

22:54 justin_smith: oh, yeah, it probably would not like a capitalized name

22:55 Trioxin: oh I have a hello world app

22:55 oddcully: cfleming: i can confirm, that clicking ``next'' and ignoring the java ee ends up in a clojure prohect

22:55 Trioxin: and my own namespace

22:55 cfleming: Nice

22:55 oddcully: s/h/j/

22:55 Trioxin: aaaaaand

22:55 some code I've never tried to understand sooo

22:55 lol

22:56 oddcully: from what is generated this looks like a `lein new xxx`

22:56 cfleming: Trioxin: Right click on the project.clj file in the root, and select Run REPL for <whatever>

22:56 oddcully: That's exactly what it is

22:57 oddcully: shall i dare to use e.g. `figwheel` for the template?

22:57 cfleming: Fortune favours the brave

22:57 justin_smith: haha

22:57 Trioxin: the result of that didn't run my code

22:57 it ran some server

22:57 then gave me the clojure version

22:57 cfleming: Trioxin: And gave you a window on the right?

22:58 Trioxin: yeah

22:58 oddcully: works fine too...

22:58 cfleming: Trioxin: That's what you want. Now you're ready for a Clojure 101 tutorial.

22:59 Trioxin: oh but my binary or jar or whatever... something was just compiled right?

22:59 justin_smith: Trioxin: clojure has a repl

22:59 oddcully: cfleming: get lost of that java ee stuff... it's scary sh**

22:59 justin_smith: Trioxin: the repl compiles forms as you enter them

23:00 Trioxin: i was expecting hello world

23:00 justin_smith: Trioxin: the idea is that you can use the repl to interactively define things, and then use the things that work to build up your app

23:00 cfleming: oddcully: I can't do anything about that, if you never use J2EE just uninstall the J2EE plugins and you won't see that.

23:00 justin_smith: Trioxin: you can run your -main to get the hello world

23:00 oddcully: cfleming: and while you are here... can we assume, that "current-2 years" will be the target for cursive for idea?

23:00 justin_smith: Trioxin: but that's not what the repl does right away

23:01 cfleming: oddcully: Yeah, last two major versions. Currently I sort-of support 12.1 but that's going away soon. 13.1 support will go away when 15 becomes GA

23:01 Trioxin: i get what you're saying but how do I run the existing code?

23:01 justin_smith: Trioxin: what namespace is your repl in (you can tell from the prompt)

23:01 if it's in your core namespace, you can run (-main)

23:01 cfleming: justin_smith: Trioxin: actually in the title of the REPL tab

23:01 In Cursive

23:01 justin_smith: cfleming: oh, OK :)

23:01 oddcully: cfleming: cool. i'd rather buy cursive than 15

23:02 cfleming: Trioxin: click in your main editor window

23:02 Trioxin: Then Tools->REPL->Load File in REPL

23:02 Trioxin: im in core. i just ran core and it exited with code 0 and showed that in bottom console

23:02 oh k

23:03 cfleming: That will load your code into the REPL

23:03 Trioxin: it's loaded

23:03 cfleming: Then Tools->REPL->Switch NS to current file

23:03 You should see the REPL NS change to the NS of your file

23:04 Trioxin: yes

23:04 cfleming: blah.blah.core, probably

23:04 Ok, now you have your code from your editor loaded, and your REPL is in the same NS.

23:04 Go to the REPL editor at the bottom right, and type (my-function), or whatever your function is called - I don't recall what lein generates off the top of my head

23:05 Trioxin: foo

23:05 cfleming: Ok, (foo) then

23:05 Trioxin: i did but it didn't do anything

23:05 cfleming: Sorry guys, I have to go

23:05 Trioxin: i just typed it

23:06 it autocompleted

23:06 cfleming: Hit Cmd-Enter

23:06 Or Ctrl-Enter if you're on Win/Linux

23:07 oddcully: (inc cfleming)

23:07 lazy bumbot

23:07 cfleming: You should also be able to type (+ 1 2) and hit Cmd/Ctrl-Enter and see 3 come out.

23:07 Aww man, my fake internet points!!!

23:08 ro50: Hi everyone I'm a linux noob...when I tried to install leiningen the install 'worked' but I could only run lein in sudo mode

23:08 justin_smith: cfleming: I'll make sure you get them eventually

23:08 amalloy: ro50: you used apt-get?

23:08 justin_smith: ro50: it's better to just install lein to your ~/bin/ and not do a system wide install

23:08 ro50: I tried from the web site, apt get doesnt have version 2.x

23:08 amalloy: well that's good

23:08 cfleming: Ok, I really do have to go. Trioxin: assuming you can execute things there, check out Aphyr's Clojure from the ground up, or Clojure for the Brave and True, and just ignore the bit where it tells you to install Emacs :)

23:09 justin_smith: ro50: that's the right way, lein manages it's own version better than linux would do it for you

23:09 Trioxin: k thanks

23:09 oddcully: apt-get lein? that would get you lein 0.01?!

23:09 ro50: in ~/bin/ the ~ refers to the 'home ' folder?

23:09 justin_smith: ro50: right, and make sure that is on your path too of course

23:09 oddcully: ro50: yes, ~ is $HOME

23:10 justin_smith: the idea is to have it be executable, but belonging to your user only

23:10 ro50: ok ~ is home of my normal account is / is root of the entire os right

23:10 justin_smith: ro50: right

23:10 ro50: my home folder doesnt have a /bin so i make one

23:10 justin_smith: yup

23:11 ro50: many linux distros come with a shell set up to add ~/bin/ to your PATH at startup if it exists

23:11 but this is easy to fix if yours does not

23:11 s/startup/initial login/

23:12 Trioxin: Hello World!

23:13 finally

23:13 ro50: ok I installed it but it says lein is not currently installed

23:13 Trioxin: don't know why a hello world needs an argument but okay

23:13 ro50: when I type lein in the terminal

23:13 Trioxin: oic it concatenated

23:13 sweeeeeeet

23:14 justin_smith: ro50: is your ~/bin in the $PATH variable in the shell?

23:14 ro50: uh im not sure

23:14 oddcully: ro50: in a _new_ terminal try `which lein`

23:14 ro50: nothing happens

23:15 after typing $PATH I get: me@me ~ $ $PATH bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin: No such file or directory

23:15 justin_smith: also double check that ~/bin/lein is executable, and then check that ~/bin/ is on your path (you can use echo $PATH to do that)

23:15 ro50: oh, you can also get your PATH from an error message :)

23:15 so no, ~/bin/ is not on your path, and you need to add it

23:15 in your shell you can do PATH=$PATH:~/bin/

23:16 to make this happen automatically it can be added to your shell init file, usually .bashrc or .login or .profile or something

23:16 (all will be hidden files in your home directory)

23:18 ro50: oh there is already something in there for that

23:18 i will try reset and see if it works

23:18 brb

23:19 justin_smith: oh man he left before I could tell him about "bash -l"

23:19 oddcully: he'l be right back

23:20 justin_smith: oddcully: right, but he didn't need to reboot

23:20 or whatever he thought he had to do

23:20 oddcully: he is doing the ole windowsaroo: reboot to update the env

23:20 justin_smith: the ms-dance

23:21 Trioxin: so, I'm used to curly braces and this defn shows the closing ) on the same line as the last statement in it. Is it bad form to close the function on the next line?

23:22 justin_smith: Trioxin: yup

23:22 Trioxin: whyyyyyyyyyyyy

23:22 justin_smith: Trioxin: we have different standards around here

23:22 Trioxin: I like it because it means I don't get confused about which kind of code I'm reading

23:23 (if the braces are on their own lines, I'm reading an algol, if on the same line, I'm reading a lisp)

23:23 rem500: hi got it working thanks everyone

23:23 justin_smith: rem500: cool, right as you left I was like "use bash -l instead of logging out or rebooting" but I was too late

23:23 lol

23:24 rem500: has anyone else read the leiningen vs the ants story it's good

23:24 oddcully: rem500: kindled it

23:24 justin_smith: yup, that's where the name of our build tool comes from - ant is a popular build tool for java

23:24 oddcully: justin_smith: also salve

23:25 TEttinger: Trioxin: I totally used to feel that way. I quickly got accustomed to closing parens on the same line because it saves a lot of space

23:25 justin_smith: oddcully: salve?

23:25 oddcully: justin_smith: vim-salve

23:25 Trioxin: is "I don't do a whole lot." here a comment? http://hastebin.com/purosucode.lisp

23:25 TEttinger: docstring

23:26 justin_smith: Trioxin: it's considered the official documentation of that function

23:26 Trioxin: oooo

23:26 justin_smith: Trioxin: you can look up doc for functions using the doc function too

23:26 ,(doc +)

23:26 TEttinger: ,(defn foo "I don't do a whole lot." [x] (println x "Hello, World!"))

23:26 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'"

23:26 TEttinger: ,(doc foo)

23:26 clojurebot: Excuse me?

23:26 #'sandbox/foo

23:26 Trioxin: well, I hope I like this enough to not want to go to CL

23:26 TEttinger: ,(doc foo)

23:26 clojurebot: "([x]); I don't do a whole lot."

23:26 TEttinger: there we go

23:27 justin_smith: Trioxin: cursive will use doc-strings for help popups iirc

23:27 rem500: I tried to learn clojure a month or so ago but now im back even though I'm busy

23:27 TEttinger: Trioxin: it's definitely an active community here. not sure if the same can truly be said of CL, which has been a bit more subdued I would say

23:28 Trioxin: i really wanted to try lispworks but it was a billion dollars

23:28 TEttinger: you're more likely to find up-to-date libs in clojure than for CL, I would say.

23:28 rem500: i never thought id see a lisp make a comeback

23:28 oddcully: Trioxin: better pay cfleming

23:28 Trioxin: i can use all that is java in clojure right?

23:28 TEttinger: yes

23:29 also, technically, all that is Scala or Groovy or any JVM language, though Java remains the easiest to call

23:29 justin_smith: clojure / java interop works very nicely going both directions

23:29 others might not be as easy (scala makes things harder then they should be to be sure)

23:29 Trioxin: interesting

23:29 TEttinger: Olajyd used the Scala Storm stuff from Clojure, that was... interesting

23:30 it worked though

23:30 Trioxin: what about mobile dev how is that coming?

23:30 i see lein-fruit and something for android

23:31 goby

23:31 justin_smith: yeah, there are projects, I've only done things with mobile via web-apps myself

23:31 TEttinger: I think, as for many many platforms, the best approach is "make a web app that the user can view on mobile and on desktop." and clojure has excellent support for that via clojurescript

23:31 Trioxin: clochure

23:31 justin_smith: TEttinger: exactly, that's what's worked for me

23:31 oddcully: i put some cljs stuff up for me mobile dudes. my last mobie projects made made me imagine killing people

23:32 TEttinger: there are also various things that let you convert a webpage to a web app. I believe Intel's XDK consumed Appcelerator Titanium

23:32 Trioxin: well I write all my mobile in HTML5 using cordova but I was thinking for heavy lifting...

23:32 TEttinger: yep, clojure works well on servers

23:32 Trioxin: or maybe better API access on the mobile platform

23:32 well, more not better

23:33 TEttinger: I've had clojure processes open for months without intervention. And, that was on a windows laptop with overheating issues

23:35 Trioxin: wonder how hard it would be to port my ANNs from c

23:36 * Trioxin getting ahead of myself

23:36 TEttinger: I'd imagine a rewrite would be easier than a port, myself. probably a lot shorter

23:36 justin_smith: ANN ?

23:37 TEttinger: the approaches used in C programs and in Clojure programs are really not at all similar.

23:37 Trioxin: neural networks. been doing prediction code lately on a side project

23:37 TEttinger: have you looked at Torch at all?

23:37 Trioxin: no

23:37 TEttinger: Torch struck me as unusually high-level Lua meant for neural networks and other scientific code

23:38 also it has GPU acceleration for CUDA stuff

23:38 Trioxin: I started with matlab

23:38 torch seems cool

23:41 TEttinger: there's some stuff in that area for clojure but I haven't looked into it as much

23:42 oddcully: i'm parsing factorio files with instaparse... i hope there is some jlua...

23:42 TEttinger: I've found clojure is really really good for writing complex collection heavy code without making your brain explode

23:42 the immutable collections are a big contributor to brain stability

23:43 Trioxin: i see clojure has been used in robotics, that's good

23:43 justin_smith: can verify, I have an explosion-prone brain and clojure is very nice about not lighting the wick

23:44 or was that "can verify, am exploded brain"

23:44 Trioxin: well it doesn't look too touch. I'm sure if I can learn all these other languages I can get this

23:45 i'm just wanting it mostly for the paradigms

23:45 TEttinger: clojure's also hilariously good at code golf. some CL people described Clojure as a Lisp meant for writing one-liners :)

23:45 (part of the joke being that any lisp program can be rewritten as a one-liner)

23:45 (for very long lines)

23:47 Trioxin: after this I'll get into python and then my brain will be complete with programming. I've stuck with the same languages for too long and all these papers come out in PY and ppl talking about lisp paradigms. must not miss out

23:51 will it be difficult to understand CL knowing clojure?

23:51 wow you weren't overselling the java interop. that was ez

23:52 justin_smith: in my experience using clojure after common lisp and scheme, there was a break in period of being constantly annoyed about minor syntax differences, followed by everything being easy because the core building blocks were the same.

23:53 Trioxin: fair enough

23:53 justin_smith: though CL and even scheme use mutable data structures much more than we do in clojure, so they make a wider variety of programming styles possible that don't work as nicely in clojure

23:54 the tradeoff is that due to clojure being more constricted in style we get nice things like easy concurrency (due to eschewing the things that make concurrency really hard, like rampant mutation of data)

23:54 Trioxin: it is easy to code CL or scheme as if they are clojure, coding clojure like one of the others is a bit harder

23:55 (and probably not a good idea even when it isn't hard)

Logging service provided by n01se.net