#clojure log - Jun 03 2014

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

0:57 rs0: i just noticed something else about the Clojure 1.6.0 Java API

0:57 rurumate: oi clojure, when doing (binding [*snowflake* "special"] (do-things)), and do-things does concurrent things like starting threads, will the binding of *snowflake* to "special" be visible in these threads?

0:57 rs0: the public API supposedly consists *solely* of IFn and clojure.java.api.Clojure

0:57 however, IFn in turn depends on ISeq, which depends on IPersistentCollection...

0:58 tolstoy: rurumate: I got the impression that bindings are thread-local.

0:58 rs0: so the transitive dependency closure of those two classes contains more than just those two classes

0:58 rurumate: that binding will not be visible in separate threads. however, there are cases where tasks will run in the *same* thread, and therefore will see the bound value. for instance, new Thread().run() will not create a new thread; it will directly invoke the Runnable in the current thread

0:59 rurumate: another example is a ThreadPoolExecutor with a CallerRuns saturation policy. that can cause tasks to run in the submitter's thread, with the submitter's bindings

0:59 rurumate: there's apparently an InheritableThreadLocal type since Java 1.2, but Clojure doesn't appear to use it

1:00 rurumate: what about pmap or fork/join things like reducers?

1:01 rs0: unless the API makes a specific guarantee, you'd have to read the source code to find out. generally you should assume that dynamic bindings will not propagate across thread boundaries

1:02 ambrosebs: rs0: every API has an implementation

1:03 rurumate: experimentation now

1:03 rs0: ambrosebs: that's not really my point

1:03 ambrosebs: the actual IFn interface makes mention of ISeq

1:03 rpaulo: trying to use seesaw and getting: Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: No matching ctor found for class com.jgoodies.forms.layout.FormLayout. This is on (forms-panel)

1:03 rs0: ambrosebs: which makes ISeq part of the public java API, unless the contract is "you can expect ISeq to exist, but you can't expect any particular methods on it to exist"

1:04 rurumate: if bindings are not inherited, using them seems brittle because concurrency might be added to the program later on

1:04 ambrosebs: right? you still use the `seq` Var to get an ISeq

1:04 you don't actually use ISeq

1:05 tolstoy: rurumate: I think the pattern is that you rebind for a single thread so that you can "customize" that value JUST for a thread. Atoms make better "shared state" for threads.

1:05 rurumate: yeah but atoms are not automatically reset to root binding after the work is done

1:06 tolstoy: Maybe a macro?

1:06 rhg135: tolstoy, wouldn't it mess up any concurrent ops?

1:07 rurumate: also atoms are automatically shared between *all* threads which might be more than I wanted

1:07 tolstoy: (defmacro with-reset [some-atom] `(let [orig# @some-atom] ~@body (reset! some-atom orig#)).... blua blah.

1:08 rurumate: Ah, well. "Depends on the problem you're trying to solve." ;)

1:08 rs0: i've got my library virtually 100% compliant with the public java API, although i'm fudging a bit by including AFn in a few places because I didn't feel like reimplementing all that invoke() boilerplate. however i'm also evoking clojure.core/eval in order to define multimethods, and i'd really really prefer to do that through a Java API

1:10 rhg135: rs0, am indurstanding correctly that it's in java using the api to add functionality?

1:10 if so i'm in awe

1:10 rs0: rhg135: ?

1:10 ambrosebs: rs0: can you write the boilerplate in a real clojure file?

1:10 rhg135: rs0, a jav app basically using clojure as a tool?

1:11 ambrosebs: I guess I mean the calls to eval

1:11 rs0: ambrosebs: i'll probably investigate that route next

1:11 mange: rurumate: Take a look at bound-fn for maintaining bindings in different threads

1:11 rs0: ambrosebs: it's easy to invoke remove-method, which is an actual function

1:11 ambrosebs: not sure how much it will help to write a function wrapper around a macro

1:12 ambrosebs: rs0: mm

1:12 rs0: rhg135: i'm writing a java library that makes it possible to use clojure maps from java code without ruining them https://github.com/rschmitt/dynamic-object

1:13 ambrosebs: cool

1:13 rs0: it's a bit like defrecord ported to java

1:13 ambrosebs: where's the eval calls?

1:13 rhg135: uh, why can't it be in .clj and gen-class a java api?

1:13 rs0: ambrosebs: i haven't pushed them yet =)

1:14 ambrosebs: or even better just write the interface in java and do everythign else in clojure

1:14 rurumate: mange: nice find, thanks

1:14 ambrosebs: is thatpossible?

1:14 rhg135: yes

1:15 reify ftw!

1:15 ambrosebs: looks like you're using generics..

1:15 rhg135: generics are only hints for the compiler

1:15 rs0: ambrosebs: okay, *now* it's pushed

1:15 rhg135: they don't exist in bytecode

1:16 rs0: i could look at reimplementing this in clojure, but i doubt i will... it's already working

1:16 rhg135: ahh

1:16 rs0: i'd rather add new features than rewrite old ones. it's the same reason the Clojure compiler is still written in Java

1:16 ambrosebs: Don't the generics exist for the Java user? seems like we're throwing them out.

1:16 amalloy: ambrosebs: yeah, writing an interface in java and reifying it from clojure is a great interop plan. it's what i do when i need to put a java-friendly face on some clojure code

1:16 rs0: besides, i'm relying on a lot of JDK8 features, like default methods

1:17 ambrosebs: the generics are basically so that the static methods in DynamicObject return the correct types without requiring the user to downcast, which wouldn't be idiomatic

1:17 Jaood: abandon ship, swift is here

1:17 rs0: ambrosebs: within the library, it's complete downcasting anarchy and dynamic typing

1:18 rhg135: just use Objects and reflection

1:18 performance may suffer but freedom goes up

1:19 dissipate: Jaood, yeah, i'm going to totally abandon ship for swift!

1:19 rs0: rhg135: can you be more specific?

1:21 dissipate: BTW, what's with all these programming language names that it's impossible to do a proper search for, like 'go'

1:21 rs0: dissipate: the convention is to use the term 'golang' instead of just 'go'

1:21 dissipate: it's funny that people have to manually SEO the name of a programming language that came out of a web search company

1:22 dissipate: rs0, that is pretty ridiculous

1:25 rs0: i remember that people made the same criticism of C# when it first came out

1:25 because back in those days search engines would just drop all the weird symbols

1:25 apparently

1:26 ambrosebs: rs0: is there much of a performance difference with generics?

1:26 dbasch: rs0: I worked at a search engine in the late 90s, and we had to create special tokens like AT&T

1:27 rurumate: "quoting may work when searching c#"

1:27 dbasch: we had a bunch of one-off special cases in the indexer parser

1:28 rs0: ambrosebs: the generics are purely a programmer convenience thing for users of the library, who are going to be accustomed to static typing and OO

1:28 talios: rs0 - mmm, dynamic-object looks damn squishy! I like.

1:28 rs0: talios: squishy?

1:28 rurumate: dbasch: I'm in the search business too, bro :3

1:28 talios: so huggable :) nice a nice plush toy

1:28 ambrosebs: rs0: ah ok

1:28 yea looks like fun

1:29 dbasch: rurumate: I’ve been out of the search business for a while myself :)

1:29 rurumate: sad to hear it

1:29 dbasch: rurumate: 14 years, it was time to try something else

1:29 talios: hey ambrosebs!

1:29 rs0: ambrosebs: the strategy here is to bring Clojure's strengths to Java development in the most inconspicuous way possible. we lie low for a while, as the user base of dynamic-object grows steadily. eventually, clojure.jar is part of every Java deployment. then we begin Phase Two

1:29 ambrosebs: talios: hi!

1:30 talios: ambrosebs - was thinking we should get you back on the show for a 3rd round state of typed-clojure ;)

1:30 rs0: this is all explained in http://www.youtube.com/watch?v=2WLgzCkhN2g

1:30 ambrosebs: talios: oh yea sure :)

1:30 talios: let's try July sometime

1:31 talios: sounds goodo

1:32 ambrosebs - will schedule something and get back to you

1:32 ambrosebs: talios: thanks

1:32 dissipate: rs0, i doubt that is going to happen

1:33 ambrosebs: rs0: improved startup time should be phase zero :)

1:33 rs0: ambrosebs: it's really easy, just use nailgun. nothing solves everything forever like nailgun

1:33 (not actually)

1:34 i guess improved startup time could also be realized through the use of clojure-scheme, which compiles to native code by way of Gambit Scheme

1:35 dissipate: i'm not being completely serious; i mainly just wanted something that would make java development easier at my dayjob. in particular, i really wanted to get away from object serialization libraries. object serialization is a complete scam

1:36 dissipate: however, widespread availability of the Clojure runtime couldn't hurt adoption

1:39 dissipate: rs0, well, you shouldn't be doing Java development at your day job... that's a problem right there

1:43 rs0: dissipate: at least i'm not doing Scala development at my day job

1:43 dissipate: or, like, C++

1:44 dissipate: rs0, *shiver* yeah, that's pretty bad too

1:47 dbasch: rs0: you know, there are Clojure jobs

1:50 dissipate: dbasch, i think i could only do the remote ones

1:50 rs0: dbasch: is the Clojure job market a buyer's market or a seller's market?

1:51 dbasch: or is it too illiquid to say?

1:54 dissipate: rs0, probably a lot like any other job market for a niche language

1:54 rs0: dissipate: i'm not really familiar with them, or with the general experience of hunting for jobs based on language

1:57 beamso: i've seen clojure job ads locally, but clojure is typically listed as one of several languages you're required to be familiar with

1:57 dissipate: rs0, for a niche language, there are fewer jobs, but the employment tends to be a bit longer term with more loyalty on both sides. not always, but more so than 'big tent' languages.

1:58 rs0, the flip side of that, is that there can end up being a lot more tasks for dealing with legacy code.

2:01 dbasch: rs0: I think it’s too illiquid to say

2:01 for my last contract gig I wanted to use Clojure in a Java shop. The compromise was Scala, and it didn’t work out too well

2:02 Scala/Java interop is type hell

2:18 rs0: dbasch: Scala is basically C++ for the JVM

2:19 bob2: that's unfair

2:19 it's even more complicated than c++

2:19 rs0: dbasch: different versions of Scala aren't bytecode-compatible forwards or backwards, which means that Scala and Java interoperate better than Scala and Scala

2:23 bob2: i think that Scala and C++ are both examples of very solid technical competence pursuing exactly the wrong principles

2:23 bob2: those languages weren't just built by incompetent amateurs like PHP was

3:41 hellofunk: Does anyone know how to specify that a route in Compojure is an HTTPS (secure) route?

3:57 blur3d: hellofunk: you could try https://groups.google.com/d/msg/compojure/XWluMvf4CBs/OJVc_IVPsxUJ

3:57 hellofunk: blur3d thanks I found that as well.

3:58 blur3d: I dont think it handles it any other way… you just have to add handlers for it

4:01 ddellacosta: hellofunk: this is basically what you want to do: https://github.com/noir-clojure/lib-noir/blob/master/src/noir/util/middleware.clj#L59-L68. You could probably just use that with a subset of your routes too

4:04 hellofunk: Thanks ddellacosta. I may have another question for you in a while once I exhaust my current attempts to get a user's email address from the Google access token.

4:05 ddellacosta: hellofunk: sure thing

4:20 hellofunk: ddellacosta you used drawbridge much? I'm starting to the feel the pain of remote development. every little change I must push to heroku. I can't do it on localhost since there are URI that requests must come from to google

4:21 ddellacosta: hellofunk: what is the google requirement, is that for openid or oauth2?

4:21 hellofunk: oauth2

4:23 ddellacosta: hellofunk: assuming you are using mac os x or linux to develop, just change the url to be localhost in your /etc/hosts

4:24 beamso: i've done oauth work where the URL i used was localhost :/

4:24 ddellacosta: hellofunk: ^ that's the other alternative, just create an alternate app in the google settings using localhost. That's how I test oauth2 anyways

4:24 hellofunk: ah ok, that would probably do it.

4:42 noncom: is it ok to have a package and ns with a same name, on the same level?

4:42 say i have "core.clj" and package "core" on one level

4:42 won't there be any problems with requiring or other ns-related management?

4:44 clgv: noncom: that's fine, I have seen an idiom several time where the implementation details were in such a namespace, e.g. my.lib as API namespace and my.lib.* with implementation namespaces

4:45 noncom: yeah, that seems like exactly my case :)

4:45 clgv: noncom: the folder name is only the last but one package in the fullqualified package name

4:46 noncom: oh, thanks for the correction

4:46 clgv: do you work with ccw?

4:46 clgv: in java that's different. there the fullqualified package consist of all the folders below the root source folder.

4:46 noncom: yes

4:46 all the time^^

4:47 noncom: clgv: ummm.. could you give a little example on difference between java and clojure package concept?

4:49 clgv: java: src/my/lib/MyClass.java => package "my.lib", clojure: src/my/lib/myns.clj => package "my.lib.myns" where function in the ns are classes with that package

4:50 noncom: aah, that's what

4:50 clgv: hence src/my/lib.clj => my.lib and src/my/lib/impl.clj => my.lib.impl

4:52 noncom: so that in the case that i first mentioned, with "core" and "core.clj", the compiled contents of the core.clj get laid together with the "core" folder contents ?

4:52 Glenjamin: does it help to think of clojure functions as java classes?

4:52 noncom: Glenjamin: i suppose it depends on the context of your thinking

4:53 Glenjamin: it's always package.package.package.Class

4:53 noncom: yeah

4:53 Glenjamin: but in java only the Class has a file, but in clojure the namespace (which is the last 2 bits) has a file

4:54 i'm unsure if that helps, but i think i get what clgv is saying - and it had never ocurred to me before

4:57 clgv: noncom: no in your case ...core.clj and ...core/some.clj have different namespaces, in that concrete examples the difference is an additional "some" package at the end

4:57 hellofunk: ddellacosta just to confirm, while most Friend credential functions take a map, the cred fn to your oauth2 workflow just takes the actual access token, not a map

4:58 clgv: noncom: though it depends which kind of clojure constructs you consider. since there is a difference between functions and deftype/defprotocol/defrecord

4:59 noncom: just AOT compile your whole project and investigate where the implementation ends up

4:59 ddellacosta: hellofunk: yes, you can see a simple example here: https://github.com/ddellacosta/friend-oauth2/blob/master/test/friend_oauth2/test_helpers.clj#L65-L67

5:00 noncom: okay, i will experiment more into this field. really, i saw all thsese things, but did not pay much attention, but now you got me interested

5:00 clgv: but ok, back to ccw

5:01 clgv: noncom: conclusion: your namespace layout is just fine ;)

5:01 noncom: have you ever tried to generate namespaces from templates? like have a command in your repl that creates a namespace in your project, filling it with a template? the problem i get is that eclipse does not recognize the created stuff..]

5:02 clgv: noncom: also after refreshing the project?

5:02 noncom: clgv: here is my q on so: https://stackoverflow.com/questions/22784284/creating-a-source-package-folder-in-a-counterclockwise-project-programmatically

5:03 but the last statement about eclipse recognizing extensions is i am *not sure of*

5:03 yes, refresing does not elp

5:03 i though just maybe you've tried that

5:04 it does not really always recognize the created structure of folders and source files, be it .java or .clj

5:04 clgv: noncom: does "leiningen->reset project configuration" help?

5:04 noncom: and sometimes does

5:05 clgv: does that actually have consequences on a freshly started REPL?

5:08 noncom: clgv: i do not remember.. it was some time ago, and now i'm coming back to the issue. i can't find that test project. i think i have to re-create the situation and test what you suggested..

5:08 this will only be possible much later in today, so i will try and then, maybe tomorrow, write back..

5:08 clgv: ok np.

5:09 "reset project configuration" should reset the classpath settings to what they need to be

5:09 hellofunk: ddellacosta it is rather interesting that the oauth2 callback URL is taken out of the equation when integrating with Friend which instead specifies the landing-uri. someday I should pour through the source to figure out how that works.

5:10 ddellacosta: hellofunk: what do you mean?

5:11 hellofunk: ddellacosta i mean once you get through the google login form, you are taken back to the site landing page specified in the :default-landing-uri part of the friend/authenticate rather than the callback url specified with Google

5:12 beamso: are you sure you haven't noticed it redirect from the callback url to the default landing uri?

5:12 it could just be very quick

5:12 hellofunk: beamso well perhaps it is, but that's nifty that Friend manages to override that

5:13 beamso: isn't it more that google redirects to your specified uri, your app takes the tokens out and links them to a user's session then redirects to the default landing uri?

5:14 i have to admit i did the oauth stuff with a phonegap app

5:14 hellofunk: beamso well that depends on the library you are using. i tried another oauth2 library and it just honored the google callback url, you do what you want on that page.

5:15 ddellacosta: hellofunk: try turning off https://github.com/cemerick/friend/blob/master/src/cemerick/friend.clj#L152

5:17 hellofunk: but you do certainly land on the callback before being redirected: google certainly doesn't know anything about your site other than what you tell it

5:18 hellofunk: ddellacosta ok, it's just really fast and I find rather interesting that Friend takes over there. I don't mind it, just shows the extent of operation that chas did.

5:18 ddellacosta: hellofunk: yes, it's a nice feature to have it redirect back to the page you intended to go to, agreed

5:18 hellofunk: ddellacosta which would work regardless of the workflow in action

5:19 ddellacosta: yep

5:19 hellofunk: unifies them

5:55 when you have a mutable atom in a ring server page, does each separate visitor to the server get only the initial state for the atom, or are changes to that atom visible to all visitors?

5:56 justin_smith: hellofunk: atoms are synchronized in state across threads

5:56 so changes made in one request should be visible to another

5:56 hellofunk: ok, thanks.

6:17 so ddellacosta, i'm using this guy's little fn to pull the email from google from access token: https://coderwall.com/p/y9w4-g

6:18 ddellacosta that fn uses a different oauth library. i tried to use his function with the access token returned from your oauth2 but that google user email fn seems to depend on the additional parts of the access token that your oauth2 strips out

6:20 ddellacosta for example your returns a nice and clean map with just :access-token. google returns a larger map that also includes expiration time, and :id_token and more. so whatever reason, those seem necessary when using the google email fn mentioned above.

6:21 ddellacosta: hellofunk: as I said previously, friend-oauth2 does not collect or use this information as it is not part of the oauth2 spec. If you want to use *all* the data google returns you'll need to patch friend-oauth2 yourself

6:22 hellofunk: otherwise, you'll have to use clj-http w/ the default way of accessing Google APIs via oauth2, what I linked you to yesterday

6:22 hellofunk: https://github.com/dakrone/clj-http, https://developers.google.com/accounts/docs/OAuth2?hl=en

6:23 hellofunk: ddellacosta ah ok, so Google is returning things in its oauth2 that are not actually oauth2-specific?

6:23 ddellacosta: hellofunk: yes, although I guess they may be part of the OpenID connect spec which I have not implemented as of yet

6:24 hellofunk: in any case, to save yourself some pain you may want to just patch friend-oauth2 for the time being to intercept what Google is sending you back, that will be simpler than doing a separate api call

6:24 hellofunk: ddellacosta ok; it is a bit confusing that OpenID Connect seems to be a part of the OAuth2 process, as if they are synonymous

6:25 ddellacosta: hellofunk: it is an extension to oauth2, and I was not aware of it (and may not have been around) when I started working on this

6:26 hellofunk: ddellacosta when patching a library such as yours, I suppose that instead of linking to clojars i'd just download the source and place it along with mine?

6:28 apologize for how green I am with some of this stuff, general dev workflow, etc

6:29 ddellaco_: hellofunk: sorry, got disconnected

6:29 hellofunk: no prob ddellaco_ did you see my question?

6:29 ddellacosta_: hellofunk: the simplest way is just to include the workflow itself in your codebase

6:29 hellofunk: and replace it at such a point that the openid connect flow is supported

6:30 hellofunk: which will be Real Soon Now

6:30 hellofunk: ddellacosta i've often wondered how github users collaborate; if multiple people are manipulating the same code base, I guess none of them would be using project.clj to specify dependencies, they'd just have the code in the src/ folder

6:31 ddellacosta_: hellofunk: ...most of the time if you are building a production app this is not an issue, in terms of dependencies

6:31 hellofunk: but it sounds like you need this ASAP so this is the best thing I can suggest

6:32 hellofunk: ddellacosta when i look at a repo and see many contributors to it, i assume this means that most of them would have the entire source mirrored in their project rather than using a lein dependency, is that sorta right?

6:34 ddellacosta_: hellofunk: I'm not sure I follow; if there are many contributors to a clojure project, it just means folks have patched it and submitted a pull request/committed at some point. It doesn't indicate anything about how the contributors have used it. Perhaps they used checkouts to test it in the context of another project, or just ran lein install...if that's what you mean.

6:36 hellofunk: you don't necessarily even need to be running that project in the context of another one to test and make changes, if that's what you were getting at--but I'm not entirely sure where you were coming from with that question, sorry.

6:36 hellofunk: ddellacosta, thanks -- having nor formal or institutional training or education in modern development workflows, and working mostly by myself, i'm often frustrated by how little i know about the general process that everyone takes for granted

6:36 ddellacosta_: hellofunk: ah, gotcha. Don't feel bad about asking questions, and sorry if I'm not always giving you the best responses.

6:37 hellofunk: just be patient and it'll become more clear

6:38 hellofunk: on that note, unfortunately I have to get going, but ping me again if you have questions. Hopefully some of the info I gave you will get you on your way.

6:38 hellofunk: ddellacosta_ thanks again!

6:38 ddellacosta_: hellofunk: np, cheers. :-)

6:59 cfleming: Hi everyone - I'm wondering how :refer-clojure :exclude works in cljs. Does it exclude symbols from cljs.core, macros, or both?

7:16 ambrosebs: *checks the source*

7:17 cfleming: ambrosebs: I tried that, but still wasn't sure :-)

7:18 ambrosebs: looks like it excludes everything.

7:19 try it: (ns my.ns (:refer-clojure :exclude [for])) (for [a [1]] a)

7:19 :)

7:19 cfleming: So for a given name, it'll exclude it from both? That was what I suspected, but couldn't tell.

7:19 Hehe

7:19 ambrosebs: yea I think the core-name? predicate in cljs.analyzer resolves core vars/macros

7:19 cfleming: The problem is I need a symbol defined as both a macro and a sym - I could set up a test case but I'm lazy :-)

7:19 ambrosebs: and that takes :excludes into account

7:20 cfleming: Ok, thanks - I'll assume that for the moment.

7:20 There's not much doc about a lot of these cases in cljs

7:20 ambrosebs: I'm sure we'll get to 0.1 one day.

7:21 cfleming: I'm working on indexing cljs now, it's surprisingly tricky

7:22 ambrosebs: what does that mean?

7:22 cfleming: I'm working on indexing cljs for Cursive.

7:23 It's tricky because the same name can and frequently does refer to two things.

7:23 ambrosebs: oh. hi colin :D

7:23 cfleming: :)

7:23 Hi Ambrose

7:23 ambrosebs: (thought your name looked familiar)

7:24 cfleming: Of course, it's additionally tricky because there's no doc about how this stuff actually works, and I'm not familiar enough with the code yet.

7:24 ambrosebs: and you're getting lazy

7:25 cfleming: Fortunately Clojure smiles on laziness.

7:25 ambrosebs: agreed

7:25 cfleming: That's my excuse, anyway

7:25 ambrosebs: I always look up cljs.analyzer instead of running cljs code :P

7:25 cfleming: Yeah, the code is actually really nice, it's very easy to understand in general.

7:26 It definitely looks like a v2 of the Clojure code :)

7:29 ambrosebs: yea. Looking forward to v3 with tools.analyzer.js

7:31 cfleming: Nice.

7:31 I must admit I'm a little lost with all the analyzers - I'm going to investigate them soon to get it all straight in my head.

7:32 Exciting things happening with clj compilation though, the GSOC projects look great.

7:38 ambrosebs: yea loving the foundation our students are building.

8:00 noncom: hey what's up with core.async?

8:00 so many talks were here

8:00 suddenly all is gone

8:01 did everyone finally understand everything about it/

8:01 ?

8:02 ambrosebs: all gone?

8:03 noncom: well, no more talks..

8:03 i loved reading them since that let me learn many new things

8:03 now however i am here, there is not much of them...

8:03 or maybe i am here at wrong times...

8:05 ambrosebs: I think #clojurescript discusses it every so often

8:06 noncom: ah, that's what - they moved to a separate channel

8:10 centrapheta: Hey all, so I thought of a programming challenge: Given 7 9 8 7 6 5 4 3 2 5 6 7 3 4 2 4 5 8 7 = 476 Goal: find out what mathematical operators (minus, multiply, divide, add) satisfy that solution (476)

8:10 Order of operation is variable.

8:10 Dynamic programming :)

8:10 Example output: http://pastebin.com/yDpS3Na4

8:15 * locks uses prolog and solves it in 3 lines

8:17 centrapheta: locks, :o how?

8:17 locks, Using dynamic programming?

8:26 clgv: centrapheta: is there a dp strategy, i.e. does the bellman principle apply?

8:27 centrapheta: clgv, dp[i][j][k] = Can I make the number k using the numbers a[i ... j].

8:28 clgv: ah right. that trick. large table then, exponential in the result size (476)

8:30 centrapheta: Just curious to see some clojure dp solutions :)

8:31 clgv: centrapheta: well if they shall be really fast, it's only almost imperative with clojure syntax

8:32 dp is just nested loops anyway ;)

8:33 mdrogalis: Just Wiki'ed the Bellman principle. That was too much before coffee.

8:33 clgv: mdrogalis: will get much easier after the coffee ;)

8:34 mdrogalis: As do most things. :)

8:35 clgv: mdrogalis: hm well, the wikipedia page does not have an easy top level explanation it seems ;)

8:36 mdrogalis: clgv: I didn't want to call you a liar, but.. :P

8:36 centrapheta: If I want to make X with the numbers A[i ... j], then I find a position v such that A[i ... v - 1] can make Y, A[v ... j] can make Y', and either Y + Y', Y * Y', Y - Y', or Y / Y' is equal to X.

8:36 That is how you compute A[i][j][X].

8:37 If you want to find some sequence that does, then in A[i][j][X] you store the position at which you split (v) and the operator you chose.

8:37 _Every_ expression that you can form using the numbers in A[i ... j] is of the form (Y) op (Y'), where Y is an expression obtained from A[i ... v - 1], Y' is an expression obtained from A[v ... j], and op is either +, -, *, or /.

8:38 mdrogalis: What is happening. D:

8:38 centrapheta: If I'm trying to find several, I'll store the several v, but that (since the number of answers is already exponential) will be exponential in space and time.

8:38 mdrogalis: Make it stop D:

8:38 clgv: mdrogalis: there are easier problems to learn DP ;)

8:38 mdrogalis: Ha. I'm just kidding, at any rate. Carry on :P

8:39 clgv: in fact a trivial on is the Fibonacci sequence. a more representative but still simple one is binomial coefficients

8:40 so back to linear algebra and matrices ^^

8:41 mdrogalis: Hah

8:59 adsisco: any good library to connect to mysql besides sqlkorma?

9:02 beamso: adsisco: clojure.java.jdbc?

9:05 adsisco: beamso: which is better?

9:07 alexherbo2: Hi

9:08 beamso: adsisco: i've only used clojure.java.jdbc

9:10 ddellacosta: adsisco: clojure.java.jdbc is lower level. You can use DSLs on top of it like HoneySQL or the more basic one available with clojure.java.jdbc (java-jdbc/dsl)

9:10 dabbelingClj: Hi there! I got a complex JSOn document/file, which clojure lib fits best to drill in and extract data from JSON?

9:10 ddellacosta: adsisco: korma is a bit more magical and higher level, and wraps up more functionality in its DSL

9:12 dabbelingClj: take a look at https://github.com/clojure/data.json and https://github.com/dakrone/cheshire and see which one you like better

9:13 dabbelingClj: ddellacosta: thanks, i have alook!

9:13 alexherbo2: How list all functions ?

9:13 cshell: Is there a way to build regex patterns by referencing other regex patterns in clojure?

9:14 alexherbo2: I’m writing syntax highlighting for Kakoune; i need the list of function names.

9:14 cshell: alexherbo2: http://clojure.github.io/clojure/

9:15 ddellacosta: cshell: you're talking about somehow composing regexes? Haven't heard of anything like that in Clojure

9:16 cshell: ddellacosta: Yeah, I’m writing a GC log parser and there are a lot of repeating patterns that happen so I was hoping to leverage some reuse

9:16 shep-home: cshell: sounds like you want a real parser :-)

9:16 Glenjamin: http://clojuredocs.org/clojure_core/clojure.core/re-pattern perhaps?

9:16 shep-home: https://github.com/Engelberg/instaparse

9:17 "there may be times when it is useful to build parsers with parser combinators."

9:17 alexherbo2: cshell: is there a function to get this list?

9:17 cshell: shep-home: haha, yeah

9:18 Glenjamin: thanks - that might work actually

9:18 alexherbo2: or i have to wget the page and parse it

9:18 ddellacosta: alexherbo2: try (map first (ns-publics 'clojure.core)) for example

9:18 cshell: Glenjamin: I was using the #”…” syntax but that might not work for what I’m doing

9:19 alexherbo2: ddellacosta: thanks

9:19 ^^

9:19 ddellacosta: alexherbo2: np

9:36 broquaint: If cshell was still about I would've suggested seqex - https://github.com/jclaggett/seqex

9:41 ddellacosta: broquaint: cool stuff

9:58 eflynn: is there anything wrong with a collection of atoms?

9:59 ddellacosta: eflynn: needs more context, but if you have a collection of atoms it begs the question of why you don't have an atom of a collection instead

10:00 eflynn: ddellacosta: because the atoms would be shared in other collections, but yeah the same thought occurred to me too

10:01 ddellacosta: writing a scheme interpreter in clojure

10:02 ddellacosta: eflynn: what part of the interpreter is this?

10:02 Glenjamin: the purpose of the atom-collections is some sort of reference lookup?

10:02 clgv: eflynn: well if you never need to coordinate between the atoms to have some consistent operation on that collection that might be fine

10:04 eflynn: ddellacosta: the environment part. you can see something like what i have here: https://github.com/gregsexton/SICP-Clojure/blob/master/src/sicp/ch4.clj this is not my code

10:05 ddellacosta: if you make scheme without set! or define it’s pretty easy

10:08 ddellacosta: eflynn: I'm not totally following what that code is doing, but if you needed an analogue to set!, could you just have something that looked up a value in a table inside (a collection in) an atom?

10:08 eflynn: swap!-ed it, to be clear

10:09 eflynn: sorry, that may not be too helpful...but good luck. Very cool project. :-)

10:12 eflynn: ddellacosta: yeah it’s hella confusing. an environment is represented as a collection of ‘frames’ and if a frame is changed, other environments that share that frame need to see it.

10:13 ddellacosta: eflynn: I see, so that code actually does what you're talking about, huh--I see it makes a frame via creation of a new atom. Hrm

10:14 * ddellacosta makes note to self to actually finish SICP some day

10:14 eflynn: ddellacosta: it was converted from a scheme version so maybe it’s not very clojure-y

10:26 dabbelingClj: How do I get the "type" of a clojure expression?

10:26 cbp: (type expr)

10:26 dabbelingClj: !

10:26 thanks i tried :type

10:28 cbp: dabbelingClj: that would work like this: (:type (meta expr)), but only for clojure values with that metadata added

10:29 dabbelingClj: cbp no its fine it works liek expected

10:54 I'm trying to acces data from a clojure Map, usually i use: (keys {:a 1, :b 2}), which gives: (:a :b), which is fine but Cheshire returns also keys which are not :keywords? how do i access those?

10:55 llasram`: ,(let [m {"a" 1}] [(m "a") (get m "a")])

10:55 clojurebot: [1 1]

11:02 dabbelingClj: llasram`: why i need the let?

11:03 sluukkonen: you don't, it's just for demonstration purposes

11:03 (m "a") and (get m "a") where m is the map are the important bits

11:04 dabbelingClj: So this is my code: (keys (parse-stream (clojure.java.io/reader "data.json"))) which gives : ("entities" "in_reply_to_status_id_str" "place" "user")

11:05 mpenet: dabbelingClj: cheshire can keywordise the keys btw

11:06 dabbelingClj: (get "user" (parse-stream (clojure.java.io/reader "C:\\Temp\\tweedlsclj2\\resources\\tweedls_data.json"))) <- nil

11:06 mpenet: ,(doc get)

11:06 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

11:06 dabbelingClj: I dont get it should be dead simple...

11:06 mpenet: you're inverting the parameters

11:06 dabbelingClj: ah!

11:06 mpenet: ,(get {"a" 1} "a")

11:06 clojurebot: 1

11:06 llasram`: And Clojure takes a pretty extreme "garbage in, garbage out" stance

11:07 dabbelingClj: makes sense!

11:09 hyPiRion: There should be a clojure variant with support wheels for such mistakes.

11:09 And I don't mean core.typed here

11:10 dabbelingClj: no its fine its an "ovious" API mistake on my side

11:11 can I put that (parse-stream (clojure ...) in a def ?

11:12 ha ok I always forget that i have to evaluate "every *new" expression in LT

11:13 nested gets I see a use case for -> and ->> :D

11:13 Glenjamin: if i have some related things i sometimes wrap in a (do)

11:13 or just shift+cmd+enter to re-eval the whole file

11:14 and i've got a keybinding for "save all + (tools.repl.namespace/refresh)"

11:16 clgv: damn, I thought I could use "balagan". but it seems it extracts all possible paths from the given data and then filters those that match the query. that is not really usable with a data structure of 2GB and lots of arrays in it

11:16 hhenkel: Hi all, I'm trying to cummulate the result of a for loop into a let binding. That works so far, only issue is, that I only get the last return value of the for loop: https://www.refheap.com/86232

11:17 Glenjamin: hhenkel: it's generally best to not think of for as a loop

11:17 it's a list comprehension

11:17 hhenkel: I used trace to see that the for loop is executed two times and give me a result two times.

11:18 Glenjamin: yes, good point, thanks for the clarification.

11:18 Glenjamin: although this looks sort-of right

11:18 clgv: hhenkel: does config/substitute-all-the-vars return different keys?

11:18 Glenjamin: the ->> is actually making it trickier to read though imo

11:18 gfredericks: (defmacro throw-data [s m] `(throw (ex-info ~s ~m)))

11:20 mpenet: gfredericks: should be in core, dunno how many times I wrote this

11:20 hhenkel: clgv: yes, I would say so. Every execution gives me a map.

11:20 mpenet: gfredericks: throw-ex-info, or throw+ or whatever

11:20 gfredericks: throwx

11:21 throan

11:21 throat

11:21 Glenjamin: hhenkel: if every execution gives a map, you probably want (reduce merge) instead of into

11:21 gfredericks: throne*

11:21 mpenet: feel free to add this to catch-data, wouldn't hurt

11:21 Glenjamin: then you basically have slingshot though, no?

11:21 clgv: hhenkel: huh? a map? well then "into" will use "merge" since you use "into" with a map as target. I thought it returns key-value-pairs

11:21 mpenet: a slim, slingshot

11:21 gfredericks: Glenjamin: without unnecessary features

11:22 hhenkel: clgv: Glenjamin: It gives me a datastructure descibing attributes of a server.

11:23 Glenjamin: ,(into {} [{:a 1} {:b 2}])

11:23 clojurebot: {:a 1, :b 2}

11:23 Glenjamin: ,(into {} [{:a 1} {:a 2}])

11:23 clojurebot: {:a 2}

11:23 clgv: Glenjamin: that's what I meant ^^

11:23 Glenjamin: hhenkel: can you give an example of what you want the input and output to be?

11:23 clgv: ,(into {} [[:a 1] [:b 2]])

11:23 clojurebot: {:a 1, :b 2}

11:24 clgv: hhenkel: and that's what I thought your code does ^^

11:25 hhenkel: ,(into {} ({:a 1 b:2} {:a 3 :b 4}))

11:25 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

11:25 clgv: hhenkel: why do you use "into" if your "for" does not contain key-value pairs?

11:27 PigDude: clojure has no notion of package privacy which means i need to make a huge namespace to share private functions between my code?

11:27 hhenkel: Glenjamin: I updated https://www.refheap.com/86232

11:27 clgv: PigDude: I would make them public.

11:27 PigDude: if my code can require foo.util, so can anybody else, it seems like a clean API is more difficult to achieve in clojure unless you write very large namespaces

11:27 that's what i do now clgv

11:28 cbp: ,(apply merge '({:a 1 :b 2} {:c 3 :d 4}))

11:28 clojurebot: {:d 4, :c 3, :a 1, :b 2}

11:28 llasram`: PigDude: You can annotate namespaces as :private. It's just a hint to the library user, but is an explicit one

11:28 clgv: usually it is a bad idea to make functions private anyway. there are some examples for that in clojure.core as well

11:28 hhenkel: clgv: I simply tried to adopt some code I was using at a different point and did not think about the datatype in the first place.

11:28 PigDude: llasram`: when would a code user see the :private metadata?

11:29 llasram`: PigDude: When the generated/manully-written documentation?

11:29 clgv: PigDude: how about an "api" namespace that contains only the functions a regular user is supposed to use?

11:30 llasram`: PigDude: It sounds like you expect people to just randomly depend on random namespaces, then burn down your house if you change anything they can access :-)

11:30 clgv: hhenkel: you want a vector or sequence of all the configs?

11:31 hhenkel: but you want to force immediate evaluation?

11:31 hhenkel: then use "doall" or "vec"

11:31 hhenkel: (into {}...) merges all your distinct maps together to one

11:32 hhenkel: clgv: okay, so I do "vec" instead of "into {}" then, right?

11:32 clgv: yes

11:33 llasram: ~tias

11:33 clojurebot: Try it and see! You'll get results faster than asking someone in #clojure to evaluate it for you, and you'll get that warm, fuzzy feeling of self-reliance.

11:33 llasram: Mmmmmm.... fuzzy....

11:34 gtrak: I like my peaches a bit cold.

11:34 devn: mushy peas, please

11:35 hhenkel: clgv: Thanks, that works like a charm.

11:36 clgv: hhenkel: better build up from scratch next time ;)

11:37 hhenkel: clgv: Yes, definitely.

11:39 PigDude: llasram: yes? :)

11:40 llasram: this is honestly how i often see my relationship with code users when i work on a library

11:40 llasram: you're probably right

11:40 clgv: that is what i do now, the API is in core

11:40 clgv: llasram thanks for the advice!

11:45 clgv: PigDude: http://steve-yegge.blogspot.de/2010/07/wikileaks-to-leak-5000-open-source-java.html

11:45 PigDude: :P

11:46 clgv: *I* have yet to see the case where java's security is useful, but i understand that in practice it's very important, and allows you to run untrusted code

11:47 clgv: (thinking of package privacy and such)

11:47 clgv: funny post bw

11:47 *btw

11:48 'The Agile Java community has denounced the Wikileaks move as a form of terrorism. "It was probably instigated by those Aspect-Oriented Programming extremists," speculates Agile Java designer Claudia Hewitt, age 29. "I always knew they wanted to use my code in ways I couldn't predict in advance," she added.'

11:49 gtrak: PigDude: steveyegge?

11:49 clgv: gtrak: yes ^^

11:49 PigDude: yea clgv sent me the link

11:49 gtrak: :-)

11:49 gfredericks: Veyeg Geste

11:50 gtrak: that was a much better age of his rants.

12:27 shriphani: hi. anyone here used quil? I have a question about images.

12:28 dbasch: ~anyone

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

12:28 shriphani: I am performing some animation using the standard routines and at the end I want the image to be displayed on top the animation one

12:28 done *

12:28 the image call seems to put the loaded image in the background

12:30 nbeloglazov: shriphani: can you show your code?

12:30 shriphani: sure one sec.

12:30 nbeloglazov: https://www.refheap.com/86236

12:31 see the draw routine and the call to image at the end

12:33 nbeloglazov: and that does this: http://shriphani.com/pics/bug.png

12:33 I want the image to lie on top of the animation. Is that not possible ?

12:36 nbeloglazov: out of curiosity, what happens if you switch renderer to :java2d or :p2d/:p3d?

12:37 shriphani: yup that works !

12:37 wee !

12:41 nbeloglazov: which renderer works?

12:41 java2d and p2d/p3d or only java2d?

12:43 justin_smith: shriphani: I think this has to do with how opengl handles identical z indexes

12:43 ie. it handles them kind of indeterminately

12:51 shriphani: nbeloglazov, both java2d, p2d and p3d

12:51 s/both/all/

12:54 nbeloglazov: shriphani: cool. Actually opengl renderer is not recommended to use in processing/quil anyway :)

12:55 stompyj: Just a poll, do people use jetty, tomcat, other app servers?

12:56 justin_smith: on aws I have used tomcat (via beanstalk)

12:56 because the was the mandated platform

12:56 gtrak: all the lein-ring stuff uses jetty, which means a lot of people use jetty

12:57 justin_smith: really, http-kit (maybe a few instances) behind nginx/varnish is simpler to set up, and performs much better

12:57 cbp: I just use http-kit behind nginx

12:57 justin_smith: gtrak: at dev time, sure

12:57 lein-ring in production is not a good idea

12:57 stompyj: my lein ring uberjar works find, but lein ring uberWAR is failing, with a very ambigious error

12:57 I figured most people are using jetty (that what I’m currently trying to do)

12:57 gtrak: stompyj: we opted for dropping lein-ring and building a custom servlet.

12:58 it's easy.

12:58 still using jetty though.

12:58 stompyj: well, I’m just trying to checkout from git, lein ring uberwar, copy to jetty and bounce server. That should be super easy too

12:58 but ok

12:58 enough people are using jetty that I shouldn’t necc. avoid it

12:59 has anyone seen when uberjar works, but uberwar fails?

12:59 I’m just getting a NullPointerException, but nothing else relating to my project

12:59 hiredman: stompyj: when are you getting the error?

13:00 stompyj: hiredman: immediately after running “lein ring uberwar"

13:00 Exception in thread "main" java.lang.NullPointerException, compiling:(util.clj:90:1)

13:00 oh geez

13:00 I’m a moron

13:01 ignore me. :)

13:01 cbp: lein profile.clj errors are ze worst

13:13 bbloom: dnolen_: i just discovered another use case for specify

13:13 on the jvm side that is

13:13 i have two different protocols in two different namespaces, but they have a common method name.... i can't use reify b/c then the names conflict as methods on the generated type

13:13 oh well. i'll just need to use a deftype

13:13 and extend

13:14 or rename

13:15 dnolen_: bbloom: I thought that shouldn't matter, two different protocols in two different namespaces

13:15 bbloom: dnolen_: reify only creates class methods, not protocol methods

13:16 dnolen_: oh huh, did not know that - that seems like the real issue

13:17 bbloom: i guess so, but i don't know how you'd address it without changing the interop characteristics of reify and/or making it inconsistent with deftype

13:17 deftype has the same issue, of course

13:19 Bronsa: bbloom: maybe making the method names for protocol interfaces include the namespace segment could fix it?

13:19 dnolen_: cool stuff http://rigsomelight.com/2014/06/03/devcards-taking-interactivity-to-the-next-level.html

13:19 bbloom: Bronsa: would be a seriously breaking change for interop

13:21 Bronsa: bbloom: yeah, that sucks

13:23 bbloom: dnolen_: video is a bit long so i just clicked through it. seems neat

13:40 bhauman: bbloom: I suck at videos, it took me forever to get that stupid thing dome

13:41 bbloom: bhauman: for introductory videos, the 60 second rule applies :-)

13:42 bhauman: bhauman: I hear you, but way beyond my skill level

13:42 bbloom: when i saw "14:10" i immediately said "not gonna watch this" and only bothered to press play b/c david mentioned the thing

13:42 bhauman: designing videos is just like designing code: it's done not when there is nothing left to add, but when there is nothing left to take away

13:44 bhauman: bbloom: yeah it’s a hard sell but, its something that IMHO was hard to express.

13:45 bbloom: Although apple did it in like 3 minutes

13:45 bbloom: bhauman: you mean the playground demo? heh

13:51 arrdem: Bronsa: t.a.jvm can't express the class method reach set of an expression in the general case, right? I'm pondering if there's static analysis I can do to prove out clojure.lang.Var/alter* or warn if present.

13:53 seangrove: bhauman: I feel you, you always want to spend time emphasis/explaining parts that you feel are important. Hard to resist that

13:59 stompyj: videos are particularly tricky, we can scan text, so it’s easy to skim and find the good parts/parts we’re interested in, or scan quickly and figure out if the writing is worth reading

13:59 videos are a blind investment.

14:00 Bronsa: arrdem: well, if you require that all the dependencies must be analyzed by t.a.j, you might be able to write a pass that does that I

14:01 gtrak: there needs to be like a clojure video feed.

14:01 twitter acct

14:01 it's hard to find good ones if I just go look for them, but sometimes that's what I want.

14:01 for working out or something.

14:02 cbp: how do you get the doc for a namespace?

14:02 bhauman: seangrove: yeah its like when you try to talk a client down from adding music to there website.

14:03 arrdem: Bronsa: okay, I'll play with it some. I think the answer is that you generally can't, but the hinting requirements on methdo invocations may enable the cases that I care about.

14:03 that or you can if you're willing to implement and eat an expensive pointer analysis.

14:04 Bronsa: arrdem: uhm derp. I assumed you were talking about static methods, not instance methods.

14:04 arrdem: Bronsa: oh static methods are what I care about, instance methods are hard to impossible.

14:05 so I should be alright.

14:08 * seangrove holds his breath, goes into #meteor

14:08 seangrove: Time to meet the community

14:09 bhauman: seangrove: good luck man

14:09 TimMc: Foley: Sounds of pots and pans hitting the wall, pottery breaking.

14:12 aperiodic: dakrone: is it a conscious choice that there is no way to set a default key-fn in cheshire?

14:12 Jaood: seangrove: you gave up on cljs? :)

14:13 seangrove: Jaood: Oh, of course not :) But we have some reasons for dealing with meteor

14:14 * seangrove rages at https://news.ycombinator.com/item?id=7841556

14:26 dbasch: why the rage seangrove?

14:27 seangrove: dbasch: Bad decisions winning again and again

14:27 bbloom: dbasch: dnolen_ myself and seangrove have all trashed shadow dom a bunch in this room, check the logs :-)

14:28 dbasch: bbloom: but why? I don’t know shadowdom but I’m sure it’s web scale :P

14:29 seangrove: dbasch: It's definitely web-scale, where web-scale means as horrible as everything else on the web :P

14:29 bbloom: dbasch: it's a very complex non-solution to the modularity problem of web pages

14:30 dbasch: why can’t we go back to the 80s, when screens were represented as grids instead of trees?

14:31 justin_smith: why not upgrade from trees to graphs? then we get fully fractal page rendering for free

14:31 hiredman: emacs still does that

14:32 I was looking at the source for the mac gui for emacs and all the rendering code still treats the screen as a matrix of characters

14:32 dbasch: justin_smith: then we can have turing-complete web pages

14:33 TimMc: Do everything in LaTeX.

14:33 bbloom: LaTeX, it's a lisp with fexprs! :-P

14:37 dbasch: I don’t even. http://stackoverflow.com/questions/24015415/clojure-defining-a-macro-that-uses-the-carret-metadata-syntax

14:39 justin_smith: the dude seems to have a fundamental misunderstanding of what metadata is for (based on that and his other SO questions)

14:40 amalloy: i saw that one this morning, dbasch. didn't you comment on it? did it get removed, or am i inventing memories?

14:40 dbasch: amalloy: I removed my comment after reading the other question

14:40 amalloy: I have no idea what that person is trying to do

14:41 Raynes: what is this i dont even

14:42 dbasch: I also don’t understand why people are so fascinated with macros, or think they are the solution to random problems

14:42 it’s like regular expressions

14:43 amalloy: *shrug* the new, novel thing you don't understand always seems like it must be the easy solution to all your hard problems

14:43 ToxicFrog: dbasch: because after using a language that has them for a while, you really miss them when you go to a language that doesn't.

14:43 Much like regular expressions.

14:44 Raynes: I actually don't really ever miss macros in other languages.

14:44 ToxicFrog: Oh. I do.

14:44 Raynes: Most of what I've used macros for that actually required macros has been relatively superficial syntactical things.

14:44 dbasch: ToxicFrog: you reminded me of that famous question about parsing html with regular expressions

14:44 ToxicFrog: (no, cpp does not count)

14:45 Raynes: well, yes, macros are syntax transforms, their most obvious application is making new syntax for things that are inconvient to do "plainly".

14:45 hyPiRion: Raynes: You have never tried to perform a variadic loop unroll through #define in C, it looks like

14:45 amalloy: dbasch: it's really more of a famous *answer*. the guy didn't even ask to parse html with regular expressions, he was just looking for a particular tag

14:45 bbloom: i much prefer eval over macros

14:45 i'm guilty of (doseq [...] (eval `(...)))

14:45 amalloy: wat

14:45 bbloom: works great, much easier to reason about & write than macros

14:46 dbasch: amalloy: yes, this one http://stackoverflow.com/a/1732454/586880

14:46 amalloy: bbloom: that's madness. you can just use a local macro

14:46 bbloom: amalloy: but then i have to NAME the macro :-P

14:46 amalloy: bbloom: pull in macrolet, man

14:46 or any utils library with a cousin of it

14:46 sbi_: lol :D

14:47 Raynes: ToxicFrog: Sure, but I just don't often find places where a macro makes things objectively better.

14:47 dbasch: I assume that the maintainer of my code will be an idiot, and that’s true even if I’m the only person to ever see my code

14:47 justin_smith: most of the time if I need to use a macro it is because I am using a macro and need a macro to compose functionality with it

14:47 bbloom: how is it any different to do (defmacro m [args] `(...args...)) (m a b c) rather than (doseq [x [a b c]] (eval `....

14:47 dbasch: especially if I’m the only person to see my code, as I get dumber with age

14:47 Raynes: It's certainly an important and amazing feature of lisps.

14:47 But I can live without it in other languages.

14:47 justin_smith: "if I need to write a macro" that is

14:48 bbloom: i may be a crazy person, but i no longer feel that eval is evil :-P

14:49 Jaood: you are evil ;)

14:49 Raynes: You're pretty screwed up, man.

14:50 Jaood: we should be talking about swift

14:50 bbloom: i find that i need a lot less syntax-quote and unquote to do simple top-level eval usage

14:51 dbasch: Jaood: swift is so yesterday, nobody cares anymore :P

14:51 I looked at it and my first impression was that it looked like a proprietary version of go. Not interesting unless you need to do iOS development.

14:54 Jaood: dbasch: and OS X

14:55 dbasch: Jaood: well, you have more choices if you’re sticking to OSX

14:59 amalloy: haha, excellent. google's first autocomplete suggestion for "printstacktrace s": "should be removed"

15:00 bbloom: haha

15:01 TimMc: amalloy: "clojure is |nil"

15:01 amalloy: it turns out to be not quite as funny: apparently that's the warning message netbeans gives you if you have "e.printStackTrace();" as the body of an exception handler

15:02 bbloom: some IDE decided that was as good enough as any codegen default

15:02 and people leave it there

15:02 dbasch: just like FIXME in clojure projects :P

15:06 TimMc: I had to add this to a java project to be able to use some of the Clojure persistent data structures and I don't know why. :-( https://github.com/timmc/johnny/commit/340a217e4554ca296351affbc20911aeb805d85a#diff-c6d534713fa591414088043313740566R18

15:07 (If this sounds familiar, I'm revisiting a project from a while back: http://clojure-log.n01se.net/date/2013-10-25.html#17:15)

15:07 Apparently there's something weird with the order in which Clojure classes have to load.

15:09 hiredman: yeah, RT really wants to be loaded first

15:09 TimMc: RT.init() yells at you if you call it.

15:09 hiredman: sure

15:10 you just need to load the class, not call any methods

15:10 similar to jdbc driver kind of things

15:10 Class.forName("clojure.lang.RT");

15:11 TimMc: Yeah, I suppose that would be more clear to the reader.

15:11 The error I get if I don't preload it is really bizarre though.

15:12 Something about contains? not supporting PersistentList -- but this occurs during PersistentTreeSet's class init.

15:14 hiredman: TimMc: is the java app multithreaded at all?

15:14 it could be some kind of concurrent classloading issue

15:15 TimMc: Nah, I'm just running the JUnit tests.

15:18 l1x: guys, what is your take on dealing with files in Clojure? Should I use java.io.File to pass in to functions dealing with files or just string and convert it locally to a File type? both cases how would you deal with the different path element separators (windows

15:18 and macos)

15:18 amalloy: $google raynes fs

15:19 lazybot: [Raynes/fs · GitHub] https://github.com/Raynes/fs

15:19 justin_smith: l1x: also, the existing java libs already abstract over that stuff, and it is not hard to interop with them

15:21 l1x: a project I contributed to once tried to account for the separator used by each OS, but it turned out that broke things and the right way is to use '/' everywhere and let java.io.File decide when that needs translating

15:21 l1x: justin_smith: i was thinking having a function that reads files, but i am not sure if i should pass in a [] with the path so it can construct the platform specific File of it or should i pass in a File from each function i have

15:21 cbp: lix File can take multiple strings and will automatically add the separator no?

15:22 l1x: cbp: exactly

15:22 justin_smith: cbp: sure, but if you use '/' it turns that into the right separator for the platform

15:26 cbp: you see my sick pr sdegutis, i got you 2 stars

15:26 er

15:26 ignore that

15:28 justin_smith: /ignore that

15:46 johnwalker: why doesn't (.start (Thread. #(println "print"))) print "print"?

15:47 o_o

15:49 cbp: johnwalker: it does

15:50 johnwalker: if you're using cider it's not consistent with where it shows you your prints

15:50 johnwalker: oh what the fuck

15:51 cbp: when you use multiple threads

15:51 johnwalker: that explains a lot actually

15:51 because using .run gave me some output

15:51 thanks cbp

15:52 dbasch: johnwalker: check your *nrepl-server* buffer

15:54 johnwalker: right on dbasch

15:55 thanks :)

16:09 fifosine: Is there a way I can define a set but not generate its contents (because it is very large) and ask for a random member of that set?

16:10 bbloom: fifosine: clojure's collections are extensional

16:10 fifosine: bbloom: What does that mean?

16:10 bbloom: fifosine: mathematical term for the opposite of another mathematical term: intentional

16:10 extensional means the collections list all the members

16:11 intentional means it lists the criteria to be a member

16:11 ystael: bbloom: inten_s_ional

16:11 bbloom: ystael: dur, you're right

16:11 ystael: amalloy can tell you that my spelling sucks

16:11 fifosine: anyway, the point is: you can just define a function for membership testing & pass that function around

16:12 fifosine: you don't need it to be a clojure set

16:12 fifosine: bbloom: In the end, what I'd like to do is be able to query a random color (from the 256^3 space of colors) that is not in the given set of colors. What I don't want to do is have to make that entire color space.

16:12 bbloom: just use a predicate directly

16:12 l1x: is there an easy way to pass in a list of a function that calls an another function and puts the list elements as parameters?

16:12 bbloom: fifosine: what's wrong with simply creating a random-color function?

16:13 l1x: your explaination is not clear, please give an example

16:13 fifosine: bbloom: So, inside this random-color function I generate a random color, then check that it doesn't exist in the given set. If it does, then what, call random-color again? I don't want the stack to explode as the given set grows

16:14 l1x: (defn test [&params] (test2 param0 param1 param2....paramN))

16:14 PigDude: i noticed lein taking longer and longer, with all plugins removed it take 10s to start, without them it was taking 30+s. what do you do about this?

16:14 fifosine: bbloom: I want a random and unique color

16:14 Bronsa: l1x: I think you're talking about apply

16:14 l1x: Bronsa: hmm maybe

16:14 PigDude: oh sorry wrong channel

16:14 Bronsa: ,(apply + [1 2 3])

16:14 clojurebot: 6

16:14 ystael: fifosine: the algorithm you give is tail recursive, so if you use `recur` you need not worry about the stack

16:14 fifosine: ystael: You're right, didn't realize

16:14 ystael: this is a common way to generate random elements when the excluded set is small

16:15 bbloom: fifosine: how many colors are you generating?

16:16 fifosine: bbloom: At some point, up to half of all colors

16:16 bbloom: Would a set difference make more sense in this case?

16:16 bbloom: fifosine: setting aside that i feel like you've got a serious design problem that i don't understand yet... you'd need a custom data structure to do this efficiently

16:17 you have a total ordering of colors, so you can create an extent map

16:17 an extent map is a sorted set of ranges of used colors

16:18 there are many extent map data structures, such as bitmap trees and stuff like that

16:18 but really, i think this is totally crazy... so please explain what you're actually trying to accomplish

16:18 i'm sure there is a much simpler solution

16:18 fifosine: bbloom: I'm trying to paint a canvas with 1 pixel per unique color

16:19 bbloom: fifosine: as like an art project? or what?

16:19 fifosine: bbloom: For fun

16:19 bbloom: yeah, that's what i meant

16:19 ok

16:19 well, if it's for fun, go crazy :-P

16:19 fifosine: I still want it to be fast

16:20 amalloy: fifosine: so just loop over all colors, in order, right? do you need it to be random?

16:20 fifosine: amalloy: I want it to be random

16:20 ystael: fifosine: so essentially your problem is: generate an initial segment of length canvas-pixel-count, of a permutation of the vector of all 2^24 colors, where that permutation is chosen uniformly at random over all permutations of the color space?

16:21 bbloom: ystael: that's an interesting way to reason about it

16:21 fifosine: ystael: See the top answer here: https://codegolf.stackexchange.com/questions/22144/images-with-all-colors

16:22 I wanted to do this in clojure

16:22 So I'm curious to find a fast way to query a unique color

16:22 Yes, the colors are a permutation, but a specific permutation

16:23 ystael: oh. if you don't want a _random_ permutation, it's much easier, you just have to prove that your generator does not visit the same tuple twice

16:24 which is easier to do by static analysis than by choosing a clever data structure to make that fact manifest in the code

16:24 fifosine: ystael: What static analysis is available?

16:25 bbloom: he means simply reasoning about your code

16:27 fifosine: ystael: The solutions I see are: generate the color space, select a random color, and remove it one-by-one; perform a set difference between all colors and all used colors and select a random one; or recursively select a random color until we find one that has not been chosen.

16:27 amalloy: fifosine: for example, you can use the chinese remainder theorem to generate an ordering that appears random and is guaranteed to not repeat

16:27 fifosine: None of these seem like the best approach

16:28 ystael: fifosine: You're going back and forth on whether you want the colors to appear in a random or deterministic order

16:28 bbloom: fifosine: do you have something slow working yet?

16:28 start there!

16:28 amalloy: think of each color as a number from 1 to N (where N is a prime number somewhere near 2^24). pick another prime P, and a "seed" color X. compute X*P, X*P*P, X*P*P*P, all mod N

16:29 fifosine: bbloom: I do, but it's written in python, so I'm trying to convert it

16:29 amalloy: those are guaranteed to not repeat until you've exhausted all choices

16:29 bbloom: amalloy: that's neat!

16:29 fifosine: amalloy: This is the chinese remainder theorem?

16:29 amalloy: as i remember it, anyway. number theory was ten years ago; the details may be a smidge off

16:30 fifosine: Should N be larger than 2^24?

16:30 amalloy: if you want all possible colors available, then yeah, pick the smallest prime larger than taht

16:30 (and ignore any results which are too large to be rendered as a color)

16:32 ystael: amalloy: I don't think that's good enough; you need P to be a primitive root modulo N (generator of the multiplicative group of Z/NZ).

16:32 amalloy: ,(let [n 13, x 5, p 7] (for [i (range n)] (mod (apply * x (repeat i p)) n)))

16:32 clojurebot: (5 9 11 12 6 ...)

16:32 amalloy: ystael: i don't know what that means, but i think i'm right as long as P and N are both prime (as i stipulated)

16:32 &(let [n 13, x 5, p 7] (for [i (range n)] (mod (apply * x (repeat i p)) n)))

16:32 lazybot: ⇒ (5 9 11 12 6 3 8 4 2 1 7 10 5)

16:33 fifosine: ystael: amalloy's conditions are more strict than yours, I think

16:34 ystael: &(let [n 13, x 7, p 5] (for [i (range n)] (mod (apply * x (repeat i p)) n)))

16:34 lazybot: ⇒ (7 9 6 4 7 9 6 4 7 9 6 4 7)

16:34 ystael: amalloy: Nope.

16:35 fifosine: nice example

16:36 amalloy: huh. well, i don't see what's wrong, ystael, and your objection was beyond my vocabulary. can you explain in baby-talk for me?

16:37 ystael: You're asking for (1, p, p^2, ...) to visit all the nonzero (multiplicatively invertible) entries of Z/nZ.

16:38 This does happen for some p, but not all p, and it's not directly identifiable with whether or not p is prime.

16:39 If p does generate all of the nonzero entries of Z/nZ in this way, it's called a primitive root modulo p. The number of primitive roots modulo p is Phi(p - 1) (Euler Phi function) which can be proved with a little bit of group theory.

16:40 GFREDERICKSdotCO: cemerick: ping

16:40 ystael: Sorry, some wrong letters there; every 'p' after "it's called a primitive root modulo" in that last line should be an 'n'.

16:42 If you know about cyclic groups, this is rooted in the fact that the multiplicative group of Z/nZ (n prime) is a cyclic group of order (n - 1). For n = 13, this means a cyclic group of order 12.

16:44 But that has a bunch of proper subgroups -- 7 happens to be a primitive root, but neither 7^2 = 10, 7^3 = 5, or 7^4 = 9 is one.

16:44 (because (7^2)^6 = (7^3)^4 = (7^4)^3 = 7^12 = 1)

16:44 * arrdem isn't convinced that ystael is speaking english

16:45 gfredericks: ystael: because 2 and 3 and 4 divide 12 amirite?

16:45 ystael: gfredericks: precisely

16:45 amalloy: yeah, i'm afraid introductory number theory was the furthest i got in that direction. i'm now just wondering what it is i misremembered, and particularly puzzled that i gave an answer that was *close* to being right

16:47 gfredericks: I've thought a lot about how to visualize groups as anything other than a multiplication table and never came up with anything promising

16:47 ystael: amalloy: It's a beautiful idea and I'm going to steal it if that's OK, but for it to work you need to check that p is a primitive root

Logging service provided by n01se.net