#clojure logs

2014-12-05

00:44timvishetanyone using cider 0.8.1 and austin 0.1.5, after running (austin-exec) with the default phantomjs exec-env get WARNINGs for basically every public cljs.core entity?
00:45timvishetoh, and you have to try to M-x cider-load-file to trigger the WARNINGs
00:46timvishetseems to well and truly fubar the repl, i have to cider-restart each time
01:30rritochWhat is the URL of the web history of this chatroom?
01:32otticlojure-log.n01se.net
01:33rritochotti: Thanks :)
01:34ottihm how can i splitup tests with leiningen? because i wrote some helper functions for a few tests, put them into a file /tests/helpers.clj. and now i have all the other tests in separate files.
01:34ottibut when i want to load them within core-test.clj there are problems with the namespaces, namely it can't find the namespace because it looks at /src/app/test-files.clj
01:34justin_smithotti: if you put the files in the classpath (ie. under the test/ directory) they can be required by the other files
01:35ottijustin_smith: hm didn't work
01:35justin_smithotti: does the path to the file match the namespace in the file?
01:35justin_smithbecause it needs to
01:35rritochotti: The only way I know of that you can split-up test is to use 'lein test :only test-namespace/some-test
01:36justin_smithotti for example if the file is in test/helpers.clj the namespace needs tobe called helpers
01:36ottijustin_smith: it is
01:36justin_smithotti: then the other reason it wouldn't load is if there is an error in the file
01:37ottii only could solve it by linking the test directory within /src and use the following namespace scheme for the files: test.my-test-namespace.test-file
01:37justin_smithotti: that should not be needed at all. I use namespaces under test/ frequently with no issue
01:37ottibut that sucks because on lein run the test files are considered too
01:37ottijustin_smith: i try as you suggested again
01:38justin_smithlein run won't load or use files that are not required by your core namespace anyway, so that isn't even an issue
01:38ottibut who do you explain the fact, that i once got an exception, while executing
01:39justin_smithand if the namespace is test.my-test-namespace.test-file than the path needs to be test/test/my_test_namespace/test_file.clj
01:39otti'lein run' within the tests
01:39justin_smithotti: something must have required or attempted to compile the file, but lein run wouldn't do that on its own
01:39ottihm
01:40justin_smithotti: perhaps you had :aot :all turned on?
01:40ottihm think, i just found the issue
01:40ottijustin_smith: no
01:40ottijustin_smith: it could be because i use vim-fireplace and run :Eval (core.test/run-tests)
01:41ottiwhich is connected to the repl that probably then goes looking within /src/app/
01:41ottifor the required files
01:41ottiinstead of /test/app/
01:41justin_smithclojure.test/run-tests does not load any files
01:41justin_smithit only runs the tests that you have defined / loaded previously
01:42justin_smithperhaps fireplace loaded the files? I don't know how fireplace does things. lein should only be looking for test namespaces under test/
01:43ottifireplace connects to the repl (lein repl) and, yes i have to load the files
01:43ottiby calling :Require from within vim
01:50ottihm very strange
01:52justin_smithotti: you say "probably then goes looking within /src/app for the required files instead of /test/app/"
01:52justin_smithotti: the way the classpath works, files under src/ and files under test/ are considered the same location
01:53justin_smithso you can't count on src/app/foo.clj vs. test/app/foo.clj - they are both the same relative path
01:53ottijustin_smith: i don't know probably i made some mistakes the first time that i started to write the tests
01:53justin_smithOK
01:53ottibecause i removed the link within /src to /test
01:54ottiand changed the namespaces
01:54ottiand no namespace exceptions
01:54ottithus it works now
01:54ottijustin_smith: thanks for the clearance
01:56justin_smithnp
02:08rritochI found another variation of classloader initiated incompatibility during compilation. I am unsure if this is related to yesterday's issue or not. http://pastebin.com/ydcQ9fVc
02:09justin_smithrritoch: Bronsa came up with a fix for that issue today BTW
02:10rritochCool, I haven't had a chance to check all of the logs
02:10rritochDoes it resolve this issue also?
02:11justin_smithI think it should. But I'm not sure of that.
02:12rritochjustin_smith: Do you have a link to the solution? Bronsa was very active
02:13rritochHmm,maybe I found it
02:14rritochIs this patch supposed to fix it? http://sprunge.us/YddP?diff
02:14justin_smithyeah, that's the one
02:16rritochInteresting that he decided to go with the baseLoader. I suppose that is a good idea because the way it is currently you don't have any control over what classloader gets used
02:16rritochI was thinking that it would be better to check interned classes first though
02:18rritochSuch as adding a map from the fully qualified classname, to the class for any class that gets interned, and checking against that whenever the fully qualified classname is used to ensure consistancy of classes within namespaces.
02:19rritochI don't think this patch fixes this new issue though, I'll have to double check something in the compiler to see.
02:23rritochOk, yes, this should fix the case I found also. The case in this pastebin shortcuts to RT.classForName which was just resolving to Class/forName before this patch. So it looks like the patch resolves both issues.
02:23rritochI still think it would be more stable though to check against interned classes first
02:25rritochThis additonal control over which classloader is used will certainly help, but could make some systems less stable if library developers start abusing the feature.
02:29rritochEither way, this problem was very helpful in learning how clojure classloading works. At least now I don't have to ignore the stacktrace portions that start with compiler, since I know what they're doing now :)
02:32kenrestivorritoch: they were talking about how they'd put the fix in jira and, if you want it, you might want to vote it up.
02:33kenrestivoi don't remember the ticket number but it's in the logs
02:35rritochSure, I'll vote-up anything that gives more control to the developer. I tried a lot of different tricks trying to get control over which classloader would be used and there really was no way around that Class.forName code
02:36rritochI'm still a bit curious though what the real cause of yesterdays issue was though, as far as I can tell the only thing that could have caused it is if the non-fully qualified name is getting resolved to a qualified name at some point, but short of adding debugging notices to the compiler I couldn't tell.
02:37rritochLooking at the code example, any non-qualified name checks interned classes so I'm not sure how the example was bypassing the interned class
02:38rritochChanging the interned class would alter which class was used at the top level, but not within the let
02:39rritochI even started using let* for my tests to ensure there was no "funny-business" going on within the macro that was applying the clojure.core namespace during macro expansion.
02:40rritochI just couldn't figure out a test, short of adding debugging messages to the Compiler, to see if the symbol was getting resolved to the fully qualified name within the let* statement.
02:42rritochIt would be nice if the compiler had a *debug-compile* setting so we could see the internal processes without needing to hack the compiler
02:46rritochWould the &env in a macro show if a symbol in a let* has been resolved to a fully qualifed name?
02:47rritochOr would it just show the final eval'd value
03:14epichero_i need to spend a few hours getting cider setup with autocomplete setup with my customized emacs using evil mode and hooks...
03:15sm0keis there something like try-let ?
03:16sm0kewhere the let binding are available in the finally clause
03:16opqdonutsm0ke: just have try inside let?
03:17opqdonutthat's how e.g. with-open is defined IIRC
03:17opqdonutyep: https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L3512
03:17Empperirritoch: I used to use ccw
03:17Empperithese days I use IntelliJ + Cursive
03:19sm0kerritoch: what if the binding cause exception/
03:19sm0kesorry ^ opqdonut
03:19rritochEmpperi: Heh, I just had to install IntelliJ today. I stick with counterclockwise because I program in a lot of different languages, and eclipse has good support for nearly every language I code in, accept possibly C#
03:19Empperiwell, IntelliJ has support for as wide variety of languages
03:19Empperimaybe even wider
03:20EmpperiI personally do clojure, java, javascript, dart, bit of ruby, bit of python
03:20Empperiand of course html, css, markdown etc
03:20rritochEmpperi: ccw is fairly broken, but anything I can't do from eclipse I can do from a shell, or PSPad, so I'm able to deal with it.
03:21Empperiyeah, ccw isn't that bad really
03:21Empperiit's the eclipse I had problems with
03:21Empperiused it for maybe 10 years
03:21mavbozolong live clojure!!! http://matthiasnehlsen.com/blog/2014/12/04/Farewell-Scala/
03:21opqdonutsm0ke: with-open with multiple bindings desugars into a nested try-let-try-let...
03:21opqdonutsm0ke: so if e.g. the third binding fails, the first two get freed
03:21opqdonuts/freed/closed/
03:23andyfrritoch: Sometimes adding debug print?s to the Clojure compiler is the quickest way to find out what you want.
03:27rritochandyf: Well, I'm about to start playing with that code soon, but I don't see any "installation" instructions. Once I get it compiled with ant, how do I install it into the localrepo?
03:28andyfrritoch: mvn install
03:28andyfThere may be other ways, but that should do it.
03:28rritochandyf: ty, that sounds easy enough
03:32andyfIf you want to skip running the tests: mvn -Dmaven.test.skip=true
03:32andyfI mean: mvn -Dmaven.test.skip=true install
03:33andyfThat particular command is not on this web page, but the -Dmaven.test.skip=true part is: http://dev.clojure.org/display/community/Developing+Patches
03:34rritochandyf: Thanks, I made a note of it. I don't think I'll have time to start tinkering until monday though
03:36rritochandyf: My primary goal is to create encapsulated namespaces to make it possible to have separate virtual runtimes (sandboxes?) within clojure, so OSGi modules can have a safe environment free of namespace and version conflicts.
03:37rritochandyf: It won't support multiple versions of clojure itself, but it could support independent versions of anything else.
03:37andyfI don't know if I would ever need such a thing, but sounds worth learning about some time. I have briefly wondered about ways to avoid problems with conflicting library dependencies in Clojure programs.
03:38andyfThe most common solution is to modify dependencies until only a single version of each library is in use.
03:38andyfbut that can be difficult, and in some cases impossible.
03:39rritochandyf: Well I've found two methods that people are using. One is creating a custom namespace, and the other is to use a clojure "shim" library.
03:39rritocherr, creating a custom classloader
03:39rritochBoth methods involve toying with java classloaders, which is a guaranteed way to run into troubles
03:40andyfI've been developing a Clojure lint tool called Eastwood, which evaluates the Clojure code it is analyzing, and to avoid library conflicts between that program and what Eastwood itself uses, I've copied libraries into Eastwood, and renamed their namespaces to something that other programs don't use.
03:40andyfcrude, but effective
03:43rritochWell, that sounds like it would work in most cases
03:47rritochIn my apps I'm using OSGi which already provides isolation for java classes within a module, but getting that isolation to clojure is inefficient. Modules would either need to include their own runtime, which ads a significant overhead to the load time, or classloading "magic" needs to be done to isolate the runtime. I intend to change namespace handling so the namespace registration ...
03:47rritochclojure.lang.Namespace/namespaces gets stored in thread-local memory, making it possible to isolate environments
03:57rritochThinking more about the issue though, as it relates to OSGi integration, any version with namespace isolation support could be shared, so this would support multiple versions of clojure, but would only need one runtime per version, so multiple modules depending on the same clojure version could share a single runtime.
03:57rritochAt least that's the goal.
03:58rritochI certainly could end up with an environment that is completely unstable and unusable
03:58andyfOut of curiosity, do you have an application that needs this?
03:59rritochYes, I'm developing a web platform/framework which needs it
04:00rritochhttps://github.com/search?q=user%3Arritoch+clj-grid
04:02rritochThe system uses a MVC design pattern, that is now namespace based instead of class based, and provides jsp support for templates that are easy to manage by web designers
04:03rritochI also have "dreams" of eventually support libGDX as a OSGi module, but I haven't even attempted that yet. I still have a lot of core issues to deal with.
04:04andyfSo the web framework will not achieve its goals without OSGi support?
04:06rritochandyf: The OSGi support is to provide plugins, and facilitate commercial interest in the platform.
04:07rritochandyf: Businesses aren't going to be very interested in developing plugins that can only be delivered via maven (open source), by giving the download and install option it opens up commercial interests.
04:10andyfAren't there closed source Java libraries delivered via jar files?
04:13rritochandyf: Yes, but OSGi provides module isolation, so you don't end up with as many plugin conflicts, such as are faced by wordpress
04:13borkdudedoes anyone still use lein cucumber? https://github.com/nilswloka/lein-cucumber
04:15cflemingrritoch: I'd be very interested to hear about what you come up with.
04:15cflemingrritoch: I'm no longer using OSGi, but I have a similar problem with IntelliJ plugins.
04:15cflemingrritoch: i.e. I'd like to be able to load Clojure code into plugins without replicating the Clojure runtime across each of them.
04:16rritochandyf: I believe openbravo provides modular support without OSGi, but for the most part OSGi is becoming an industry standard which is why I decided on OSGi as the basis for modularity.
04:18rritochandyf: To provide JSP support I'm already locked into the apache license anyhow, ...
04:19rritochWhen given the choice between anything and jboss, I'll choose anything, after JBoss's greedy patent lawsuits when their patents should have been completely invalid since day one since they patented a common software development practice, of having database fields mapped to object fields.
04:19rritochBecause of those lawsuits I will do whatever it takes to avoid using ANY JBoss product
04:20rritochI also don't include any ORM support in my apps to ensure that JBoss can't get their greedy hands on any of my work
04:21shiranaihitorritoch: i always just figured JBoss was way too "Enterprisey", but i guess they're full of shit too
04:24lxsameerhey folks, is ther any solution to build android apps using clojure /
04:24rritochWell, I've watched that situation closely because it is a huge thorn in the side of web development, that most web developers aren't aware of
04:24shiranaihitorritoch: plenty of other app servers around, though?
04:24rritochRecent supreme court decisions seem to have invalidated JBoss's patent on ORM design, and most software patents, but there hasn't yet been a case to test that theory.
04:25rritochshiranaihito: There aren't many that I can find that are stable and well maintained, other than Apache Tomcat
04:25shiranaihitoi'm not sure that matters.. court decisions will always favour the wealthy and politically connected anyway
04:25shiranaihitoJetty?
04:27rritochshiranaihito: I've started running into jetty a lot lately, and haven't tried it yet. I didn't find jetty until after I was already locked into tomcat libraries.
04:28shiranaihitorritoch: afaik, Jetty is very good.. i don't have experience running it in a Serious environment though, so that this for what it's worth
04:28shiranaihitoi'm basing my own Clojure web app development on top of Jetty though
04:30shiranaihitorritoch: one considerable advantage that Jetty has is that you can embed it in a stand-alone Java/Clojure application
04:30shiranaihito"so that this for what it's worth" <-- _take_ this for what it's worth, even..
04:31rritochshiranaihito: Tomcat can also
04:32shiranaihitoalright, i guess that's new
04:32rritochshiranaihito: Currently I'm depending on [org.apache.tomcat/tomcat-jasper "7.0.52"] which provides me all of tomcat
04:32shiranaihitowasn't Jasper the JSP engine.. ?
04:33cflemingborkdude: I've received at least one request to support it in Cursive, so someone is: https://github.com/cursiveclojure/cursive/issues/478
04:33borkdudecfleming ah ok. It doesn't work anymore on my machine, but I think it's because Firefox updated itself
04:34cflemingborkdude: Ok - I've never used it myself.
04:34rritochshiranaihito: Yes, as much as possible I am avoiding accessing anything in the catalina namespaces though. Tomcat uses layers and layers of wrapperrs and containers so to keep things light-weight I've been making my own servlet contexts and servlet config's to avoid the overhead
04:35rritochshiranaihito: As of now, deployment to tomcat servers is fairly seamless since I'm using the same libraries, but other than running JSP's from the command line I haven't yet made a stand-alone server with it
04:35shiranaihitorritoch: hmm.. i don't quite follow
04:36gavilancomunThere can be slight differences in interpretation of the Servlet 3 spec between Tomcat and Jetty, but they can be worked around
04:36rritochshiranaihito: Catalina code in the tomcat library is what provides the servletconfig's and servletcontext's required by the JSP specification
04:36shiranaihitohow do you "run JSP from the command line"?
04:36shiranaihitodo you mean the Servlet specification? :P
04:36rritochyeah :)
04:37shiranaihito:P
04:37shiranaihitobut still, "running JSP" from the command line (or anywhere for that matter) sounds weird
04:37rritochThe code to run jsp from the command line is all in http://www.github.com/rritoch/clj-grid-core , it wasn't easy
04:38rritochshiranaihito: Well, the intention behind that is to eventually provide CGI capability
04:38gavilancomunThe two issue I have had are scanning jars for annotations alongside web_fragment.xml files...
04:39rritochshiranaihito: Running via CGI would be slow, and cause the loss of all persistence benefits, but it is good for testing
04:39rritochshiranaihito: Currently I only use the command line support for testing/debugging
04:39gavilancomunand how the notion of current URL changes it calls to redirect() and calls to .forward() with a relative URL.
04:40gavilancomun*it* -> with
04:40shiranaihitorritoch: but "CGI" is what Servlets replace, right? it's just an interface for running code that's "called" by a server over the Internet?
04:40shiranaihitodflkjdsfdf
04:41shiranaihitorritoch: "called" by a browser, that is
04:41shiranaihitosorry.. i'm in a brainfarty mood, apparently
04:41shiranaihitoJSP (Java Server Pages) is just a View layer for Servlet -based web applications, right?
04:43rritochshiranaihito: JSP compiles to a servlet so it can provide the entire application, but typically a lot of back-end java is used
04:45rritochshiranaihito: Either way, I'm only using it for a view layer to JSP web applications
04:45shiranaihitorritoch: yeah i know, but people don't write JSP for that aspect
04:45rritocherr, clj web applications
04:45shiranaihito:p
04:46shiranaihitorritoch: but yeah.. CGI.. i'm not even sure what you mean with that.. it used to be something like, a way to hand off a HTTP request to a separate process (one per request?), right?
04:47shiranaihitobut why would you not use just plain Servlets or something on top of that instead?
04:48rritochshiranaihito: Running it via CGI means there's no need for an application server. CGI are just command line applications, delivery of metadata occurs by environment variables, and content (for post/put/etc.) delivered on stdin
04:49shiranaihitorritoch: yes, but why do it like that, instead of using Servlets or some other established, non-ancient standard for accomplishing the same (and more)?
04:49rritochshiranaihito: This way I can test features directly from the command line without needing to deploy an application server
04:50rritochshiranaihito: Testing as CGI requires one command "lein run", no need to launch a server, install updates, or open a web browser
04:50shiranaihitorritoch: ok, but you could use a http client too.. which would be a better fit with making a web app, since it's going to be used over http anyway
04:51shiranaihitowouldn't "lein run" launch a web server too, typically? :p
04:52rritochshiranaihito: Not with this platform, with this system lein run deploys a virtual web request, though I haven't added stdin reading or environment variable reading yet, so it isn't yet CGI compliant.
04:52rritochshiranaihito: At some point I'll add something like 'lein grid server' to launch a stand-alone web server, and it's on my todolist
04:52shiranaihitorritoch: "virtual web request"? .. so you're doing "web-like" stuff to avoid doing actual web stuff? :p
04:53rritochBut first I need to deal with this isolation issue
04:53rritochshiranaihito: Yes, development has been much faster that way
04:55shiranaihitorritoch: i'm still confused by what you're doing, and why, but.. i guess that's alright :P
04:55shiranaihitocarry on! :P
05:05rritochshiranaihito: The WHY is a big question I'm having a difficult time with lately, there isn't really any interest in this project outside my own mind, but I hope to be able to build enterprise class web applications in clojure that are easily maintained with a large team of developers
05:06rritochshiranaihito: Your jetty project is the only other project I've heard of that has JSP support in clojure
05:06Empperiwait, what, why?
05:06Empperijsp in clojure?
05:06Empperiman
05:07shiranaihitorritoch: if your goal is to write easily maintained web apps in Clojure, i don't see how "CGI-through-JSP-somehow" is the means towards that
05:07shiranaihitoyou could check out ring-jetty for some inspiration?
05:08shiranaihitoit sets up a stand-alone Jetty instance and gives it a custom (Jetty-specific) request handler thingy, that calls ring handlers
05:08rritochshiranaihito: ring is a deadzone for my application because ring rejects tomcat dependencies
05:08shiranaihitoi think that's pretty straightforward, and i'm using parts of that for my own cute little web framework
05:08shiranaihitorejects?
05:09rritochYes, rejects, removes the dependency because it contains a servlet implementation
05:10shiranaihitorritoch: you mean there's some kind of dependency conflict with Lein?
05:10shiranaihitocan you use the "exclude" command to work around it?
05:10rritochNo, I mean the ring plugin specifically rejects the dependency
05:11EmpperiI know for a fact that several people are running clojure + ring apps on top of tomcat
05:11rritochshiranaihito: I don't think so, exclude works at the package level, not the class level
05:11rritochEmpperi: Yes, they do that with the uberwar
05:11Empperieven if that is not the recommended way to do it
05:11Empperiyes, which is the right way to do it anyway
05:12Empperithe whole concept of using jars from tomcat's lib directory is just dumb
05:12Empperiimho
05:12Empperimakes deployments so much harder and gains nothing
05:13Empperisince one should run only one app per tomcat anyway so that when you need to restart tomcat because of one app you don't have to put other apps down too
05:13Empperiand only "gain" you could gain with tomcat lib directory based jar packages is the situation where you have same dependencies for multiple apps
05:14ordnungswidrigEmpperi: containers should hide all the libs they use to the deployed apps
05:14Empperiand even if you *do* run several apps on top of same tomcat instance (which I don't recommend) then only thing you'll lose if you encapsulate that jar to each war is some disc space
05:15Empperiordnungswidrig: yes, indeed. App decides what libraries they need, not the container
05:15ordnungswidrigEmpperi: we know all the fun with log4j and jbos
05:15Empperiand that's my point, there is absolutely no reasonable reason to put jar packages into tomcat lib directory for your app
05:15rritochshiranaihito: I don't know if they've changed the issue, but the exclusion code is @ https://github.com/weavejester/lein-ring/blob/0c9dff39929a8be35a04f2afc8580ab6b0e1d2d2/src/leiningen/ring/uberwar.clj#L26-L33
05:15Empperiit's an antipattern and the world is better without it
05:17Empperiif it is a problem for your server that you might have even few megabytes more of data on it's disc then you have a completely different problem altogether
05:17maxpnhow to implement javascript-like setTimeout() in Clojure?
05:17rritochshiranaihito: I attempted to use ring, but it was skipping my tomcat dependency because it contains a servlet so I wasn't able to get jsp support with tomcat+ring
05:17ordnungswidrigEmpperi: there are still links or file systems that do deduplication for that
05:17ordnungswidrigmaxmartin: there's a lib called atat
05:17rritochshiranaihito: If I was aware of jetty+ring at the time the project may have gone in a different direction
05:17godd2maxpn you sure you dont just want sleep?
05:18ordnungswidrigrritoch: I never heard someone wanting jsp support in a ring app :)
05:18maxpn godd2: yes, sleep but not in main thred
05:18godd2maxpn you can just put it in a future
05:18ordnungswidrigmaxmartin: (future (Thread/sleep 1000) (prn "foo"))
05:19shiranaihitorritoch: i can't tell what happened.. but that's ok.. did you have servlet.jar in your tomcat's global lib folder or something btw? that might cause a conflict
05:19ordnungswidrig&(future (Thread/sleep 1000) (prn "foo"))
05:19lazybotjava.lang.SecurityException: You tripped the alarm! future-call is bad!
05:19ordnungswidriglzybot: I'm sorry
05:19maxpngodd2: thank you, that is it!
05:19maxpnthank you all
05:20rritochordnungswidrig: Typical web designers simply won't be able to use clojure directly. JSP templates can be made which are 99% HTML, and typically web designers will just copy/paste in the JSP codes they need.
05:21ordnungswidrigrritoch: To my experience they prefer more something like mustache
05:21rritochordnungswidrig: JSP support in web apps is purely to facilitate employing web designers onto the projects.
05:23rritochordnungswidrig: I'm talking about professional web designers, not programmers experimenting with web design.
05:23ordnungswidrigrritoch: I know what you mean, it's just contrary to my experience with professional web designers.
05:24ordnungswidrigrritoch: I guess the preferences of web designers in this regard vary a lot over different communitites
05:25rritochordnungswidrig: Well, most web designers I've dealt with require templates to be as close to pure html as possible
05:28ordnungswidrigrritoch: sure. To my experience they prefer mustache, freemarker, velocity or like that. All those, like JSP, use html with some extra syntax sprinkled over the tags. As a developer I try to avoid JSP because that binds you to a servlet container and those scary compilcated JSP engines.
05:30rritochordnungswidrig: Well, the advantage of the platform I'm building is that it really can support any templating engine that's java based, including jsp
05:31rritochordnungswidrig: I'm dealing with all of the complexity within the platform itself
05:31ordnungswidrigrritoch: ok, that's a point.
05:31ordnungswidrigrritoch: good luck to you :-P
05:31bja /.er in me says JSP isn't an advantage
05:31rritochordnungswidrig: If clojure outputs directly to stdout (println) I have that bound to the servlets output stream, that opens a lot of possiblities
05:32rritochordnungswidrig: But in all of my example apps I'm jut forwarding to jsp's
05:32rritochordnungswidrig: I also recently made a .clj specific servlet, so you can even forward to a .clj script
05:40kraswhich is better in terms of performance #(nth % (- (count %) 1)) or #(first (reverse %)) ?
05:40krasfor taking the last item
05:43algernonI'd think (last %) would be, if I may offer a third choice.
05:43kras4clojure problem #19, restriction on last :-)
05:44rritochkras: For a large list the first would be faster because reverse isn't lazy, I believe rseq would be the fastest ##(time (first (rseq (range 10000))))
05:44lazybotjava.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.Reversible
05:44shiranaihitorritoch: as someone pointed out, you can just use a templating engine like Velocity or FreeMarker
05:44dgellowhi #clojure
05:44shiranaihitothere's no need for JSP.. if you're writing a web app, you'll just be spewing out HTML anyway, regardless of how you generate it
05:45daniel```hi dgellow
05:45rritochEek, didn't know lazy sequences aren't reversable :(
05:46rritochshiranaihito: Most of my web designers know JSP, and there is a large market of JSP template designers
05:47shiranaihitorritoch: JSP is alright as a templating engine - i think its best feature is custom tags that can be nested, that enables a lot of modularity
05:47dgellowIs cemerick/Friend the de facto library for everything about authentication ? Or do you know other lib with a similar purpose ?
05:48shiranaihitobut similar things can be achieved with Velocity or FreeMarker.. i'm not sure it warrants the complexity of the JSP setup etc
05:48algernonkras: ah :)
05:49rritochshiranaihito: Ex. on odesk there are 920 velocity developers, but over 16,000 JSP developers
05:50shiranaihitorritoch: sure, but you're just producing HTML.. learning Velocity or FreeMarker is not difficult either - they're all templates for producing HTML anyway
05:50shiranaihitobut i guess the biggest mystery to me is that CGI stuff
05:53shiranaihitoit sounded like in a way, you'd be testing whether your actual app code can be called (from the command line)
05:54shiranaihitobut that wouldn't really be a problem, right? .. it would be more useful to test the app's code itself, and you don't need to involve HTTP/CGI for most of that
05:54rritochAnyhow, I need to get back to work, but adding jetty support seems reasonable. Eventually I want to swap out all of the tomcat dependent code into it's own library, but that's just one of MANY core issues that I need to deal with. The urgent one is namespace isolation for modules.
05:55shiranaihito(for example, most of your functions probably don't have to take a HttpServletRequest as a parameter)
05:56shiranaihitorritoch: don't strive for excessive generality either :) .. whatever that might happen to mean in practice
05:56rritochshiranaihito: None do, I dynamically bind a *servlet-request* variable from the servlet, so every function has access to the request automatically
05:57shiranaihitorritoch: alright, but again, what would you need some kind of CGI contraption for? :)
05:57daniel```dgellow: it is, yes
05:57daniel```dgellow: i have looked for others, its by far the most used
05:57krasany suggestions on whom to follow on 4clojure, for learning from their solutions
05:57shiranaihitorritoch: besides, that doesn't sound very functional
05:57rritochshiranaihito: As I said, it reduces development time for these core systems because it doesn't require the overhead of a server
05:58rritochshiranaihito: The goal is to provide functions for access to the request
05:58shiranaihitorritoch: well what's the problem with running a server?
05:58shiranaihitofunctions that would access the global request variable?
05:59rritochshiranaihito: Time, it takes 1 second to type lein run and get the results, up to a minute to restart a tomcat server
05:59rritochshiranaihito: Previously I also had to install updates to tomcat, similar to the ring uberwar process
06:00shiranaihitorritoch: it takes.. let's say 1 second (to mirror your estimate :p) to start up a stand-alone embedded Jetty server :p
06:00rritochshiranaihito: But I've bound the classloader to the development source paths now so I can develop the web apps now in real time, I only use the CGI mode for debugging core features
06:01rritochshiranaihito: Ok, well the other advantage of CGI mode is that it will work on nearly every web server
06:01rritochAnyhow, here is an example of how this *servlet-request* design gets converted into functional syntax. https://github.com/rritoch/clj-grid-mvc/blob/master/src/com/vnetpublishing/clj/grid/mvc/base/controller.clj#L49-L54
06:01shiranaihitorritoch: well, your app server will just take in http connections anyway right?
06:02shiranaihitoso it doesn't really matter if it's tomcat or jetty or jboss etc
06:02shiranaihito"nearly any web server" will be able to proxy connections to your app server
06:02christiaanbHi, I'm helping in organising the annual dutch functional programming day (http://wwwhome.cs.utwente.nl/~jankuper/fp-dag/), and I was wondering what the best way is to notify the members of your community of this event?
06:04rritochhmm, just noticed I need to repair that function. Anyhow, I need to get back to work, but those "action"'s need to be changed with name, I was testing actions in controllers and must have been half-asleep when I coded it.
06:09TEttingerchristiaanb, there is the clojure mailing list, which seems appropriate
06:09rritochshiranaihito: As of now this doesn't have a stand alone application server, it is running via CGI mode or tomcat. I intend to use http-kit to provide a stand alone server, but I first need to deal with namespace isolation.
06:10christiaanbTEttinger: thanks
06:11TEttingerchristiaanb, might be worth reaching out to any companies in the netherlands doing clojure dev, I don't know how you would get a list...
06:12christiaanbTEttinger: I think I'll try the user groups for that
06:12dgellowdaniel```: thanks
07:17trissI'm always saying (vec (repeat n some-value))
07:18trissis that the easiest way of filling a vector with a default value?
07:18Bronsathat's the best way
07:19trisscheers Bronsa.
07:21bjaboo: (read-string (pr-str (keyword "")))
07:22bjaactually boo my logic that allows me to try to keyword ""
07:49TimMcbja: boo to code that keywords arbitrary strings as opposed to statically known values.
07:50bjawell, they're not *supposed* to be arbitrary
07:51bjathere was a bug that resulted in something along the lines of (keyword (string/join [" " "foo"])) to occur
08:06mavbozowill clojure eXchange 2014 London videos made available in youtube?
08:16scottjmavbozo: weren't previous ones available on skillsmatter.com only using vimeo but not accessible on vimeo's site?
08:17mavbozoscottj: oh, those videos are in skillsmatter.com. thanks scottj.
08:17mavbozo(inc scottj)
08:17lazybot⇒ 2
09:08trisshey all. so I'm writing my first proper app in clojure.
09:08trissI want to do the frontend in clojurescript
09:08trisswhat's the simplest way of adding clojurescript as a dependancy?
09:09trissis iyt possible to use lein to add it to an existing project or do i have to manually edit the project.clj?
09:57sveritriss: what I usually do is take a template and work on from there
09:58sveritriss: adding things later is a bit different, for this I generate a template (for instance with lein new chestnut tempname) and copy & paste the relevant pieces to my existing app
10:01trissthanks sveri....
10:01trissso create a new cljs project and copy the missing deps from there.
10:02sveritriss: this is a tedious thing to do, but usually only a one time setup, so I just do it
10:14mnngfltgHey. Does anyone mock out dependencies like writing to the database? I've tried `conjure` with clojure.test and found it cumbersome.
10:28bjamnngfltg: mostly no. I write functions that return data and test the functions
10:29bjaI mostly assume that the libraries I use to connect to external sources work
10:29bjathose libraries have their own tests
10:29mnngfltgbja, right
10:29mnngfltgbja, but what about glue code, e.g. code with side-effecets that, say, writes to the database
10:30bjamnngfltg: code doesn't do that typically. It does something, and then finally writes to the db
10:30bjaI can test the transforms I do
10:30mnngfltgbja, in my experience that's not always easy to do
10:31bjamaybe not easy, but I try very hard to make that part of my design
10:31bjahelps me live a much happier life
10:31mnngfltgI would be happier too :)
10:31bjathe places I talk to the external world now are mostly over core.async channels
10:31bjaand those are trivial to mock out when I need to
10:32bjai.e. in some logic that handles various failure modes
10:32mnngfltginteresting
10:32mnngfltgso having a queue helps you decouple the code from the actual side effects
10:33bjaI mean, writing to or reading from a channel is a side effect, but I can usually isolate the actual writing to a db from the control logic that operates on channels
10:33csd_What do I need to do to a key-value object to treat it as if it were a JSON object?
10:33bjathen I can test the control logic by creating various plain old channels and putting input on them or getting a value from them
10:33bjaand my transforms can be mostly pure
10:34bjathat's probably some sort of pattern with a name, but I couldn't tell you which one
10:35mnngfltgbja, it's an interesting approach, though maybe a bit too heavy if I don't have a use for core.async otherwise
10:36mnngfltgcsd_, what do you mean by "treat as a JSON object"?
10:36mnngfltgcsd_, generate a JSON string? (see cheshire or clojure/data.json
10:38EvanR,(:a {:a 1})
10:38clojurebot1
10:38EvanR,(2 {2 1})
10:38clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
10:38EvanR,({2 1} 2)
10:38clojurebot1
10:38justin_smith,(ifn? :a)
10:38clojurebottrue
10:38justin_smith,(ifn? 2)
10:38clojurebotfalse
10:38justin_smith,(ifn? {})
10:38clojurebottrue
10:38csd_mnngfltg: the chrome.storage api returns data in key/value pairs. dyntable wants JSON. i'm having trouble passing the object returned by the chrome api into dynatable, so I'm guessing it's because it's in some incorrect object format
10:39EvanRis it possible implement ifn in clojure
10:39csd_oh shoot i thought this was #javascript
10:39EvanRfor newtypes
10:39mnngfltgcsd_, JSON.stringify() ? :)
10:39bja#(.stringify js/JSON %)
10:39justin_smithEvanR: absolutely. Anything made with defrecord does it they way {} does by default.
10:40justin_smithEvanR: but you can get creative with it easily with deftype
10:40EvanRi keep getting confused about what can/cant implement protocols/interfaces
10:41justin_smithifn? tests for clojure.lang.IFn
10:41EvanRwhich is an interface or protocol
10:42justin_smithI think it's an interface. Reagardless, protocol is just a very thin abstraction on interface.
10:42justin_smithand every protocol has an underlying interface that gets created
10:43EvanRjava classes can have protocol impls
10:43EvanRbut not interfaces?
10:43justin_smithjava classes can easily have interfaces. It's a bit more work for them to integrate with protocols. nothing stops them from having both.
10:44EvanRalright
10:44justin_smithinterfaces are part of the jvm. protocols are a clojure thing
10:44EvanRbut you cant implement a protocol for an interface?
10:45justin_smithno, but you can implement an interface for an interface, and every protocol has an underlying implementation as an interface
10:49pepijndevosa protocol also generates an interface, right?
10:49justin_smithright, that's what I was saying
10:49pepijndevoseh, right
10:51mikerodDidn't this get discussed yesterday and puredanger ended up saying that Rich had no particular problems with allowing a protocol to extend a protocol or interface?
10:51puredangerI'm not sure that's the correct summary :)
10:51pepijndevosIf anyone has any performance advice, I'd be very happy. This code is a lot slower than equivalent imperative Scala: https://www.refheap.com/c337db72c94175657d1217372
10:51puredangerprotocols can definitely extend to interfaces now
10:52llasramWell, the protocol implementation lookup definitely works pretty hard to do the right thing for interfaces
10:52mikerodI've always been torn on why protocols do not allow the extension to other protocol/interfaces like the interfaces do. I tried to think it was idiomatic in Clojure, but that doesn't seem true when looking at the clojure.lang.* impl's
10:52EvanRwhat exactly does protocol extend protocol mean anyway, have an implementation? or is this inheritance
10:52puredangerit is not inheritance
10:52mikerodEvanR: inheritance is what I'm thinking
10:52puredangerat least I don't think of it as inheritance
10:52mikerodType hierarchy inheritance is mostly my focus
10:53puredangerit means an implementation of the protocol exists for a type
10:53mikerodI see a lot of interface inheritance used in clojure.lang. If Clojure is mostly against that sort of thing, why is it done so pervasively there?
10:53puredangerI personally think it would be useful to extend protocols to other protocols. that introduces some problems, but I think it would allow abstraction layering (not concrete implementation layering) that would be useful. I do not know whether Rich would support that or not.
10:54puredangerinterface inheritance is fine
10:54puredangerit's concrete extension that is a no-go
10:54mikerodpuredanger: yes I agree and see that concrete extension is no good and is the main issue on this topic I think
10:54EvanRwhat is concrete extension
10:54justin_smithpepijndevos: where does that Node class come from?
10:55puredangerclass extends class
10:55EvanRand in this case extends means inheritance
10:55mikerodI guess if I want the "isa" relationships for protocols then Clojure does support ad-hoc hiearaches or I can just drop down and extend protocol generated interfaces
10:55pepijndevosjustin_smith line 27
10:55puredangerEvanR: yes, talking in Java terms atm
10:55justin_smithpepijndevos: d'oh, I must not be fully awake yet
10:55EvanRand "isa" means, is a subtype? a isa b means a works wherever b works?
10:56puredangerpepijndevos: you're using boxed math for one thing
10:56mikerodEvanR: I mean if I have a protocol for Animal and I have a protocol for Dog and I have a class that implements Dog, let's call it ActualDog, I'd like to be able to say that ActualDog "isa" Animal
10:57puredangerEvanR: this is not precise enough wrt concrete class vs interface
10:57mikerod(dumb example of course :) )
10:57puredangermikerod: right, you can extend ActualDog to Animal and ActualDog to Dog
10:57pepijndevospuredanger, enlighten me. You mean I should use +' and friends?
10:57EvanRmikerod: without implementing Animal?
10:57puredangerbut you can't extend Dog to Animal
10:58mikerodpuredanger: yes, it just requires more of a hunt to figure out all the things you must extend to
10:58EvanRshudders
10:58mikerodpuredanger: I just think the maintenance barrier is a bit higher
10:58puredangerone trick for this is to extend Object to Animal, then check satisfies? and install an extension for the concrete type you've encoutnered
10:58EvanRhow do i union two sets?
10:58EvanR,(union #{1} #{2})
10:58clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: union in this context, compiling:(NO_SOURCE_PATH:0:0)>
10:58puredangerEvanR: clojure.set/union
10:59mikerodpuredanger: that is an interesting way
10:59EvanR,(clojure.set/union #{1} #{2})
10:59clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>
10:59puredangermikerod: I've used it quite a bit and it works fine. note you only have to install it the first time you encounter the new concrete type
10:59puredangerafter that there is an extension installed for the concrete type so it routes directly
10:59justin_smithpepijndevos: +' is the opposite of what you want. Boxed means each number is actually an object (usually of type java.lang.Long or java.lang.Double) instead of a primitive long or double type (not Objects). You need type hints for this.
11:00mikerodThis isn't a huge barrier to me anyways. I just have a had a few cases where it has came up. The toughest part about protocols to me is still that you can't rely on a given type that `satisfies?` it to actually implement its functions.
11:00puredangerjustin_smith: +1
11:00mikerodpuredanger: that is pretty clever :)
11:00pepijndevosah... can I do *warn-on-boxed* yet? Browsing jira....
11:00puredangerit actually came up in a talk at the very first conj and Rich said this from the audience
11:00puredangerpepijndevos: you can in 1.7 alphas
11:01pepijndevosI have those... so I'll try that.
11:01puredangermikerod: chouser (I believe) tried to live-code it and it didn't go so well :)
11:01mikerodpuredanger: the dangers of live coding I guess
11:01puredangerlive coding suggestions from Rich no less :)
11:01justin_smithpuredanger: I have an idea to put together a repo that is just a bunch of files with clojure.test, making assertions about whether reflection or boxing occurs, as a "living document" demonstrating where hinting is needed or useful and where it is not.
11:02justin_smithI may just work on that today.
11:02mikerodthat just sounds intense
11:02justin_smith(capturing the reflection / boxing warnings via with-out-str)
11:03puredangerjustin_smith: there are some examples of how to do that in the clojure tests if you want to steal
11:03justin_smithpuredanger: awesome, thanks
11:03puredangermikerod: you might find this useful - http://david-mcneil.com/post/3495351254/clojure-protocol-adapters
11:03puredangerDavid and I were working together when he wrote this and it's the same ideas
11:04EvanRmikerod: maybe this idea is more about "required prerequisite protocol of a protocol"
11:05puredangerand then of course, a protocol is nothing more than a map with a well-known structure. you can also just muck with it directly to do all kinds of advanced stuff.
11:05pepijndevosso is it *unchecked-math*?
11:06justin_smithpuredanger: my spidey-sense tells me that could get very ugly if misused...
11:06puredangerpepijndevos: (set! *unchecked-math* true)
11:06EvanRadvanced, powerful ;)
11:06puredangeror (set! *unchecked-math* :warn-on-boxed) if you want the warnings
11:06justin_smithpepijndevos: I think the warnings turn on with *unchecked-math* - you may or may not need *warn-on-reflection* turned on too (regardless, you want both if you care about perf)
11:07puredangerwarn-on-reflection is separate, but you probably should use that too
11:07justin_smithcool, thanks for the info
11:07justin_smith(inc puredanger)
11:07lazybot⇒ 23
11:07puredangerI did the boxed warning work after reading way too much bytecode for the Alioth perf stuff :)
11:08puredangerjustin_smith: you could certainly abuse it :) great power / great responsibility /etc :)
11:08justin_smithhaha, nothing motivates better than having your own itch to scratch
11:08justin_smithpuredanger: I did mention spidey-sense for a reason
11:08puredangerClojure leaves its internals open. if you have the ability to use them for good (and are willing to accept the maintenance costs associated), go for it.
11:09EvanRtheres the ability to mess with internal junk for idiosyncratic purposes then theres whether you will encourage people to try it
11:09EvanRin ruby, both are true
11:09EvanRacross the board
11:09EvanRand its terrible
11:11mikerod(inc puredanger)
11:11lazybot⇒ 24
11:11mikerodpuredanger: thanks that link is good. I haven't seen it before.
11:11mikerodEvanR: yes that is the idea
11:11mikerodEvanR: the link pretty much captures the issue though I think for the most part
11:12EvanRmikerod: for a sense of required anything, maybe a first step is to require a whole protocol to be implemented by a single class?
11:13EvanRotherwise we can add new requirements through project documentation at will, if the system doesnt help
11:13mikerodEvanR: are you talking about the idea of a given type possibly not implementing a "required" protocol function that you need?
11:13EvanRyesterday i heard you dont have to implement all the methods of a protocol, and that confuses me
11:14justin_smithyeah, clojure does not force full protocol or interface implementation
11:14EvanRthats like, a prerequisite before that other prerequisite
11:15EvanRon the other hand its not like its ensuring you follow an interfaces spec either, even if you do have an impl
11:15EvanRso back to policy docs
11:15justin_smithright, that's a turing complete problem I think
11:15EvanRdepending on the spec language
11:16EvanRspecs involving meta physics propositions i dont expect to be computer assisted any time soon
11:16pepijndevosI wonder how big a difference unboxed math makes... we'll know in a minute.
11:17puredangerif you're doing math, 2-3 orders of magnitude :)
11:18puredangerbut if that's not your bottleneck, then won't matter of course
11:22EvanRis there something like update-in but just sets the value instead of applying a function
11:22EvanRi know constantly can do it but thats such a long word
11:22puredangerassoc-in ?
11:22EvanRsweet
11:23EvanRblast
11:23puredangerit does what you want, just doesn't follow the update form
11:23puredangersince it's not an update
11:25puredanger(inc crossclj)
11:25lazybot⇒ 8
11:25puredangeronce again, super helpful as I research things http://crossclj.info
11:32ajmccluskeyIs there a neat way to flatten a nested map entry? Have {:A {:B :C}}, want [:A :B :C].
11:32EvanR,(flatten {:A {:B :C}}
11:32EvanR,(flatten {:A {:B :C}})
11:32clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
11:32clojurebot()
11:32ajmccluskey{:A {:B :C}} is meant to be a map entry there, not a whole map.
11:32ajmccluskeyEvanR: yeah, that surprised me too :p
11:33mikerodEvanR: justin_smith what I wish there was available for protocols was a way to at "check" if a given object implements a function
11:33EvanRafter re-reading the doc i would expect it to crash on maps
11:33mikerodinstead of just throwing something liek an AbstractMethodError
11:33mikerodcould always try-catch for control flow though! :P
11:33mikerodI tend to implement my protocols on Object with some special value like ::undefined
11:33EvanRbetter, assume they implemented it, what is the reason to support partial protocol impls?
11:34mikerodthen control flow around that in functions that expect some functions to be implemented, but can try to recover if they are not
11:34EvanRsounds backwards from the perspective of a library writer
11:36mikerodby "recover" I mean do something that makes sense if possible
11:36EvanRsends an email to the person responsible for the partially defined thing to get them to complete it?
11:37ajmccluskeymikerod: agree with EvanR - sounds like a lot of work. I would go with expecting someone who says they implement a protocol to, you know, implement it
11:37mikerodajmccluskey: I suppose
11:37EvanRi mean if they wanted to put a dummy that just crashes, they can
11:37mikerodAbstractMethodErrors it is then ;)
11:37ajmccluskeymikerod: wait, are you doing anything safety critical? I'm not going to die on the table because of this am I?
11:38EvanRor if the protocol is designed to be partially implemented, require an in-band method to describe that officially (or use more than one protocol)
11:38mikerodI actually wish even in the Java side that you could mark methods in a way that makes it clear yo do not implement them. Optional interface methods are very strange to me
11:38mikerodIf an interface has optional methods, it sounds like a broken abstraction because you dont' know what the contract is of the objects your given
11:39mikerodhttp://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
11:39mikerodand the UnsupportedOperationException
11:39mikerodfor reference http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#add(E)
11:39mikerodI get it here, I think the interface should have been 2 interfaces
11:40mikerodThe whole Immutable vs Editable or w/e
11:40EvanRbadly design protocol support
11:43yocapybaraanyone have any opinions on what the most performant way to get a digest (like md5 or sha1) from a clojure map?
11:43mikerodFrom the protocol perspective, the only reason I could see not requiring all functions on a protocol to be implemented is for some dynamic development. However, for "real" stuff I can't really see why there would be partial impl's.
11:43mikerodAnd protocols should be small to avoid the issue of having too much to implement
11:43yocapybaraI pulled up pandect but running (sha1 {:a "b"}) gives me an error that there's no implementation of :compute-sha1686 for PersistentArrayMap
11:49EvanR,(values {:a 1 :b 2})
11:49clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: values in this context, compiling:(NO_SOURCE_PATH:0:0)>
11:49EvanR,(keys {:a 1 :b 2})
11:49clojurebot(:b :a)
11:51ajmccluskey,(vals {:a 1 :b 2})
11:51clojurebot(2 1)
12:03justin_smithmikerod: the general approach in Clojure is that if something is needed in dynamic development, it is valid. The differences between work in the repl and what works in files are actively minimized, and I actually think that is a good thing.
12:13EvanRif i were going to make a mutable data structure, what do i use. vars?
12:15nkozaevanr: you can use deftype, it supports mutable fields
12:15justin_smithEvanR: a var is just a mutable container, the thing in it doesn't mutate, it just points at a new thing when reassigned
12:15justin_smithEvanR: you can also use java.util.HashMap, or arrays, or whatever
12:16puredangerdeftype supports marking fields with ^:unsynchronized-mutable or ^:volatile-mutable hints
12:16clojurebotGabh mo leithscéal?
12:16EvanRmy idea was to put the var in something as a mutable field
12:17dnolen_Bronsa: you haven't tried dead code elimination with tools.analyzer have you?
12:17puredangerwhy?
12:17justin_smithif you ever use a thread, an atom or ref may be a better pick than a var for that
12:17clojurebotbecause that's not how macros work
12:17EvanRbut it sounds like i need a deftype
12:17dnolen_EvanR: is there some reason an atom does not suffice?
12:17puredangerputting a var in a mutable field of a deftype sounds like the wrong answer to most questions :)
12:17EvanRyes
12:18EvanRpuredanger: two different ideas, not combined
12:18puredangergood :)
12:19Bronsadnolen_: no, doing dead code elimination in clojure is nearly impossible without altering the language semantics. but arrdem should have done some tree shaking with oxcart -- which has cljs-like semantics
12:21EvanRi have a map of references to mutable objects, each having two mutable fields. so i guess a regular map in an atom for the top level would work, but the important part is that the map entries might point to the same object
12:21Bronsadnolen_: sorry, I blindly assumed you meant tree shaking with "dead code elimination", was I wrong?
12:22EvanRin my mind the values are refs to objects, rather than regular values
12:22OscarZwas thinking of core.async.. are channels usually used as local variables that die after some function call or does it make sense to create some kind of "global" channel that could be used for multiple requests ?
12:22dnolen_Bronsa: not wrong, but what is the problem exactly if it can be summarized?
12:23puredangerEvanR: atoms (and refs etc) expect their values to be immutable. updates via swap! to an atom may be retried, which is a bad idea with mutable objects.
12:23EvanRfor the deftype, its required to put ^:volatile-mutable ? the method name to set a field must be set-foo! ?
12:24EvanRpuredanger: that part should be ok, because updating the map is its own operation, nothing is getting mutated there. but the objects would be modified some other way. a map of refs is immutable
12:24Bronsadnolen_: in clojure? w/ a resident compiler there's no way to know for sure if you're never going to need a Var.
12:24EvanRi dont know if im using the right terminology for refs
12:24puredangerthe syntax to set mutable fields inside a deftype is: (set! <field> <expr>)
12:24hiredmantree shaking/dead code elimination is a whole program optimization, but in clojure the compilation unit is a single form
12:24Bronsadnolen_: i.e. you could get it dynamically via resolve, eval
12:25dnolen_Bronsa: does not compute. For a production artifact with whole program optimization? I don't see how it's any different for JavaScript
12:25dnolen_production artifact doesn't need eval
12:25dnolen_well
12:25dnolen_"might not need"
12:25EvanRinside a deftype? eh.. maybe i need a record
12:25puredangerEvanR: records only have final fields
12:25EvanRwhats a final field?
12:25puredangerEvanR: you can cheat with arrays though (which are mutable)
12:25puredangerEvanR: cannot be changed
12:26dnolen_Bronsa: in anycase this answers my question, no one has tried to do a Closure style tree shaking pass on the AST
12:26Bronsadnolen_: right in cljs since there's no resident compiler, reified namespaces & the compilation unit is the ns/program tree shaking should be trivial
12:26puredangerEvanR: here's an example alioth program that uses deftype with mutable fields to do dirty fast things http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&amp;lang=clojure&amp;id=5
12:27dnolen_Bronsa: as to why I care, if some one had already started on this for Clojure than it would be nice to reuse for ClojureScript such that Google Closure only works on pre-shaken source
12:27dnolen_Bronsa: Scala.js is doing this and it can have a dramatic effect of advanced compile times
12:27Bronsadnolen_: I mean, arrdem has -- but he needed to make some assumptions on the clj code
12:27dnolen_Bronsa: using tools.analyzer?
12:27Bronsadnolen_: well then you might reuse his impl, one sec
12:27Bronsadnolen_: yes
12:27Bronsadnolen_: https://github.com/oxlang/oxcart/blob/master/src/main/clojure/oxcart/passes/tree_shake.clj
12:27EvanRok so i would make a method set-foo! and implement it as (set! foo ...
12:28dnolen_Bronsa: great thanks
12:28trisshey all... I'm messing with lein-cljsbuild
12:28trisswhere can i find out/goog/base.js?
12:28puredangerEvanR: yes, you could do that. You can't define methods in a deftype though. Rather you define an interface or protocol and implement it in the deftype
12:28EvanRpuredanger: and when passing the "deftype" value around, this is a ref to an object right
12:28trissif it's not there is my build likely to be misconfigured.
12:28triss?
12:28dnolen_triss: that's specified by :output-dir
12:29puredangerEvanR: yes, will be an object with real (public) fields that you could access via (.- obj field) too
12:29Bronsadnolen_: I'm not much familiar with that code but IIRC all that's doing is trivially merging the var reach set of every def & removing from the program AST the defs not reachable
12:29dnolen_Bronsa: cool, I will take a look
12:29trisssplendid thanks dnolen_
12:29puredangerEvanR: just to reiterate, this is all rarely used, way off the beaten path stuff, specifically for the purposes of performance or implementing low-level stuff
12:30EvanRmy algorithm is more straight forward in terms of mutable objects
12:30EvanRbut maybe not rendered as clojure
12:31puredangermutable objects are pretty intentionally hard to create or use in Clojure
12:31puredangerit should feel like you are actively fighting the grain
12:31puredangeras you are
12:31EvanRso far so good then
12:33Bronsa,(deftype x [^:volatile-mutable x] Object (toString [_] (set! (.x _) 1) "foo"))
12:33clojurebotsandbox.x
12:33Bronsa,(x. 1)
12:33clojurebot#<ClassCastException java.lang.ClassCastException: sandbox.x cannot be cast to compile__stub.sandbox.x>
12:35EvanRhmmm, a vector of two vars ;)
12:36{blake}At what point when you're building a web app do you say "OK, that's enough--too much--Javascript. I'm going to incorporate CLJS."?
12:36bbloom{blake}: mkdir
12:36puredanger(inc bbloom)
12:36lazybot⇒ 50
12:37EvanRcp ~/jsutils/* ~/project/js/
12:37{blake}Heh. 'k.
12:40justin_smithBronsa: puredanger: I started a repo as a demo of when / how type hints are usefull. PR for demonstrating tricky or interesting corners of the domain are quite welcome. To keep things simple I am just testing for the existing warnings rather than testing for reflection or boxing directly.
12:41justin_smithhttps://github.com/noisesmith/hint-hint oops, almost forgot to link the repo
12:42EvanRi got it
12:43EvanRits a map of refs to regular clojure structures
12:48EvanR,(ref (ref 0))
12:48clojurebot#<Ref@4270f8: #<Ref@6c7a9: 0>>
12:48EvanRsweet
12:49justin_smith~ref
12:49clojurebotIt's greek to me.
12:49justin_smith~refs
12:49clojurebotI don't understand.
12:49justin_smith~stm
12:49puredangerthis kind of thing is generally a bad idea :) most people find they are happiest with no more refs than you can hold in one hand.
12:49clojurebotI don't understand.
12:49justin_smithI forget where the factoid about using refs went...
12:50justin_smithEvanR: the common thing to find is an atom holding a map. If alteration is heavily parallel, you will see a small number of refs, each holding a map.
12:52hiredmanfewer
12:57gfredericksis there a general way to flip a bit on a Byte?
12:57gfredericksI had to special case the sign bit
12:58gfrederickswhich can't possibly be necessary
12:58gfredericks,(bit-shift-left 1 7)
12:58clojurebot128
12:58gfredericks^ can't really use that on a byte since it's out of range
12:58puredangerthis sounds like the kind of thing where ztellman must have made a library :)
12:59gfredericksI could have 8 constants lying around but that seems sooper weird
12:59bja_I feel like there was a binary protocol library that ztellman built which would apply here
12:59puredangergloss
12:59puredangerbut I don't think it does
13:00puredangerjava bytes are (stupidly) signed but surely there's a lib that does this right
13:01gfrederickswhat happens in java if you do (1 << 7) on a byte?
13:01justin_smith,(byte (bit-shift-left 1 7))
13:01clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 128>
13:02justin_smith,(set! *unchecked-math* true)
13:02clojurebot#<IllegalStateException java.lang.IllegalStateException: Can't change/establish root binding of: *unchecked-math* with set>
13:02gfredericksoh I hadn't thought of that
13:02Bronsa,(alter-var-root *unchecked-math* (constantly true))
13:02justin_smith,(binding [*unchecked-math* true] (byte (bit-shift-left 1 7)))
13:02clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Var>
13:02clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 128>
13:03Bronsa,(alter-var-root #'*unchecked-math* (constantly true))
13:03clojurebottrue
13:03justin_smith,(byte (bit-shift-left 1 7))
13:03clojurebot-128
13:03justin_smiththanks Bronsa
13:03Bronsajustin_smith: binding won't work there, you need *unchecked-math* to be true at compile time
13:03justin_smithgot it
13:03Bronsaand it's quite annoying
13:04justin_smithBronsa: my approach to this in the hint-hint lib https://github.com/noisesmith/hint-hint/blob/master/src/org/noisesmith/hint_hint/capture_warnings.clj
13:04gfredericksthanks justin_smith Bronsa
13:06Bronsajustin_smith: uhm, does hint-hint cover only "when to use type hints" or can it also be "type hinting wtfs galore"?
13:06justin_smithBronsa: the latter would be great - maybe in a separate namespace to differentiate useful tricks from gotchas
13:07justin_smithBronsa: my motivation is that whenever questions come up here about type hints, we get a lot of "I think..." or "well actually..." so something that demonstrates all the points would be useful I think.
13:07Bronsanice, I'll find some time to contribute
13:07justin_smithBronsa: awesome! thanks.
13:18EvanRwell thats not going to work very well either. so next is to do it all without mutation by simulating refs with indexes into another map
13:19EvanRand always use indirection
13:20EvanRforgotten objects with no references to them wont be collected by a gc, but since its just for a local algorithm it doesnt matter
13:21justin_smithEvanR: by local, do you mean it all happens in one thread, and in one let block?
13:22EvanRits a pure function, referentially transparent, and its not multithreaded
13:22justin_smithif so, you could get away with a java.util.HashMap / java.util.Arraylist
13:22EvanRwell that would make sense
13:23EvanRis the java syntax attrocious though?
13:23puredangermuch less attrocious than mutable deftypes and refs of refs :)
13:24justin_smithEvanR: ##(doto (java.util.HashMap.) (.put "a" 1))
13:24lazybot⇒ {"a" 1}
13:24justin_smiththe doto is useful for chaining, because .put does not return the map
13:24EvanRwell ill try the immutable way, since all my assoc-ins gets and update-ins started shattering when i tried to use mutable objects
13:25EmpperiI'm curios, haven't ever tried this
13:25EvanRill try the immutable secondary space first
13:25Empperi,(doto (java.util.HashMap.) (.put :a 1))
13:25clojurebot{:a 1}
13:25Empperi,(:a (doto (java.util.HashMap.) (.put :a 1)))
13:25bja_does java have something like python's __getitem__ that you could use?
13:25clojurebot1
13:25Empperinice
13:25Empperiit should have worked but wanted to check
13:25Empperibja_: what das __getitem__ do?
13:26Empperidoes
13:26Empperimaybe I'll just google
13:26bja_I've implemented assoc-in/update-in with python's mutable collections with __getitem__/__setitem__
13:26bja_it's the dict/array item access syntax
13:26bja_foo[0], bar['baz']
13:26bja_it'd probably be some sort of interface in java
13:26Empperi,(doc get)
13:26clojurebot"([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."
13:26bja_map's .get maybe
13:27justin_smithbja_: get-in / assoc-in I would guess
13:27Empperi,({"a" 1} "a")
13:27clojurebot1
13:27Empperi,(get {"a" 1} "a")
13:27bja_err, do get-in/assoc-in work with HashMaps of HashMaps?
13:27clojurebot1
13:27justin_smith,(get-in {:a {:b 0}} [:a :b]) ;; bja_
13:27clojurebot0
13:27justin_smith,(assoc-in {:a {:b 0}} [:a :b :c] 3) ;; bja_
13:28clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Associative>
13:28justin_smith,(assoc-in {:a {:b 0}} [:a :b] :c 3) ;; bja_
13:28clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: core/assoc-in>
13:28justin_smitherr...
13:28Empperi:)
13:28bja_well, I meant java.util.HashMap. I know they obviously work in clojure (I was implmenting get-in/assoc-in/update-in in python because I missed them from clojure)
13:29bja_nvm, I'm just causing chaos at this point. ignore my line of questions/comments please :)
13:29Empperi,(get-in (doto (java.util.HashMap.) (.put :a (doto (java.util.HashMap.) (.put :b 1)))) [:a :b])
13:29clojurebot1
13:30justin_smithbja_: looks like that's your answer though
13:30bja_ah, nice
13:32EvanR(get-in the choppa)
13:32bja_so get-in works, but assoc-in/update-in won't work because HashMap is not clojure.lang.Associative
13:32justin_smithmakes sense
13:37ppppaulhello clojures
13:43justin_smithhello
13:50ppppaulhello again
13:51EvanRis there dissoc-in
13:51EvanRor something
13:54justin_smithEvanR: I think flatland/useful may have dissoc-in
13:55justin_smithEvanR: https://github.com/flatland/useful/blob/develop/src/flatland/useful/map.clj#L81 it's here
13:56ppppaulflatland/useful no documentation :/
13:56whodidthisif i have a map (def cool {1 "a" 2 "b" 3 "c"}) whats a nice way to automatically bind the map values into globals cool-1, cool-2, cool-3, instead of using (get cool 1)
13:56justin_smithppppaul: did you look at the link? the doc strings are pretty comprehensive
13:57ppppauli'm looking through the code now
13:57ppppauli like it. but even something like auto generated readme could be helpful
13:57justin_smithppppaul: I think that's what this does https://github.com/flatland/useful/blob/develop/build-docs.sh
13:57justin_smithyou could clone the repo and run it
13:58ppppaul:D
13:59justin_smithhttp://flatland.org/useful/ <- I think this is generated from that script
13:59ppppaulnice!
14:01ppppaulanyone who has some experiecne with lighttable and cljs i could use some help in #lighttable
14:03ppppaultrying to get my console logging to print to the lighttable console instead of the browser console
14:05ppppaulis this even possible?
14:07BobSchackppppaul: Are you connected to the lighttable browser or an external one?
14:08ppppaulexternal
14:08ppppaulcan't do HTTP stuff in the browser LT opens
14:08ppppaulCORS problems
14:09BobSchackWhat kind of HTTP stuff are you talking about? DOM manipulation?
14:10ppppaulHTTP requests to servers other than localhost
14:11ppppauleven GET requests fail
14:14arrdemjustin_smith: so what's going on with hint_hint?
14:17justin_smitharrdem: the idea is that its a set of unit tests that prove where type hints are needed
14:18justin_smitharrdem: and any gotchas (eg. things that aren't actually useful)
14:20justin_smitharrdem: https://github.com/noisesmith/hint-hint/blob/master/test/org/noisesmith/hint_hint_test.clj current state of the tests - doing things that either provoke a warning or not, and using test/is to verify whether a warning happens
14:25oggienew to clojure and trying to understand how to do if /else logic... Anyone up for helping me out?
14:25justin_smith,(if true :ok :no)
14:26clojurebot:ok
14:26justin_smith,(if fase :ok :no)
14:26BobSchackppppaul: Have you tried shoreleave remote (http://shoreleave.github.io/shoreleave-remote/#shoreleave.remotes.jsonp)?
14:26clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: fase in this context, compiling:(NO_SOURCE_PATH:0:0)>
14:26justin_smith,(if false :ok :no)
14:26clojurebot:no
14:26oggiejustin_smith I tried that, but It doesn't work how I'm doing it
14:26justin_smithoggie: what are you actaully trying to do?
14:27oggiecheck to see if a username/password is not passed in (nil) and act differently
14:28oggiehere's what I have
14:28oggiesession (-> (if (not-any? nil? [username password]) (alia/cluster {:contact-points cluster :credentials {:user username, :password password}}) (alia/cluster {:contact-points cluster}) ) (alia/connect keyspace))
14:28oggieso don't add username/pass to the session if it's nil
14:32justin_smithoggie: that looks right, as long as the {:contact-points ...} map should be the first arg to alia/connect
14:33justin_smiththe (alia/cluster {:contact-points ...}) that is
14:33oggiejustin_smith it is supposed to be 1st
14:34oggieit works if I hard code the username/password in there and not use the if
14:34oggiehmm. maybe I do have it right
14:34oggie:-)
14:35oggiethis is tough coming from Java for years
14:35justin_smithoggie: it may be clearer with let bindings instead of ->
14:36oggieok
14:51arrdemis there a trick for looking a value up out of a map throwing if it doesn't exist?
14:51amalloyarrdem: use python
14:52EvanRuhm..
14:52justin_smith,(get {:b 0} :b (lazy-seq (throw (Exception. "boom"))))
14:52EvanR,(:abc {})
14:53clojurebot0
14:53EvanR,({} :abc)
14:53clojurebotnil
14:53justin_smith,(get {:b 0} :a (lazy-seq (throw (Exception. "boom"))))
14:53llasramOh, slowness
14:53clojurebotnil
14:53justin_smithkinda hackish
14:53clojurebot#<Exception java.lang.Exception: boom>
14:53justin_smithactually works in a real repl though
14:53Bronsajustin_smith: you can never know when that'll throw though
14:53llasramI think clojurebot is just lagging
14:54Bronsaor even if that will throw at all
14:54justin_smithBronsa: where would the gotcha be? if the value was not used?
14:54Bronsajustin_smith: yep
14:54Bronsajustin_smith: suppose (if (symbol? x) x 'foo)
14:55llasram&((fn safe-get [m k] (let [v (get m k ::not-found)] (if-not (identical? ::not-found v) v (throw (ex-info "not-found" {:m m, :k k}))))) {} :foo)
14:55lazybotclojure.lang.ExceptionInfo: not-found {:m {}, :k :foo}
14:56llasramlazybot: not so lazy today, now are you!
14:56justin_smith&((fn safe-get [m k] (if-not (contains? m k) (throw (Exception. "boom")) (get m k))) {} :foo)
14:56lazybotjava.lang.Exception: boom
14:56arrdemllasram: that's nicer than the one I came up with. yoink!
14:57arrdemjustin_smith and I had the same solution
14:57Bronsa,((fn safe-get [m k] (if-let [[_ v] (find m k)] v (throw (Exception. "boom"))) {} :foo)
14:58clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
14:58Bronsawell.
14:58Bronsayou get the idea.
14:58justin_smithBronsa: oh yeah, find is a nice way to do that one
14:58llasramOh nice, yeah
14:59arrdemwon't that be identical to llasram's solution? both only do one lookup, whereas the contains? version will do two.
15:00llasramBut Bronsa's doesn't depend on a magical sentinel which you can't ever have as a value in the map
15:00justin_smithit's more elegant, but only one lookup as with llasram's
15:00arrdemah good point. In this context I don't care, the set of possible keys is strings only, but yeah in theory Bronsa wins.
15:00arrdem(inc Bronsa)
15:00lazybot⇒ 77
15:02justin_smith(inc Bronsa)
15:02lazybot⇒ 78
15:03dnolen_ClojureScript 0.0-2411 out
15:03EvanRwhy doesnt (fn [x] (prn x) x) work in the middle of a -> macro sequence
15:04arrdemEvanR: ((fn ..)) will.
15:04EvanRohk
15:04justin_smith,(macroexpand '(-> 1 (fn [x] (prn x) x)))
15:04clojurebot#<CompilerException java.lang.IllegalArgumentException: Parameter declaration 1 should be a vector, compiling:(NO_SOURCE_FILE:0:0)>
15:04arrdemEvanR: (-> x (fn [x] x)) -> (fn x [x] x)
15:05llasramEvanR: bonus protip: (-> ... (doto prn) ...)
15:05justin_smith,(macroexpand '(-> foo (fn [x] (prn x) x)))
15:05clojurebot(fn* foo ([x] (prn x) x))
15:06justin_smith(inc llasram)
15:06lazybot⇒ 42
15:06justin_smithyeah that's actually the right way to do it
15:07wirrrbelI wanted to checkout yesql and ring / rook
15:07wirrrbelup until now my project was clojurescript only
15:08wirrrbelnow I wonder where to put my sql file
15:09justin_smithwirrrbel: relative to the classpath means if you ask for "some/where/foo.sql" it can be in "src/some/where/foo.sql"
15:11wirrrbeljustin_smith: thank you
15:36EvanRnote to self core.match patterns do not introduce variables that shadow
15:36EvanRthought i was going insane
15:42ppppaulcan i pretty print in cljs?
15:43ppppauli'm having issues printing to the console :/
15:52dnolen_ppppaul: sadly no pretty printer built in - jonasen had a port of bblooms' fipp - might be useable unsure
15:53dnolen_and by "not built in" I mean I haven't received a clojure.pprint patch
16:03ppppaulhmm. i'll deal without one for now...
16:09kenrestivois it kosher to use send for serializing synchronous access to i/o, where i *want* it to block?
16:11kenrestivoi suppose i could use send-off and then deref to block. but i'm wondering why not use send instead?
16:11llasramkenrestivo: Why are you using an agent if you want synchronous access?
16:12kenrestivobecause some operations i want the agent send-off behavior.. others i don't
16:13llasramCan you share the broader context some?
16:13kenrestivoit's just a device
16:14kenrestivoso i've got an agent serializing access to it
16:15amalloykenrestivo: deref doesn't block at all
16:16llasramOk. Well, my 2 cents is that it doesn't sound like an agent is the best fit :-)
16:16amalloyit's not clear what difference between send and send-off is relevant here
16:16kenrestivoah right, only on futures/promises, not on agents
16:16justin_smithkenrestivo: how about a thread reading a queue and writing to device, it also gets passed a promise that it delivers to when the write is done?
16:16kenrestivoyeah, i think the agent approach isn't going to work. thanks.
16:16amalloykenrestivo: if you want exclusive, synchronous read/write access to a device, i'd just use a mutex
16:17llasram(inc amalloy)
16:17lazybot⇒ 201
16:17amalloyyou can cobble together stuff with agents and await and blah blah blah, but like...locks aren't strictly bad
16:17kenrestivowas hoping to avoid j.u.c. interop, but i guess why not.
16:17amalloykenrestivo: ?????? ##(doc locking)
16:17lazybot⇒ "Macro ([x & body]); Executes exprs in an implicit do, while holding the monitor of x. Will release the monitor of x in all circumstances."
16:18dbaschamalloy: there was a mixup, we sent rich hickey a cardboard cutout of you
16:18kenrestivonice
16:18amalloydbasch: that was you crouching in the bushes with a camera? i thought i'd become interesting to the paparazzi somehow
16:18dbaschit was hand-drawn
16:18kenrestivoamalloy: once again, thanks for showing me a new corner of clojure i had no idea existed
16:18dbaschno word from rich hickey yet
16:19dbaschthe clojureazzi
16:20EvanRa queue with max size 1 would also work
16:21EvanRand you would have to muck with mutices
16:21EvanRwouldnt*
16:21justin_smithEvanR: I thought there was an implication that he only sometimes wanted to block
16:21justin_smithalso, locking isn't much of a muck at all
16:22EvanRwell P and V are crap
16:23justin_smithP and V?
16:23llasramPevear and Volokhonsky?
16:23EvanRissue the lock command on a mutex object, then later... you had better issue the unlock on the same mutex
16:23amalloyhe's a letter connoisseur
16:23amalloyEvanR: that's what locking guarantees to do
16:23justin_smithEvanR: that's now how locking works ##(doc locking)
16:23lazybot⇒ "Macro ([x & body]); Executes exprs in an implicit do, while holding the monitor of x. Will release the monitor of x in all circumstances."
16:24EvanRyes ok
16:24justin_smithall you do is wrap your code in the locking macro, it's not messy
16:24EvanRbut im not sure exactly how even this corresponds to sometimes blocking
16:25justin_smithEvanR: he wanted to block on the write sometimes, and not others. So you want a queue with a larger size than 1, and a way to indicate the write completed (thus my suggestion of a promise)
16:25EvanRwas the same implication also implying that you also sometimes forgo even doing your write?
16:25EvanRoh
16:26EvanRthis policy is way past my concurrent semantics comfort level, crash when queue is maxed?
16:27EvanRblock anyway
16:27EvanRdont write?
16:27justin_smithit would block on a full queue, let you go on your merry way otherwise. But a full queue indicates slowing you down is probably the right thing to do anyway.
17:10_ak__Is there anyone from north-west England, around Manchester or Liverpool here this evening?
17:23FliPPehhttp://sprunge.us/LYDZ?clj - how's that for my first not-entirely-useless clojure program? Any obviously bad things?
17:26kenrestivoFliPPeh: at first glance, there are a couple things you're doing there that might already have functions in clojure.core to do what you want. but rewriting clojure.core functions can be a good learning exercise.
17:27kenrestivo,(doc keyword) ;; for example
17:27clojurebot"([name] [ns name]); Returns a Keyword with the given namespace and name. Do not use : in the keyword strings, it will be added automatically."
17:27amalloykenrestivo: huh? he calls keyword himself
17:27FliPPeh,(keyword "something with spaces")
17:27clojurebot:something with spaces
17:27FliPPehThat looks evil
17:28amalloyFliPPeh: i don't see why you're converting to keywords at all
17:28amalloyjust use strings as your map keys
17:28FliPPehWell what I'm doing there is taking a string that may contain spaces and other weird things and turns those into simple dashes
17:28FliPPehI could, but keywords feels more clojury
17:28justin_smith FliPPeh: another vote for just using strings as keys
17:29amalloyno. don't build keywords out of user-controlled data
17:29FliPPehAlrighty
17:29justin_smithkeywords are good if you are designing the data structure as literals, but getting it from somewhere else, just leave it a string
17:30amalloyotherwise i'd say this is all fairly reasonable, except that i'd use line-seq instead of slurp+lineify
17:31amalloyget a reader, call line-seq, then chunk those based on blank lines, then put the chunks into maps
17:32dbaschFliPPeh: also, you don’t need two separate requires
17:32FliPPehLike partition-by on an empty line=
17:32FliPPeh?*
17:32amalloysure, seems fine
17:33EvanR,(atom? (atom 0))
17:33clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:0:0)>
17:34dbasch,(type (atom 0)) ;; EvanR
17:34clojurebotclojure.lang.Atom
17:34FliPPehAh, doesn't seem like line-seq will work here. Apparently it wants a buffered reader, but those don't work on /proc files
17:34hiredmanwhat makes you say that?
17:35FliPPehWell, that's what the repl is telling me
17:35hiredmanwhat makes you say the repl is telling you that?
17:35dbaschFliPPeh: what error do you get?
17:36kidpolloHola @dbasch
17:36FliPPehWhoops pardon, I indeed misread
17:36clojerI've downloaded a JAR lib that I want to include in my Clojure project. Where should I put it and how to included in project.clj and any file which :require s it?
17:36FliPPeh"(line-seq (java.io.BufferedReader. (java.io.FileReader. "/proc/cpuinfo")))" does the trick just fine
17:36dbaschkidpollo: howdy
17:37dbaschclojer: is it something that wasn’t available in a public repository? Because if so, you don’t need to download it
17:37kidpolloI am trying to 1 up my clojure fu to the next level by hanging out with the cool kids :P
17:38clojerdbasch: Downloaded from an individual developer's website.
17:39clojerdbasch: I've already downloaded it. How to add it to the project?
17:39sg2002clojer: https://github.com/kumarshantanu/lein-localrepo
17:40dbaschthat’s one way, or you could stick it in a local maven repo
17:41dbaschclojer: http://nakkaya.com/2010/03/16/adding-custom-libraries-into-local-leiningen-repository/ like this
17:41clojerdbasch: Do you mean in my .m2 repo?
17:41dbaschclojer: no
17:42dbaschyou could hack your .m2 repo, but I wouldn’t recommend it
17:42clojerdbasch: Nothing fancy .... please :)
17:42kenrestivokidpollo: or you could do 4clojure.com exercises
17:42dbaschclojer: I think the article I linked is the easiest way
17:42dbaschat least it’s what I did the last time I had to do this, a couple of years ago
17:43whodidthishttps://www.refheap.com/94472 how do i get the symbol bound to n replace the last n in this macro
17:43arohnerfun friday: Puppet Docs + HP Lovecraft in a markov chain: http://thedoomthatcametopuppet.tumblr.com/
17:44kidpollokenrestivo: that also
17:44clojerdbasch: Kreist, what a lot of ceremony.
17:45dbaschclojer: well, you are including an artifact for which you don’t have the source and that doesn’t happen to be in a repository anywhere
17:46dbaschmeaning, you’re using a dependency management tool (lein)
17:46kenrestivothere used to be a lein-local. i think it's deprecated, but it probably would't be to hard to have a lein plugin that wraps the mvn ceremony to install a local jar into ~/.m2
17:46clojerdbasch: Been spoiled by Ruby for too long, maybe. `require_relative <module>`. Done.
17:46arohneryou can 'lein install' arbitrary jars
17:47arohnerit generates a minimal pom for you
17:47EvanRheh require_relative
17:47clojerarohner: Now yer talkin'
17:47EvanRautoloading yall
17:48kenrestivo"gem install hairball" :-P
17:48amalloyclojer: well. that's nice in some ways, and lein is nice in others. clojure (and java) would much rather automatically download dependencies for you, from a repository, than have jars floating around your whole filesystem
17:48arohnerclojer: I must be misremembering. you can certainly 'mvn install' :https://maven.apache.org/plugins/maven-install-plugin/usage.html
17:48amalloyare you sure this thing you're trying to use isn't in any repo anywhere?
17:49amalloydownloading jars by hand is a desperation move, a last resort
17:49clojeramalloy: I don't think so but I'll double-check.
17:50arohnerclojer: and if you're doing a 'serious' project, it's often worthwhile to have your own private repo
17:50arohnerusing e.g. nexus or https://github.com/technomancy/s3-wagon-private
17:52whodidthishttps://www.refheap.com/94473 or is this possible somehow, defin with the created symbol instead of n
17:52kenrestivoeverything else, googling "libraryname maven" found some repo somewhere with it.
17:57dbaschwhodidthis: I don’t understand what you’re trying to do
17:58justin_smithwhodidthis: the way def works, it will always define n
17:58whodidthisok, im a bit of a bad then
17:59justin_smithare you trying to pass a string to def-k and end up with that string being a def with the value "nice"?
17:59whodidthisyes :(
17:59justin_smith(defmacro def-k [k] `(def ~(symbol k) "nice"))
17:59justin_smithstill very silly
17:59justin_smithbut that should actually work
18:00dbaschwhodidthis: look into intern
18:00justin_smithyeah, intern is actually a nicer way to do it, as long as the metadata that def adds isn't important to you
18:02whodidthisi wanted to find a nice way to get a maps keys and values deffed, like {1 "a" 2 "b"} => (def value-1 "a") (def value-2 "b")
18:02EvanRhah
18:02EvanRphp extract
18:02EvanRonly global
18:02dbaschwhodidthis: that is a strange requirement
18:03whodidthisso i could access them with values/value-1 instead of (get values/values 1)
18:03EvanRif you use that a lot on a large map, you wont know heads from tails
18:03dbaschif you need to keep global state, you shouldn’t be defining variables willy-nilly
18:03whodidthisit was just a nice color scheme :(
18:12amalloyyeah, just leave it in the map. value-1 doesn't save a lot of characters compared to (values 1), and it avoids some other headaches
18:12celwellHi, I'm trying to get a single Set of all page numbers. I have this code, which works, but I was wondering if I could get any feedback for a more idiomatic way of writing it.
18:12celwell(reduce #(apply conj %1 (s/split (:pages %2) #","))
18:12celwell #{}
18:12celwell [{:id 1 :pages "1,2,3,4"}
18:12celwell {:id 2 :pages "2,3,4,6,7"}
18:12celwell {:id 8 :pages "9,10,12"}])
18:15EvanR(concat (map (comp split-on-comma :pages)))
18:17weavejes_(mapcat (comp split-on-comma :pages) data)
18:17weavejes_(set *1)
18:19celwellThanks, I like weavejes_'s answer the best.
18:20amalloy(reduce into #{} (map (comp split-on-comma :pages) xs)) is also possible
19:21{blake}OK, so I'm creating a login. I go to the page, get the login (sony/password) and now I want to go back to "/" with the "sony" in the session map. I was looking at "redirect" but it doesn't take a body.
19:31{blake}If something is a library and not in clojars, do you just download it and make it part of your own code?
19:32zeapo{blake}: that depend on the licence. Check if you can redistribute it.
19:33xeqi{blake}: it might be in http://search.maven.org/
19:35{blake}xeqi: 'tis not.
19:40justin_smith{blake}: for doing a redirect and also putting something in the session, maybe try (assoc (redirect url) :session updated-session)
19:40justin_smithredirect should return a response map I think
19:40justin_smithor, if that was a login, it could be (assoc (redirect-after-post url) :session updated-session)
19:40{blake}justin_smith: Thanks, lemme try.
19:42{blake}(inc justin_smith)
19:42lazybot⇒ 152
19:42dbasch{blake}: it is a clojure library and it’s not on clojars?
19:43{blake}I've SO got to run through all my compojure stuff again. I'm not thinking right at all.
19:43{blake}dbasch: Yeah, it's a little weavejester thing called "decorate".
19:44dbasch{blake}: ask weavejester to put it on clojars
19:45dbaschor fork it and do it yourself
19:45amalloyoh my gosh it's five years old
19:46amalloyit looks like a bad version of robert.hooke, or maybe just convenience wrappers over alter-var-root?
19:47{blake}It was more of an idle question. It's just what happens when you chase around the web looking for helpful information. Sometimes the most helpful (looking) stuff relies on ephemera.
19:54justin_smith{blake}: crossclj.info is good for seeing which libraries people are using
19:55justin_smithhttp://crossclj.info
19:55justin_smithand more usage often means more helpful
19:56{blake}justin_smith: Yeah, but in this case, I was looking for explanation and found this: http://blog.experimentalworks.net/2010/02/dealing-with-sessions-in-compojure/
19:56{blake}Which uses that "decorate" thing. Though I did manage to figure out that I didn't need it. So I got that going for me.
19:57{blake}Wow, midje's up there.
20:00justin_smithyeah, I was surprised it was so prevalent
20:01justin_smithaha, decorate is doing the "decorator pattern", which you can also do with standard ring middleware
20:12{blake}justin_smith: Right, I sorta guessed that. I read it and thought "Hey, isn't that what you always do with everything ring-based?"
20:29thearthurthis core.logic SO question needs some attention: http://stackoverflow.com/questions/27324013/core-logic-unification-matches-value-in-map-but-not-key
20:35amalloythearthur: you're arthur ulfeldt? the question's only been up for five hours, and it has three upvotes; i'm sure it will get some answers when someone qualified comes across it. and if it doesn't, you certainly have the resources to put a bounty on it
20:36TEttingerasked by shaft, amalloy
20:36amalloyTEttinger: yes, i see that. so?
20:36thearthuramalloy: thats me, yep. it's just bugging me and i'm impatient :-)
20:37TEttingeroh, i thought bounties were added by the asker
20:37amalloyanyone can put a bounty on anything
20:38TEttingerstack overflow/exchange is certainly different
20:38justin_smiththearthur: oh hi, I'm noisesmith on stackoverflow, we've crossed paths there a few times
20:38amalloyi mean, in practice most of the time people put bounties on their own questions because they really want an answer
20:39amalloybut some third party can do it if they want an answer too, or just if they think it was a good question that deserves an answer; when you have as much rep as arthur, spending 50 on someone else's question is no big deal
20:39TEttingerrep is precious! I have like 9!
20:40thearthurperhaps I should switch nicks to match everywhere else
20:41thearthurI'm unable to find an add bounty button on this question
20:42amalloythearthur: you can't, because it's only five hours old
20:42amalloyyou're supposed to let it simmer for a bit :P
20:42thearthur(dec thearthur)
20:42lazybotYou can't adjust your own karma.
20:42amalloyor just like...mention dnolen_ and http://stackoverflow.com/questions/27324013/core-logic-unification-matches-value-in-map-but-not-key in the same line
20:43TEttingerdnolen_ with the underscore of inactiveness?
20:43amalloyhe'll get it eventually, i imagine
20:43TEttingerthere's also $mail
20:44TEttingerthat's one of the more widely used features on my lazybot
20:50amalloy$mail TEttinger i heard you like mail
20:50lazybotMessage saved.
20:52TEttinger$mail amalloy yes I do
20:52lazybotMessage saved.
20:52amalloy$login
20:52lazybotYou've been logged in.
20:52amalloy$unmail TEttinger amalloy
20:52lazybotDeleted unread messages from TEttinger to amalloy
20:52amalloyhacks
20:52amalloy$logout
20:52lazybotYou've been logged out.
20:52TEttingerheh, I didn't know you had a login
20:52TEttingernice
20:55tuftis there a repl client for clojuredocs.org? e.g. (clojuredocs cond) to see examples of cond
20:56justin_smith$grim clojure.core/cond is similar
20:56lazybothttp://grimoire.arrdem.com/1.6.0/clojure.core/cond
21:01andyftuft: github.com/jafingerhut/cd-client
21:02andyftuft: But the data you get via the API is currently stuck at about sep 2014 when they upgraded the rest of the site from clojure 1.3 source to 1.6
21:03andyfThere is an issue requesting updating the API data, too, at github.com/zk/ClojureDocs
21:18timvisher-xubuntanyone aware of a port of tools.trace to clojurescript?
21:20justin_smithtimvisher-xubunt: I bet you could do some nice tracing and even step debugging with the browser's inspector
21:22timvisher-xubuntjustin_smith: that's probably true. but i'm headless at the moment and would prefer to continue to be.
21:22timvisher-xubunttools.trace is _so_ nice but it doesn't look like anyone's tried to port it yet
21:22timvisher-xubuntstuartsierra: i'm assuming you haven't heard anything?
21:23timvisher-xubuntactually, you stopped maintaining it iirc, sorry :|
21:32Jesterman81hey ladies/gents, quick question. I have a clojure web app using hiccup with something like [:a {:href “/img/foo.jppg”}]
21:32Jesterman81do I have to manually add the context if I am deploying to a tomcat instance?
21:33justin_smithJesterman81: it's easier if your app is at the root, I don't know if there is any nice automated way to add the context to links
21:34justin_smithJesterman81: our approach has been to make a function that generates a route for a resource or endpoint, and call that
21:34justin_smithand let that function adjust for the context path etc.
21:34amalloyjustin_smith: i think the only thing you can do is write a function like make-link, and have that function know what the context is
21:35justin_smiththat also ends up helping when the client want's different URLs but you don't want to do a major app rewrite
21:35justin_smithamalloy: figures, yeah that's what we do
21:35Jesterman81thanks, I was hoping I just wasn’t missing something easy
21:36justin_smithyou may get something about the context info from the container in the request map
21:36justin_smithcouldn't hurt to dump the request map as you receive it in tomcat and look for something useful
21:38Jesterman81ill take a look at the request and see whats in there
21:40justin_smithanother option would be using a config to export the context as a system property that the clojure app can then pick up
21:41Jesterman81thanks for the options. appreciate it
22:17FrozenlockIn compojure, is it possible to apply different middlewares to different routes? (c/routes (-> r1 m1 m2 m3) (-> r2 m4 m5 m6)) ?
22:29justin_smithFrozenlock: yes. I am a little fuzzy on the details as I don't use compojure in anger myself, but I know that middlewares can be used to wrap individual routes
22:29justin_smithit should just be a question of function composition
22:30Frozenlockjustin_smith: thanks
23:18FrozenlockAH! Found how to do it. Must use compojure.core/wrap-routes to wrap the routes *only once they have been matched*.
23:40josiah14I'm reading through a bunch of Clojure code seeing how much I can figure out/comprehend, and I ran across what looks like a very short lambda function which is a bit cryptic to me in syntax. Can anyone tell me at a high level what #(%2) does, and why calling reductions with it on a list of read-line functions requires an initial value of nil for every function in the list to get executed?
23:41justin_smithjosiah14: ##(macroexpand '#(%2))
23:41lazybot⇒ (fn* [p1__13570# p2__13569#] (p2__13569#))
23:41josiah14the actual code is like, (reductions #(%2) nil (repeat n read-line)) where 'n' is some calculated number
23:42justin_smithdoes the above macroexpansion make sense?
23:42justin_smithequivalent: (fn [a b] b)
23:42justin_smitherr
23:42justin_smith(fn [a b] (b))
23:43josiah14actually, I think so
23:43justin_smithit expects two functions, and calls the second one, ignoring the first
23:43josiah14yah, that's what I got from that. I'm still getting used to reading macros.
23:43justin_smithwell, two things, and calls the second as a no arg function actually, to be more precise
23:43josiah14is there a better function I could use there so that i can eliminate the nil initial value
23:44josiah14I would have thought #(%1) would be like that one but call every function
23:44josiah14I can't remember what the error message was
23:44justin_smithwell, the thing is the first version takes N args, and only calls the second one
23:45justin_smithso that's a really weird "reduce" in that it always throws away the accumulator
23:45justin_smithit would be much clearer as a doseq
23:45justin_smith(doseq [f (repeat n read-line)] (f))
23:45josiah14except I need the values returned from read-line
23:45justin_smithoh, reductions
23:45justin_smithsorry
23:45justin_smithit's not reduce, but reductions, so you do see each result
23:45josiah14yes
23:45josiah14basically
23:46justin_smith(doall (for [f (repeat n read-line)] (f)))
23:46justin_smithyou still get all the results, but what it's doing is much more clear
23:46josiah14i thought there had to be somethnig simpler
23:47josiah14yah, it'll probably take me a bit to get the syntax down. I know conceptually what I want to do, but then figuring out how to say it in Clojure is proving tough for impure functions, yet
23:48josiah14but then, Haskell was tough in that way too (and it's looking like this will be easier than learning all that crap about Monads, Monad Transforms, Arrows, etc.)
23:48justin_smiththe way I see it that there is a strategy of making immutable and pure very easy to do, and impurity a bit trickier
23:49justin_smithjosiah14: the general rule of thumb that has worked for me is take everything you think may have to mutate, turn it into a function argument, and do chained / recursive function calls
23:49justin_smiththat is pretty effective for translating imperative algorithms to functional world
23:49josiah14yah, same as in haskell
23:49josiah14it's IO that gets tricky, and event handling
23:50justin_smithyou can also "cheat" by making a map holding a "state of the world" under various keys as one of the parameters
23:50justin_smithin clojure integrating io/events is a bit easier I think
23:50justin_smithit's handled more pragmatically at least
23:50josiah14yah, it's looking that way - just a matter of syntax
23:50rritochjosiah14: Cant you just map over #(%1) ? As far as I can tell that would produce the same results
23:50rritochjosiah14: (map #(%1) (repeat n read-line))
23:51justin_smithrritoch: that's what the for does, but I think for is more readable in that case
23:51josiah14rritoch, yes, that works out perfectly
23:51josiah14just tested in the repl
23:52justin_smithjosiah14: beware that that is lazy
23:52justin_smiththat is why I added the doall in my for version, to match the eagerness of reduce
23:52josiah14yah, I just need to get the syntax in my head, then I think all that effort I put into Haskell will start to pay off in terms of already knowing how to think functionally
23:52josiah14justin_smith: I'm used to lazy, so no problems, there
23:56rritochjustin_smith: Is reductions being depricated? I could be wrong but it seems reductions is replaced with map transducers that have "reduction state"
23:57justin_smithit carries no deprecation warning in the latest 1.7 alpha
23:58justin_smithbut yeah, it may make a lot of sense to use a transducer