2015-03-22
| 04:41 | ane | is there a shorter way around this: (map (fn [sym] ((resolve sym) a b)) symbols) |
| 04:42 | opqdonut | well you can always say (map #((resolve %) a b) symbols) |
| 04:42 | opqdonut | but that's it I guess |
| 04:47 | ane | hm, yes. so there's no handy "anti-quote" macrothing to do what resolve does? |
| 04:50 | amalloy | how could it be a macro? you're asking it to operate on data the exists at runtime |
| 04:52 | ane | oh, not a macro |
| 04:53 | opqdonut | if you use quote, you'd have to couple it with eval |
| 06:41 | dysfun | what's the easiest way to deal with temporary file generation in clojure? |
| 06:42 | dysfun | hrm, me.raynes.fs looks easy enough |
| 08:24 | spinningarrow | The docstring for empty? says to use seq instead of (not (empty? ...)) but seq doesn't return a boolean. So is that still the right approach when writing a predicate? |
| 08:25 | Bronsa | spinningarrow: clojure generally doesn't care about true/false, truthy/falsy is usually enough |
| 08:25 | spinningarrow | Bronsa: so if a function returns truthy/falsy, it is still considered a predicate, I suppose? |
| 08:26 | gfredericks | yeah people do it all the time |
| 08:26 | Bronsa | spinningarrow: eh, no it's not strictly a predicate but we use it as a predicate all the time |
| 08:27 | gfredericks | hello Bronsa |
| 08:27 | hyPiRion | It sort-of depends – I tend to be a bit careful about that |
| 08:27 | hyPiRion | get and nth may return nil, for instance |
| 08:27 | spinningarrow | ah cool. Sorry if that was a stupid question, but I was doing a clojure course and the midje tests were explicitly checking if the predicate returned `true` or `false`. Was just wondering if that's common :) |
| 08:27 | Bronsa | gfredericks: o/ |
| 08:27 | gfredericks | \o |
| 08:27 | hyPiRion | (for correct lookups) |
| 08:27 | hyPiRion | s/correct/successful/ |
| 08:28 | spinningarrow | hyPiRion: yeah, that's a good point too! |
| 08:31 | sahil | exit |
| 08:31 | spinningarrow | so I guess that generally it's fine, but something to be careful about |
| 08:45 | hyPiRion | yeah, it depends on what the function can return |
| 08:45 | hyPiRion | you might get false negatives |
| 08:47 | gfredericks | (defn does-has? "Returns :nope if m contains k and :yep otherwise." [m k] ...) |
| 08:47 | gfredericks | I think I got that backwards |
| 08:49 | spinningarrow | gfredericks: haha |
| 08:50 | spinningarrow | well, thank you guys very much for all the clarification! I shall mess around some more in clojure-land gfredericks hyPiRion Bronsa |
| 08:51 | hyPiRion | gfredericks: just do (alter-var-root #'does-has? complement) |
| 08:55 | gfredericks | hyPiRion: no we're pretty much stuck with it; don't want to make breaking changes |
| 08:55 | bcm | spinningarrow: what clojure course is that? |
| 08:55 | hyPiRion | gfredericks: oh okay then |
| 08:56 | spinningarrow | It's this one - 'Functional programming with Clojure' (http://mooc.fi/courses/2014/clojure/) |
| 08:58 | bcm | Clojure is listed as an intermediate language. There isn't that much more to setup is there? |
| 08:59 | bcm | This course looks pretty cool |
| 08:59 | bcm | really well done use of bootstrap, too |
| 09:49 | edeferia | hi. question for the group: i would like know the most idiomatic way of doing the following: i have a list of functions (literaly as a list) and would like to use the thread macro on it. how? |
| 09:50 | justin_smith | edeferia: macros work before the compilation stage, they are not a runtime thing |
| 09:51 | justin_smith | if the list is known before runtime, you can make a macro that injects that list into a threading macro |
| 09:51 | justin_smith | otherwise, you can use reduce |
| 09:51 | justin_smith | (to get most of the same functionality, but at runtime) |
| 09:51 | edeferia | ah, got it. understand. so basically unroll the list in a macro that uses -> |
| 09:51 | justin_smith | `(-> ~x ~@fs) |
| 09:52 | justin_smith | inside a macro |
| 09:52 | justin_smith | but only works if fs are known when compiling |
| 09:52 | edeferia | they are. |
| 09:52 | hyPiRion | Well, if you have the list at compile time, why not write (-> x f-1 f-2 f-3) ? |
| 09:53 | gfredericks | yeah -> is more for readability; not so useful with macros |
| 09:53 | hyPiRion | Otherwise you can just use (defn thrush [x fs] (reduce #(%2 %1) x fs)) |
| 09:53 | edeferia | hyPiRion: because although the list of functions is known, their sequence can change from call to call |
| 09:54 | justin_smith | hyPiRion: yeah, that was the reduce version I was suggesting above |
| 09:54 | gfredericks | can't use -> then |
| 09:54 | gfredericks | or |
| 09:54 | gfredericks | um |
| 09:54 | gfredericks | depends on what "call to call" means |
| 09:55 | edeferia | multiple invocations of the equivalent of (-> init (…)) would have different ordered set of functions in (…) |
| 09:56 | hyPiRion | edeferia: I'd say to go with a function first (thrush), as justin_smith originally suggested. |
| 09:56 | hyPiRion | A macro won't give you any notable benefits here, at least not initially |
| 09:56 | gfredericks | and has drawbacks |
| 09:56 | gfredericks | like it's tricky to reason about |
| 09:56 | gfredericks | case in point, I still can't tell even with your last clarification whether this would work |
| 09:57 | justin_smith | right. The macro is helpful for readability, and using it programmatically like that avoids that benefit. |
| 09:57 | edeferia | agree. thank you all for the assistance. i will try justin_smith’s suggestion. thanks again. |
| 11:06 | Manaphy91 | Hi! Is there a way to create a non mutable tree, where nodes have parents and childs, with deftype? |
| 11:07 | justin_smith | Manaphy91: doubly linked and immutable doesn't work |
| 11:08 | justin_smith | Manaphy91: if you don't need parent links from the children, then yeah, you can do that with deftype |
| 11:08 | Manaphy91 | mmmh, I suppose it but I would like to ask it for a confirm... I dont linke to use loking manually but I think it's what I will do... |
| 11:08 | justin_smith | loking? |
| 11:08 | gfredericks | locking |
| 11:08 | justin_smith | why would you need to lock anything? |
| 11:10 | Manaphy91 | I would like to use this structure concurrently.... I can use atom for a race safe access... |
| 11:10 | justin_smith | Manaphy91: I thought you said it would be immutable |
| 11:11 | Manaphy91 | Yes!! |
| 11:11 | justin_smith | OK, atoms don't use locking at all, and they wrap an immutable datatype |
| 11:12 | Manaphy91 | Ok, thanks, I will try something!! |
| 11:13 | hyPiRion | Manaphy91: bbloom had a talk on immutable graphs in Clojure: https://www.youtube.com/watch?v=YgvJqWiyMRY |
| 11:14 | Manaphy91 | hyPiRion: Thanks!! |
| 11:14 | hyPiRion | at 6:10 specifically |
| 12:22 | justin_smith | hyPiRion: that bbloom talk is great, it makes me want to make an adjacency-list based follow up |
| 12:23 | justin_smith | (adjacency lists being a way to get a super general reification of traversal context, even handling cycles and cross references) |
| 12:25 | hyPiRion | yeah, it's good |
| 12:34 | spradnyesh | why do i see ***[org.clojure/tools.nrepl "0.2.6" :scope "test" :exclusions [[org.clojure/clojure]]]*** in "lein deps :tree" even though my project.clj explicitly lists ***[org.clojure/tools.nrepl "0.2.8"]*** as a dependency? |
| 12:34 | justin_smith | spradnyesh: put the tools.nrepl dep under :dev |
| 12:35 | spradnyesh | justin_smith: thanks for the pointer, let me check that |
| 12:35 | hyPiRion | spradnyesh: because bugs |
| 12:38 | spradnyesh | justin_smith: worked. thanks :) |
| 13:15 | mmg | I’m having some basic macro behavior that I don’t get and I’m trying to understand why. I started with a macro I didn’t expect to work but it’s failing in a way I wouldn’t have guessed: |
| 13:15 | mmg | (defmacro macro-foo |
| 13:15 | mmg | [should-run arg] |
| 13:15 | mmg | (when should-run arg)) |
| 13:15 | mmg | => (macroexpand '(macro-foo bar baz)) |
| 13:15 | mmg | baz |
| 13:16 | mmg | why does that just expand to baz when it can’t resolve bar at compile time? |
| 13:16 | justin_smith | because to the macro code, bar is a symbol |
| 13:16 | justin_smith | and symbols are truthy |
| 13:16 | mmg | oh.... |
| 13:16 | mmg | thank you! |
| 13:16 | justin_smith | ,(when 'ok :go) |
| 13:17 | clojurebot | :go |
| 13:17 | mmg | yeah I was thinking (when nil :go) => nil |
| 13:17 | mmg | I see what I did wrong now |
| 13:17 | mmg | thanks a ton |
| 13:17 | justin_smith | remember that a macro should return the form that you want to run |
| 13:17 | mmg | yeah, no I get that this was a dumb macro, I was just expecting failure to look different (shrug) |
| 13:17 | mmg | now I get why ;) |
| 13:17 | mmg | thanks again |
| 13:18 | justin_smith | np |
| 13:19 | justin_smith | amalloy: on the subject of bad commit histories, I have discovered that the combination of "git merge --no-commit" followed by cycles of "git add -p" and "git commit -m" is like magic |
| 13:20 | amalloy | hm. what is -m? |
| 13:20 | amalloy | something merge-related, but... |
| 13:20 | justin_smith | amalloy: oh, sorry, just supplying a message on the command line |
| 13:20 | amalloy | oh haha |
| 13:21 | amalloy | so, i do cycles of add -p, commit -m all the time. how does it interact with merge no-commit? |
| 13:21 | justin_smith | so I run git add -p, and select a "themed" group of changes, then commit them together |
| 13:21 | justin_smith | it's like a retroactive cure for add |
| 13:21 | justin_smith | amalloy: merge --no-commit means you get all the changes from the other branch, but not its history |
| 13:22 | amalloy | ah, i see now |
| 13:22 | justin_smith | so it's a way of rewriting the history of a series of messy changes because I have no attention span / focus |
| 13:22 | justin_smith | into an alternate, coherent history |
| 13:23 | amalloy | i'm still not quite sure how you end up with those changes on an alternate branch that you want to merge |
| 13:24 | justin_smith | amalloy: getting mixed up in the development process, and when it comes time to make a pr I realize the history is a total mess |
| 13:24 | amalloy | justin_smith: so you create another branch, and merge no-commit your disjointed changes? |
| 13:25 | justin_smith | right |
| 13:25 | justin_smith | then I turn them into sensible commit history |
| 13:25 | amalloy | i would usually just git reset before-dumb-changes, rather than git checkout -b some-branch before-dumb-changes |
| 13:25 | justin_smith | aha, yeah I think as usual git has multiple paths to glory |
| 13:25 | amalloy | yeah |
| 13:27 | justin_smith | oh, yeah, there was actually a reset step in there anyway (between the merge --no-commit and the add-p) |
| 13:27 | justin_smith | because even without the commits, it still stages things, so I need to reset to unstage so I can do selective staging |
| 13:28 | justin_smith | oh wow, there is a "reset -p", combine that with "add -p" and you have a nice little choose your own adventure |
| 13:30 | amalloy | justin_smith: also checkout -p |
| 13:30 | justin_smith | oh wow, nice |
| 13:33 | Glenjamin | i really like "git cola" for that sort of stuff - Qt based gui around staging/unstaging/comitting |
| 13:35 | oddcully | i use tig fiddling togetter proper commits. but i didn't knew about -p |
| 13:35 | justin_smith | magit does some of that stuff too, but I end up preferring to just use the terminal |
| 13:35 | justin_smith | yeah, -p is like a repl for building commits |
| 13:36 | Glenjamin | i dislike the linear nature of add -p |
| 13:36 | justin_smith | Glenjamin: like the way it gives you things in a predetermined order? |
| 13:36 | Glenjamin | guis are a bit better for random access, and easier to split hunks |
| 13:36 | Glenjamin | yes |
| 13:37 | kwladyka | hello, i am learning clojure, can you tell me why in this function http://pastebin.com/zTzhVfUy is "when pred"? What is the prupose of this line? |
| 13:37 | justin_smith | kwladyka: if pred is nil or false, the next line does not run |
| 13:37 | Glenjamin | kwladyka: in that scenario, (when) is equivalent to (if) |
| 13:37 | justin_smith | when is like if but only one branch |
| 13:38 | kwladyka | justin_smith yes i understand that but why is that necessary? It is example form book, it is index-of-any |
| 13:38 | justin_smith | kwladyka: if pred was nil or false, the next line would throw an exception |
| 13:38 | kwladyka | justin_smith i uderstand technical aspect "when pred" but i don't undrestand why author wrote this line |
| 13:38 | justin_smith | you'd have to look at the rest of the code to know why pred would be nil or false |
| 13:39 | justin_smith | I suspect index-filter is being called in a recursive context where pred might be updated on each loop, and might eventually be nil? |
| 13:39 | justin_smith | just a guess |
| 13:39 | kwladyka | hmm so in clojure there is no exception like try{} catch{} or something like that? Should i write in all places code prevent to exception? |
| 13:39 | justin_smith | kwladyka: there is |
| 13:39 | justin_smith | kwladyka: but that author is not using it |
| 13:40 | kwladyka | so it wouldnt be miskate if i dont write (when pred) in function like that? What is best pracice in clojure? |
| 13:40 | justin_smith | in general, exceptions (in any language) should be used for exceptional cases, not for control flow |
| 13:41 | justin_smith | we also have things like some-> that do chaining that short circuits if you hit nil |
| 13:41 | Glenjamin | kwladyka: many core functions are written to behave without exception when they receive nil |
| 13:41 | justin_smith | (doc some) |
| 13:41 | clojurebot | "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)" |
| 13:41 | justin_smith | (doc some->) |
| 13:41 | Glenjamin | ,(get nil) |
| 13:41 | clojurebot | "([expr & forms]); When expr is not nil, threads it into the first form (via ->), and when that result is not nil, through the next etc" |
| 13:41 | clojurebot | #error{:cause "Wrong number of args (1) passed to: core/get", :via [{:type clojure.lang.ArityException, :message "Wrong number of args (1) passed to: core/get", :at [clojure.lang.AFn throwArity "AFn.java" 429]}], :trace [[clojure.lang.AFn throwArity "AFn.java" 429] [clojure.lang.AFn invoke "AFn.java" 32] [sandbox$eval69 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] ... |
| 13:41 | jdeisenberg | Is there a way to specify the version of a template that you want to use in Leiningen? |
| 13:41 | Glenjamin | oh, whoops - bad example |
| 13:42 | justin_smith | jdeisenberg: no, a real peeve of mine actually |
| 13:42 | justin_smith | ,(get nil :anything) |
| 13:42 | clojurebot | nil |
| 13:42 | Glenjamin | that's what i meant :) |
| 13:42 | Glenjamin | clojure mostly gives you back nil instead of throwing null pointer exceptions |
| 13:43 | jdeisenberg | justin_smith: Thanks. Maybe I should look at Leiningen and see if I can figure out how to add that. In my copious spare time, of course :) |
| 13:43 | justin_smith | haha, of course |
| 13:44 | kwladyka | ok so if i undrestand best practice in clojure is: if function can do what should do return value, in other case return nil? |
| 13:44 | justin_smith | that's the usual thing, yeah |
| 13:45 | jjttjj | what are people's preferred clojure dynamoDB clients these days? |
| 13:46 | jjttjj | I guess I prefer operating on a higher level than having more fine tuned control, if that's a factor |
| 13:46 | kwladyka | thx! |
| 14:09 | geekyvin_ | Hey Guys, I've created a simple web-app in Clojure and deployed it in a remote server. but the problem is my application doesnt seem to serve resource files such as css/javascripts...etc. I couldnt figure out why. |
| 14:09 | geekyvin_ | I tried jetty with nginx and tomcat7 with nginx |
| 14:09 | geekyvin_ | this is my project.clj |
| 14:09 | geekyvin_ | (defproject test_web_app "0.1.0-SNAPSHOT" |
| 14:09 | geekyvin_ | :description "FIXME: write description" |
| 14:09 | geekyvin_ | :url "http://example.com/FIXME" |
| 14:09 | geekyvin_ | :dependencies [[org.clojure/clojure "1.6.0"] |
| 14:09 | geekyvin_ | [compojure "1.1.6"] |
| 14:09 | geekyvin_ | [hiccup "1.0.5"] |
| 14:09 | clojurebot | It's greek to me. |
| 14:09 | geekyvin_ | [ring-server "0.3.1"]] |
| 14:09 | geekyvin_ | :plugins [[lein-ring "0.8.12"]] |
| 14:10 | geekyvin_ | :ring {:handler test_web_app.handler/app |
| 14:10 | justin_smith | geekyvin_: don't do that |
| 14:10 | geekyvin_ | :init test_web_app.handler/init |
| 14:10 | geekyvin_ | :destroy test_web_app.handler/destroy} |
| 14:10 | justin_smith | geekyvin_: stop |
| 14:10 | geekyvin_ | :profiles |
| 14:10 | geekyvin_ | {:uberjar {:aot :all} |
| 14:10 | geekyvin_ | :production |
| 14:10 | geekyvin_ | {:ring |
| 14:10 | geekyvin_ | {:open-browser? false, :stacktraces? false, :auto-reload? false}} |
| 14:10 | geekyvin_ | :dev |
| 14:10 | geekyvin_ | {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.3.1"]]}}) |
| 14:10 | geekyvin_ | Opps...sry |
| 14:10 | geekyvin_ | Opps... |
| 14:10 | geekyvin_ | Oops.. |
| 14:10 | andyf | Gist or paste please |
| 14:10 | justin_smith | geekyvin_: how are you accessing the resource files? |
| 14:11 | geekyvin_ | its a simple web-app created with the command lein new compojure-app <web-app-name> |
| 14:12 | justin_smith | geekyvin_: that didn't answer my question |
| 14:12 | geekyvin_ | the statics files are called from html |
| 14:12 | justin_smith | what specifically is being done to fetch those resources |
| 14:12 | justin_smith | are you using wrap-resource? |
| 14:12 | justin_smith | wrap-file? |
| 14:13 | geekyvin_ | right, I found then but couldnt really find how to use them. |
| 14:14 | geekyvin_ | shld the :wrap-resource be in project.clj or in my handler? |
| 14:14 | justin_smith | wrap-resource is a function, and it should be in your handler |
| 14:18 | geekyvin_ | ok let me try that. |
| 14:18 | geekyvin_ | thank Justin. |
| 14:19 | justin_smith | np |
| 14:20 | gfredericks | "in your handler" in the sense that it's a middleware you should use |
| 14:20 | justin_smith | right, "around" would be the better preposition there |
| 15:39 | michaelr` | anyone here uses bidi? |
| 15:39 | michaelr` | err |
| 15:42 | michaelr` | i have one handler which handles both :post and :delete requests, the url of the first is /something and the second is /something/1. is there any way that I can unmatch for both urls from the same handler? |
| 15:45 | michaelr` | both routes are guarded with request methods, essentially I'd like to parametrize url generation with the request method |
| 15:49 | arrdem | Anyone messed with Racket and care to comment on it? |
| 16:02 | justin_smith | arrdem: very clean, a great language for pedagogy, not a huge library ecosystem (like most schemes) |
| 16:02 | gfredericks | technomancy likes it |
| 16:02 | gfredericks | for...kids |
| 16:03 | justin_smith | also, the way you can explicitly choose a language dialect in your source code is kind of cool |
| 16:04 | andyf | I find its mob associations make it scary to use. License enforcement by limb mangling? |
| 16:06 | justin_smith | andyf: it follows a proud tradition of "scheme" dialect names. See also gambit, larceny, guile |
| 16:06 | justin_smith | and some of them get a bit more conceptual, like stalin |
| 16:06 | andyf | Holy cow. We may have unearthed a conspiracy here |
| 16:19 | ben_vulpes | i've been away from clojure webapp development for a while (9 mos? feels like eternity...). is chestnut awesome or will it be really painful in novel ways after six months? |
| 16:21 | _2_Mini | Hola a todos |
| 17:00 | tolstoy | Is there any way to avoid this thing: 'Reflection warning, clojure/data/priority_map.clj:215:19 - call to method equiv on java.lang.Object can't be resolved (no such method).' |
| 17:00 | tolstoy | Not sure why it's showing up all of a sudden. |
| 17:01 | tolstoy | Maybe some interaction with 'aleph'? Hm. |
| 17:01 | gfredericks | that's interesting |
| 17:01 | tolstoy | Using :global-vars {*warn-on-reflection* false} doesn't help. |
| 17:02 | tolstoy | Also: 'Reflection warning, clojure/core/memoize.clj:72:23 - reference to field cache can't be resolved.' |
| 17:02 | gfredericks | tolstoy: are you using priority-map directly? or is aleph requiring it? |
| 17:03 | gfredericks | it looks like there's a "fix reflection" commit in their history included in the latest release |
| 17:03 | tolstoy | I'm not. |
| 17:03 | tolstoy | If it's a lib, I don't see it in "lein deps :tree". |
| 17:04 | gfredericks | what version of aleph are you using? |
| 17:04 | tolstoy | "0.4.0-beta3" |
| 17:06 | tolstoy | Related: http://permalink.gmane.org/gmane.comp.java.clojure.aleph/693 |
| 17:14 | tolstoy | Ah, I see it now. core.async is indeed using priority_map. |
| 17:15 | tolstoy | What's puzzling is that the latest release is from Sep 2014. |
| 17:16 | tolstoy | Ah. Update to the latest priority map, and that goes away. |
| 17:17 | tolstoy | No newer core.memoize, so out of luck there. |
| 17:25 | tolstoy | http://dev.clojure.org/jira/browse/CMEMOIZE-13 |
| 18:17 | _1_Andrz8766 | hey |
| 18:21 | _1_Andrz8766 | hello? |
| 18:21 | clojurebot | BUENOS DING DONG DIDDLY DIOS, fRaUline _1_Andrz8766 |
| 18:21 | _1_Andrz8766 | how do you use this thinh |
| 18:24 | justin_smith | _1_Andrz8766: are you new to IRC? |
| 18:26 | Bronsa | (inc clojurebot) |
| 18:26 | lazybot | ⇒ 48 |
| 19:53 | gfredericks | (inc lojurebot) |
| 19:53 | lazybot | ⇒ 1 |
| 20:01 | justin_smith | I may have done something silly. I am working on a data structure lib that represents graphs natively as adjacency lists, and I have functions that attempt to turn a graph into a tree or list |
| 20:01 | justin_smith | and the list one is just a lazy list that follows a random outgoing edge at teach step until there are no more outgoing edges left |
| 20:02 | justin_smith | so running it twice will give you two different outputs for any graph that can't be represented as a singly linked list |
| 20:02 | justin_smith | maybe that's useful? |
| 20:02 | justin_smith | if the graph has no non-cyclic paths, you get an infinite lazy-seq |
| 20:10 | gfredericks | has anybody made an arithmetic lib for dealing with pretend unsigned bytes/ints/longs? |
| 20:10 | gfredericks | presumably by using primitives but doing the arithmetic differently |
| 20:10 | justin_smith | gfredericks: that seems like a natural thing, like in some java lib that asists in jni stuff or something |
| 20:11 | gfredericks | I think java 8 might have related things |
| 20:11 | gfredericks | but that doesn't help for writing fluent clojure |
| 20:12 | gfredericks | I was also thinking that anybody who intentionally uses bigdecimal might find a set of arithmetic functions restricted to bigdecimal useful |
| 20:12 | gfredericks | to ensure they never accidentally degrade to doubles |
| 20:13 | justin_smith | gfredericks: hmm, maybe you could even keep the arithmetic the same (but only do unchecked operations) and just override like >, <, and the print method |
| 20:13 | justin_smith | because with twos compliment the rest should just work until you hit over / under flow |
| 20:13 | gfredericks | gotta be careful with shifting too |
| 20:14 | justin_smith | ahh, yeah |
| 20:19 | gfredericks | justin_smith: multiplication wouldn't work right would it? |
| 20:20 | gfredericks | without a separate impl I mean |
| 20:28 | justin_smith | "The two's-complement system has the advantage that the fundamental arithmetic operations of addition, subtraction, and multiplication are identical to those for unsigned binary numbers (as long as the inputs are represented in the same number of bits and any overflow beyond those bits is discarded from the result)." |
| 20:28 | justin_smith | that's why I was thinking it would be elegant |
| 20:28 | justin_smith | basic ops just stay the same (and thus also remain as efficient) |
| 20:29 | gfredericks | oh wow I didn't know it worked for multiplication as well |
| 20:29 | gfredericks | the more I think about it the more skeptical I am |
| 20:30 | gfredericks | thinking about the highest bit, and what determines it in an unsigned mult |
| 20:30 | justin_smith | gfredericks: I think overflow would just "accidentally" do the right thing |
| 20:31 | justin_smith | but that's easy to test with some unchecked math, or even by hand |
| 20:32 | gfredericks | where did you get this quote |
| 20:32 | justin_smith | wikipedia |
| 20:32 | gfredericks | you can't trust that did you know anybody can edit it |
| 20:32 | justin_smith | I've heard |
| 20:32 | gfredericks | it's like a button on there; *you can make it say whatever you want!* |
| 20:33 | justin_smith | gfredericks: but that wasn't my original source, it was just easier to look up :) |
| 20:34 | gfredericks | in multiplication the highest bit in the result is dependent on like every bit of the inputs |
| 20:34 | gfredericks | but in signed multiplication that bit has to be the correct sign of the result |
| 20:35 | gfredericks | but if it's also dependent on every bit of the inputs I should be able to twiddle the bits of the inputs (without changing their sign) to manipulate the sign of the outputs |
| 20:35 | gfredericks | s/outputs/output/ |
| 20:36 | justin_smith | gfredericks: the two's complement signed multiply and the unsigned multiply, when applied two to numbers with the same bit representation, are guaranteed to result in the same bits in the output |
| 20:36 | justin_smith | it's the same operation on the bit level |
| 20:36 | gfredericks | you're just stating the position I'm arguing against, right? |
| 20:37 | justin_smith | I'm telling you a fact about how two's complement multiply works |
| 20:37 | gfredericks | yes I believe you that it's true but it's also totally impossible and I'm trying to explain why |
| 20:38 | justin_smith | gfredericks: it's because what is overflow on one side, is a correct multiply on the other |
| 20:38 | justin_smith | it's a lot easier to overflow with signed multiply |
| 20:38 | gfredericks | sure, but I'm focusing on the value of the highest bit |
| 20:38 | gfredericks | after truncating overflow |
| 20:39 | gfredericks | which is a bit that must be determined by virtually every bit of the inputs I think |
| 20:40 | justin_smith | OK - they are identical for non-overflowing operations, and are respectively correct for ops that don't overflow (there are some signed results that are overflows, that are not overflows in the unsigned version) |
| 20:40 | gfredericks | huh? |
| 20:41 | justin_smith | I'm going to try to work this out in a simplified model, like with a three bit number |
| 20:41 | justin_smith | ok, maybe four bit |
| 20:41 | gfredericks | wikipedia says something about having to double the precision beforehand |
| 20:44 | justin_smith | if you want to guarantee you don't overflow, sure - double precision and extend the sign bit |
| 20:47 | gfredericks | so what you said earlier is that multiplication doesn't work if the ops are large enough to overflow, right? |
| 20:47 | gfredericks | which means the sentence in the wikipedia intro is misleading? |
| 20:49 | gfredericks | I just did 7+(-3) and got -5 |
| 20:49 | gfredericks | er 7*(-3) |
| 20:49 | gfredericks | which is the correct sign actually |
| 20:50 | gfredericks | now that I think about it I don't know what you're supposed to expect semantically from overflow of signed multiplication |
| 20:50 | gfredericks | is it equivalent to multiplication mod something somehow? |
| 20:51 | gfredericks | this must be my problem I don't actually know what I think it's supposed to do; I just assumed that signs should be well-behaved, but maybe not |
| 20:59 | justin_smith | gfredericks: so I just wrote out all the five bit numbers in standard / 2's complement, and picked a random multiplication to show that once you truncate overflowed bits, the output is the same |
| 20:59 | justin_smith | http://i.imgur.com/tZX9uuI.jpg |
| 20:59 | justin_smith | sorry it's a little sloppy - on the left is bits - unsigned / signed |
| 20:59 | justin_smith | on the right is signed on top, then bits, then unsigned |
| 21:00 | justin_smith | with the two truncated bits bracketed |
| 21:02 | gfredericks | justin_smith: but what happens when the signed op result is semantically out of range? |
| 21:02 | gfredericks | e.g., -5 * 7 |
| 21:03 | justin_smith | one second, scribbling |
| 21:03 | gfredericks | I demand moar photo graphs |
| 21:04 | gfredericks | faxed to me |
| 21:04 | justin_smith | haha |
| 21:05 | john2x | there's no date generator in test.check? |
| 21:06 | gfredericks | nope |
| 21:07 | gfredericks | what kind of distribution would you want on that? |
| 21:07 | john2x | just completely random dates. hmm I guess a constant date would work just as well for my current purposes. |
| 21:07 | gfredericks | is 19487917373191-02-28 a date? |
| 21:08 | john2x | heh yeah.. that could get tricky |
| 21:08 | gfredericks | we've got a lot of design work to do on good numeric generators |
| 21:08 | gfredericks | which would probably help with what you're wanting |
| 21:09 | gfredericks | in the meantime if you think of something obviously generally useful I can probably put it in test.chuck |
| 21:13 | justin_smith | gfredericks: with 27*7, / -5*7 they still match for the last five bits (which is all the matters since I was doing five bit two's complement) and they only diverge where they overflow |
| 21:13 | justin_smith | both end in 11101 |
| 21:14 | justin_smith | if cl-format wasn't a filthy liar when it comes to binary, I could show you that easily |
| 21:14 | justin_smith | *signed binary that is |
| 21:16 | gfredericks | ,(mod (* 27 7) 32) |
| 21:17 | clojurebot | 29 |
| 21:17 | gfredericks | ,(mod (* -5 7) 32) |
| 21:17 | clojurebot | 29 |
| 21:17 | gfredericks | which is -3 I think? |
| 21:17 | justin_smith | gfredericks: if you refer back to my jpg, it says yes |
| 21:18 | gfredericks | so I guess the semantics are multiplication mod 2^n and then wrapped around to negative as appropriate |
| 21:19 | gfredericks | and therefore the sign is chaotic |
| 21:19 | gfredericks | which is what I was intuiting before, but assumed that meant it wasn't working right |
| 21:19 | justin_smith | yeah, that sounds about right, and it is intuitive because multiplication is repeated addition |
| 21:19 | justin_smith | it's just that there are so many overflowing results you get overflowed overflow etc. :) |
| 21:20 | gfredericks | right, a chaotic sign |
| 21:20 | justin_smith | gfredericks: are you coming to clojure/west? |
| 21:20 | gfredericks | yep |
| 21:21 | gfredericks | booked my flights yesterday |
| 21:21 | justin_smith | cool |
| 21:21 | gfredericks | I've always lived closer to the east coast but I've attended clojure/west a lot more reliably |
| 21:25 | gfredericks | now I'm curious how you detect multiplication overflow |
| 21:25 | justin_smith | this will be my first clojure conference, and it will be crazy seeing all these people I know online in person |
| 21:25 | gfredericks | to the Numbers.javamobile! |
| 21:25 | justin_smith | gfredericks: you put the result in a double-sized result, then you check for any set bits |
| 21:25 | justin_smith | (in the extra sized side, of course) |
| 21:26 | justin_smith | gfredericks: but this is why I was saying before that it would be easy if you do unchecked ops :) |
| 21:26 | justin_smith | heh |
| 21:26 | justin_smith | because the unchecked results will match (while likely being useless to the application code) |
| 21:26 | gfredericks | you're just describing how to do it on a chip, no? |
| 21:26 | justin_smith | not *just* |
| 21:27 | justin_smith | you can do the same thing in an algorithm |
| 21:27 | gfredericks | Numbers.java is doing something clever |
| 21:27 | justin_smith | though I guess you would use a bigint instead of like a 128 bit int |
| 21:27 | justin_smith | interesting |
| 21:27 | gfredericks | omg there's a whole check for x == Long.MIN_VALUE && y < 0 |
| 21:27 | gfredericks | maybe that's an edge case you can't detect otherwise |
| 21:28 | gfredericks | but then after multiplying it does a divide to see what happened |
| 21:28 | gfredericks | if (x&y)/y != x then overflow |
| 21:28 | gfredericks | x*y rather |
| 21:28 | justin_smith | fascinating, nobody's using those overflow bits on hardware more's the shame |
| 21:29 | justin_smith | s/bits/flags |
| 21:29 | justin_smith | I wonder if there are like experimental languages that use that feature |
| 21:29 | justin_smith | or if everybody's like "c doesn't support it, so we don't" |
| 21:34 | rksm | What's the most idiomatic way to read in a project.clj from a jar? I need the project map normally returned from leiningen.core.project/read. |
| 21:34 | gfredericks | is it normally in the jar at all? |
| 21:35 | gfredericks | you can probably get it into the jar with some :filespecs thing and then just read it with clojure.java.io/resource |
| 21:36 | gfredericks | might be a plugin that does this kind of thing already |
| 21:37 | justin_smith | gfredericks: rksm: checking a random jar, yeah I find a project.clj |
| 21:37 | justin_smith | now how do you get a specific version of a resource that is on the class path multiple times again? I always forget |
| 21:38 | gfredericks | a random jar? is it a lib? |
| 21:38 | justin_smith | yeah |
| 21:39 | justin_smith | gfredericks: yeah, I see them in each clojure lib I check |
| 21:40 | gfredericks | huh. well what do you know. |
| 21:40 | gfredericks | seems a little bit weird |
| 21:40 | rksm | Dealing with the classpath and getting content from a jar I managed to do. However, I want to duplicate none (or at least as little as possible) from leiningen.core.project/read (https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/project.clj#L950) |
| 21:41 | rksm | As read only accepts a file (not a jar URI or jar entry reader). |
| 21:41 | rksm | Hmm... how can I convert a buffered reader to a pushback reader? |
| 21:41 | tomjack | (java.io.PushbackReader. buffered-reader) |
| 21:42 | justin_smith | rksm: so how do I get a resource from a specific jar? |
| 21:43 | rksm | tomjack: yep, that works, thanks. now I can use read-raw :) |
| 21:43 | Draggor | Is there a tutorial to start with on clojure.test? |
| 21:44 | justin_smith | Draggor: the clojuredocs page for it is decent. It's a small library. |
| 21:44 | tomjack | justin_smith: (-> (Thread/currentThread) (.getContextClassLoader) (.getResources "foo") (enumeration-seq)) will give you a seq of URLs |
| 21:44 | rksm | justin_smith: I use jar files + jar entries for it: https://github.com/cloxp/clj-system-files/blob/master/src/main/clojure/rksm/system_files.clj#L100 |
| 21:44 | justin_smith | tomjack: oh, nice |
| 21:44 | tomjack | I guess you can figure out which one is from which jar from there |
| 21:44 | tomjack | I stole that from the stuff in core.clj for data_readers.clj |
| 21:45 | justin_smith | tomjack: nice |
| 21:46 | tomjack | thank java that is possible.. |
| 21:46 | Draggor | justin_smith: in particular looking to read about doing setup/teardown and setting a variable for tests |
| 21:46 | Draggor | if I were to not use fixtures I'd just do a let form I suppose |
| 21:47 | justin_smith | Draggor: typically there is very little setup/ teardown - with pure functions you do stubbing instead of mocking |
| 21:47 | justin_smith | and the stubbing can just be data literals and the occasional function literal |
| 21:48 | Draggor | justin_smith: sure, anywhere I can see an example of that? |
| 21:48 | justin_smith | Draggor: and my preferred approach is to have all my complex logic in pure functions (as much as possible), because stubbing to test all the logic is pretty trivial, then making the side effecting stuff as simple as possible so I can avoid / minimize stubbing |
| 21:48 | justin_smith | Draggor: hmm... |
| 21:49 | justin_smith | it would be good to have a go to example for that approach |
| 21:55 | rksm | Draggor: Take a look at how authentication in leiningen itself is tested. There is a credentials function that returns the content of ~/.lein/credentials.clj.gpg: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/user.clj#L122 In order to test that without creating an actual file the var leiningen.core.user/credentials is re-defined at test time: https://github.com/technomancy/leiningen/blo |
| 21:55 | rksm | b/master/leiningen-core/test/leiningen/core/test/user.clj |
| 21:55 | rksm | Draggor: Take a look at how authentication in leiningen itself is tested. There is a credentials function that returns the content of ~/.lein/credentials.clj.gpg: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/user.clj#L122 In order to test that without creating an actual file the var leiningen.core.user/credentials is re-defined at test time: |
| 21:55 | rksm | https://github.com/technomancy/leiningen/blob/master/leiningen-core/test/leiningen/core/test/user.clj |
| 21:56 | rksm | Most of the time you are best of with directly passing dependencies to your functions, though. |
| 22:00 | Draggor | I still feel like I'm missing something simple. I want a fixture that as setup, calls a pure function that returns an immutable object I'm then going to use in my tests. What does that look like? |
| 22:02 | justin_smith | Draggor: why does the fixture need to do that? |
| 22:03 | justin_smith | fixtures are for things with side effects, they don't pass anything to the tests |
| 22:03 | justin_smith | if it's immutable, can't it be a top level def or a let binding? |
| 22:03 | Draggor | Good point |
| 22:03 | gfredericks | ,(def my-test-data 42) |
| 22:03 | clojurebot | #'sandbox/my-test-data |
| 22:04 | justin_smith | one moment, I'll upload what I am working on right now |
| 22:04 | gfredericks | I just made a computer somewhere on the internet keep the number 42 around for a little while just in case |
| 22:07 | justin_smith | https://github.com/noisesmith/adj/blob/master/test/org/noisesmith/adj_test.clj |
| 22:07 | justin_smith | I define some data structures, and do various things with them in each test |
| 22:08 | Draggor | Ahh, yes, it is that simple, thanks! |
| 22:09 | justin_smith | sadly, nothing in this project does side effects |
| 22:09 | justin_smith | though I guess I may add a db backed ns for persistent graph stuff eventually... |
| 22:09 | Draggor | What I'm doing, the side effect is user input which I can fake out in tests, the functions themselves are pure for doing the real work |
| 22:10 | justin_smith | right, and that's very simple to test |
| 22:11 | rksm | Draggor: And in case your input needs to change you can use dynamic scoping, however, be aware that this creates an indirect dependency between the dynamic state and your tests/code. https://gist.github.com/rksm/4a6c0116b32046290af3 |
| 22:12 | rksm | And to just have a "template" test the are macro is useful: https://clojure.github.io/clojure/clojure.test-api.html#clojure.test/are |
| 22:30 | underplank | Hi all. Im using the fantastic clj-http lib, and I’ve been able to find the {:throw-exception false} parameter for the get function. But im using the request function to do arbitrary requests. Is there a way to pass the :throw-exception keyword in? |
| 22:32 | underplank | hmm thats wierd. it seems that the get is actually using request under the covers. |
| 22:32 | gfredericks | do (clojure.repl/source clj-http.core/request) |
| 22:32 | gfredericks | you can see a lot of opts there |
| 22:32 | gfredericks | last I checked they weren't otherwise documented |
| 22:36 | underplank | thanks i’ll take a look |
| 22:47 | ben_vulpes | man i am baffled. where does react.js come from in the chestnut/cljs templates? |
| 22:49 | tolstoy | ben_vulpes: I think it's pulled in as a dependency of [org.omcljs/om "0.8.8"]. |
| 22:49 | tolstoy | It's in a jar file, if that helps. |
| 22:49 | ben_vulpes | hm. |
| 22:50 | tolstoy | [cljsjs/react "0.12.2-5"] |
| 22:51 | tolstoy | Last I remember (it's been a while) there's a deps.cljs in the jar and other such conventions. |
| 22:51 | ben_vulpes | i was using an ancient version of om, apparently. |
| 22:52 | spinningarrow | Which text editor or IDE do most people use for Clojure? (hope I'm not starting a war - just genuinely curious) |
| 22:53 | srid | Emacs |
| 22:53 | justin_smith | spinningarrow: emacs, though cursive (an intellij idea plugin) likely has the best tooling |
| 22:54 | srid | but I'm open to learn of better IDEs for Clojure |
| 22:54 | ben_vulpes | i know a guy who uses vim/fireplace |
| 22:55 | srid | Cursive will be available as an IntelliJ plugin for use with the Community or Ultimate editions, as well as a standalone Clojure-focused IDE. It will be a commercial product, at a similar price point to PyCharm or RubyMine. |
| 22:55 | srid | - https://cursiveclojure.com |
| 22:55 | justin_smith | srid: yes, but it is available for free right now |
| 22:55 | srid | so it is not production ready |
| 22:55 | justin_smith | srid: it's more complete than any of the other options |
| 22:57 | ben_vulpes | is emacs even production ready? |
| 22:58 | justin_smith | ben_vulpes: cider sure the hell isn't, it still changes the abi all the time |
| 22:58 | ben_vulpes | tolstoy: i should expect to see react.js get compiled onto my clojurescript path, right? |
| 22:58 | ben_vulpes | just by virtue of using org.omcljs/om "0.8.0" |
| 22:58 | ben_vulpes | or am i missing something here. |
| 22:59 | tolstoy | ben_vulpes: I think (depending on cljs compiler configuration), it gets merged into your main.js file. |
| 22:59 | ben_vulpes | hm. |
| 22:59 | tolstoy | ben_vulpes: For me, it so often "just works" that I've forgotten about it. ;) |
| 23:00 | ben_vulpes | fwiw, i get out/goog/base.js |
| 23:00 | ben_vulpes | "works on my machine..." |
| 23:01 | tolstoy | Building a project to see where it goes. |
| 23:01 | tolstoy | I have a "dev" task which does the source map and optimizations :none thing. |
| 23:02 | tolstoy | goog.addDependency("../react.inc.js", ['cljsjs.react'], []); |
| 23:02 | tolstoy | It's in my "out" directory. |
| 23:02 | ben_vulpes | when you say "dev" task, are you referring to a :dev key in your :builds vector? |
| 23:02 | ben_vulpes | er |
| 23:02 | tolstoy | Yes. |
| 23:03 | ben_vulpes | a build in the build vector with a "dev" value for the :id key, more accurately. |
| 23:03 | Draggor | rksm: are looks perfect, thanks |
| 23:03 | tolstoy | Yeah: {:builds [{:id "dev" ;; but I get what you mean. |
| 23:03 | tolstoy | I've defined an output dir as resources/public/out and react.js gets put in there. |
| 23:04 | tolstoy | Extracts from the jar, I imagine. |
| 23:06 | ben_vulpes | is it possible that the clojurescript compiler thinks it already copied the react file? |
| 23:06 | tolstoy | When I do a "release" build (:optimizations :whitespace), react.js is embedded at close to the top of the resulting "single" main.js file. |
| 23:06 | tolstoy | Are you using 0.8.8? |
| 23:07 | ben_vulpes | [org.omcljs/om "0.8.8"] |
| 23:09 | tolstoy | Oh. You're experiencing an issue or something? |
| 23:09 | ben_vulpes | it looks like om etc aren't terribly willing to compile. |
| 23:10 | tolstoy | Here's my extremely minimal build config, if that helps. |
| 23:10 | ben_vulpes | i just blew away my resources/public/out directory by hand, reran lein cljsbuild auto, and it did not drop goog/** |
| 23:10 | tolstoy | https://www.refheap.com/98782 |
| 23:11 | ben_vulpes | looks pretty identical to mine. |
| 23:11 | tolstoy | You have the most recent cljs? |
| 23:11 | tolstoy | Yeah, I'm not exploiting a whole lot on CLJS. ;) |
| 23:11 | ben_vulpes | yeah, let me restart my jvm |
| 23:12 | tolstoy | Actually, I don't have the most recent stuff (this is an EOL project). |
| 23:13 | ben_vulpes | hrm. |
| 23:14 | ben_vulpes | well i'm rolling back to 0.8.0 rc1 to see if it'll compile google closures etc |
| 23:14 | underplank | Ok, so I have a ring server that is being run. I want to se a break point in a handler and use a debug repl to have a look around and step in and out of functions. What is the best way to do this? |
| 23:15 | tolstoy | Does "lein deps :tree" reveal anything troubling? |
| 23:16 | tolstoy | Latest lib updates produce some interesting warnings, but it all works with regard to react.js. |
| 23:17 | ben_vulpes | lein figwheel screamed about misconfigured output-dir path, interestingly. |
| 23:18 | tolstoy | Ah, figwheel. Maybe comment that out and see? |
| 23:19 | ben_vulpes | now that i think about it, figwheel was how i compiled assets first. |
| 23:19 | ben_vulpes | but from inside a repl. i was working to shoehorn figwheel-from-repl into a component |
| 23:20 | tolstoy | There's been a lot of repl thrash lately. I think bhauman has been keeping up, but I've given up on it for the duration. |
| 23:20 | ben_vulpes | *sigh* |
| 23:20 | ben_vulpes | good to know, thanks. |
| 23:20 | tolstoy | According to dnolen, all the repls work great (from Emacs) using an inferior-lisp mode, but not cider. |
| 23:20 | ben_vulpes | (classic me, though: "this workflow isn't right! as part of spinning this project up i will make it do the RIGHT THING") |
| 23:21 | ben_vulpes | mk, that did it. |
| 23:21 | ben_vulpes | :output-dir "resources/public/js/out/" |
| 23:22 | tolstoy | Heh. For me, it's, "Surely I need to get a handle on line numbers properly formatted and dimmed rather than my actual hobby project I love working on." |
| 23:22 | ben_vulpes | okay, commit. |
| 23:24 | tolstoy | The QuickStart guide might interest you, if you're into back-to-basics on a path to building up again. |
| 23:29 | ben_vulpes | clojurescript quickstart? |
| 23:38 | tolstoy | Yeah. |
| 23:39 | tolstoy | https://github.com/clojure/clojurescript/wiki/Quick-Start |
| 23:42 | ben_vulpes | yeah, i'm like 80% competent with all of that |
| 23:42 | ben_vulpes | lol okay i got figwheel running awesome |
| 23:42 | ben_vulpes | now i'm just going to let go of it not being integrated in my component workflow for now, and see if i can hammer out a few om buttons or something |
| 23:42 | ben_vulpes | woo |
| 23:42 | ben_vulpes | thanks tolstoy |
| 23:43 | tolstoy | Excellent! Nah, I just mention it because cljs dev has been improving a lot lately, and it's always nice to go back to take stock. (Like re-reading clojure.core API every once in a while.) |
| 23:48 | ben_vulpes | definitely good ideas. |