2014-12-05
| 00:44 | timvishet | anyone 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:45 | timvishet | oh, and you have to try to M-x cider-load-file to trigger the WARNINGs |
| 00:46 | timvishet | seems to well and truly fubar the repl, i have to cider-restart each time |
| 01:30 | rritoch | What is the URL of the web history of this chatroom? |
| 01:32 | otti | clojure-log.n01se.net |
| 01:33 | rritoch | otti: Thanks :) |
| 01:34 | otti | hm 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:34 | otti | but 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:34 | justin_smith | otti: if you put the files in the classpath (ie. under the test/ directory) they can be required by the other files |
| 01:35 | otti | justin_smith: hm didn't work |
| 01:35 | justin_smith | otti: does the path to the file match the namespace in the file? |
| 01:35 | justin_smith | because it needs to |
| 01:35 | rritoch | otti: The only way I know of that you can split-up test is to use 'lein test :only test-namespace/some-test |
| 01:36 | justin_smith | otti for example if the file is in test/helpers.clj the namespace needs tobe called helpers |
| 01:36 | otti | justin_smith: it is |
| 01:36 | justin_smith | otti: then the other reason it wouldn't load is if there is an error in the file |
| 01:37 | otti | i 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:37 | justin_smith | otti: that should not be needed at all. I use namespaces under test/ frequently with no issue |
| 01:37 | otti | but that sucks because on lein run the test files are considered too |
| 01:37 | otti | justin_smith: i try as you suggested again |
| 01:38 | justin_smith | lein run won't load or use files that are not required by your core namespace anyway, so that isn't even an issue |
| 01:38 | otti | but who do you explain the fact, that i once got an exception, while executing |
| 01:39 | justin_smith | and 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:39 | otti | 'lein run' within the tests |
| 01:39 | justin_smith | otti: something must have required or attempted to compile the file, but lein run wouldn't do that on its own |
| 01:39 | otti | hm |
| 01:40 | justin_smith | otti: perhaps you had :aot :all turned on? |
| 01:40 | otti | hm think, i just found the issue |
| 01:40 | otti | justin_smith: no |
| 01:40 | otti | justin_smith: it could be because i use vim-fireplace and run :Eval (core.test/run-tests) |
| 01:41 | otti | which is connected to the repl that probably then goes looking within /src/app/ |
| 01:41 | otti | for the required files |
| 01:41 | otti | instead of /test/app/ |
| 01:41 | justin_smith | clojure.test/run-tests does not load any files |
| 01:41 | justin_smith | it only runs the tests that you have defined / loaded previously |
| 01:42 | justin_smith | perhaps fireplace loaded the files? I don't know how fireplace does things. lein should only be looking for test namespaces under test/ |
| 01:43 | otti | fireplace connects to the repl (lein repl) and, yes i have to load the files |
| 01:43 | otti | by calling :Require from within vim |
| 01:50 | otti | hm very strange |
| 01:52 | justin_smith | otti: you say "probably then goes looking within /src/app for the required files instead of /test/app/" |
| 01:52 | justin_smith | otti: the way the classpath works, files under src/ and files under test/ are considered the same location |
| 01:53 | justin_smith | so you can't count on src/app/foo.clj vs. test/app/foo.clj - they are both the same relative path |
| 01:53 | otti | justin_smith: i don't know probably i made some mistakes the first time that i started to write the tests |
| 01:53 | justin_smith | OK |
| 01:53 | otti | because i removed the link within /src to /test |
| 01:54 | otti | and changed the namespaces |
| 01:54 | otti | and no namespace exceptions |
| 01:54 | otti | thus it works now |
| 01:54 | otti | justin_smith: thanks for the clearance |
| 01:56 | justin_smith | np |
| 02:08 | rritoch | I 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:09 | justin_smith | rritoch: Bronsa came up with a fix for that issue today BTW |
| 02:10 | rritoch | Cool, I haven't had a chance to check all of the logs |
| 02:10 | rritoch | Does it resolve this issue also? |
| 02:11 | justin_smith | I think it should. But I'm not sure of that. |
| 02:12 | rritoch | justin_smith: Do you have a link to the solution? Bronsa was very active |
| 02:13 | rritoch | Hmm,maybe I found it |
| 02:14 | rritoch | Is this patch supposed to fix it? http://sprunge.us/YddP?diff |
| 02:14 | justin_smith | yeah, that's the one |
| 02:16 | rritoch | Interesting 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:16 | rritoch | I was thinking that it would be better to check interned classes first though |
| 02:18 | rritoch | Such 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:19 | rritoch | I don't think this patch fixes this new issue though, I'll have to double check something in the compiler to see. |
| 02:23 | rritoch | Ok, 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:23 | rritoch | I still think it would be more stable though to check against interned classes first |
| 02:25 | rritoch | This 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:29 | rritoch | Either 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:32 | kenrestivo | rritoch: 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:33 | kenrestivo | i don't remember the ticket number but it's in the logs |
| 02:35 | rritoch | Sure, 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:36 | rritoch | I'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:37 | rritoch | Looking 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:38 | rritoch | Changing the interned class would alter which class was used at the top level, but not within the let |
| 02:39 | rritoch | I 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:40 | rritoch | I 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:42 | rritoch | It 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:46 | rritoch | Would the &env in a macro show if a symbol in a let* has been resolved to a fully qualifed name? |
| 02:47 | rritoch | Or would it just show the final eval'd value |
| 03:14 | epichero_ | i need to spend a few hours getting cider setup with autocomplete setup with my customized emacs using evil mode and hooks... |
| 03:15 | sm0ke | is there something like try-let ? |
| 03:16 | sm0ke | where the let binding are available in the finally clause |
| 03:16 | opqdonut | sm0ke: just have try inside let? |
| 03:17 | opqdonut | that's how e.g. with-open is defined IIRC |
| 03:17 | opqdonut | yep: https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L3512 |
| 03:17 | Empperi | rritoch: I used to use ccw |
| 03:17 | Empperi | these days I use IntelliJ + Cursive |
| 03:19 | sm0ke | rritoch: what if the binding cause exception/ |
| 03:19 | sm0ke | sorry ^ opqdonut |
| 03:19 | rritoch | Empperi: 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:19 | Empperi | well, IntelliJ has support for as wide variety of languages |
| 03:19 | Empperi | maybe even wider |
| 03:20 | Empperi | I personally do clojure, java, javascript, dart, bit of ruby, bit of python |
| 03:20 | Empperi | and of course html, css, markdown etc |
| 03:20 | rritoch | Empperi: 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:21 | Empperi | yeah, ccw isn't that bad really |
| 03:21 | Empperi | it's the eclipse I had problems with |
| 03:21 | Empperi | used it for maybe 10 years |
| 03:21 | mavbozo | long live clojure!!! http://matthiasnehlsen.com/blog/2014/12/04/Farewell-Scala/ |
| 03:21 | opqdonut | sm0ke: with-open with multiple bindings desugars into a nested try-let-try-let... |
| 03:21 | opqdonut | sm0ke: so if e.g. the third binding fails, the first two get freed |
| 03:21 | opqdonut | s/freed/closed/ |
| 03:23 | andyf | rritoch: Sometimes adding debug print?s to the Clojure compiler is the quickest way to find out what you want. |
| 03:27 | rritoch | andyf: 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:28 | andyf | rritoch: mvn install |
| 03:28 | andyf | There may be other ways, but that should do it. |
| 03:28 | rritoch | andyf: ty, that sounds easy enough |
| 03:32 | andyf | If you want to skip running the tests: mvn -Dmaven.test.skip=true |
| 03:32 | andyf | I mean: mvn -Dmaven.test.skip=true install |
| 03:33 | andyf | That 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:34 | rritoch | andyf: Thanks, I made a note of it. I don't think I'll have time to start tinkering until monday though |
| 03:36 | rritoch | andyf: 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:37 | rritoch | andyf: It won't support multiple versions of clojure itself, but it could support independent versions of anything else. |
| 03:37 | andyf | I 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:38 | andyf | The most common solution is to modify dependencies until only a single version of each library is in use. |
| 03:38 | andyf | but that can be difficult, and in some cases impossible. |
| 03:39 | rritoch | andyf: 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:39 | rritoch | err, creating a custom classloader |
| 03:39 | rritoch | Both methods involve toying with java classloaders, which is a guaranteed way to run into troubles |
| 03:40 | andyf | I'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:40 | andyf | crude, but effective |
| 03:43 | rritoch | Well, that sounds like it would work in most cases |
| 03:47 | rritoch | In 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:47 | rritoch | clojure.lang.Namespace/namespaces gets stored in thread-local memory, making it possible to isolate environments |
| 03:57 | rritoch | Thinking 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:57 | rritoch | At least that's the goal. |
| 03:58 | rritoch | I certainly could end up with an environment that is completely unstable and unusable |
| 03:58 | andyf | Out of curiosity, do you have an application that needs this? |
| 03:59 | rritoch | Yes, I'm developing a web platform/framework which needs it |
| 04:00 | rritoch | https://github.com/search?q=user%3Arritoch+clj-grid |
| 04:02 | rritoch | The 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:03 | rritoch | I 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:04 | andyf | So the web framework will not achieve its goals without OSGi support? |
| 04:06 | rritoch | andyf: The OSGi support is to provide plugins, and facilitate commercial interest in the platform. |
| 04:07 | rritoch | andyf: 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:10 | andyf | Aren't there closed source Java libraries delivered via jar files? |
| 04:13 | rritoch | andyf: Yes, but OSGi provides module isolation, so you don't end up with as many plugin conflicts, such as are faced by wordpress |
| 04:13 | borkdude | does anyone still use lein cucumber? https://github.com/nilswloka/lein-cucumber |
| 04:15 | cfleming | rritoch: I'd be very interested to hear about what you come up with. |
| 04:15 | cfleming | rritoch: I'm no longer using OSGi, but I have a similar problem with IntelliJ plugins. |
| 04:15 | cfleming | rritoch: i.e. I'd like to be able to load Clojure code into plugins without replicating the Clojure runtime across each of them. |
| 04:16 | rritoch | andyf: 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:18 | rritoch | andyf: To provide JSP support I'm already locked into the apache license anyhow, ... |
| 04:19 | rritoch | When 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:19 | rritoch | Because of those lawsuits I will do whatever it takes to avoid using ANY JBoss product |
| 04:20 | rritoch | I 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:21 | shiranaihito | rritoch: i always just figured JBoss was way too "Enterprisey", but i guess they're full of shit too |
| 04:24 | lxsameer | hey folks, is ther any solution to build android apps using clojure / |
| 04:24 | rritoch | Well, 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:24 | shiranaihito | rritoch: plenty of other app servers around, though? |
| 04:24 | rritoch | Recent 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:25 | rritoch | shiranaihito: There aren't many that I can find that are stable and well maintained, other than Apache Tomcat |
| 04:25 | shiranaihito | i'm not sure that matters.. court decisions will always favour the wealthy and politically connected anyway |
| 04:25 | shiranaihito | Jetty? |
| 04:27 | rritoch | shiranaihito: 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:28 | shiranaihito | rritoch: 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:28 | shiranaihito | i'm basing my own Clojure web app development on top of Jetty though |
| 04:30 | shiranaihito | rritoch: one considerable advantage that Jetty has is that you can embed it in a stand-alone Java/Clojure application |
| 04:30 | shiranaihito | "so that this for what it's worth" <-- _take_ this for what it's worth, even.. |
| 04:31 | rritoch | shiranaihito: Tomcat can also |
| 04:32 | shiranaihito | alright, i guess that's new |
| 04:32 | rritoch | shiranaihito: Currently I'm depending on [org.apache.tomcat/tomcat-jasper "7.0.52"] which provides me all of tomcat |
| 04:32 | shiranaihito | wasn't Jasper the JSP engine.. ? |
| 04:33 | cfleming | borkdude: I've received at least one request to support it in Cursive, so someone is: https://github.com/cursiveclojure/cursive/issues/478 |
| 04:33 | borkdude | cfleming ah ok. It doesn't work anymore on my machine, but I think it's because Firefox updated itself |
| 04:34 | cfleming | borkdude: Ok - I've never used it myself. |
| 04:34 | rritoch | shiranaihito: 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:35 | rritoch | shiranaihito: 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:35 | shiranaihito | rritoch: hmm.. i don't quite follow |
| 04:36 | gavilancomun | There can be slight differences in interpretation of the Servlet 3 spec between Tomcat and Jetty, but they can be worked around |
| 04:36 | rritoch | shiranaihito: Catalina code in the tomcat library is what provides the servletconfig's and servletcontext's required by the JSP specification |
| 04:36 | shiranaihito | how do you "run JSP from the command line"? |
| 04:36 | shiranaihito | do you mean the Servlet specification? :P |
| 04:36 | rritoch | yeah :) |
| 04:37 | shiranaihito | :P |
| 04:37 | shiranaihito | but still, "running JSP" from the command line (or anywhere for that matter) sounds weird |
| 04:37 | rritoch | The code to run jsp from the command line is all in http://www.github.com/rritoch/clj-grid-core , it wasn't easy |
| 04:38 | rritoch | shiranaihito: Well, the intention behind that is to eventually provide CGI capability |
| 04:38 | gavilancomun | The two issue I have had are scanning jars for annotations alongside web_fragment.xml files... |
| 04:39 | rritoch | shiranaihito: Running via CGI would be slow, and cause the loss of all persistence benefits, but it is good for testing |
| 04:39 | rritoch | shiranaihito: Currently I only use the command line support for testing/debugging |
| 04:39 | gavilancomun | and how the notion of current URL changes it calls to redirect() and calls to .forward() with a relative URL. |
| 04:40 | gavilancomun | *it* -> with |
| 04:40 | shiranaihito | rritoch: 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:40 | shiranaihito | dflkjdsfdf |
| 04:41 | shiranaihito | rritoch: "called" by a browser, that is |
| 04:41 | shiranaihito | sorry.. i'm in a brainfarty mood, apparently |
| 04:41 | shiranaihito | JSP (Java Server Pages) is just a View layer for Servlet -based web applications, right? |
| 04:43 | rritoch | shiranaihito: JSP compiles to a servlet so it can provide the entire application, but typically a lot of back-end java is used |
| 04:45 | rritoch | shiranaihito: Either way, I'm only using it for a view layer to JSP web applications |
| 04:45 | shiranaihito | rritoch: yeah i know, but people don't write JSP for that aspect |
| 04:45 | rritoch | err, clj web applications |
| 04:45 | shiranaihito | :p |
| 04:46 | shiranaihito | rritoch: 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:47 | shiranaihito | but why would you not use just plain Servlets or something on top of that instead? |
| 04:48 | rritoch | shiranaihito: 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:49 | shiranaihito | rritoch: 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:49 | rritoch | shiranaihito: This way I can test features directly from the command line without needing to deploy an application server |
| 04:50 | rritoch | shiranaihito: Testing as CGI requires one command "lein run", no need to launch a server, install updates, or open a web browser |
| 04:50 | shiranaihito | rritoch: 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:51 | shiranaihito | wouldn't "lein run" launch a web server too, typically? :p |
| 04:52 | rritoch | shiranaihito: 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:52 | rritoch | shiranaihito: 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:52 | shiranaihito | rritoch: "virtual web request"? .. so you're doing "web-like" stuff to avoid doing actual web stuff? :p |
| 04:53 | rritoch | But first I need to deal with this isolation issue |
| 04:53 | rritoch | shiranaihito: Yes, development has been much faster that way |
| 04:55 | shiranaihito | rritoch: i'm still confused by what you're doing, and why, but.. i guess that's alright :P |
| 04:55 | shiranaihito | carry on! :P |
| 05:05 | rritoch | shiranaihito: 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:06 | rritoch | shiranaihito: Your jetty project is the only other project I've heard of that has JSP support in clojure |
| 05:06 | Empperi | wait, what, why? |
| 05:06 | Empperi | jsp in clojure? |
| 05:06 | Empperi | man |
| 05:07 | shiranaihito | rritoch: 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:07 | shiranaihito | you could check out ring-jetty for some inspiration? |
| 05:08 | shiranaihito | it sets up a stand-alone Jetty instance and gives it a custom (Jetty-specific) request handler thingy, that calls ring handlers |
| 05:08 | rritoch | shiranaihito: ring is a deadzone for my application because ring rejects tomcat dependencies |
| 05:08 | shiranaihito | i think that's pretty straightforward, and i'm using parts of that for my own cute little web framework |
| 05:08 | shiranaihito | rejects? |
| 05:09 | rritoch | Yes, rejects, removes the dependency because it contains a servlet implementation |
| 05:10 | shiranaihito | rritoch: you mean there's some kind of dependency conflict with Lein? |
| 05:10 | shiranaihito | can you use the "exclude" command to work around it? |
| 05:10 | rritoch | No, I mean the ring plugin specifically rejects the dependency |
| 05:11 | Empperi | I know for a fact that several people are running clojure + ring apps on top of tomcat |
| 05:11 | rritoch | shiranaihito: I don't think so, exclude works at the package level, not the class level |
| 05:11 | rritoch | Empperi: Yes, they do that with the uberwar |
| 05:11 | Empperi | even if that is not the recommended way to do it |
| 05:11 | Empperi | yes, which is the right way to do it anyway |
| 05:12 | Empperi | the whole concept of using jars from tomcat's lib directory is just dumb |
| 05:12 | Empperi | imho |
| 05:12 | Empperi | makes deployments so much harder and gains nothing |
| 05:13 | Empperi | since 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:13 | Empperi | and only "gain" you could gain with tomcat lib directory based jar packages is the situation where you have same dependencies for multiple apps |
| 05:14 | ordnungswidrig | Empperi: containers should hide all the libs they use to the deployed apps |
| 05:14 | Empperi | and 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:15 | Empperi | ordnungswidrig: yes, indeed. App decides what libraries they need, not the container |
| 05:15 | ordnungswidrig | Empperi: we know all the fun with log4j and jbos |
| 05:15 | Empperi | and that's my point, there is absolutely no reasonable reason to put jar packages into tomcat lib directory for your app |
| 05:15 | rritoch | shiranaihito: 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:15 | Empperi | it's an antipattern and the world is better without it |
| 05:17 | Empperi | if 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:17 | maxpn | how to implement javascript-like setTimeout() in Clojure? |
| 05:17 | rritoch | shiranaihito: 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:17 | ordnungswidrig | Empperi: there are still links or file systems that do deduplication for that |
| 05:17 | ordnungswidrig | maxmartin: there's a lib called atat |
| 05:17 | rritoch | shiranaihito: If I was aware of jetty+ring at the time the project may have gone in a different direction |
| 05:17 | godd2 | maxpn you sure you dont just want sleep? |
| 05:18 | ordnungswidrig | rritoch: I never heard someone wanting jsp support in a ring app :) |
| 05:18 | maxpn | godd2: yes, sleep but not in main thred |
| 05:18 | godd2 | maxpn you can just put it in a future |
| 05:18 | ordnungswidrig | maxmartin: (future (Thread/sleep 1000) (prn "foo")) |
| 05:19 | shiranaihito | rritoch: 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:19 | ordnungswidrig | &(future (Thread/sleep 1000) (prn "foo")) |
| 05:19 | lazybot | java.lang.SecurityException: You tripped the alarm! future-call is bad! |
| 05:19 | ordnungswidrig | lzybot: I'm sorry |
| 05:19 | maxpn | godd2: thank you, that is it! |
| 05:19 | maxpn | thank you all |
| 05:20 | rritoch | ordnungswidrig: 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:21 | ordnungswidrig | rritoch: To my experience they prefer more something like mustache |
| 05:21 | rritoch | ordnungswidrig: JSP support in web apps is purely to facilitate employing web designers onto the projects. |
| 05:23 | rritoch | ordnungswidrig: I'm talking about professional web designers, not programmers experimenting with web design. |
| 05:23 | ordnungswidrig | rritoch: I know what you mean, it's just contrary to my experience with professional web designers. |
| 05:24 | ordnungswidrig | rritoch: I guess the preferences of web designers in this regard vary a lot over different communitites |
| 05:25 | rritoch | ordnungswidrig: Well, most web designers I've dealt with require templates to be as close to pure html as possible |
| 05:28 | ordnungswidrig | rritoch: 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:30 | rritoch | ordnungswidrig: 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:31 | rritoch | ordnungswidrig: I'm dealing with all of the complexity within the platform itself |
| 05:31 | ordnungswidrig | rritoch: ok, that's a point. |
| 05:31 | ordnungswidrig | rritoch: good luck to you :-P |
| 05:31 | bja | /.er in me says JSP isn't an advantage |
| 05:31 | rritoch | ordnungswidrig: If clojure outputs directly to stdout (println) I have that bound to the servlets output stream, that opens a lot of possiblities |
| 05:32 | rritoch | ordnungswidrig: But in all of my example apps I'm jut forwarding to jsp's |
| 05:32 | rritoch | ordnungswidrig: I also recently made a .clj specific servlet, so you can even forward to a .clj script |
| 05:40 | kras | which is better in terms of performance #(nth % (- (count %) 1)) or #(first (reverse %)) ? |
| 05:40 | kras | for taking the last item |
| 05:43 | algernon | I'd think (last %) would be, if I may offer a third choice. |
| 05:43 | kras | 4clojure problem #19, restriction on last :-) |
| 05:44 | rritoch | kras: 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:44 | lazybot | java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.Reversible |
| 05:44 | shiranaihito | rritoch: as someone pointed out, you can just use a templating engine like Velocity or FreeMarker |
| 05:44 | dgellow | hi #clojure |
| 05:44 | shiranaihito | there'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:45 | daniel``` | hi dgellow |
| 05:45 | rritoch | Eek, didn't know lazy sequences aren't reversable :( |
| 05:46 | rritoch | shiranaihito: Most of my web designers know JSP, and there is a large market of JSP template designers |
| 05:47 | shiranaihito | rritoch: 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:47 | dgellow | Is cemerick/Friend the de facto library for everything about authentication ? Or do you know other lib with a similar purpose ? |
| 05:48 | shiranaihito | but similar things can be achieved with Velocity or FreeMarker.. i'm not sure it warrants the complexity of the JSP setup etc |
| 05:48 | algernon | kras: ah :) |
| 05:49 | rritoch | shiranaihito: Ex. on odesk there are 920 velocity developers, but over 16,000 JSP developers |
| 05:50 | shiranaihito | rritoch: sure, but you're just producing HTML.. learning Velocity or FreeMarker is not difficult either - they're all templates for producing HTML anyway |
| 05:50 | shiranaihito | but i guess the biggest mystery to me is that CGI stuff |
| 05:53 | shiranaihito | it sounded like in a way, you'd be testing whether your actual app code can be called (from the command line) |
| 05:54 | shiranaihito | but 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:54 | rritoch | Anyhow, 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:55 | shiranaihito | (for example, most of your functions probably don't have to take a HttpServletRequest as a parameter) |
| 05:56 | shiranaihito | rritoch: don't strive for excessive generality either :) .. whatever that might happen to mean in practice |
| 05:56 | rritoch | shiranaihito: None do, I dynamically bind a *servlet-request* variable from the servlet, so every function has access to the request automatically |
| 05:57 | shiranaihito | rritoch: alright, but again, what would you need some kind of CGI contraption for? :) |
| 05:57 | daniel``` | dgellow: it is, yes |
| 05:57 | daniel``` | dgellow: i have looked for others, its by far the most used |
| 05:57 | kras | any suggestions on whom to follow on 4clojure, for learning from their solutions |
| 05:57 | shiranaihito | rritoch: besides, that doesn't sound very functional |
| 05:57 | rritoch | shiranaihito: As I said, it reduces development time for these core systems because it doesn't require the overhead of a server |
| 05:58 | rritoch | shiranaihito: The goal is to provide functions for access to the request |
| 05:58 | shiranaihito | rritoch: well what's the problem with running a server? |
| 05:58 | shiranaihito | functions that would access the global request variable? |
| 05:59 | rritoch | shiranaihito: Time, it takes 1 second to type lein run and get the results, up to a minute to restart a tomcat server |
| 05:59 | rritoch | shiranaihito: Previously I also had to install updates to tomcat, similar to the ring uberwar process |
| 06:00 | shiranaihito | rritoch: it takes.. let's say 1 second (to mirror your estimate :p) to start up a stand-alone embedded Jetty server :p |
| 06:00 | rritoch | shiranaihito: 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:01 | rritoch | shiranaihito: Ok, well the other advantage of CGI mode is that it will work on nearly every web server |
| 06:01 | rritoch | Anyhow, 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:01 | shiranaihito | rritoch: well, your app server will just take in http connections anyway right? |
| 06:02 | shiranaihito | so it doesn't really matter if it's tomcat or jetty or jboss etc |
| 06:02 | shiranaihito | "nearly any web server" will be able to proxy connections to your app server |
| 06:02 | christiaanb | Hi, 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:04 | rritoch | hmm, 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:09 | TEttinger | christiaanb, there is the clojure mailing list, which seems appropriate |
| 06:09 | rritoch | shiranaihito: 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:10 | christiaanb | TEttinger: thanks |
| 06:11 | TEttinger | christiaanb, 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:12 | christiaanb | TEttinger: I think I'll try the user groups for that |
| 06:12 | dgellow | daniel```: thanks |
| 07:17 | triss | I'm always saying (vec (repeat n some-value)) |
| 07:18 | triss | is that the easiest way of filling a vector with a default value? |
| 07:18 | Bronsa | that's the best way |
| 07:19 | triss | cheers Bronsa. |
| 07:21 | bja | boo: (read-string (pr-str (keyword ""))) |
| 07:22 | bja | actually boo my logic that allows me to try to keyword "" |
| 07:49 | TimMc | bja: boo to code that keywords arbitrary strings as opposed to statically known values. |
| 07:50 | bja | well, they're not *supposed* to be arbitrary |
| 07:51 | bja | there was a bug that resulted in something along the lines of (keyword (string/join [" " "foo"])) to occur |
| 08:06 | mavbozo | will clojure eXchange 2014 London videos made available in youtube? |
| 08:16 | scottj | mavbozo: weren't previous ones available on skillsmatter.com only using vimeo but not accessible on vimeo's site? |
| 08:17 | mavbozo | scottj: oh, those videos are in skillsmatter.com. thanks scottj. |
| 08:17 | mavbozo | (inc scottj) |
| 08:17 | lazybot | ⇒ 2 |
| 09:08 | triss | hey all. so I'm writing my first proper app in clojure. |
| 09:08 | triss | I want to do the frontend in clojurescript |
| 09:08 | triss | what's the simplest way of adding clojurescript as a dependancy? |
| 09:09 | triss | is iyt possible to use lein to add it to an existing project or do i have to manually edit the project.clj? |
| 09:57 | sveri | triss: what I usually do is take a template and work on from there |
| 09:58 | sveri | triss: 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:01 | triss | thanks sveri.... |
| 10:01 | triss | so create a new cljs project and copy the missing deps from there. |
| 10:02 | sveri | triss: this is a tedious thing to do, but usually only a one time setup, so I just do it |
| 10:14 | mnngfltg | Hey. Does anyone mock out dependencies like writing to the database? I've tried `conjure` with clojure.test and found it cumbersome. |
| 10:28 | bja | mnngfltg: mostly no. I write functions that return data and test the functions |
| 10:29 | bja | I mostly assume that the libraries I use to connect to external sources work |
| 10:29 | bja | those libraries have their own tests |
| 10:29 | mnngfltg | bja, right |
| 10:29 | mnngfltg | bja, but what about glue code, e.g. code with side-effecets that, say, writes to the database |
| 10:30 | bja | mnngfltg: code doesn't do that typically. It does something, and then finally writes to the db |
| 10:30 | bja | I can test the transforms I do |
| 10:30 | mnngfltg | bja, in my experience that's not always easy to do |
| 10:31 | bja | maybe not easy, but I try very hard to make that part of my design |
| 10:31 | bja | helps me live a much happier life |
| 10:31 | mnngfltg | I would be happier too :) |
| 10:31 | bja | the places I talk to the external world now are mostly over core.async channels |
| 10:31 | bja | and those are trivial to mock out when I need to |
| 10:32 | bja | i.e. in some logic that handles various failure modes |
| 10:32 | mnngfltg | interesting |
| 10:32 | mnngfltg | so having a queue helps you decouple the code from the actual side effects |
| 10:33 | bja | I 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:33 | csd_ | What do I need to do to a key-value object to treat it as if it were a JSON object? |
| 10:33 | bja | then I can test the control logic by creating various plain old channels and putting input on them or getting a value from them |
| 10:33 | bja | and my transforms can be mostly pure |
| 10:34 | bja | that's probably some sort of pattern with a name, but I couldn't tell you which one |
| 10:35 | mnngfltg | bja, it's an interesting approach, though maybe a bit too heavy if I don't have a use for core.async otherwise |
| 10:36 | mnngfltg | csd_, what do you mean by "treat as a JSON object"? |
| 10:36 | mnngfltg | csd_, generate a JSON string? (see cheshire or clojure/data.json |
| 10:38 | EvanR | ,(:a {:a 1}) |
| 10:38 | clojurebot | 1 |
| 10:38 | EvanR | ,(2 {2 1}) |
| 10:38 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 10:38 | EvanR | ,({2 1} 2) |
| 10:38 | clojurebot | 1 |
| 10:38 | justin_smith | ,(ifn? :a) |
| 10:38 | clojurebot | true |
| 10:38 | justin_smith | ,(ifn? 2) |
| 10:38 | clojurebot | false |
| 10:38 | justin_smith | ,(ifn? {}) |
| 10:38 | clojurebot | true |
| 10:38 | csd_ | 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:39 | EvanR | is it possible implement ifn in clojure |
| 10:39 | csd_ | oh shoot i thought this was #javascript |
| 10:39 | EvanR | for newtypes |
| 10:39 | mnngfltg | csd_, JSON.stringify() ? :) |
| 10:39 | bja | #(.stringify js/JSON %) |
| 10:39 | justin_smith | EvanR: absolutely. Anything made with defrecord does it they way {} does by default. |
| 10:40 | justin_smith | EvanR: but you can get creative with it easily with deftype |
| 10:40 | EvanR | i keep getting confused about what can/cant implement protocols/interfaces |
| 10:41 | justin_smith | ifn? tests for clojure.lang.IFn |
| 10:41 | EvanR | which is an interface or protocol |
| 10:42 | justin_smith | I think it's an interface. Reagardless, protocol is just a very thin abstraction on interface. |
| 10:42 | justin_smith | and every protocol has an underlying interface that gets created |
| 10:43 | EvanR | java classes can have protocol impls |
| 10:43 | EvanR | but not interfaces? |
| 10:43 | justin_smith | java classes can easily have interfaces. It's a bit more work for them to integrate with protocols. nothing stops them from having both. |
| 10:44 | EvanR | alright |
| 10:44 | justin_smith | interfaces are part of the jvm. protocols are a clojure thing |
| 10:44 | EvanR | but you cant implement a protocol for an interface? |
| 10:45 | justin_smith | no, but you can implement an interface for an interface, and every protocol has an underlying implementation as an interface |
| 10:49 | pepijndevos | a protocol also generates an interface, right? |
| 10:49 | justin_smith | right, that's what I was saying |
| 10:49 | pepijndevos | eh, right |
| 10:51 | mikerod | Didn'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:51 | puredanger | I'm not sure that's the correct summary :) |
| 10:51 | pepijndevos | If 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:51 | puredanger | protocols can definitely extend to interfaces now |
| 10:52 | llasram | Well, the protocol implementation lookup definitely works pretty hard to do the right thing for interfaces |
| 10:52 | mikerod | I'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:52 | EvanR | what exactly does protocol extend protocol mean anyway, have an implementation? or is this inheritance |
| 10:52 | puredanger | it is not inheritance |
| 10:52 | mikerod | EvanR: inheritance is what I'm thinking |
| 10:52 | puredanger | at least I don't think of it as inheritance |
| 10:52 | mikerod | Type hierarchy inheritance is mostly my focus |
| 10:53 | puredanger | it means an implementation of the protocol exists for a type |
| 10:53 | mikerod | I 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:53 | puredanger | I 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:54 | puredanger | interface inheritance is fine |
| 10:54 | puredanger | it's concrete extension that is a no-go |
| 10:54 | mikerod | puredanger: yes I agree and see that concrete extension is no good and is the main issue on this topic I think |
| 10:54 | EvanR | what is concrete extension |
| 10:54 | justin_smith | pepijndevos: where does that Node class come from? |
| 10:55 | puredanger | class extends class |
| 10:55 | EvanR | and in this case extends means inheritance |
| 10:55 | mikerod | I 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:55 | pepijndevos | justin_smith line 27 |
| 10:55 | puredanger | EvanR: yes, talking in Java terms atm |
| 10:55 | justin_smith | pepijndevos: d'oh, I must not be fully awake yet |
| 10:55 | EvanR | and "isa" means, is a subtype? a isa b means a works wherever b works? |
| 10:56 | puredanger | pepijndevos: you're using boxed math for one thing |
| 10:56 | mikerod | EvanR: 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:57 | puredanger | EvanR: this is not precise enough wrt concrete class vs interface |
| 10:57 | mikerod | (dumb example of course :) ) |
| 10:57 | puredanger | mikerod: right, you can extend ActualDog to Animal and ActualDog to Dog |
| 10:57 | pepijndevos | puredanger, enlighten me. You mean I should use +' and friends? |
| 10:57 | EvanR | mikerod: without implementing Animal? |
| 10:57 | puredanger | but you can't extend Dog to Animal |
| 10:58 | mikerod | puredanger: yes, it just requires more of a hunt to figure out all the things you must extend to |
| 10:58 | EvanR | shudders |
| 10:58 | mikerod | puredanger: I just think the maintenance barrier is a bit higher |
| 10:58 | puredanger | one trick for this is to extend Object to Animal, then check satisfies? and install an extension for the concrete type you've encoutnered |
| 10:58 | EvanR | how do i union two sets? |
| 10:58 | EvanR | ,(union #{1} #{2}) |
| 10:58 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: union in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 10:58 | puredanger | EvanR: clojure.set/union |
| 10:59 | mikerod | puredanger: that is an interesting way |
| 10:59 | EvanR | ,(clojure.set/union #{1} #{2}) |
| 10:59 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set> |
| 10:59 | puredanger | mikerod: 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:59 | puredanger | after that there is an extension installed for the concrete type so it routes directly |
| 10:59 | justin_smith | pepijndevos: +' 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:00 | mikerod | This 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:00 | puredanger | justin_smith: +1 |
| 11:00 | mikerod | puredanger: that is pretty clever :) |
| 11:00 | pepijndevos | ah... can I do *warn-on-boxed* yet? Browsing jira.... |
| 11:00 | puredanger | it actually came up in a talk at the very first conj and Rich said this from the audience |
| 11:00 | puredanger | pepijndevos: you can in 1.7 alphas |
| 11:01 | pepijndevos | I have those... so I'll try that. |
| 11:01 | puredanger | mikerod: chouser (I believe) tried to live-code it and it didn't go so well :) |
| 11:01 | mikerod | puredanger: the dangers of live coding I guess |
| 11:01 | puredanger | live coding suggestions from Rich no less :) |
| 11:01 | justin_smith | puredanger: 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:02 | justin_smith | I may just work on that today. |
| 11:02 | mikerod | that just sounds intense |
| 11:02 | justin_smith | (capturing the reflection / boxing warnings via with-out-str) |
| 11:03 | puredanger | justin_smith: there are some examples of how to do that in the clojure tests if you want to steal |
| 11:03 | justin_smith | puredanger: awesome, thanks |
| 11:03 | puredanger | mikerod: you might find this useful - http://david-mcneil.com/post/3495351254/clojure-protocol-adapters |
| 11:03 | puredanger | David and I were working together when he wrote this and it's the same ideas |
| 11:04 | EvanR | mikerod: maybe this idea is more about "required prerequisite protocol of a protocol" |
| 11:05 | puredanger | and 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:05 | pepijndevos | so is it *unchecked-math*? |
| 11:06 | justin_smith | puredanger: my spidey-sense tells me that could get very ugly if misused... |
| 11:06 | puredanger | pepijndevos: (set! *unchecked-math* true) |
| 11:06 | EvanR | advanced, powerful ;) |
| 11:06 | puredanger | or (set! *unchecked-math* :warn-on-boxed) if you want the warnings |
| 11:06 | justin_smith | pepijndevos: 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:07 | puredanger | warn-on-reflection is separate, but you probably should use that too |
| 11:07 | justin_smith | cool, thanks for the info |
| 11:07 | justin_smith | (inc puredanger) |
| 11:07 | lazybot | ⇒ 23 |
| 11:07 | puredanger | I did the boxed warning work after reading way too much bytecode for the Alioth perf stuff :) |
| 11:08 | puredanger | justin_smith: you could certainly abuse it :) great power / great responsibility /etc :) |
| 11:08 | justin_smith | haha, nothing motivates better than having your own itch to scratch |
| 11:08 | justin_smith | puredanger: I did mention spidey-sense for a reason |
| 11:08 | puredanger | Clojure 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:09 | EvanR | theres the ability to mess with internal junk for idiosyncratic purposes then theres whether you will encourage people to try it |
| 11:09 | EvanR | in ruby, both are true |
| 11:09 | EvanR | across the board |
| 11:09 | EvanR | and its terrible |
| 11:11 | mikerod | (inc puredanger) |
| 11:11 | lazybot | ⇒ 24 |
| 11:11 | mikerod | puredanger: thanks that link is good. I haven't seen it before. |
| 11:11 | mikerod | EvanR: yes that is the idea |
| 11:11 | mikerod | EvanR: the link pretty much captures the issue though I think for the most part |
| 11:12 | EvanR | mikerod: for a sense of required anything, maybe a first step is to require a whole protocol to be implemented by a single class? |
| 11:13 | EvanR | otherwise we can add new requirements through project documentation at will, if the system doesnt help |
| 11:13 | mikerod | EvanR: are you talking about the idea of a given type possibly not implementing a "required" protocol function that you need? |
| 11:13 | EvanR | yesterday i heard you dont have to implement all the methods of a protocol, and that confuses me |
| 11:14 | justin_smith | yeah, clojure does not force full protocol or interface implementation |
| 11:14 | EvanR | thats like, a prerequisite before that other prerequisite |
| 11:15 | EvanR | on the other hand its not like its ensuring you follow an interfaces spec either, even if you do have an impl |
| 11:15 | EvanR | so back to policy docs |
| 11:15 | justin_smith | right, that's a turing complete problem I think |
| 11:15 | EvanR | depending on the spec language |
| 11:16 | EvanR | specs involving meta physics propositions i dont expect to be computer assisted any time soon |
| 11:16 | pepijndevos | I wonder how big a difference unboxed math makes... we'll know in a minute. |
| 11:17 | puredanger | if you're doing math, 2-3 orders of magnitude :) |
| 11:18 | puredanger | but if that's not your bottleneck, then won't matter of course |
| 11:22 | EvanR | is there something like update-in but just sets the value instead of applying a function |
| 11:22 | EvanR | i know constantly can do it but thats such a long word |
| 11:22 | puredanger | assoc-in ? |
| 11:22 | EvanR | sweet |
| 11:23 | EvanR | blast |
| 11:23 | puredanger | it does what you want, just doesn't follow the update form |
| 11:23 | puredanger | since it's not an update |
| 11:25 | puredanger | (inc crossclj) |
| 11:25 | lazybot | ⇒ 8 |
| 11:25 | puredanger | once again, super helpful as I research things http://crossclj.info |
| 11:32 | ajmccluskey | Is there a neat way to flatten a nested map entry? Have {:A {:B :C}}, want [:A :B :C]. |
| 11:32 | EvanR | ,(flatten {:A {:B :C}} |
| 11:32 | EvanR | ,(flatten {:A {:B :C}}) |
| 11:32 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 11:32 | clojurebot | () |
| 11:32 | ajmccluskey | {:A {:B :C}} is meant to be a map entry there, not a whole map. |
| 11:32 | ajmccluskey | EvanR: yeah, that surprised me too :p |
| 11:33 | mikerod | EvanR: justin_smith what I wish there was available for protocols was a way to at "check" if a given object implements a function |
| 11:33 | EvanR | after re-reading the doc i would expect it to crash on maps |
| 11:33 | mikerod | instead of just throwing something liek an AbstractMethodError |
| 11:33 | mikerod | could always try-catch for control flow though! :P |
| 11:33 | mikerod | I tend to implement my protocols on Object with some special value like ::undefined |
| 11:33 | EvanR | better, assume they implemented it, what is the reason to support partial protocol impls? |
| 11:34 | mikerod | then control flow around that in functions that expect some functions to be implemented, but can try to recover if they are not |
| 11:34 | EvanR | sounds backwards from the perspective of a library writer |
| 11:36 | mikerod | by "recover" I mean do something that makes sense if possible |
| 11:36 | EvanR | sends an email to the person responsible for the partially defined thing to get them to complete it? |
| 11:37 | ajmccluskey | mikerod: 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:37 | mikerod | ajmccluskey: I suppose |
| 11:37 | EvanR | i mean if they wanted to put a dummy that just crashes, they can |
| 11:37 | mikerod | AbstractMethodErrors it is then ;) |
| 11:37 | ajmccluskey | mikerod: wait, are you doing anything safety critical? I'm not going to die on the table because of this am I? |
| 11:38 | EvanR | or 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:38 | mikerod | I 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:38 | mikerod | If 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:39 | mikerod | http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html |
| 11:39 | mikerod | and the UnsupportedOperationException |
| 11:39 | mikerod | for reference http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#add(E) |
| 11:39 | mikerod | I get it here, I think the interface should have been 2 interfaces |
| 11:40 | mikerod | The whole Immutable vs Editable or w/e |
| 11:40 | EvanR | badly design protocol support |
| 11:43 | yocapybara | anyone have any opinions on what the most performant way to get a digest (like md5 or sha1) from a clojure map? |
| 11:43 | mikerod | From 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:43 | mikerod | And protocols should be small to avoid the issue of having too much to implement |
| 11:43 | yocapybara | I pulled up pandect but running (sha1 {:a "b"}) gives me an error that there's no implementation of :compute-sha1686 for PersistentArrayMap |
| 11:49 | EvanR | ,(values {:a 1 :b 2}) |
| 11:49 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: values in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 11:49 | EvanR | ,(keys {:a 1 :b 2}) |
| 11:49 | clojurebot | (:b :a) |
| 11:51 | ajmccluskey | ,(vals {:a 1 :b 2}) |
| 11:51 | clojurebot | (2 1) |
| 12:03 | justin_smith | mikerod: 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:13 | EvanR | if i were going to make a mutable data structure, what do i use. vars? |
| 12:15 | nkoza | evanr: you can use deftype, it supports mutable fields |
| 12:15 | justin_smith | EvanR: a var is just a mutable container, the thing in it doesn't mutate, it just points at a new thing when reassigned |
| 12:15 | justin_smith | EvanR: you can also use java.util.HashMap, or arrays, or whatever |
| 12:16 | puredanger | deftype supports marking fields with ^:unsynchronized-mutable or ^:volatile-mutable hints |
| 12:16 | clojurebot | Gabh mo leithscéal? |
| 12:16 | EvanR | my idea was to put the var in something as a mutable field |
| 12:17 | dnolen_ | Bronsa: you haven't tried dead code elimination with tools.analyzer have you? |
| 12:17 | puredanger | why? |
| 12:17 | justin_smith | if you ever use a thread, an atom or ref may be a better pick than a var for that |
| 12:17 | clojurebot | because that's not how macros work |
| 12:17 | EvanR | but it sounds like i need a deftype |
| 12:17 | dnolen_ | EvanR: is there some reason an atom does not suffice? |
| 12:17 | puredanger | putting a var in a mutable field of a deftype sounds like the wrong answer to most questions :) |
| 12:17 | EvanR | yes |
| 12:18 | EvanR | puredanger: two different ideas, not combined |
| 12:18 | puredanger | good :) |
| 12:19 | Bronsa | dnolen_: 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:21 | EvanR | i 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:21 | Bronsa | dnolen_: sorry, I blindly assumed you meant tree shaking with "dead code elimination", was I wrong? |
| 12:22 | EvanR | in my mind the values are refs to objects, rather than regular values |
| 12:22 | OscarZ | was 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:22 | dnolen_ | Bronsa: not wrong, but what is the problem exactly if it can be summarized? |
| 12:23 | puredanger | EvanR: 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:23 | EvanR | for the deftype, its required to put ^:volatile-mutable ? the method name to set a field must be set-foo! ? |
| 12:24 | EvanR | puredanger: 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:24 | Bronsa | dnolen_: in clojure? w/ a resident compiler there's no way to know for sure if you're never going to need a Var. |
| 12:24 | EvanR | i dont know if im using the right terminology for refs |
| 12:24 | puredanger | the syntax to set mutable fields inside a deftype is: (set! <field> <expr>) |
| 12:24 | hiredman | tree shaking/dead code elimination is a whole program optimization, but in clojure the compilation unit is a single form |
| 12:24 | Bronsa | dnolen_: i.e. you could get it dynamically via resolve, eval |
| 12:25 | dnolen_ | Bronsa: does not compute. For a production artifact with whole program optimization? I don't see how it's any different for JavaScript |
| 12:25 | dnolen_ | production artifact doesn't need eval |
| 12:25 | dnolen_ | well |
| 12:25 | dnolen_ | "might not need" |
| 12:25 | EvanR | inside a deftype? eh.. maybe i need a record |
| 12:25 | puredanger | EvanR: records only have final fields |
| 12:25 | EvanR | whats a final field? |
| 12:25 | puredanger | EvanR: you can cheat with arrays though (which are mutable) |
| 12:25 | puredanger | EvanR: cannot be changed |
| 12:26 | dnolen_ | Bronsa: in anycase this answers my question, no one has tried to do a Closure style tree shaking pass on the AST |
| 12:26 | Bronsa | dnolen_: right in cljs since there's no resident compiler, reified namespaces & the compilation unit is the ns/program tree shaking should be trivial |
| 12:26 | puredanger | EvanR: 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&lang=clojure&id=5 |
| 12:27 | dnolen_ | 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:27 | dnolen_ | Bronsa: Scala.js is doing this and it can have a dramatic effect of advanced compile times |
| 12:27 | Bronsa | dnolen_: I mean, arrdem has -- but he needed to make some assumptions on the clj code |
| 12:27 | dnolen_ | Bronsa: using tools.analyzer? |
| 12:27 | Bronsa | dnolen_: well then you might reuse his impl, one sec |
| 12:27 | Bronsa | dnolen_: yes |
| 12:27 | Bronsa | dnolen_: https://github.com/oxlang/oxcart/blob/master/src/main/clojure/oxcart/passes/tree_shake.clj |
| 12:27 | EvanR | ok so i would make a method set-foo! and implement it as (set! foo ... |
| 12:28 | dnolen_ | Bronsa: great thanks |
| 12:28 | triss | hey all... I'm messing with lein-cljsbuild |
| 12:28 | triss | where can i find out/goog/base.js? |
| 12:28 | puredanger | EvanR: 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:28 | EvanR | puredanger: and when passing the "deftype" value around, this is a ref to an object right |
| 12:28 | triss | if it's not there is my build likely to be misconfigured. |
| 12:28 | triss | ? |
| 12:28 | dnolen_ | triss: that's specified by :output-dir |
| 12:29 | puredanger | EvanR: yes, will be an object with real (public) fields that you could access via (.- obj field) too |
| 12:29 | Bronsa | dnolen_: 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:29 | dnolen_ | Bronsa: cool, I will take a look |
| 12:29 | triss | splendid thanks dnolen_ |
| 12:29 | puredanger | EvanR: 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:30 | EvanR | my algorithm is more straight forward in terms of mutable objects |
| 12:30 | EvanR | but maybe not rendered as clojure |
| 12:31 | puredanger | mutable objects are pretty intentionally hard to create or use in Clojure |
| 12:31 | puredanger | it should feel like you are actively fighting the grain |
| 12:31 | puredanger | as you are |
| 12:31 | EvanR | so far so good then |
| 12:33 | Bronsa | ,(deftype x [^:volatile-mutable x] Object (toString [_] (set! (.x _) 1) "foo")) |
| 12:33 | clojurebot | sandbox.x |
| 12:33 | Bronsa | ,(x. 1) |
| 12:33 | clojurebot | #<ClassCastException java.lang.ClassCastException: sandbox.x cannot be cast to compile__stub.sandbox.x> |
| 12:35 | EvanR | hmmm, 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:36 | bbloom | {blake}: mkdir |
| 12:36 | puredanger | (inc bbloom) |
| 12:36 | lazybot | ⇒ 50 |
| 12:37 | EvanR | cp ~/jsutils/* ~/project/js/ |
| 12:37 | {blake} | Heh. 'k. |
| 12:40 | justin_smith | Bronsa: 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:41 | justin_smith | https://github.com/noisesmith/hint-hint oops, almost forgot to link the repo |
| 12:42 | EvanR | i got it |
| 12:43 | EvanR | its a map of refs to regular clojure structures |
| 12:48 | EvanR | ,(ref (ref 0)) |
| 12:48 | clojurebot | #<Ref@4270f8: #<Ref@6c7a9: 0>> |
| 12:48 | EvanR | sweet |
| 12:49 | justin_smith | ~ref |
| 12:49 | clojurebot | It's greek to me. |
| 12:49 | justin_smith | ~refs |
| 12:49 | clojurebot | I don't understand. |
| 12:49 | justin_smith | ~stm |
| 12:49 | puredanger | this 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:49 | clojurebot | I don't understand. |
| 12:49 | justin_smith | I forget where the factoid about using refs went... |
| 12:50 | justin_smith | EvanR: 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:52 | hiredman | fewer |
| 12:57 | gfredericks | is there a general way to flip a bit on a Byte? |
| 12:57 | gfredericks | I had to special case the sign bit |
| 12:58 | gfredericks | which can't possibly be necessary |
| 12:58 | gfredericks | ,(bit-shift-left 1 7) |
| 12:58 | clojurebot | 128 |
| 12:58 | gfredericks | ^ can't really use that on a byte since it's out of range |
| 12:58 | puredanger | this sounds like the kind of thing where ztellman must have made a library :) |
| 12:59 | gfredericks | I could have 8 constants lying around but that seems sooper weird |
| 12:59 | bja_ | I feel like there was a binary protocol library that ztellman built which would apply here |
| 12:59 | puredanger | gloss |
| 12:59 | puredanger | but I don't think it does |
| 13:00 | puredanger | java bytes are (stupidly) signed but surely there's a lib that does this right |
| 13:01 | gfredericks | what happens in java if you do (1 << 7) on a byte? |
| 13:01 | justin_smith | ,(byte (bit-shift-left 1 7)) |
| 13:01 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 128> |
| 13:02 | justin_smith | ,(set! *unchecked-math* true) |
| 13:02 | clojurebot | #<IllegalStateException java.lang.IllegalStateException: Can't change/establish root binding of: *unchecked-math* with set> |
| 13:02 | gfredericks | oh I hadn't thought of that |
| 13:02 | Bronsa | ,(alter-var-root *unchecked-math* (constantly true)) |
| 13:02 | justin_smith | ,(binding [*unchecked-math* true] (byte (bit-shift-left 1 7))) |
| 13:02 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Var> |
| 13:02 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for byte: 128> |
| 13:03 | Bronsa | ,(alter-var-root #'*unchecked-math* (constantly true)) |
| 13:03 | clojurebot | true |
| 13:03 | justin_smith | ,(byte (bit-shift-left 1 7)) |
| 13:03 | clojurebot | -128 |
| 13:03 | justin_smith | thanks Bronsa |
| 13:03 | Bronsa | justin_smith: binding won't work there, you need *unchecked-math* to be true at compile time |
| 13:03 | justin_smith | got it |
| 13:03 | Bronsa | and it's quite annoying |
| 13:04 | justin_smith | Bronsa: 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:04 | gfredericks | thanks justin_smith Bronsa |
| 13:06 | Bronsa | justin_smith: uhm, does hint-hint cover only "when to use type hints" or can it also be "type hinting wtfs galore"? |
| 13:06 | justin_smith | Bronsa: the latter would be great - maybe in a separate namespace to differentiate useful tricks from gotchas |
| 13:07 | justin_smith | Bronsa: 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:07 | Bronsa | nice, I'll find some time to contribute |
| 13:07 | justin_smith | Bronsa: awesome! thanks. |
| 13:18 | EvanR | well 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:19 | EvanR | and always use indirection |
| 13:20 | EvanR | forgotten objects with no references to them wont be collected by a gc, but since its just for a local algorithm it doesnt matter |
| 13:21 | justin_smith | EvanR: by local, do you mean it all happens in one thread, and in one let block? |
| 13:22 | EvanR | its a pure function, referentially transparent, and its not multithreaded |
| 13:22 | justin_smith | if so, you could get away with a java.util.HashMap / java.util.Arraylist |
| 13:22 | EvanR | well that would make sense |
| 13:23 | EvanR | is the java syntax attrocious though? |
| 13:23 | puredanger | much less attrocious than mutable deftypes and refs of refs :) |
| 13:24 | justin_smith | EvanR: ##(doto (java.util.HashMap.) (.put "a" 1)) |
| 13:24 | lazybot | ⇒ {"a" 1} |
| 13:24 | justin_smith | the doto is useful for chaining, because .put does not return the map |
| 13:24 | EvanR | well ill try the immutable way, since all my assoc-ins gets and update-ins started shattering when i tried to use mutable objects |
| 13:25 | Empperi | I'm curios, haven't ever tried this |
| 13:25 | EvanR | ill try the immutable secondary space first |
| 13:25 | Empperi | ,(doto (java.util.HashMap.) (.put :a 1)) |
| 13:25 | clojurebot | {:a 1} |
| 13:25 | Empperi | ,(:a (doto (java.util.HashMap.) (.put :a 1))) |
| 13:25 | bja_ | does java have something like python's __getitem__ that you could use? |
| 13:25 | clojurebot | 1 |
| 13:25 | Empperi | nice |
| 13:25 | Empperi | it should have worked but wanted to check |
| 13:25 | Empperi | bja_: what das __getitem__ do? |
| 13:26 | Empperi | does |
| 13:26 | Empperi | maybe I'll just google |
| 13:26 | bja_ | I've implemented assoc-in/update-in with python's mutable collections with __getitem__/__setitem__ |
| 13:26 | bja_ | it's the dict/array item access syntax |
| 13:26 | bja_ | foo[0], bar['baz'] |
| 13:26 | bja_ | it'd probably be some sort of interface in java |
| 13:26 | Empperi | ,(doc get) |
| 13:26 | clojurebot | "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present." |
| 13:26 | bja_ | map's .get maybe |
| 13:27 | justin_smith | bja_: get-in / assoc-in I would guess |
| 13:27 | Empperi | ,({"a" 1} "a") |
| 13:27 | clojurebot | 1 |
| 13:27 | Empperi | ,(get {"a" 1} "a") |
| 13:27 | bja_ | err, do get-in/assoc-in work with HashMaps of HashMaps? |
| 13:27 | clojurebot | 1 |
| 13:27 | justin_smith | ,(get-in {:a {:b 0}} [:a :b]) ;; bja_ |
| 13:27 | clojurebot | 0 |
| 13:27 | justin_smith | ,(assoc-in {:a {:b 0}} [:a :b :c] 3) ;; bja_ |
| 13:28 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Associative> |
| 13:28 | justin_smith | ,(assoc-in {:a {:b 0}} [:a :b] :c 3) ;; bja_ |
| 13:28 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: core/assoc-in> |
| 13:28 | justin_smith | err... |
| 13:28 | Empperi | :) |
| 13:28 | bja_ | 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:29 | bja_ | nvm, I'm just causing chaos at this point. ignore my line of questions/comments please :) |
| 13:29 | Empperi | ,(get-in (doto (java.util.HashMap.) (.put :a (doto (java.util.HashMap.) (.put :b 1)))) [:a :b]) |
| 13:29 | clojurebot | 1 |
| 13:30 | justin_smith | bja_: looks like that's your answer though |
| 13:30 | bja_ | ah, nice |
| 13:32 | EvanR | (get-in the choppa) |
| 13:32 | bja_ | so get-in works, but assoc-in/update-in won't work because HashMap is not clojure.lang.Associative |
| 13:32 | justin_smith | makes sense |
| 13:37 | ppppaul | hello clojures |
| 13:43 | justin_smith | hello |
| 13:50 | ppppaul | hello again |
| 13:51 | EvanR | is there dissoc-in |
| 13:51 | EvanR | or something |
| 13:54 | justin_smith | EvanR: I think flatland/useful may have dissoc-in |
| 13:55 | justin_smith | EvanR: https://github.com/flatland/useful/blob/develop/src/flatland/useful/map.clj#L81 it's here |
| 13:56 | ppppaul | flatland/useful no documentation :/ |
| 13:56 | whodidthis | if 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:56 | justin_smith | ppppaul: did you look at the link? the doc strings are pretty comprehensive |
| 13:57 | ppppaul | i'm looking through the code now |
| 13:57 | ppppaul | i like it. but even something like auto generated readme could be helpful |
| 13:57 | justin_smith | ppppaul: I think that's what this does https://github.com/flatland/useful/blob/develop/build-docs.sh |
| 13:57 | justin_smith | you could clone the repo and run it |
| 13:58 | ppppaul | :D |
| 13:59 | justin_smith | http://flatland.org/useful/ <- I think this is generated from that script |
| 13:59 | ppppaul | nice! |
| 14:01 | ppppaul | anyone who has some experiecne with lighttable and cljs i could use some help in #lighttable |
| 14:03 | ppppaul | trying to get my console logging to print to the lighttable console instead of the browser console |
| 14:05 | ppppaul | is this even possible? |
| 14:07 | BobSchack | ppppaul: Are you connected to the lighttable browser or an external one? |
| 14:08 | ppppaul | external |
| 14:08 | ppppaul | can't do HTTP stuff in the browser LT opens |
| 14:08 | ppppaul | CORS problems |
| 14:09 | BobSchack | What kind of HTTP stuff are you talking about? DOM manipulation? |
| 14:10 | ppppaul | HTTP requests to servers other than localhost |
| 14:11 | ppppaul | even GET requests fail |
| 14:14 | arrdem | justin_smith: so what's going on with hint_hint? |
| 14:17 | justin_smith | arrdem: the idea is that its a set of unit tests that prove where type hints are needed |
| 14:18 | justin_smith | arrdem: and any gotchas (eg. things that aren't actually useful) |
| 14:20 | justin_smith | arrdem: 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:25 | oggie | new to clojure and trying to understand how to do if /else logic... Anyone up for helping me out? |
| 14:25 | justin_smith | ,(if true :ok :no) |
| 14:26 | clojurebot | :ok |
| 14:26 | justin_smith | ,(if fase :ok :no) |
| 14:26 | BobSchack | ppppaul: Have you tried shoreleave remote (http://shoreleave.github.io/shoreleave-remote/#shoreleave.remotes.jsonp)? |
| 14:26 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: fase in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:26 | justin_smith | ,(if false :ok :no) |
| 14:26 | clojurebot | :no |
| 14:26 | oggie | justin_smith I tried that, but It doesn't work how I'm doing it |
| 14:26 | justin_smith | oggie: what are you actaully trying to do? |
| 14:27 | oggie | check to see if a username/password is not passed in (nil) and act differently |
| 14:28 | oggie | here's what I have |
| 14:28 | oggie | session (-> (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:28 | oggie | so don't add username/pass to the session if it's nil |
| 14:32 | justin_smith | oggie: that looks right, as long as the {:contact-points ...} map should be the first arg to alia/connect |
| 14:33 | justin_smith | the (alia/cluster {:contact-points ...}) that is |
| 14:33 | oggie | justin_smith it is supposed to be 1st |
| 14:34 | oggie | it works if I hard code the username/password in there and not use the if |
| 14:34 | oggie | hmm. maybe I do have it right |
| 14:34 | oggie | :-) |
| 14:35 | oggie | this is tough coming from Java for years |
| 14:35 | justin_smith | oggie: it may be clearer with let bindings instead of -> |
| 14:36 | oggie | ok |
| 14:51 | arrdem | is there a trick for looking a value up out of a map throwing if it doesn't exist? |
| 14:51 | amalloy | arrdem: use python |
| 14:52 | EvanR | uhm.. |
| 14:52 | justin_smith | ,(get {:b 0} :b (lazy-seq (throw (Exception. "boom")))) |
| 14:52 | EvanR | ,(:abc {}) |
| 14:53 | clojurebot | 0 |
| 14:53 | EvanR | ,({} :abc) |
| 14:53 | clojurebot | nil |
| 14:53 | justin_smith | ,(get {:b 0} :a (lazy-seq (throw (Exception. "boom")))) |
| 14:53 | llasram | Oh, slowness |
| 14:53 | clojurebot | nil |
| 14:53 | justin_smith | kinda hackish |
| 14:53 | clojurebot | #<Exception java.lang.Exception: boom> |
| 14:53 | justin_smith | actually works in a real repl though |
| 14:53 | Bronsa | justin_smith: you can never know when that'll throw though |
| 14:53 | llasram | I think clojurebot is just lagging |
| 14:54 | Bronsa | or even if that will throw at all |
| 14:54 | justin_smith | Bronsa: where would the gotcha be? if the value was not used? |
| 14:54 | Bronsa | justin_smith: yep |
| 14:54 | Bronsa | justin_smith: suppose (if (symbol? x) x 'foo) |
| 14:55 | llasram | &((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:55 | lazybot | clojure.lang.ExceptionInfo: not-found {:m {}, :k :foo} |
| 14:56 | llasram | lazybot: not so lazy today, now are you! |
| 14:56 | justin_smith | &((fn safe-get [m k] (if-not (contains? m k) (throw (Exception. "boom")) (get m k))) {} :foo) |
| 14:56 | lazybot | java.lang.Exception: boom |
| 14:56 | arrdem | llasram: that's nicer than the one I came up with. yoink! |
| 14:57 | arrdem | justin_smith and I had the same solution |
| 14:57 | Bronsa | ,((fn safe-get [m k] (if-let [[_ v] (find m k)] v (throw (Exception. "boom"))) {} :foo) |
| 14:58 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 14:58 | Bronsa | well. |
| 14:58 | Bronsa | you get the idea. |
| 14:58 | justin_smith | Bronsa: oh yeah, find is a nice way to do that one |
| 14:58 | llasram | Oh nice, yeah |
| 14:59 | arrdem | won't that be identical to llasram's solution? both only do one lookup, whereas the contains? version will do two. |
| 15:00 | llasram | But Bronsa's doesn't depend on a magical sentinel which you can't ever have as a value in the map |
| 15:00 | justin_smith | it's more elegant, but only one lookup as with llasram's |
| 15:00 | arrdem | ah good point. In this context I don't care, the set of possible keys is strings only, but yeah in theory Bronsa wins. |
| 15:00 | arrdem | (inc Bronsa) |
| 15:00 | lazybot | ⇒ 77 |
| 15:02 | justin_smith | (inc Bronsa) |
| 15:02 | lazybot | ⇒ 78 |
| 15:03 | dnolen_ | ClojureScript 0.0-2411 out |
| 15:03 | EvanR | why doesnt (fn [x] (prn x) x) work in the middle of a -> macro sequence |
| 15:04 | arrdem | EvanR: ((fn ..)) will. |
| 15:04 | EvanR | ohk |
| 15:04 | justin_smith | ,(macroexpand '(-> 1 (fn [x] (prn x) x))) |
| 15:04 | clojurebot | #<CompilerException java.lang.IllegalArgumentException: Parameter declaration 1 should be a vector, compiling:(NO_SOURCE_FILE:0:0)> |
| 15:04 | arrdem | EvanR: (-> x (fn [x] x)) -> (fn x [x] x) |
| 15:05 | llasram | EvanR: bonus protip: (-> ... (doto prn) ...) |
| 15:05 | justin_smith | ,(macroexpand '(-> foo (fn [x] (prn x) x))) |
| 15:05 | clojurebot | (fn* foo ([x] (prn x) x)) |
| 15:06 | justin_smith | (inc llasram) |
| 15:06 | lazybot | ⇒ 42 |
| 15:06 | justin_smith | yeah that's actually the right way to do it |
| 15:07 | wirrrbel | I wanted to checkout yesql and ring / rook |
| 15:07 | wirrrbel | up until now my project was clojurescript only |
| 15:08 | wirrrbel | now I wonder where to put my sql file |
| 15:09 | justin_smith | wirrrbel: relative to the classpath means if you ask for "some/where/foo.sql" it can be in "src/some/where/foo.sql" |
| 15:11 | wirrrbel | justin_smith: thank you |
| 15:36 | EvanR | note to self core.match patterns do not introduce variables that shadow |
| 15:36 | EvanR | thought i was going insane |
| 15:42 | ppppaul | can i pretty print in cljs? |
| 15:43 | ppppaul | i'm having issues printing to the console :/ |
| 15:52 | dnolen_ | ppppaul: sadly no pretty printer built in - jonasen had a port of bblooms' fipp - might be useable unsure |
| 15:53 | dnolen_ | and by "not built in" I mean I haven't received a clojure.pprint patch |
| 16:03 | ppppaul | hmm. i'll deal without one for now... |
| 16:09 | kenrestivo | is it kosher to use send for serializing synchronous access to i/o, where i *want* it to block? |
| 16:11 | kenrestivo | i suppose i could use send-off and then deref to block. but i'm wondering why not use send instead? |
| 16:11 | llasram | kenrestivo: Why are you using an agent if you want synchronous access? |
| 16:12 | kenrestivo | because some operations i want the agent send-off behavior.. others i don't |
| 16:13 | llasram | Can you share the broader context some? |
| 16:13 | kenrestivo | it's just a device |
| 16:14 | kenrestivo | so i've got an agent serializing access to it |
| 16:15 | amalloy | kenrestivo: deref doesn't block at all |
| 16:16 | llasram | Ok. Well, my 2 cents is that it doesn't sound like an agent is the best fit :-) |
| 16:16 | amalloy | it's not clear what difference between send and send-off is relevant here |
| 16:16 | kenrestivo | ah right, only on futures/promises, not on agents |
| 16:16 | justin_smith | kenrestivo: 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:16 | kenrestivo | yeah, i think the agent approach isn't going to work. thanks. |
| 16:16 | amalloy | kenrestivo: if you want exclusive, synchronous read/write access to a device, i'd just use a mutex |
| 16:17 | llasram | (inc amalloy) |
| 16:17 | lazybot | ⇒ 201 |
| 16:17 | amalloy | you can cobble together stuff with agents and await and blah blah blah, but like...locks aren't strictly bad |
| 16:17 | kenrestivo | was hoping to avoid j.u.c. interop, but i guess why not. |
| 16:17 | amalloy | kenrestivo: ?????? ##(doc locking) |
| 16:17 | lazybot | ⇒ "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:18 | dbasch | amalloy: there was a mixup, we sent rich hickey a cardboard cutout of you |
| 16:18 | kenrestivo | nice |
| 16:18 | amalloy | dbasch: that was you crouching in the bushes with a camera? i thought i'd become interesting to the paparazzi somehow |
| 16:18 | dbasch | it was hand-drawn |
| 16:18 | kenrestivo | amalloy: once again, thanks for showing me a new corner of clojure i had no idea existed |
| 16:18 | dbasch | no word from rich hickey yet |
| 16:19 | dbasch | the clojureazzi |
| 16:20 | EvanR | a queue with max size 1 would also work |
| 16:21 | EvanR | and you would have to muck with mutices |
| 16:21 | EvanR | wouldnt* |
| 16:21 | justin_smith | EvanR: I thought there was an implication that he only sometimes wanted to block |
| 16:21 | justin_smith | also, locking isn't much of a muck at all |
| 16:22 | EvanR | well P and V are crap |
| 16:23 | justin_smith | P and V? |
| 16:23 | llasram | Pevear and Volokhonsky? |
| 16:23 | EvanR | issue the lock command on a mutex object, then later... you had better issue the unlock on the same mutex |
| 16:23 | amalloy | he's a letter connoisseur |
| 16:23 | amalloy | EvanR: that's what locking guarantees to do |
| 16:23 | justin_smith | EvanR: that's now how locking works ##(doc locking) |
| 16:23 | lazybot | ⇒ "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:24 | EvanR | yes ok |
| 16:24 | justin_smith | all you do is wrap your code in the locking macro, it's not messy |
| 16:24 | EvanR | but im not sure exactly how even this corresponds to sometimes blocking |
| 16:25 | justin_smith | EvanR: 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:25 | EvanR | was the same implication also implying that you also sometimes forgo even doing your write? |
| 16:25 | EvanR | oh |
| 16:26 | EvanR | this policy is way past my concurrent semantics comfort level, crash when queue is maxed? |
| 16:27 | EvanR | block anyway |
| 16:27 | EvanR | dont write? |
| 16:27 | justin_smith | it 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:23 | FliPPeh | http://sprunge.us/LYDZ?clj - how's that for my first not-entirely-useless clojure program? Any obviously bad things? |
| 17:26 | kenrestivo | FliPPeh: 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:27 | kenrestivo | ,(doc keyword) ;; for example |
| 17:27 | clojurebot | "([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:27 | amalloy | kenrestivo: huh? he calls keyword himself |
| 17:27 | FliPPeh | ,(keyword "something with spaces") |
| 17:27 | clojurebot | :something with spaces |
| 17:27 | FliPPeh | That looks evil |
| 17:28 | amalloy | FliPPeh: i don't see why you're converting to keywords at all |
| 17:28 | amalloy | just use strings as your map keys |
| 17:28 | FliPPeh | Well what I'm doing there is taking a string that may contain spaces and other weird things and turns those into simple dashes |
| 17:28 | FliPPeh | I could, but keywords feels more clojury |
| 17:28 | justin_smith | FliPPeh: another vote for just using strings as keys |
| 17:29 | amalloy | no. don't build keywords out of user-controlled data |
| 17:29 | FliPPeh | Alrighty |
| 17:29 | justin_smith | keywords are good if you are designing the data structure as literals, but getting it from somewhere else, just leave it a string |
| 17:30 | amalloy | otherwise i'd say this is all fairly reasonable, except that i'd use line-seq instead of slurp+lineify |
| 17:31 | amalloy | get a reader, call line-seq, then chunk those based on blank lines, then put the chunks into maps |
| 17:32 | dbasch | FliPPeh: also, you don’t need two separate requires |
| 17:32 | FliPPeh | Like partition-by on an empty line= |
| 17:32 | FliPPeh | ?* |
| 17:32 | amalloy | sure, seems fine |
| 17:33 | EvanR | ,(atom? (atom 0)) |
| 17:33 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 17:34 | dbasch | ,(type (atom 0)) ;; EvanR |
| 17:34 | clojurebot | clojure.lang.Atom |
| 17:34 | FliPPeh | Ah, doesn't seem like line-seq will work here. Apparently it wants a buffered reader, but those don't work on /proc files |
| 17:34 | hiredman | what makes you say that? |
| 17:35 | FliPPeh | Well, that's what the repl is telling me |
| 17:35 | hiredman | what makes you say the repl is telling you that? |
| 17:35 | dbasch | FliPPeh: what error do you get? |
| 17:36 | kidpollo | Hola @dbasch |
| 17:36 | FliPPeh | Whoops pardon, I indeed misread |
| 17:36 | clojer | I'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:36 | FliPPeh | "(line-seq (java.io.BufferedReader. (java.io.FileReader. "/proc/cpuinfo")))" does the trick just fine |
| 17:36 | dbasch | kidpollo: howdy |
| 17:37 | dbasch | clojer: is it something that wasn’t available in a public repository? Because if so, you don’t need to download it |
| 17:37 | kidpollo | I am trying to 1 up my clojure fu to the next level by hanging out with the cool kids :P |
| 17:38 | clojer | dbasch: Downloaded from an individual developer's website. |
| 17:39 | clojer | dbasch: I've already downloaded it. How to add it to the project? |
| 17:39 | sg2002 | clojer: https://github.com/kumarshantanu/lein-localrepo |
| 17:40 | dbasch | that’s one way, or you could stick it in a local maven repo |
| 17:41 | dbasch | clojer: http://nakkaya.com/2010/03/16/adding-custom-libraries-into-local-leiningen-repository/ like this |
| 17:41 | clojer | dbasch: Do you mean in my .m2 repo? |
| 17:41 | dbasch | clojer: no |
| 17:42 | dbasch | you could hack your .m2 repo, but I wouldn’t recommend it |
| 17:42 | clojer | dbasch: Nothing fancy .... please :) |
| 17:42 | kenrestivo | kidpollo: or you could do 4clojure.com exercises |
| 17:42 | dbasch | clojer: I think the article I linked is the easiest way |
| 17:42 | dbasch | at least it’s what I did the last time I had to do this, a couple of years ago |
| 17:43 | whodidthis | https://www.refheap.com/94472 how do i get the symbol bound to n replace the last n in this macro |
| 17:43 | arohner | fun friday: Puppet Docs + HP Lovecraft in a markov chain: http://thedoomthatcametopuppet.tumblr.com/ |
| 17:44 | kidpollo | kenrestivo: that also |
| 17:44 | clojer | dbasch: Kreist, what a lot of ceremony. |
| 17:45 | dbasch | clojer: 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:46 | dbasch | meaning, you’re using a dependency management tool (lein) |
| 17:46 | kenrestivo | there 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:46 | clojer | dbasch: Been spoiled by Ruby for too long, maybe. `require_relative <module>`. Done. |
| 17:46 | arohner | you can 'lein install' arbitrary jars |
| 17:47 | arohner | it generates a minimal pom for you |
| 17:47 | EvanR | heh require_relative |
| 17:47 | clojer | arohner: Now yer talkin' |
| 17:47 | EvanR | autoloading yall |
| 17:48 | kenrestivo | "gem install hairball" :-P |
| 17:48 | amalloy | clojer: 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:48 | arohner | clojer: I must be misremembering. you can certainly 'mvn install' :https://maven.apache.org/plugins/maven-install-plugin/usage.html |
| 17:48 | amalloy | are you sure this thing you're trying to use isn't in any repo anywhere? |
| 17:49 | amalloy | downloading jars by hand is a desperation move, a last resort |
| 17:49 | clojer | amalloy: I don't think so but I'll double-check. |
| 17:50 | arohner | clojer: and if you're doing a 'serious' project, it's often worthwhile to have your own private repo |
| 17:50 | arohner | using e.g. nexus or https://github.com/technomancy/s3-wagon-private |
| 17:52 | whodidthis | https://www.refheap.com/94473 or is this possible somehow, defin with the created symbol instead of n |
| 17:52 | kenrestivo | everything else, googling "libraryname maven" found some repo somewhere with it. |
| 17:57 | dbasch | whodidthis: I don’t understand what you’re trying to do |
| 17:58 | justin_smith | whodidthis: the way def works, it will always define n |
| 17:58 | whodidthis | ok, im a bit of a bad then |
| 17:59 | justin_smith | are you trying to pass a string to def-k and end up with that string being a def with the value "nice"? |
| 17:59 | whodidthis | yes :( |
| 17:59 | justin_smith | (defmacro def-k [k] `(def ~(symbol k) "nice")) |
| 17:59 | justin_smith | still very silly |
| 17:59 | justin_smith | but that should actually work |
| 18:00 | dbasch | whodidthis: look into intern |
| 18:00 | justin_smith | yeah, intern is actually a nicer way to do it, as long as the metadata that def adds isn't important to you |
| 18:02 | whodidthis | i 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:02 | EvanR | hah |
| 18:02 | EvanR | php extract |
| 18:02 | EvanR | only global |
| 18:02 | dbasch | whodidthis: that is a strange requirement |
| 18:03 | whodidthis | so i could access them with values/value-1 instead of (get values/values 1) |
| 18:03 | EvanR | if you use that a lot on a large map, you wont know heads from tails |
| 18:03 | dbasch | if you need to keep global state, you shouldn’t be defining variables willy-nilly |
| 18:03 | whodidthis | it was just a nice color scheme :( |
| 18:12 | amalloy | yeah, 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:12 | celwell | Hi, 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:12 | celwell | (reduce #(apply conj %1 (s/split (:pages %2) #",")) |
| 18:12 | celwell | #{} |
| 18:12 | celwell | [{:id 1 :pages "1,2,3,4"} |
| 18:12 | celwell | {:id 2 :pages "2,3,4,6,7"} |
| 18:12 | celwell | {:id 8 :pages "9,10,12"}]) |
| 18:15 | EvanR | (concat (map (comp split-on-comma :pages))) |
| 18:17 | weavejes_ | (mapcat (comp split-on-comma :pages) data) |
| 18:17 | weavejes_ | (set *1) |
| 18:19 | celwell | Thanks, I like weavejes_'s answer the best. |
| 18:20 | amalloy | (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:32 | zeapo | {blake}: that depend on the licence. Check if you can redistribute it. |
| 19:33 | xeqi | {blake}: it might be in http://search.maven.org/ |
| 19:35 | {blake} | xeqi: 'tis not. |
| 19:40 | justin_smith | {blake}: for doing a redirect and also putting something in the session, maybe try (assoc (redirect url) :session updated-session) |
| 19:40 | justin_smith | redirect should return a response map I think |
| 19:40 | justin_smith | or, 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:42 | lazybot | ⇒ 152 |
| 19:42 | dbasch | {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:44 | dbasch | {blake}: ask weavejester to put it on clojars |
| 19:45 | dbasch | or fork it and do it yourself |
| 19:45 | amalloy | oh my gosh it's five years old |
| 19:46 | amalloy | it 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:54 | justin_smith | {blake}: crossclj.info is good for seeing which libraries people are using |
| 19:55 | justin_smith | http://crossclj.info |
| 19:55 | justin_smith | and 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:00 | justin_smith | yeah, I was surprised it was so prevalent |
| 20:01 | justin_smith | aha, 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:29 | thearthur | this core.logic SO question needs some attention: http://stackoverflow.com/questions/27324013/core-logic-unification-matches-value-in-map-but-not-key |
| 20:35 | amalloy | thearthur: 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:36 | TEttinger | asked by shaft, amalloy |
| 20:36 | amalloy | TEttinger: yes, i see that. so? |
| 20:36 | thearthur | amalloy: thats me, yep. it's just bugging me and i'm impatient :-) |
| 20:37 | TEttinger | oh, i thought bounties were added by the asker |
| 20:37 | amalloy | anyone can put a bounty on anything |
| 20:38 | TEttinger | stack overflow/exchange is certainly different |
| 20:38 | justin_smith | thearthur: oh hi, I'm noisesmith on stackoverflow, we've crossed paths there a few times |
| 20:38 | amalloy | i mean, in practice most of the time people put bounties on their own questions because they really want an answer |
| 20:39 | amalloy | but 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:39 | TEttinger | rep is precious! I have like 9! |
| 20:40 | thearthur | perhaps I should switch nicks to match everywhere else |
| 20:41 | thearthur | I'm unable to find an add bounty button on this question |
| 20:42 | amalloy | thearthur: you can't, because it's only five hours old |
| 20:42 | amalloy | you're supposed to let it simmer for a bit :P |
| 20:42 | thearthur | (dec thearthur) |
| 20:42 | lazybot | You can't adjust your own karma. |
| 20:42 | amalloy | or 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:43 | TEttinger | dnolen_ with the underscore of inactiveness? |
| 20:43 | amalloy | he'll get it eventually, i imagine |
| 20:43 | TEttinger | there's also $mail |
| 20:44 | TEttinger | that's one of the more widely used features on my lazybot |
| 20:50 | amalloy | $mail TEttinger i heard you like mail |
| 20:50 | lazybot | Message saved. |
| 20:52 | TEttinger | $mail amalloy yes I do |
| 20:52 | lazybot | Message saved. |
| 20:52 | amalloy | $login |
| 20:52 | lazybot | You've been logged in. |
| 20:52 | amalloy | $unmail TEttinger amalloy |
| 20:52 | lazybot | Deleted unread messages from TEttinger to amalloy |
| 20:52 | amalloy | hacks |
| 20:52 | amalloy | $logout |
| 20:52 | lazybot | You've been logged out. |
| 20:52 | TEttinger | heh, I didn't know you had a login |
| 20:52 | TEttinger | nice |
| 20:55 | tuft | is there a repl client for clojuredocs.org? e.g. (clojuredocs cond) to see examples of cond |
| 20:56 | justin_smith | $grim clojure.core/cond is similar |
| 20:56 | lazybot | http://grimoire.arrdem.com/1.6.0/clojure.core/cond |
| 21:01 | andyf | tuft: github.com/jafingerhut/cd-client |
| 21:02 | andyf | tuft: 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:03 | andyf | There is an issue requesting updating the API data, too, at github.com/zk/ClojureDocs |
| 21:18 | timvisher-xubunt | anyone aware of a port of tools.trace to clojurescript? |
| 21:20 | justin_smith | timvisher-xubunt: I bet you could do some nice tracing and even step debugging with the browser's inspector |
| 21:22 | timvisher-xubunt | justin_smith: that's probably true. but i'm headless at the moment and would prefer to continue to be. |
| 21:22 | timvisher-xubunt | tools.trace is _so_ nice but it doesn't look like anyone's tried to port it yet |
| 21:22 | timvisher-xubunt | stuartsierra: i'm assuming you haven't heard anything? |
| 21:23 | timvisher-xubunt | actually, you stopped maintaining it iirc, sorry :| |
| 21:32 | Jesterman81 | hey ladies/gents, quick question. I have a clojure web app using hiccup with something like [:a {:href “/img/foo.jppg”}] |
| 21:32 | Jesterman81 | do I have to manually add the context if I am deploying to a tomcat instance? |
| 21:33 | justin_smith | Jesterman81: 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:34 | justin_smith | Jesterman81: our approach has been to make a function that generates a route for a resource or endpoint, and call that |
| 21:34 | justin_smith | and let that function adjust for the context path etc. |
| 21:34 | amalloy | justin_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:35 | justin_smith | that also ends up helping when the client want's different URLs but you don't want to do a major app rewrite |
| 21:35 | justin_smith | amalloy: figures, yeah that's what we do |
| 21:35 | Jesterman81 | thanks, I was hoping I just wasn’t missing something easy |
| 21:36 | justin_smith | you may get something about the context info from the container in the request map |
| 21:36 | justin_smith | couldn't hurt to dump the request map as you receive it in tomcat and look for something useful |
| 21:38 | Jesterman81 | ill take a look at the request and see whats in there |
| 21:40 | justin_smith | another option would be using a config to export the context as a system property that the clojure app can then pick up |
| 21:41 | Jesterman81 | thanks for the options. appreciate it |
| 22:17 | Frozenlock | In compojure, is it possible to apply different middlewares to different routes? (c/routes (-> r1 m1 m2 m3) (-> r2 m4 m5 m6)) ? |
| 22:29 | justin_smith | Frozenlock: 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:29 | justin_smith | it should just be a question of function composition |
| 22:30 | Frozenlock | justin_smith: thanks |
| 23:18 | Frozenlock | AH! Found how to do it. Must use compojure.core/wrap-routes to wrap the routes *only once they have been matched*. |
| 23:40 | josiah14 | I'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:41 | justin_smith | josiah14: ##(macroexpand '#(%2)) |
| 23:41 | lazybot | ⇒ (fn* [p1__13570# p2__13569#] (p2__13569#)) |
| 23:41 | josiah14 | the actual code is like, (reductions #(%2) nil (repeat n read-line)) where 'n' is some calculated number |
| 23:42 | justin_smith | does the above macroexpansion make sense? |
| 23:42 | justin_smith | equivalent: (fn [a b] b) |
| 23:42 | justin_smith | err |
| 23:42 | justin_smith | (fn [a b] (b)) |
| 23:43 | josiah14 | actually, I think so |
| 23:43 | justin_smith | it expects two functions, and calls the second one, ignoring the first |
| 23:43 | josiah14 | yah, that's what I got from that. I'm still getting used to reading macros. |
| 23:43 | justin_smith | well, two things, and calls the second as a no arg function actually, to be more precise |
| 23:43 | josiah14 | is there a better function I could use there so that i can eliminate the nil initial value |
| 23:44 | josiah14 | I would have thought #(%1) would be like that one but call every function |
| 23:44 | josiah14 | I can't remember what the error message was |
| 23:44 | justin_smith | well, the thing is the first version takes N args, and only calls the second one |
| 23:45 | justin_smith | so that's a really weird "reduce" in that it always throws away the accumulator |
| 23:45 | justin_smith | it would be much clearer as a doseq |
| 23:45 | justin_smith | (doseq [f (repeat n read-line)] (f)) |
| 23:45 | josiah14 | except I need the values returned from read-line |
| 23:45 | justin_smith | oh, reductions |
| 23:45 | justin_smith | sorry |
| 23:45 | justin_smith | it's not reduce, but reductions, so you do see each result |
| 23:45 | josiah14 | yes |
| 23:45 | josiah14 | basically |
| 23:46 | justin_smith | (doall (for [f (repeat n read-line)] (f))) |
| 23:46 | justin_smith | you still get all the results, but what it's doing is much more clear |
| 23:46 | josiah14 | i thought there had to be somethnig simpler |
| 23:47 | josiah14 | yah, 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:48 | josiah14 | but 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:48 | justin_smith | the way I see it that there is a strategy of making immutable and pure very easy to do, and impurity a bit trickier |
| 23:49 | justin_smith | josiah14: 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:49 | justin_smith | that is pretty effective for translating imperative algorithms to functional world |
| 23:49 | josiah14 | yah, same as in haskell |
| 23:49 | josiah14 | it's IO that gets tricky, and event handling |
| 23:50 | justin_smith | you can also "cheat" by making a map holding a "state of the world" under various keys as one of the parameters |
| 23:50 | justin_smith | in clojure integrating io/events is a bit easier I think |
| 23:50 | justin_smith | it's handled more pragmatically at least |
| 23:50 | josiah14 | yah, it's looking that way - just a matter of syntax |
| 23:50 | rritoch | josiah14: Cant you just map over #(%1) ? As far as I can tell that would produce the same results |
| 23:50 | rritoch | josiah14: (map #(%1) (repeat n read-line)) |
| 23:51 | justin_smith | rritoch: that's what the for does, but I think for is more readable in that case |
| 23:51 | josiah14 | rritoch, yes, that works out perfectly |
| 23:51 | josiah14 | just tested in the repl |
| 23:52 | justin_smith | josiah14: beware that that is lazy |
| 23:52 | justin_smith | that is why I added the doall in my for version, to match the eagerness of reduce |
| 23:52 | josiah14 | yah, 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:52 | josiah14 | justin_smith: I'm used to lazy, so no problems, there |
| 23:56 | rritoch | justin_smith: Is reductions being depricated? I could be wrong but it seems reductions is replaced with map transducers that have "reduction state" |
| 23:57 | justin_smith | it carries no deprecation warning in the latest 1.7 alpha |
| 23:58 | justin_smith | but yeah, it may make a lot of sense to use a transducer |