2015-09-23
| 00:00 | rritoch | TEttinger: My project is a fork of armed bear common lisp, with the key difference that mine is 100% maven compatible (The developers of ABCL specifically refuse to support using ABCL from maven), also my fork passes all of the ansi tests. |
| 00:00 | rritoch | TEttinger: ABCL isn't compatible with clojure at all really since it can't be included as a dependency in it's current state. |
| 00:01 | TEttinger | I don't think clojure has a huge amount of effort put into interop relative to other important language features. the key features were all present in 1.0 for java interop except for maybe a few for gen-class things? |
| 00:01 | TEttinger | I think the STM was probably much more challenging than playing nicely with java |
| 00:02 | rritoch | TEttinger: As for the multithreadding issue, there's a few reasons. It inherited ABCL's circular dependencies which outnumber class files 10x1 at least, and the massive use of static finals for things that should be "interned". |
| 00:03 | arrubin | TEttinger: For a lot of development, it can make a huge difference though. Having good database drivers through JDBC for instance. |
| 00:03 | TEttinger | what's the problem with static finals? I'm a bit unclear since I don't know a better way to imitate a constant in java |
| 00:04 | rritoch | TEttinger: It's is an architectural flaw with the ABCL codebase that it has placed most of it's symbols as static finals so they can't be utilized in a thread-local context. |
| 00:05 | rritoch | TEttinger: It isn't a problem with the java language, and it is something that can technically be corrected. The other developer on the jrelisp project I believe is working on that issue. Along with CLI support. |
| 00:06 | rritoch | Err, maybe CLI isn't the correct term, he's working on .NET support. I don't recall the name of the interpreter. |
| 00:07 | TEttinger | CLR is a common term but not a synonym for CLI. CLR is common language runtime |
| 00:07 | TEttinger | not sure what CLI stands for in .NET context |
| 00:08 | rritoch | aconz2: Either way, if your trying to make a big splash I can suggest a few open source projects that you could probably produce with the aid of jrelisp & clojure. |
| 00:08 | rritoch | TEttinger: Sorry, I think your right, I think it was CLR. I'm really not a big .NET fan. |
| 00:10 | rritoch | aconz2: Notably are opencyg, which I believe has it's own native lisp implementation, and common-lisp-stat. Neither of those projects will run on a JVM (yet) and could both make headlines if ported to clojure/JVM. |
| 00:11 | TEttinger | it really is remarkable to me what the MS team managed to do with C# relative to Java. generics without boxing and a really well-thought-out collection API that uses a similar concept to clojure's seq abstraction (almost all collection methods operate on the IEnumerable interface and return one as well), technically more powerful first-class functions than java's lambdas (since lambdas aren't closures)... |
| 00:12 | TEttinger | the open source version of most of .NET appears to include immutable data structures in the core lib |
| 00:12 | TEttinger | including an equivalent to transients |
| 00:16 | rritoch | aconz2: Small correction, it isnt' opencyg, it's opencyc (https://en.wikipedia.org/wiki/Cyc). Porting Cyc to clojure brings about 50% of AI technology to clojure, and porting common-lisp-state brings advanced statistical analysis to clojure. I've considered both projects but I'm not going to touch either project without funding since I neither work in the AI field or statistical analysis. |
| 00:19 | TEttinger | a direct port might not be ideal for the common-lisp-state one, I would say. the approaches to pure/lazy functional code are different between the original language and in clojure, and statistics stuff seems like a perfect match for immutable/persistent data since you never want to change the data you're analyzing in the process of analyzing it |
| 00:21 | TEttinger | if you can do what it does in broad capability terms, that would be huge. even a small library that does statistics work that is challenging now would be nice |
| 01:43 | rritoch | Does anyone know how to fix vinyasa? "Failed: Java files did not properly compile [{java source directory}] |
| 01:47 | rritoch | Looks like a known issue (https://github.com/zcaudate/vinyasa/issues/4) |
| 01:55 | rritoch | I re-reported the issue as it's a slightly different, but related problem. https://github.com/zcaudate/vinyasa/issues/20 |
| 03:14 | neurostorm | i have som keyvals in a hash-map and would like to use it in a let... like (def b {:x 1 :y 2}) (let [b] (+ x y)) , can it be done? |
| 03:15 | justin_smith | neurostorm: no |
| 03:16 | neurostorm | ah, come on... a macro perhaps? |
| 03:17 | justin_smith | neurostorm: if the map is known at compile time, you could make that macro |
| 03:17 | neurostorm | i just want to dynamicly set some bindings... they are not known at compile time. |
| 03:17 | justin_smith | macros only run at compile time |
| 03:18 | justin_smith | and I'm not alone in the opinion that magical bindings that are inaccessible while reading the code and only known at runtime lead to terrible unreadable code |
| 03:18 | justin_smith | (which is why nobody made this functionality yet) |
| 03:18 | neurostorm | yeah, i just wanted easy access to some data retuned from a request. |
| 03:19 | justin_smith | then pass the data in? |
| 03:19 | neurostorm | and would like a generic mehtod to do that. |
| 03:19 | justin_smith | you know about destructuring, right? |
| 03:20 | neurostorm | i do, and its nice, but for 10 vars 2 leves inside a map, it does not look nice. |
| 03:20 | justin_smith | with destructuring you can bind the keys you expect to find to local values. That totally works. But how would you even write code that does anything meaningful with bindings you don't even know the names for until runtime? |
| 03:21 | justin_smith | you are allowed to spread the left hand side of a let binding over multiple lines, I do it all the time |
| 03:22 | neurostorm | i know the names, but would like to avoid have to do the deconstruction. And i would like to use this different placeres with different names. |
| 03:22 | justin_smith | neurostorm: best of luck |
| 03:22 | neurostorm | jusk asking... |
| 03:23 | justin_smith | I'm doing my best to explain why this feature doesn't exist. If you don't agree with the rationale, feel free to try it I guess. |
| 03:24 | justin_smith | the general clojure approach is that bindings should be explicit and clear, and any time you refer to some binding, it should be simple to see where that binding came from. It's something I personally like a lot about mainstream clojure code. But of course there are ways to break these rules if you really want. |
| 03:25 | rritoch | neurostorm: See: https://clojuredocs.org/clojure.core/binding |
| 03:26 | justin_smith | rritoch: that has nothing to do with what he wants. He wants the values to be magically bound without him having to type out their names (getting them automatically from a map only known at runtime). |
| 03:26 | justin_smith | binding has all the same limitations that let does |
| 03:27 | neurostorm | i understand your argument, and maybe in general its a bad ide. Still i would have thought it was possible to set some binding in a more dymanic manner. I just want a closure or let-over-lambda make some keyvals from a hash-map accessible in the scope. |
| 03:27 | justin_smith | you can do it, but it doesn't exist yet |
| 03:27 | justin_smith | of course it is possible, it would probably involve a macro plus eval |
| 03:29 | rritoch | justin_smith: Oh, ok. I see the problem. |
| 03:31 | neurostorm | ok... well, better ditch that idear. thanks for the input. |
| 03:32 | rritoch | neurostorm: Sure, you can do it, but your going to have errors constantly, especially if you use variables not defined in the provided map. |
| 03:33 | rritoch | neuostorm: Basically you just create a function that accepts a map and a form, you wrap the form in a function definition & let statement populated with the key/value pairs. |
| 03:35 | rritoch | neurostorm: I'd think it would be something like... (fn [myvars myform] (do #_manipulate form #_(eval form which returns a function) #_( call function with values from myvars to populate let values) |
| 03:36 | rritoch | neorostorm: You could make a macro which would generate that code so your final product is cleaner. It is going to be very error prone because your call to eval will fail if undefined variables (keys) are used. |
| 03:37 | rritoch | neurostorm: If you can think it up, clojure can find a way to do it, but just because you can do something, doesn't mean you should. |
| 03:38 | neurostorm | yes, i can see your point, will be difficult to use without make much more error handling. |
| 03:38 | justin_smith | which is fixed by explicitly attempting to bind those keys, which brings us back to how you would do it with destructuring anyway |
| 03:46 | rritoch | neurostorm: If your going to use that psudocode, you should also switch the order of the arguments from myvars myform to myform myvars and take a partial of it since your form isn't going to change on each call. |
| 07:43 | ashwink005 | can anyone suggest a good source to learn how to write deftests? |
| 07:43 | ashwink005 | i.e. compojure project testing |
| 08:08 | sandbags | amalloy_: ping .. wanted to ask you about (apply map list (partition xs)) |
| 08:32 | triss | gosh I'm sure I'm finding searching the JIRA way harder than it should be.... |
| 08:33 | triss | I'm told a ticket exists for adding documentation strings/error messages to :pre and :post conditions exists but I really can't find it. |
| 08:34 | triss | does anyone know where it is? |
| 08:44 | puredanger | I looked and I don't see it |
| 08:46 | puredanger | I I must be misremembering |
| 08:48 | triss | ah thanks v much puredanger... good to know I'm not gong blind! |
| 09:13 | the-kenny | Anyone noticed issues with leiningen and clojure.test/use-fixtures? It seems that my :once fixture is run in parallel (or nested). |
| 09:14 | the-kenny | Background: I start a webserver for an api in there. When running the tests with C-c , in Emacs, everything works fine. When I run `lein test', I get an AddressAlreadyInUseError and my logging says the server is started once, then stopped immediately, without any tests in-between |
| 09:19 | the-kenny | Okay, it works fine after updating Clojure from 1.6 to 1.7 |
| 09:26 | jeremyheiler | the-kenny: are you sure you didn't have any lingering processes? |
| 09:26 | the-kenny | jeremyheiler: It might have been that, yeah. That wouldn't explain why it worked in the REPL though. |
| 09:26 | the-kenny | I just wrote some code to randomize the port the server listens on for every test. That should prevent that in the future. |
| 09:27 | jeremyheiler | occasionally i'll find that i have 10 nrepl servers running because they were never closed by emacs |
| 09:27 | jeremyheiler | or whatever should have closed them |
| 09:28 | noncom | what is the most idiomatic way to get all dates for the current week with clj-time? |
| 09:38 | bja | jeremyheiler: that's more realistic anyway (randomized ports). if you had a service that needed to both bind a port and have multiple copies listening on the same ip, you'd need to either assign those ip:port combinations ahead of time or use some sort of registry (I use zookeeper for an nrepl registry) |
| 09:50 | bja | noncom, I feel like you'd have to define current week |
| 09:50 | bja | do you mean the next 7 days (inclusive of today) |
| 09:50 | bja | do you mean this Sunday through Saturday cycle? Monday through Sunday? Thursday through Wednesday? |
| 09:51 | bja | in any event, I'd imagine the answer involves either take or take-while and clj-time.periodic/periodic-seq |
| 09:52 | egli | bja: yes probably, but how do you get the start of the week? |
| 09:52 | bja | how do you define the start of the week? |
| 09:52 | mungojelly | yeah weeks start differently in different cultures |
| 09:52 | egli | let's assume monday :-) |
| 09:53 | egli | if I knew the current weekday I could (ago date ,,,) |
| 09:54 | jeremyheiler | bja: sure, wasn't arguing against randomized ports :-) |
| 10:00 | bja | (monday? (first (take 7 (periodic-seq (ago (-> (today) day-of-week dec days)) (days 1))))) |
| 10:02 | bja | (require '[clj-time.core :refer [ago days day-of-week today]] '[clj-time.periodic :refer [periodic-seq]] '[clj-time.predicates :refer [monday?]]) |
| 10:03 | bja | that code probably has a bug if the day is monday |
| 10:03 | bja | actually, (days 0) works |
| 10:03 | bja | well, works the way I want it to |
| 10:03 | egli | bja: is there a day-of-week function? I can't find it on http://clj-time.github.io/clj-time/doc/index.html |
| 10:03 | bja | it's part of the DateTime protocol |
| 10:04 | bja | http://clj-time.github.io/clj-time/doc/clj-time.core.html#var-DateTimeProtocol |
| 10:04 | egli | ah, you're right |
| 10:04 | egli | did a search on http://clj-time.github.io/clj-time/doc/index.html where it wasn't listed |
| 10:04 | bja | the latest docs are for 0.8 though |
| 10:04 | bja | I think clj-time has newer versions |
| 10:09 | mungojelly | add the current day, stop if it's monday, go back and add days until one of them is monday, add days to the end until it makes seven |
| 10:12 | noncom | bja: egli: mungojelly: so, take (now), find current day-of-the-week, lapse back to, say, monday, that's the start. add 7 - that's the end.. correct? that is straightforward but i thought maybe there is a simpler way |
| 10:12 | bja | noncom, my code works |
| 10:12 | bja | just remove the monday? first functions where I prove the first day is a monday |
| 10:13 | bja | it returns a seq, starting with monday and containing datetimes for the entire week |
| 10:13 | bja | there is a function called ago which does the legwork for you |
| 10:13 | bja | so you just need to find monday, and then tell periodic seq to start with monday, and give you datetimes in day increments |
| 10:13 | noncom | bja: ah, i see, spotted your code. i missed that while reading the char |
| 10:13 | noncom | *chat |
| 10:13 | noncom | very cool! |
| 10:14 | bja | periodic-seq is awesome |
| 10:14 | troydm | is it possible to create alist in clojure? or even a pair? |
| 10:14 | bja | troydm: what do you mean? |
| 10:14 | bja | '(1 2) is a list |
| 10:15 | bja | if you were inclined to do so, you could have a reader dispatch on some new mutable list and have syntax for it |
| 10:19 | csd_ | How might I translate the CL macro (defmacro macro (&rest fn-names) '(progn ,(if fn-names '',fn-names '*fns*)))? The double syntax quote has me confused |
| 10:22 | troydm | bja: I mean something like (cons 1 2) in Scheme |
| 10:23 | bja | no, if you want something like that define it and then add syntax for it via reader dispatch |
| 10:25 | troydm | ic |
| 10:26 | bja | by define it, I mean create the data type and functions to manipulate it, and then use http://clojure.org/reader#toc4 |
| 10:26 | jeremyheiler | csd_: which are backticks and which are quotes? my editor doesn't differentiate them |
| 10:26 | jeremyheiler | my irc client* |
| 10:26 | jeremyheiler | they all look like single quotes to me |
| 10:26 | bja | ^^^ what jeremyheiler said |
| 10:27 | csd_ | jeremyheiler: all are single quotes |
| 10:27 | jeremyheiler | csd_: that doesn't compile |
| 10:27 | jeremyheiler | so, my approach is to macroexpand the cl code to see the output |
| 10:28 | csd_ | hm maybe the book i'm looking at has a transcription error |
| 10:28 | jeremyheiler | the quote in front of progn is probably a backtick |
| 10:29 | jeremyheiler | because of the , in front of if |
| 10:29 | csd_ | see fn profile at the bottom of the page 290 https://books.google.com/books?id=eH6jBQAAQBAJ&lpg=PA913&dq=paradigms%20in%20artificial&pg=PA290#v=onepage&q=profile1&f=false |
| 10:30 | csd_ | sorry, unprofile |
| 10:30 | jeremyheiler | it doesn't let me see page 290 |
| 10:30 | jeremyheiler | wait, nvm, it does |
| 10:32 | jeremyheiler | csd_ ok, i got it. the quote in front of progn needs to be a backtick `, not a single quote ' |
| 10:32 | jeremyheiler | also, the two quotes in front of ,fnames need to be backticks, not single quotes |
| 10:32 | jeremyheiler | that at least compiles... |
| 10:35 | csd_ | i'd think you can just directly translate that backtick to clojure's backtick / single quote, right? |
| 10:35 | jeremyheiler | i think so |
| 10:35 | jeremyheiler | and cl , is clj ~ |
| 10:35 | csd_ | yeah |
| 10:35 | jeremyheiler | it's hard to tell which is a backtick and which is a quote in that book |
| 10:35 | jeremyheiler | i have a copy at home, but i'm not at home, so i can verify :-/ |
| 10:36 | csd_ | but if fn-names is a list, i can see why '~ makes sense, but not why the extra ' |
| 10:37 | csd_ | maybe because without it, the unquote at the beginning of `if` will unquote it too> |
| 10:37 | jeremyheiler | in clojure, you may want to quote a symbol before syntax quoting it so that it doesn't become namespace-qualified |
| 10:39 | csd_ | why syntax-quote at all? why not just use only regular quote |
| 10:39 | jeremyheiler | ,'bar |
| 10:39 | clojurebot | bar |
| 10:39 | jeremyheiler | ,`bar |
| 10:39 | clojurebot | sandbox/bar |
| 10:40 | jeremyheiler | see how the syntax quote implies a namespace |
| 10:40 | csd_ | yeah |
| 10:41 | csd_ | ,''bar |
| 10:41 | clojurebot | (quote bar) |
| 10:41 | csd_ | ,`'bar |
| 10:41 | clojurebot | (quote sandbox/bar) |
| 10:41 | csd_ | ,'`bar |
| 10:41 | clojurebot | (quote sandbox/bar) |
| 10:42 | TMA | ,``bar |
| 10:42 | clojurebot | (quote sandbox/bar) |
| 10:42 | csd_ | i guess i should probably just install a CL compiler and see what this actually expands to and compare that with what happens in clojure |
| 10:44 | jeremyheiler | csd_: i consulted the resident cl'er who sits next to me and it is bakctick, quote |
| 10:44 | jeremyheiler | ,`'~'(foo bar baz) |
| 10:44 | clojurebot | (quote (foo bar baz)) |
| 10:45 | jeremyheiler | ,`~'(foo bar baz) |
| 10:45 | clojurebot | (foo bar baz) |
| 10:45 | TMA | ,`quote |
| 10:45 | clojurebot | quote |
| 10:45 | sobel | here i sit at my javajob with a data integration engineer (sql lackey) title. contemplating whether i might need to find me a proper clojob. |
| 10:46 | TMA | oh, so quote symbol is a special case |
| 10:46 | jeremyheiler | csd_: so this code is evaluating fn-names once, and then quoting it so the list of fn-names isn't called as a function. |
| 10:46 | jeremyheiler | (defmacro macro (&rest fn-names) `(progn ,(if fn-names `',fn-names '*fns*))) |
| 10:46 | jeremyheiler | (macro foo bar baz) ;=> (PROGN '(FOO BAR BAZ)) |
| 10:47 | csd_ | ohh |
| 10:48 | csd_ | right and so if there wasnt the unquote before the `if` sexp then that extra backtick wouldnt have been necessary |
| 10:49 | jeremyheiler | ,(do (defmacro macro [& fn-names] `(do ~(if fn-names `'~fn-names '*fns*))) (macro foo bar baz)) |
| 10:49 | clojurebot | (foo bar baz) |
| 10:50 | jeremyheiler | ,(do (defmacro macro [& fn-names] `(do ~(if fn-names `'~fn-names '*fns*))) (macroexpand '(macro foo bar baz))) |
| 10:50 | clojurebot | (do (quote (foo bar baz))) |
| 10:51 | jeremyheiler | csd_: correct, but then the if would be the resulting expansion |
| 10:53 | csd_ | yeah |
| 10:53 | csd_ | i'd imagine that as you work more with macros that this all becomes idiomatic eventually |
| 10:54 | jeremyheiler | yeah, but then you try to write a macro that expands into a macro |
| 10:55 | jeremyheiler | if you successfully do it, you become a wizard |
| 10:55 | csd_ | good luck maintaining it too :-P |
| 10:55 | jeremyheiler | lol |
| 10:55 | csd_ | thanks for explaining this all to me, very helpful |
| 10:55 | jeremyheiler | sur! |
| 10:55 | jeremyheiler | sure* |
| 12:55 | codefinger | Pupeno: here's another option that might work well for you case (deploy local artifacts) https://github.com/heroku/lein-heroku |
| 12:59 | jeremyheiler | that looks nice. i wasn't a fan of the git approach for clojure/java |
| 13:00 | codefinger | jeremyheiler: what was the rub? i agree in some cases -- especially since JVM artifacts so portable |
| 13:01 | jeremyheiler | having a lot of stuff in my git repos that don't need to be sent to heroku |
| 13:01 | jeremyheiler | especially when my build pipline is designed for deploying a jar |
| 13:02 | codefinger | jeremyheiler: yea, i'm not a fan of checking things into Git that don't need to be there. So lein-heroku is perfect for uberjars |
| 13:32 | pseudonymous | Hey - can anyone explain why this explodes (kicker: it never does when testing in a repl) https://gist.github.com/anonymous/3e9f961067277e71cee0 |
| 13:34 | amalloy | uh, because you are referring to stuff in cider.nrepl? |
| 13:35 | amalloy | if-require doesn't really work at all |
| 13:35 | amalloy | hm, actually if-require looks okayish |
| 13:36 | amalloy | but you have to call it at the top level to be effective, not inside a function |
| 13:36 | pseudonymous | I hope so, I literally spent 2 hours baby-stepping through its writing. |
| 13:36 | pseudonymous | Oh, and then capture the results in a def ? ) |
| 13:36 | amalloy | actually as written i'm not sure it even works at the top level, because you're using a let |
| 13:37 | amalloy | doing requires outside of ns is pretty tricky |
| 13:39 | pseudonymous | amalloy: Yea, I'm coming to see that :( |
| 13:40 | justin_smith | pseudonymous: the only time I have successfully used require at runtime, is if I also use resolve instead of referring to the symbols required directly |
| 13:40 | justin_smith | pseudonymous: this is helpful for avoiding needing to do AOT for example |
| 13:42 | justin_smith | pseudonymous: the problem is that clojure won't compile code that calls cider.nrepl unless cider.nrepl is available at compile time. Your macro needs to be a bit more magical than it is. |
| 13:42 | justin_smith | or you need to use resolve |
| 13:42 | justin_smith | (perhaps even a combination of these things - the macro could use resolve!) |
| 13:44 | pseudonymous | justin_smith: not quite sure I follow. Just tested something from another library (which I already use in other files) - that worked. If I'm understanding you correctly, this trick will basically only work provided the ns in question is already referred to in other parts of the project ? |
| 13:45 | justin_smith | pseudonymous: the compiler won't compile code that calls things that it can't resolve |
| 13:45 | justin_smith | pseudonymous: which means you need to manually use resolve yourself |
| 13:45 | justin_smith | it works accidentally if the namespace is actually available because someone else (eg. your lein tooling) required the thing already |
| 13:45 | pseudonymous | Ah, so the reason why it works for other libs is that I'm already using them and they're already resolved. This one isn't, so I'm fubar'ed. |
| 13:46 | justin_smith | right |
| 13:46 | justin_smith | but, clojure will gladly compile code that *attempts* to resolve something at runtime |
| 13:46 | pseudonymous | So time to delve into the mysteries of resolve... |
| 13:46 | justin_smith | so instead of foo.bar/baz you use (resolve 'foo.bar/baz) and cross your fingers it doesn't blow up with a nil at runtime |
| 13:47 | justin_smith | ,(resolve 'this.does.not/exist) |
| 13:47 | clojurebot | nil |
| 13:47 | justin_smith | ,(resolve 'clojure.set/union) |
| 13:47 | clojurebot | nil |
| 13:47 | justin_smith | ,(require 'clojure.set) |
| 13:47 | clojurebot | nil |
| 13:47 | justin_smith | ,(resolve 'clojure.set/union) |
| 13:47 | clojurebot | #'clojure.set/union |
| 13:47 | justin_smith | see, magic! |
| 13:48 | pseudonymous | Oooh. Hmm Well.. that shouldn't be a problem, the macro is written to guard against that exact case |
| 13:48 | justin_smith | pseudonymous: right, you don't even need require - just use resolve, and sometimes you get nil and deal with it |
| 13:48 | justin_smith | easy-peasy |
| 13:49 | justin_smith | if resolve returns something non-nil, you know you can use it |
| 13:49 | justin_smith | also this is all terrible and should have a fancy evocative name like monkey-summoning |
| 13:49 | pseudonymous | eh? Which part, exactly ? |
| 13:50 | justin_smith | conditional behaviors determined by the side effects of other dependencies |
| 13:50 | pseudonymous | I can't remember exactly *where* I found it, but Immutant has a dev plugin which (in hindsight) used resolve to conditionally pull in various plugins |
| 13:50 | justin_smith | which can lead to weaird things like bugs that only happen if you require foo.bar in another namespace - just consider how weird that is |
| 13:51 | justin_smith | I'm not saying it's never useful! but let's be real about how spooky and illogical it is |
| 13:52 | pseudonymous | justin_smith: well it's not like I'd want to build everything around it, but for the odd wrapper somewhere, it should be OK, so long as it isn't extremely necessary to have it (which is exactly the case here) |
| 13:53 | justin_smith | pseudonymous: sure, just trying to keep perspective about the terrible consequences if we accept this sort of thing as normal - using resolve at runtime should always be guilty until proven otherwise |
| 13:54 | justin_smith | but sometimes it's a fine way to do something that would be a total mess if you couldn't do it that way |
| 13:54 | pseudonymous | justin_smith: btw, this was really enlightening. It's so much simpler and doesn't require a custom macro (and THAT is a real win in my book). On the downside, I spent all that time writing one ;__; |
| 13:55 | justin_smith | heh :) |
| 13:58 | amalloy | pseudonymous: you also could have just found someone else's implementation of it. that macro has been written many times |
| 14:00 | pseudonymous | amalloy: I searched a little (not well enough) and found something much like the macro I wrote - but the one I came across didn't support a vector-style libspec, so I set out modifying it, with terrible results (repl issues) and finally I decided to write everything one step at a time to minimize chances of screwing up. It was educational enough, so I'm OK with having done it. |
| 14:01 | justin_smith | clearly we need a variation on "require", more like "nice-to-have" |
| 14:02 | justin_smith | (ns foo.bar (:nice-to-have [dwim.core :as dwim])) ... |
| 14:04 | bja | justin_smith: I'm going to steal "monkey-summoning" for the next time I do something ambiguously evil in clojure |
| 14:04 | justin_smith | bja: heh, I really think it should be reserved for situations where a feature might ambiguously exist and you don't know until runtime, but OK |
| 14:05 | bja | ok, there is a precise usage |
| 14:05 | justin_smith | bja: I guess that could also be called "petting schroedinger's cat" |
| 14:05 | bja | how about for conditional execution between deployed scenarios and non-deployment |
| 14:05 | justin_smith | oh yeah... |
| 14:07 | bja | justin_smith: so this is monkey summoning? https://gist.github.com/3b4096aeec6a4f6992ab |
| 14:08 | justin_smith | bja: since you get significant difference in definitions based on runtime environment it could count |
| 14:09 | justin_smith | funny enough, I did something similar as a lein plugin (so that we could unambiguously see the state of the git repo inside artifacts) |
| 14:09 | bja | yeah, we have a ring middleware that exposes this |
| 14:10 | bja | we just have it stashed inside a utility library |
| 14:10 | bja | along with like 30 components |
| 14:28 | neoncontrails | Is any particular data type implied by the term 'register'? |
| 14:29 | neoncontrails | I typically think of registers as lists, but must they be? |
| 14:29 | rhg135 | stacks maybe |
| 14:31 | rhg135 | I always hear 'push onto' which screams stack |
| 14:32 | neoncontrails | Yeah that's true. Would it be preposterous to call a string a register? |
| 14:33 | rhg135 | it technically could be used as one |
| 14:34 | rhg135 | but semantically, they're very different |
| 14:38 | neoncontrails | Yeah that's sort of what I was thinking too. Thanks, just wanted to make sure it wouldn't be wildly inaccurate to call this generic arithmetic calculator a register machine |
| 14:38 | neoncontrails | it's structurally like one, but uses concatenate instead of cons to build the result |
| 14:42 | mikerod | would I be correct in thinking that from a stacktrace - if I see a my.ns.name__init.<clinit> in it that that means that it is an AOT-compiled loading path vs no AOT files present? |
| 14:43 | mikerod | I guess what I mean is, is it true that my.ns.name__init does not exist at all if there is no AOT compilation |
| 14:43 | mikerod | in a purely JIT world, there are no classes loaded that have a name suffixed with __init |
| 14:53 | rhg135 | I think that file gets compiled on load even on no aot |
| 14:57 | mikerod | rhg135: I was trying to determine if that were true or not |
| 14:58 | rhg135 | i may be wrong though |
| 15:00 | mikerod | I don't see anywhere in clojure.lang.Compiler that refers to that suffix other than Compiler.compile() which is for AOT |
| 15:01 | mikerod | I searched all over for both RT.LOADER_SUFFIX |
| 15:01 | mikerod | and __init strings |
| 15:01 | mikerod | and when I track the JIT compile path, I don't see any place that'd be generated. it is meant to compile the ns itself, so it may not have any place in the JIT world |
| 15:02 | mikerod | this was just something helpful in troubleshooting a crazy classloader issue with some mixed AOT (bad). I started thinking the presence of the my.ns__init at all meant there was loading off of AOT classes |
| 15:09 | RedNifre | So I just started with the REPL and for fun, I tried (def man doc) but it says "can't take value of a macro". What does that mean? |
| 15:09 | jeremyheiler | ,(doc doc) |
| 15:09 | clojurebot | "([name]); Prints documentation for a var or special form given its name" |
| 15:09 | jeremyheiler | ,(source doc) |
| 15:09 | clojurebot | Source not found\n |
| 15:09 | rhg135 | that doc is a macro |
| 15:09 | jeremyheiler | yeah |
| 15:10 | RedNifre | does that mean that it only works when I type it in the REPL? That it's sort of not meant to be used in the code? Or is it more complicated and I should learn about macros first? |
| 15:11 | jeremyheiler | macros are code that generate code, and cannot be referenced |
| 15:11 | jeremyheiler | they only exist at compile time, not runtime |
| 15:11 | rhg135 | you can't pass it around like a function |
| 15:12 | rhg135 | ,+ |
| 15:12 | clojurebot | #object[clojure.core$_PLUS_ 0x281717fa "clojure.core$_PLUS_@281717fa"] |
| 15:12 | rhg135 | ,doc |
| 15:12 | clojurebot | #error {\n :cause "Can't take value of a macro: #'clojure.repl/doc"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojure.... |
| 15:16 | justin_smith | RedNifre: also, the repl uses clojure.repl (which includes doc), and your files won't have access to clojure.repl unless you explicitly require it |
| 15:16 | justin_smith | RedNifre: but usually you only need the stuff from clojure.repl in ... a repl |
| 15:16 | RedNifre | makes sense |
| 15:17 | mungojelly | i guess the reason macros and functions are both all lower case is so you can add an optional different shape to a function that already has callers?! |
| 15:17 | justin_smith | mungojelly: what does that even mean? |
| 15:18 | mungojelly | if you're not going to change existing function calls silently to macros, then it would make sense to distinguish them so you can see in the code if things are macros, so i assume the invisibility is to sneak them in like that |
| 15:18 | justin_smith | functions and macros are both lower case because that's how it's been as long as lisps have been case sensitive, upper case macros are a convention in languages with crappy macros that only do string substitution, because string substitution breaks things in really weird ways |
| 15:19 | mungojelly | i'm just talking about for readability, in clojure you have to guess whether things are macros or not, a lot of stuff is like, how does this function do this, oh ok it's all macros it turns out, all lower case just means "function or macro" and you have to learn/guess/experiment to know which is which |
| 15:20 | jeremyheiler | "all lower case" is just the status quo in clojure |
| 15:20 | justin_smith | mungojelly: the assumption that a macro would not be lower case is newer than lisp macros are |
| 15:20 | mungojelly | it's become "obvious" to me that defn is a macro, but it gradually got "obvious" over the course of several weeks of getting accustomed to it |
| 15:21 | RedNifre | By the way, how far does clojure go on the functional side? Are things like curried functions, monads etc. included? |
| 15:21 | ToBeReplaced | i would consider a change from function to macro a breaking, non-backwards compatible change in any library |
| 15:21 | justin_smith | RedNifre: neither of those. Because we get varargs and dynamic typing instead, respectively |
| 15:21 | mungojelly | someone a couple days ago here was talking about writing their own currying so that must not be there? there's monads somewhere but no one uses them |
| 15:22 | mungojelly | ToBeReplaced: then do you think there's any reason to have the same style for them? |
| 15:22 | justin_smith | RedNifre: but the normal data types are all immutable |
| 15:22 | ToBeReplaced | mungojelly: no, i loosely agree that i'd rather see a naming convention for macros that distinguishes them from functions |
| 15:23 | RedNifre | Why is "defn" a macro instead of a function? Is it to not allow strange programs that define functions at runtime? |
| 15:23 | justin_smith | RedNifre: the opposite, because you can't use macros first class |
| 15:23 | justin_smith | wait... |
| 15:23 | mungojelly | RedNifre: it's just to write the syntax of it, to make it shaped the way it is |
| 15:23 | amalloy | RedNifre: here is one of the basic things distinguishing macros from functions |
| 15:24 | ToBeReplaced | RedNifre: "intern" is the function it calls... it's just convenience around that |
| 15:24 | amalloy | functions always evaluate all of their arguments before running the function |
| 15:24 | RedNifre | awww |
| 15:24 | amalloy | so if defn were a function, (defn foo [x] 1) would evaluate foo (which doesn't exist), then [x], (which doesn't exist), and then 1 |
| 15:24 | RedNifre | I was hoping for Io-like "lazy if you want" evaluation of parameters. |
| 15:24 | justin_smith | nope! |
| 15:24 | mungojelly | yeah a macro is like, wait, hold on, before you evaluate those things, i'm gonna rearrange them a little, ok now evaluate them |
| 15:26 | RedNifre | If Clojure has strict evaluation, how can the defn macro use a regular function internally? How to write a function body without evaluating it? |
| 15:27 | justin_smith | RedNifre: btw you can do (defmacro man [& args] (cons 'doc args)) |
| 15:27 | mungojelly | fn is a "special form" right? even more powerful yet |
| 15:27 | rhg135 | quoting |
| 15:28 | mungojelly | and there's some built-in reader macros that look for some ~*!@*~&!@ around words but there's no (easy) way to add more of those |
| 15:28 | rhg135 | and code is just data |
| 15:28 | amalloy | RedNifre: various "special forms" have special evaluation rules |
| 15:28 | RedNifre | I guess I'll have to read more of the book before I drown in an endless sea of further questions (currently reading "seven languages in seven weeks") |
| 15:28 | ToBeReplaced | RedNifre: "intern" is the "def" part, "fn" is the special form part |
| 15:28 | amalloy | eg, "if" is a special form, whose evaluation rule is different from the rule for function calls |
| 15:29 | neoncontrails | RedNifre: These are awesome questions, but don't worry if none of this makes sense to you yet. Macros are without a doubt the most advanced feature of the language, and I noticed in #clojure-beginners you're literally beginning your first REPL session |
| 15:29 | RedNifre | ah, so I guess (defn id [a] a) is a macro for something like (intern "id" ["a"] '(getParam "a")) huh? |
| 15:30 | rhg135 | sorta |
| 15:30 | justin_smith | RedNifre: 'a instead of "a", and it uses the fn special form |
| 15:30 | justin_smith | and then fn calls fn* which calls some java |
| 15:30 | RedNifre | Yes, I'm in my first REPL session and in the first Clojure chapter of the book :) |
| 15:31 | amalloy | RedNifre: that is the general idea, yes. wrong in basically every particular, but going in the right direction |
| 15:31 | mungojelly | ,(macroexpand '(defn twice [n] (* n 2))) |
| 15:32 | rhg135 | clojurebot is gone |
| 15:32 | mungojelly | :( |
| 15:33 | ToBeReplaced | in case it's of interest... i wrote a lib a while back that uses intern to programmatically create public functions instead of writing a bunch of defns: https://github.com/ToBeReplaced/lettercase/blob/master/src/org/tobereplaced/lettercase.clj#L11 |
| 15:33 | oddcully | so we are finally botfree |
| 15:33 | RedNifre | humans win |
| 15:33 | oddcully | jay! |
| 15:33 | neoncontrails | I noticed that. Who maintains clojurebot? I feel moved to help |
| 15:34 | mungojelly | i think it's hiredman |
| 15:35 | neoncontrails | hiredman: do you need more hands to help with Clojurebot? |
| 15:40 | hiredman | nope |
| 15:42 | RedNifre | I don't understand why (< 1) is true but (<) is not allowed. My intuition is that (<) should also be true. |
| 15:43 | RedNifre | ...because all elements or an empty list are ordered in accending order, like all elements in a list with one element in it. |
| 15:44 | justin_smith | RedNifre: that's actually a fair point, and you're not the first one to bring it up here |
| 15:44 | justin_smith | ,(=) |
| 15:44 | amalloy | justin_smith: it's more true for = than for < though |
| 15:45 | amalloy | i think gfredericks argued fairly convincingly on that point last time |
| 15:45 | justin_smith | right, I was attempting to provide an even better example |
| 15:45 | amalloy | notably, RedNifre, you'd lose the "law" that < is the inverse of >= |
| 15:46 | RedNifre | Is it? What about (< 1) vs (>= 1)? Both are true... |
| 15:46 | amalloy | oh, are they? i guess so. i take it back then |
| 15:49 | RedNifre | How much success did you have trying to introduce Clojure at the office? |
| 15:49 | neoncontrails | I've always just thought of < > as functions with a fixed arity of 1 or 2, defaulting to true in the base case |
| 15:49 | neoncontrails | Is that not right? |
| 15:49 | RedNifre | No, you can also do (< 1 2 3) -> true or (< 1 2 3 1) -> false |
| 15:50 | neoncontrails | Oh interesting. That's more consistent with other arithmetic functions, I suppose |
| 15:50 | RedNifre | I tried (< 1) and was surprised that it worked, then I remembered that + works for varargs, so it made sense to try (< 1 2 3) which worked and (<) which didn't. |
| 15:51 | RedNifre | Strange, (+) is 0 but (-) isn't allowed. |
| 15:52 | RedNifre | (*) is 1, which makes sense, so I guess it gives me the Monoid for * or +, but why not for - or /? Shouldn't (-) be 0 and (/) be 1? |
| 15:53 | amalloy | RedNifre: - and / aren't monoids either way, because they're not associative |
| 15:53 | RedNifre | point taken |
| 16:00 | neoncontrails | amalloy: Not to sound creepy, but do you blog? I feel like I could learn a lot from you |
| 16:01 | amalloy | no. i wrote a few articles several years ago, mostly about clojure, when i was working at hubpages |
| 16:02 | amalloy | http://amalloy.hubpages.com/ confuses me, because it says i have 7 articles but only lists 4 of them and i don't see any way to find the rest |
| 16:02 | neoncontrails | If you ever feel inspired to start one, I'd love to read it. |
| 16:05 | neoncontrails | Even reading your solutions to 4clojure-like problems (if not those problems exactly) would be a great resource. Your solutions remind me of what good code can look like |
| 16:05 | amalloy | you can mostly find my writings on stack overflow and in #clojure |
| 16:05 | amalloy | neoncontrails: well, so look at my 4clojure solutions then |
| 16:05 | neoncontrails | Heh, I didn't know they were published. I'll go look |
| 16:06 | amalloy | although actually not all of them are things i would endorse; i replaced my solutions with other users' solutions if they reported a bug like "hey my solution to #43 isn't working" |
| 16:06 | amalloy | neoncontrails: (almost) everyone's 4clojure solutions are published |
| 16:06 | amalloy | once you solve a problem, you can see anyone's solution unless they opt out |
| 16:07 | neoncontrails | I noticed yeah. Which is a cool idea, but certain problems I couldn't solve right away |
| 16:09 | shem | it is edifying to see good code in small portions. |
| 16:10 | justin_smith | yeah, that makes the bots very useful, when they are here |
| 16:10 | justin_smith | but bot-running is a chore |
| 16:14 | RedNifre | I just noticed that nil behaves like an empty list/set/map/string etc. but not as 0 in (+ nil) or 1 in (* nil). So I guess the rule for nil is that it's an empty container? Or what exactly? |
| 16:14 | justin_smith | RedNifre: it is equal to the Java NULL |
| 16:15 | RedNifre | but you can't (map count nil) in java and get an empty map. |
| 16:15 | justin_smith | RedNifre: and not equal to 0, and overloaded with the empty list for cons, and overloaded with false for truth checks |
| 16:16 | justin_smith | RedNifre: also seq treats nil as an empty sequence (and eg. map, filter, etc. call seq on their last arg) |
| 16:16 | RedNifre | ah, that makes sense. |
| 16:16 | justin_smith | it's a weird mix of historical reason stuff |
| 16:16 | lodin_ | RedNifre: seq of an empty collection returns nil. |
| 16:16 | lodin_ | ,(seq {}) |
| 16:17 | justin_smith | but for our particular lineage, equality with 0 is not part of the heritage |
| 16:17 | lodin_ | No bot? |
| 16:17 | RedNifre | Regarding other languages, what do you think of Scala, Erlang and Haskell? |
| 16:17 | RedNifre | bot broke earlier today. |
| 16:18 | justin_smith | Scala isn't simple enough, Haskell is great but makes me feel stupid, I haven't tried Erlang |
| 16:20 | neoncontrails | Heh. Yeah, the evaluation of nil has taken some getting used to. |
| 16:20 | neoncontrails | Someone pointed out to me here (was it you, justin_smith?) to use (not (seq (<your list>)) as a base case for recursion |
| 16:21 | neoncontrails | That hasn't gotten less weird to me in the past three weeks, heh |
| 16:21 | amalloy | justin_smith probably would have told you to use empty? |
| 16:21 | justin_smith | neoncontrails: in the original lisp, a list was a cell containing the current item's value and a cell containing the address of the next cell. There was a special nil cell which meant "there is not next cell", and using that alone meant an empty list |
| 16:21 | justin_smith | amalloy: yes, I would have |
| 16:22 | neoncontrails | right, which enabled (null? the-empty-list) to return true right? |
| 16:22 | justin_smith | right |
| 16:24 | RedNifre | Hm, looks like I don't have "null?". Is that a 1.7 thing? I just went with the Clojure in the Ubuntu repository which is 1.6... how old is that one and how much does Clojure change between versions? |
| 16:24 | justin_smith | the current value was the Content of the Address Register, and the address of the next cell was in the Content of the Decrement Register, leading to the famous "car" and "cdr" functions (which I keep forgetting don't exist in clojure) |
| 16:24 | neoncontrails | just a wild guess, but is the presence/absence of that sentinel cell predicated on whether the language spec supports tail-end recusion? |
| 16:24 | justin_smith | no |
| 16:25 | amalloy | RedNifre: they're talking about a different language |
| 16:25 | neoncontrails | Don't they by another name? first:car::rest:cdr |
| 16:25 | justin_smith | sure, yeah |
| 16:26 | justin_smith | RedNifre: yeah, sorry, this is all legacy / background |
| 16:31 | lodin_ | nil is actually a bit odd in Clojure I think, since it complects (to use Clojure jargon) empty collections and missing values. |
| 16:32 | justin_smith | lodin_: and falseness |
| 16:33 | neoncontrails | Scold me if I'm being a little too Louis Reasoner here: would this definition work in Clojure the way null? does in Scheme? |
| 16:33 | neoncontrails | (defn null? [lat] (or (empty? lat) (= (first lat) nil))) |
| 16:33 | justin_smith | neoncontrails: shoudl null? return true for [nil 1] ? |
| 16:34 | neoncontrails | Aw man. Right you are |
| 16:34 | justin_smith | neoncontrails: try (comp nil? seq) |
| 16:35 | lodin_ | That too. I would probably be OK with empty collections being false though (like empty list in Python is false), which they're not in Clojure, so you have to seq it. |
| 16:35 | justin_smith | except I think that gives a result you wouldn't expect for "" |
| 16:35 | justin_smith | #(and (coll? %) (nil? (seq %))) something like this maybe? |
| 16:36 | amalloy | justin_smith: should it return false for nil? |
| 16:36 | justin_smith | oh, right |
| 16:36 | justin_smith | :P |
| 16:36 | justin_smith | so wrap the whole thing in a (or (nil? %) (and ...)) |
| 16:37 | justin_smith | which probably still gets it wrong for some case |
| 16:37 | RedNifre | Hm, I'm not sure I understand varargs and "empty?"... this gives me "array is not a function" or "empty list is not a function" errors... but I thought the "empty?" check would preventh that? What's wrong with this: (defn >>= [maybe & f] (if (empty? f) maybe (if (= maybe nil) nil (>>= (apply (first f) [maybe]) (rest f))))) |
| 16:38 | RedNifre | I'm trying to use it like (>>= "hello" count #(+ 3 %)) |
| 16:40 | justin_smith | RedNifre: that (rest f) adds a new level of list nesting at each recursion |
| 16:40 | justin_smith | maybe you want (apply >>= ...) |
| 16:41 | RedNifre | oh, right, the list counts as one parameter... good catch... |
| 16:41 | RedNifre | I guess apply also works with multiple lists, huh? |
| 16:41 | justin_smith | it works with multiple args, only the last arg is unpacked |
| 16:41 | lodin_ | RedNifre: And you don't need (apply (first f) [arg]), just do ((first f) arg). |
| 16:42 | justin_smith | unless you expect to unpack arg... |
| 16:42 | justin_smith | which does not seem correct here |
| 16:42 | justin_smith | oh wait, the vector, hah, neverm ind |
| 16:42 | justin_smith | yeah, drop the apply and the vector |
| 16:43 | lodin_ | RedNifre: The base case, so to speak, of apply takes a function and a sequence. Then there's convenience forms that essentially conses stuff onto the args. |
| 16:44 | RedNifre | great, this works now: (defn >>= [maybe & f] (if (empty? f) maybe (if (= maybe nil) nil (apply >>= ((first f) maybe) (rest f))))) |
| 16:44 | justin_smith | (+ 1 2 3) (apply + 1 2 [3]) (apply + 1 [2 3]) and (apply + [1 2 3]) are all the same thing |
| 16:45 | lodin_ | RedNifre: See also some-> btw. |
| 16:46 | RedNifre | Hm, I don't understand the doc for some-> and (some-> "hello" count #(+ 3 %)) gives me something odd... |
| 16:46 | justin_smith | RedNifre: some-> rewrites forms |
| 16:47 | justin_smith | it would work if you changed #(+ 3 %) to (+ 3) or (#(+ 3 %)) |
| 16:49 | RedNifre | indeed it does but I neither understand why nor what "rewrites forms" means. |
| 16:49 | RedNifre | But it's getting late anyway, gotta go. |
| 16:49 | RedNifre | Well, the language looks interesting, so I guess I'll be here again tomorrow :) |
| 16:49 | justin_smith | RedNifre: try (macroexpand '(some-> "hello" count)) |
| 16:49 | justin_smith | it's a macro, it rewrites the code before compiling it |
| 16:50 | justin_smith | RedNifre: admittedly (macroexpand '(-> "hello" count)) is much easier to read, and gives almost as much information (given that some-> is much like -> ...) |
| 16:51 | RedNifre | Hm, I peeked ahead, macros are part of chapter two so I'll hopefully be wiser tomorrow ;) |
| 16:51 | RedNifre | Thank you all for your help and have a good night. |
| 16:51 | justin_smith | you too |
| 16:54 | lodin_ | I think maybe I will start to call macros "user-defined keywords". |
| 16:54 | justin_smith | lodin_: but we already have something called keywords |
| 16:55 | lodin_ | Haha, yes. So "User-defined syntax keywords"? |
| 16:55 | justin_smith | lodin_: "user defined syntax" |
| 16:56 | justin_smith | because it doesn't just define a symbol, it defines a syntax for evaluation |
| 16:56 | justin_smith | or else it didn't need to be a macro |
| 16:58 | lodin_ | justin_smith: I wanted to avoid syntax because I think non-lisp people associate syntax with stuff like semicolons, where the brackets to, if a comma is allowed at the end of a list, if whitespaces matters, etc. |
| 16:58 | lodin_ | And keywords are not thought of as syntax, but rather language features. |
| 16:58 | amalloy | lodin_: stuff like, whether you need []s around the bindings in a let? |
| 16:59 | lodin_ | amalloy: Or that you have [] instead of () in bindings. And #{} for literal sets, etc. |
| 17:00 | amalloy | right, my point is that that *is* syntax, and it's exactly what macros do |
| 17:00 | amalloy | let is a macro |
| 17:03 | lodin_ | amalloy: Right. So is defn, but in most other languages I think people would think of it as "the keyword for defining a function". |
| 17:04 | amalloy | i don't think that's true at all. java and c, for example, don't have any keyword for defining a function |
| 17:04 | lodin_ | amalloy: "class"? |
| 17:06 | mungojelly | people associate syntax with getting confused by syntax which is why they should associate macros with syntax so they'll know what's going on when they're confused by the syntax of macros |
| 17:07 | amalloy | a keyword indeed, for defining a class |
| 17:09 | mungojelly | project naming around here is funny! i feel like i'm supposed to think of just one quirky word for my names! but i think i'm going to go with stringplayground |
| 17:20 | lodin_ | mungojelly, amalloy: I've found that people that do not know any lisp but are sufficiently interested think that writing macros is what you do all day as a lisp programmer. I've read and heard people be hindered in learning Clojure because of it, because they think they should write a macro to solve the problem (or "write a program to write the program"), rather than just solving it directly. |
| 17:30 | neoncontrails | justin_smith: curious. Why is this? http://pastebin.com/N0PTgx6a |
| 17:34 | lodin_ | neoncontrails: null-v2? always returns true (because it returns a function). |
| 17:38 | neoncontrails | Hmm. I see that you're right, I must've mistranslated his idea |
| 17:39 | irctc | Hi everyone. :) |
| 17:39 | lodin_ | neoncontrails: When he wrote (comp nil? seq) he ment the function seq. Not as a placeholder for a sequence. |
| 17:40 | lodin_ | *meant |
| 17:40 | neoncontrails | Oh! That makes sense |
| 17:40 | lodin_ | neoncontrails: So (def null-v2? (comp nil? seq)) |
| 17:40 | irctc | Does anyone know how to refer to an actual html file from compojure handler without actually writing views functions with Hiccup html generating? |
| 17:41 | irctc | I want to simply point to an existing html file, not to a function that will generate it. |
| 17:48 | irctc | does anyone have experience doing this in Compojure? |
| 17:49 | lodin_ | irctc: I don't really, but would compojure.route/files function help you? |
| 17:51 | irctc | I tried with ring resource-response but that didn't seem to work. |
| 17:52 | irctc | Thanks lodin_ that seems like it could help. I'll test it out in a min and get back to you with the results. :) |
| 17:59 | irctc | lodin_ for some reason it just skips over my designated route and evaluates true for a route which accepts some parameters. |
| 18:00 | irctc | Maybe I'm not using it right. I am new to Clojure so maybe I'm not doing something as I should. |
| 18:01 | lodin_ | irctc: Haven't really used compojure, so I'm not of much help I'm afraid. |
| 18:03 | irctc | Ok, thanks for pointing me to some resources though. I appreciate that. :) |
| 18:13 | hlolli | ,(defn debug [s] (prn s)) |
| 18:14 | hlolli | ,(defn quoted-prn [f] (prn `@f)) |
| 18:14 | hlolli | ,(quted-prn (debug "dontcare")) |
| 18:15 | hlolli | sandbox broken? |
| 18:15 | hlolli | ,(quoted-prn (debug "dontcare")) |
| 18:17 | hlolli | How can I deref an arity and symbolic quote it? |
| 18:17 | lodin_ | hlolli: Huh? |
| 18:17 | hlolli | the `~ and ~@ dont work |
| 18:18 | lodin_ | hlolli: What do you want to achieve? |
| 18:19 | hlolli | In what I wrote above Id want it to print (#'sandbox/debug "dontcare") |
| 18:20 | lodin_ | hlolli: Then you want to resolve 'debug, using the function resolve. |
| 18:20 | CVTJNII | What is the best way in Clojure to perform a function on two contiguous values in a vector, returning a vector that is one entry shorter? So say if I have [ 1 2 3 4 5 ] and I want to add contiguous entries, getting [ 3 5 7 9 ]. |
| 18:21 | hlolli | you mean `(resolve f) instead of `@f ? |
| 18:22 | lodin_ | CVTJNII: Don't know about best, but you could do (map + x (rest x)) where x is your vector. |
| 18:23 | lodin_ | hlolli: f will be a list containing the symbol 'debug and the string "dontcare". |
| 18:23 | CVTJNII | lodin_, That's a lot better than what I thought I'd have to do, thanks |
| 18:24 | lodin_ | CVTJNII: map is extra nice in that it works on functions with higher arities than one. |
| 18:25 | hlolli | all I get is (clojure.core/resolve sandbox.quoted-prn/f) |
| 18:26 | hlolli | sorry if I mistunderstand you |
| 18:26 | lodin_ | hlolli: What is it you want to do again? Really. |
| 18:26 | hlolli | ,(defn debug [s] (prn s)) |
| 18:26 | hlolli | ,(defn quoted-prn [f] (prn `(resolve f))) |
| 18:26 | lodin_ | Wait. You're not using defmacro. |
| 18:27 | hlolli | ,(quoted-prn (debug "dontcare")) |
| 18:27 | hlolli | hoping for (#'sandbox/debug |
| 18:27 | hlolli | "dontcare") |
| 18:30 | lodin_ | hlolli: I'm still not really sure what you want to do, but you probably want to use defmacro somewhere. |
| 18:31 | hlolli | hmm yes, when you mention it |
| 18:33 | lodin_ | hlolli: If you use defmacro, the values that you get in your parameters are unevaluated Clojure forms, which is probably want you want. Don't use ` or anything in there yet. |
| 18:35 | hlolli | yes, I think so too. But maybe it doesnt matter that Im calling from (clojure.core/quote namespace.function arg) instead of (namespace/function arg) |
| 18:36 | lodin_ | hlolli: ? |
| 18:36 | hlolli | nevermind :) |
| 18:37 | hlolli | my technical english is also bad. |
| 18:39 | lodin_ | hlolli: Just see what happens if you do (defmacro quoted-prn [f] (prn f)). |
| 18:41 | hlolli | It will print correctly, still doesnt give me namespace before the function name. |
| 18:43 | hlolli | only if I symbolic-quote it as argument... but maybe I wont need it in my case... |
| 18:43 | hlolli | symbolic-quote I mean ` symbol |
| 18:43 | lodin_ | hlolli: You shouldn't do syntax quote (is the proper term, I think) at all in this case. |
| 18:44 | lodin_ | hlolli: What you get is unevaluated, meaning that the symbol is just a symbol. It's up to you to decide what to do with it. |
| 18:44 | hlolli | yes I think so too, thanks so much |
| 18:45 | lodin_ | hlolli: Which is why you need resolve. Resolves looks up what's associated with a symbol in the namespace. |
| 18:45 | lodin_ | s/Resolves/resolve/. |
| 18:46 | TEttinger | clojurebot seems down. hiredman, no rush, but is clojurebot easy to bring back? |
| 18:47 | hiredman | yeah, just got oomkilled |
| 18:48 | lodin_ | hlolli: Note that it will only work if you have something that resolves as the first value in your form. |
| 18:48 | TEttinger | thanks hiredman |
| 19:04 | Trioxin | I should be able to run Clojure on rPI no problem right |
| 19:04 | Trioxin | it comes with JVM on it |
| 19:05 | Trioxin | maybe even arduino too? |
| 19:07 | spoofednoob | on a raspberry you are better served with Clojurescript/nodejs |
| 19:09 | spoofednoob | for arduino you are out of luck ;) |
| 19:27 | irctc | Take care everyone. Good night! :) |
| 19:40 | triss | hey all.. just raised a jira about allowing messages to be specified for pre and post conditions: http://dev.clojure.org/jira/browse/CLJ-1817 |
| 19:41 | triss | would somebody mind checking it for anything I might have missed? |
| 19:41 | triss | all comments much appreciated! |
| 19:57 | triss | erm I accidentally inserted my ticket twice? can i delete it or is leaving an apologetic message the only way to get rid of it? |
| 19:58 | triss | oh poop... bit worried that all made quite a bit of email noise and stuff. sorry if anyone recieved it! |
| 20:07 | mungojelly | triss: i'm new here but i think that idea sounds awesome, i've been wanting more places in clojure to put strings explaining |
| 20:12 | amalloy | just send them an email apologizing for the excess emails |
| 20:18 | triss | amalloy: sounds like a plan! |
| 20:19 | triss | cheers mungojelly... pleased someone thinks its a reasonable idea! |
| 20:19 | mungojelly | just to be clear, the "core" ns means nothing, and this core.clj has no particular purpose and i should just delete it and put a nameofminethatmakessensetome.clj? |
| 20:21 | mungojelly | triss: i think it's the best sweet spot between the idea that code is just self documenting (which it isn't), and sprinkling random observations around (which just get out of date or are noise), if there's text attached to it in an actually meaningful way, then it really accurately explains itself. but idk that's just my guesses/intuitions. |
| 20:22 | mungojelly | i'm thinking for stringplayground i'm going to start with a stringplayground.sandbox and then next i'm planning to add stringplayground.slides which will be blending infinite string sequences and then stringplayground.swingset can be a gui frontend 8) |
| 20:25 | triss | mungojelly: I like to think so. Error messages make nice docs sometimes. |
| 20:25 | mungojelly | one of my favorite parts of clojure so far is the idiom of bringing in a long .ed name into a shorthand form, like it's something.thingy.blah so it's :as s.t.blah or whatever, and then if you read the file you can expand that shorthand in your mind, it's succinct without being um encoded |
| 22:28 | mungojelly | how can i get "lein test" to run inline unit tests? i tried putting (with-test ...) around things and it doesn't see them? |
| 22:35 | mungojelly | or should i use midje? |
| 22:44 | justin_smith | mungojelly: lein test looks for files under test/ in your project, and loads those, it doesn't load regular namespaces for test definitions directly |
| 22:47 | mungojelly | am i missing some benefit to putting tests separate from other code? why not mix them? |
| 22:48 | justin_smith | it's just a preference thing I think |
| 22:48 | justin_smith | I don't have a strong opinion on it myself |
| 22:49 | justin_smith | mungojelly: as a workaround you could make test/foo/bar_test.clj that just requires your regular ns, and that would make the test definitions load so that lein test runs them |
| 22:49 | justin_smith | it's a little silly, but it would work |
| 22:49 | mungojelly | well i'm looking instead at midje, it seems sensible and interesting so far |
| 22:50 | justin_smith | lein test and clojure.test are two different things btw |
| 22:50 | justin_smith | clojure.test is part of clojure itself, lein test is just a tool using it |
| 22:55 | mungojelly | hmm, midje has an infix bit to its syntax with the => thing so someone called it "faux infix" that's funny, it's like infix is so rare around here it doesn't register as existing even if it does |
| 22:55 | justin_smith | it's called "faux infix" because clojure doesn't start by resolving => and applying it to the surrounding forms |
| 22:55 | justin_smith | because there's no way to make clojure do that |
| 22:55 | justin_smith | so it's faux |
| 22:56 | mungojelly | ok sure i see, it has a prefix too so it doesn't actually infix |
| 22:57 | mungojelly | i think it's pretty whatever you call it, the prefixing and then infixing, very readable |
| 22:57 | justin_smith | the "fact" is the part of the form that clojure resolves, and the fact macro is the thing that looks for => and generates the resulting forms |
| 22:58 | mungojelly | it does make sense to choose who gets to decide the syntax, and "the middle" isn't as defined a place as the beginning. hmm, the end is perfectly well defined too but i've never heard of any backwards lisps. |
| 22:59 | justin_smith | mungojelly: forth works that way |
| 22:59 | mungojelly | no it's just endless, i mean just like lisp syntax but reversed |
| 22:59 | justin_smith | the funny thing, with postfix you don't need parens - the interpreter / compiler whatever just invokes each word as it gets to it |
| 22:59 | mungojelly | ((n 2 +) [n] foo defn) |
| 23:00 | justin_smith | mungojelly: what I'm saying is that because it is postfix it doesn't need parens |
| 23:00 | justin_smith | so they don't use them |
| 23:00 | mungojelly | you don't need them if you otherwise distinguish who gets to determine the syntax |
| 23:00 | mungojelly | forth just is lacking in syntax, thus why everyone hates it i suppose, i found it fun enough, but i didn't make anything serious with it |
| 23:01 | mungojelly | but if you do a reverse lisp then you can have the last element be a macro that decides what happens with the evaluation of the earlier elements |