2016-02-04
| 00:31 | Tilk | hello |
| 00:40 | hammer | hey there |
| 00:41 | hammer | any tips for newbies? |
| 00:42 | hammer | hello? |
| 00:42 | clojurebot | BUENOS DING DONG DIDDLY DIOS, fRaUline hammer |
| 01:00 | lambda-11235 | hello? |
| 01:00 | clojurebot | BUENOS DING DONG DIDDLY DIOS, fRaUline lambda-11235 |
| 01:01 | lambda-11235 | What's fRaUline? |
| 01:58 | kenrestivo | german for "miss"? |
| 07:57 | dysfun | what are my alternatives to core.async in clojurescript if i want something with a very light footprint and i simply want channels and none of the async stuff? |
| 07:57 | justin_smith | dysfun: totally locking up because you have no threads |
| 07:58 | dysfun | lol |
| 07:58 | justin_smith | dysfun: more seriously, promises and callbacks? kind of sucks though |
| 07:58 | justin_smith | but you won't get channels |
| 07:58 | dysfun | *sigh* |
| 07:58 | dysfun | are there any more light footprint options? |
| 07:59 | dysfun | (i don't want a huge js file out of the other end) |
| 08:00 | justin_smith | probably not in cljs, but you might have luck with js-csp or something, there's a few libs that seem to try to do this, but I don't have a size comparison |
| 08:05 | dysfun | gosh, the only current browser they don't work in is opera mini |
| 08:06 | justin_smith | that sounds interesting, and agents implicitly have queues that are effectively channels, so there you go! |
| 08:07 | dysfun | that was what i was thinking |
| 08:07 | dysfun | there's a sort of odd similarity between actors and agents |
| 08:08 | justin_smith | agents are inside out actors |
| 08:08 | justin_smith | all the logic is always on the outside, passed in |
| 08:13 | dysfun | i think a channel can be accomplished with a persistentqueue and an atom |
| 08:14 | justin_smith | swap! retries and agents lock instead of retrying, so I wouldn't use an atom |
| 08:15 | justin_smith | well, maybe retrying on the queue operation is OK |
| 08:26 | dysfun | justin_smith: for a channel, not an agent |
| 08:26 | justin_smith | dysfun: the tricky thing with using an atom for a channel is you want a single op that returns the top item while removing it |
| 08:27 | justin_smith | dysfun: you'll find a pair of refs handles this much more cleanly |
| 08:27 | dysfun | great. thanks. |
| 08:27 | dysfun | now i just have to write an stm |
| 08:27 | justin_smith | actually just one ref, but you need a transaction that alters the channel while removing the next item (for reads) |
| 08:28 | dysfun | not helping |
| 08:28 | justin_smith | well given the lack of threads you don't even need an atom |
| 08:28 | justin_smith | just punch the state in the gut and accept what you get |
| 08:28 | dysfun | yes, but atoms are sensible primitives |
| 08:28 | dysfun | and obviously they're quite fast |
| 08:29 | justin_smith | given the absence of threads, what do they do for you? |
| 08:29 | dysfun | they provide a nice convenient interface over immutable data |
| 10:22 | Glenjamin | you still need somewhere to mutate, and cljs doesn't have vars |
| 10:41 | jsabeaudry | Let's say I want to (swap! a assoc :b :c) (swap! a update :d conj :e), would the clean way to write this be: (swap! a #(-> % (assoc :b :c) (update :d conj :e))) ? Is there a cleaner way? |
| 10:50 | justin_smith | Glenjamin: sure, but I also find it funny cljs has atoms but no vars |
| 11:56 | engblom | I am curious of why Clojure is faster when run with 'lein run' rather than 'java -jar whatever-standalone.jar'? |
| 11:56 | engblom | I am using (time ....) to measure, so the loading is not taking into account. |
| 11:56 | engblom | not need to be taken* |
| 11:59 | justin_smith | the java -jar version doesn't have hotspot turned on, hotspot has short term costs (the price of gathering the metrics and calculating optimizations) that are balanced by the optimizations it brings in later |
| 11:59 | justin_smith | err, I mean the lein version has hotspot turned off |
| 12:00 | justin_smith | so it could be a difference caused by hotspot getting ready to optimize (or even optimizing) but not doing enough yet for you to see the difference |
| 12:00 | engblom | Thanks! That explains |
| 12:00 | engblom | I will check my simple benchmark with a bit bigger loop |
| 12:01 | justin_smith | engblom: this could explain it - if you use (criterium.core/bench ...) instead of (time ...) you'll get a better answer |
| 12:01 | justin_smith | criterium is good at making sure hotspot has kicked in (if it can) |
| 12:08 | phillord | I found several orders of magnitude difference between criterium and time |
| 12:08 | engblom | Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release. |
| 12:08 | engblom | So the hotspot is never used for me... |
| 12:08 | justin_smith | engblom: right, lein did that |
| 12:08 | justin_smith | java -jar won't give you that message |
| 12:08 | phillord | benchmarking well is very hard -- in general, you need to launch multiple times, with randomisation. Unless it's really really vital, I wouldn't bother. |
| 12:08 | justin_smith | so the java -jar gets optimized, lein run does not |
| 12:10 | justin_smith | phillord: what's wrong with using criterium with representative inputs? the reason it's different from time is because it's avoiding a bunch of noise sources that time is prone to |
| 12:11 | phillord | justin_smith: nothing wrong with it, just saying that the results you get might not reflect what happens outside of criterium |
| 12:11 | justin_smith | phillord: I'd say contrarywise that time doesn't reflect the results of the thing you are supposedly timing |
| 12:11 | dysfun | justin_smith: so i ended up using compare-and-set! |
| 12:12 | justin_smith | dysfun: ah, that sounds right |
| 12:12 | engblom | phillord: I am trying to understand so I could be able to get the raspberry pi gpio library a bit faster. Currently it runs at about 42kHz if you do nothing else than turning on and off a led. Compare it to this: http://codeandlife.com/2015/03/25/raspberry-pi-2-vs-1-gpio-benchmark/ |
| 12:12 | engblom | phillord: The only thing slower is shell... |
| 12:13 | justin_smith | engblom: oh, another gotcha here is that the ARM jvm is hardly optimized compared to the x86 jvm |
| 12:14 | justin_smith | so you'd want to be sure any benchmarking is happening on the ARM device |
| 12:14 | engblom | justin_smith: I am doing all the benchmarking at the rpi2 |
| 12:14 | justin_smith | cool |
| 12:15 | phillord | engblom: your running clojure on a PI? What's your boot time? |
| 12:15 | justin_smith | phillord: in my experience it's within usability ranges as long as you don't use lein - under 10 seconds |
| 12:15 | justin_smith | with lein it's insane and useless |
| 12:16 | justin_smith | minute long startups |
| 12:16 | phillord | justin_smith: I'm surprised -- I just assumed it would be awful and never tried |
| 12:16 | justin_smith | clojure is remarkably snappy when you get the tooling out of the way |
| 12:17 | engblom | phillord: I measured time to get a repl: 1m 6s |
| 12:17 | justin_smith | still a slow tool, but not like c++ compiler slow |
| 12:17 | dysfun | huh, does & not work in protocols? |
| 12:17 | dysfun | or is there something special about a function called >! ? |
| 12:18 | phillord | engblom: not so bad -- about the same as my netbook |
| 12:18 | justin_smith | definitely nothing special about >! |
| 12:18 | engblom | phillord: It is fully acceptable as I anyway do not need to restart the repl during development. I send everything over with vim fireplace... |
| 12:19 | dysfun | clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: No single method: _GT__BANG_ of interface: irresponsible.baud.LineProto found for function: >! of protocol: LineProto, compiling:(/var/folders/k6/glc05svd5d194k8kgqfwkrph0000gn/T/boot.user9054690600505278700.clj:1:1) |
| 12:19 | phillord | engblom: learn something every day! |
| 12:19 | dysfun | https://gist.github.com/jjl/3b7f4ed3bd41f8c10079 |
| 12:19 | engblom | phillord: This is my library (the first I ever made in clojure): https://github.com/engblom/gpio |
| 12:21 | justin_smith | dysfun: I'm getting "no single method" no matter how I try to use & in protocol method arg lists |
| 12:21 | dysfun | well that's quite irritating |
| 12:21 | justin_smith | dysfun: haha, time to do a clojure.core (defprotocol ITedious (foo [this]) (foo [this that]) (foo [this that other]) ....) |
| 12:22 | phillord | I might well give that a go, looks like fun |
| 12:22 | dysfun | justin_smith: hrm, do you not have to implement all of a protocol then? |
| 12:22 | justin_smith | dysfun: there is no requirement that one implement every method on a protocol |
| 12:22 | justin_smith | dysfun: of course you get a runtime error if you call one that was not implemented |
| 12:22 | dysfun | i think i can use that |
| 12:23 | justin_smith | this goes for Interfaces too in clojure (unlike javac) |
| 12:25 | engblom | phillord: By the way, if you ever run Clojure on RPI2, make sure you use oracle-jdk. Openjdk will take more than 7 minutes for repl and is unstandable slow on arm. |
| 12:26 | phillord | ah, that's interesting |
| 12:26 | engblom | Openjdk lacks JIT |
| 12:26 | kwladyka | justin_smith i back to "old" topic.... http://clojure.github.io/tools.logging/#clojure.tools.logging.impl/get-logger so (get-logger (find-factory) logger-ns) <- how is it works? get-logger i understand get implementation of Factory by namespace... but how is it works? Each namespace can have another Logger? How can i know Logger for third party module then? |
| 12:26 | engblom | JIT for arm |
| 12:26 | justin_smith | engblom: the default PI os for rpiII is oracle iirc |
| 12:26 | phillord | I'd heard that overtone has a 6-7 min boot time on PI, but that was a while back. Maybe this is why. |
| 12:27 | engblom | Probably. OpenJDK is running in interpreted mode on ARM, while Oracle-JDK is able to use JIT. |
| 12:27 | justin_smith | kwladyka: for java logging, loggers are configured per class |
| 12:27 | justin_smith | kwladyka: java doesn't even have namespaces |
| 12:28 | justin_smith | kwladyka: this is why the solution I was trying to encourage you to use was pure interop - because the java stuff isn't using the clojure.tools.logging.impl stuff |
| 12:31 | kwladyka | justin_smith not sure if i understand. Clear Java solution (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) doesn't need namespace, but Clojure solution use namespace? |
| 12:34 | kwladyka | please correct me if i dont understand: this solution http://stackoverflow.com/questions/13760095/java-dynamically-change-logging-level turn off logging for all handlers where handlers are... namespaces? They use empty string here Logger.getLogger( "" ) |
| 12:36 | rhg135 | 20s to run nil on rpi1 with openjdk, hmm |
| 12:37 | kwladyka | justin_smith or maybe do you know site where i can clearly understand that? :) |
| 12:38 | engblom | rhg135: If you have a rpi1, could you please benchmark my gpio library? I would want to know if it is usable on rpi1. I can paste quickly somewhere some code for you to test. |
| 12:39 | rhg135 | Yeah, engblom, that's fine. |
| 12:39 | engblom | rhg135: http://pastebin.com/dTKKDcKc |
| 12:40 | engblom | rhg135: That would turn on and off a led 1 000 000 times as fast as possible. |
| 12:42 | rhg135 | With criterium? If so, idk if it'll be done today |
| 12:44 | engblom | rhg135: For me it is already enough if you run that program exactly as it is without criterium. That will already tell if it is usable |
| 12:44 | rhg135 | and I don't need anything on the gpio port? |
| 12:45 | engblom | rhg135: no, you do not need anything |
| 12:45 | justin_smith | kwladyka: had a meeting, back now |
| 12:46 | kwladyka | justin_smith sorry if my question or not on high level. Just for some reason it confuse me. |
| 12:46 | justin_smith | kwladyka: clojure.tools.logger has per-namespace config for logging, java logging has per package and class configs. But you can get the "root" which they all default to. |
| 12:46 | rhg135 | Cool, I will go run that |
| 12:47 | justin_smith | kwladyka: jvm logging is a mess, sorry. |
| 12:47 | kwladyka | justin_smith oh now it is more clear |
| 12:47 | justin_smith | OK |
| 12:47 | kwladyka | justin_smith so it is impossible to log off flyway using clojure.tools.logger ? |
| 12:48 | justin_smith | kwladyka: if you just want to set verbosity for java logging, you can use a logging.properties file for whichever logging backend is being used (there are a few out there) |
| 12:49 | justin_smith | kwladyka: clojure.tools.logger is just a set of macros for using the java logging from clojure |
| 12:50 | justin_smith | if you set up clojure.tools.logger to control the same logging subsystem that flyway is using, then you could use clojure.tools.logging to control flyway's verbosity |
| 12:50 | justin_smith | but to me it seems easier to just configure the logger flyway is using directly |
| 12:50 | justin_smith | either with a properties file if you want to set it statically, or the code I shared before for altering the level at runtime |
| 12:52 | kwladyka | (:import org.slf4j.LoggerFactory) (ch.qos.logback.classic Logger Level)) (.setLevel (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) Level/WARN))) <- like that? |
| 12:52 | mpenet | "clojure.tools.logging" :> |
| 12:52 | justin_smith | yup, where WARN could be ERROR or whatever if you chose |
| 12:52 | justin_smith | mpenet: yes, right, he started it |
| 12:52 | justin_smith | haha |
| 12:53 | kwladyka | justin_smith ok so the question is... how can i be sure flyway will use exactly slf4j? |
| 12:54 | kwladyka | and how to set this only for block of code |
| 12:56 | justin_smith | slf4j is an abstraction layer over a few different loggers |
| 12:56 | kwladyka | justin_smith oh is it like clojure.tools.logging? |
| 12:56 | kwladyka | but for Java |
| 12:57 | kwladyka | and how can i set this only for block of code in tests? i don't want turn off logging for everything |
| 12:57 | kwladyka | only for flyway reset database |
| 12:58 | justin_smith | clojure.tools.logging is a wrapper over slf4j, commons-logging, log4j, java.util.logging, slf4j is a wrapper over log4j and java.util.logging and the whole world of java logging is so messy it makes me angry |
| 12:58 | jweiss | i was given this code to create a sorted set of ranges, like #{[1 2] [4 5] [6 7]}, but it's buggy: (apply sorted-set-by (fn [[from-a to-a] [from-b to-b]] (< to-a (dec from-b))) rs) |
| 12:58 | justin_smith | kwladyka: that code snippet doesn't turn the logging off, it just adjusts the level of logging, you can change it back afterward |
| 12:59 | jweiss | not sure what the issue is, i don't know what a comparator is supposed to do. i thought it returns an int, not just true or false? |
| 12:59 | justin_smith | jweiss: you don't need sorted-set-by, sorted-set will handle vectors just fine |
| 13:00 | jweiss | justin_smith: ok, just for my edification, is that comparator bad or is that how it's supposed to be? |
| 13:00 | justin_smith | ,(instance? java.util.Comparator >) |
| 13:00 | clojurebot | true |
| 13:01 | mpenet | kwladyka: you can silence it via a log4j.properties file |
| 13:01 | justin_smith | mpenet: he wants it only in one block of code |
| 13:01 | mpenet | just add en entry where it logs only "error" |
| 13:01 | mpenet | ah |
| 13:01 | justin_smith | which is why the thing with Logger/ROOT_LOGGER_NAME etc. the little interop with ch.qos |
| 13:02 | justin_smith | ,(.compare > 1 2) |
| 13:02 | clojurebot | 1 |
| 13:02 | justin_smith | ,(.compare < 1 2) |
| 13:02 | clojurebot | -1 |
| 13:02 | justin_smith | jweiss: maybe that helps? ^ |
| 13:03 | justin_smith | jweiss: sorted-set-by is going to use the function provided as its comparator, and call compare |
| 13:03 | jweiss | justin_smith: yep, thanks. i don't exactly see what's wrong with the code above, but i'll try just plain sorted set |
| 13:04 | justin_smith | jweiss: yeah, sorted-set should work, because compare already knows how to sort two element vectors |
| 13:04 | justin_smith | ,(sorted-set [6 7] [1 2] [4 5] [3 4]) |
| 13:04 | clojurebot | #{[1 2] [3 4] [4 5] [6 7]} |
| 13:07 | justin_smith | jweiss: fun thing is that all clojure functions implement comparator |
| 13:07 | justin_smith | ,(.compare list 1 2) |
| 13:07 | clojurebot | #error {\n :cause "clojure.lang.PersistentList cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentList cannot be cast to java.lang.Number"\n :at [clojure.lang.AFunction compare "AFunction.java" 56]}]\n :trace\n [[clojure.lang.AFunction compare "AFunction.java" 56]\n [sun.reflect.NativeMethodAccessorImpl invoke0 "NativeMethodAcc... |
| 13:07 | justin_smith | oops! |
| 13:07 | justin_smith | doesn't always work |
| 13:07 | justin_smith | ,(.compare (constantly true) 1 2) |
| 13:07 | clojurebot | -1 |
| 13:07 | jweiss | justin_smith: using sorted set doesn't behave correctly with the function I have that will combine ranges: like (add-interval #{[1 2] [4 5]} [3 3]) should be #{[1 5]} |
| 13:08 | jweiss | then again, the sorted-set-by didn't work right either, but worked better :) |
| 13:08 | justin_smith | jweiss: you want the sorting operator to accomplish that? |
| 13:08 | justin_smith | jweiss: the sorting operator can decide which items are redundant, and where to put the ones that remain, but it cannot alter any of the values in the coll |
| 13:09 | justin_smith | maybe you want a new custom collection type instead |
| 13:09 | jweiss | justin_smith: right the other function i have would disj from the set and then conj a new item |
| 13:10 | justin_smith | jweiss: OK, but the sorting function can only order things, and decide on a pair by pair basis if things are >, <, or = |
| 13:10 | justin_smith | it can't merge things or eliminate based on a three way comparison |
| 13:10 | justin_smith | because .compare is called on two items at a time |
| 13:10 | jweiss | justin_smith: the other function call subseq, eg (subseq ranges <= [from from] <= [to to]) which i also don't quite understand how that works |
| 13:11 | justin_smith | OK, the sorted-set should give you [1 2] [3 3] [4 5] in that order, your code has to decide what it can merge |
| 13:12 | justin_smith | and that ordering is perfect for merging via reduce |
| 13:13 | jweiss | yeah good point, i don't understand how the function i was given works but i see how to do it with reduce |
| 13:17 | justin_smith | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [3 3] [3 5]]) |
| 13:17 | clojurebot | [[1 5]] |
| 13:18 | justin_smith | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [3 3] [3 5] [7 10] [9 20] [420 666]]) |
| 13:18 | clojurebot | [[1 5] [7 20] [420 666]] |
| 13:18 | jweiss | excellent, thanks |
| 13:18 | jweiss | (inc justin_smith) |
| 13:18 | justin_smith | sadly lazybot is not with us |
| 13:28 | kwladyka | justin_smith logger factory depend on system where app is run? |
| 13:47 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges |
| 13:47 | jweiss | el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [8 8]]) |
| 13:47 | jweiss | ugh |
| 13:47 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 13:47 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [8 8]]) |
| 13:47 | clojurebot | [[1 3] [4 5] [7 8]] |
| 13:48 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [6 6]]) |
| 13:48 | clojurebot | [[1 3] [4 5] [7 6]] |
| 13:48 | justin_smith | jweiss: yeah, the reduce fails if the items are not sorted |
| 13:48 | jweiss | ah right |
| 13:48 | amoe | I would like to get pretty-printed output like 'pprint' from clojure.tools.logging and also use a format string like 'logf', and not have to explicitly pretty-print in every call, and also avoid premature evaluation of the pretty-printing depending on the log level. Any way to achieve this? |
| 13:49 | justin_smith | jweiss: you'd also see issues if any of the ranges were sorted wrong |
| 13:49 | justin_smith | or if they contained things not numbers |
| 13:49 | jweiss | justin_smith: right, i can guarantee the ranges will be correct |
| 13:50 | justin_smith | amoe: sounds like a cool logging lib you're about to implement |
| 13:50 | amoe | justin_smith: I thought so :) |
| 13:51 | amoe | I think maybe I can use this to help out https://github.com/AvisoNovate/pretty/blob/master/src/io/aviso/logging.clj |
| 13:52 | amoe | Will check into this tomorrow, I think |
| 14:00 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[3 3]] [[1 2] [4 5]]) |
| 14:00 | clojurebot | [[3 2] [4 5]] |
| 14:01 | justin_smith | jweiss: the init should be [[i i]] where i is the lower bound of the first range |
| 14:01 | justin_smith | easy enough to set up in a function, of course |
| 14:01 | jweiss | justin_smith: i see |
| 14:02 | jweiss | so i really want to conj the new range onto the sorted set, i thought the initializer was the item i'm adding |
| 14:03 | justin_smith | oh no, no, this reduce only does the combining, none of the sorting |
| 14:03 | justin_smith | I mean you could fix it to do the insertion, but that would be different |
| 14:03 | jweiss | wouldn't i just call sorted-set at the end? |
| 14:04 | justin_smith | but yeah, basically put the item into the sorted list or set of ranges, then do the reduce to combine apropriately |
| 14:04 | jweiss | i see thanks |
| 14:04 | justin_smith | and maybe put back into a sorted set again when it's done even |
| 14:05 | justin_smith | sadly you can't peek or pop sorted-sets, if you could that would simplify the whole thing |
| 14:06 | jweiss | right, will have to vec it and then turn it back to a sorted set. fortunately these lists will never be very long |
| 14:06 | justin_smith | well, the reduce can use a sorted-set |
| 14:06 | justin_smith | since they are at least seq-able |
| 14:15 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 2] [3 3] [4 5]]) |
| 14:15 | clojurebot | [[1 2] [3 3] [4 5]] |
| 14:15 | jweiss | justin_smith: i'm still missing something here |
| 14:16 | justin_smith | what's missing? |
| 14:16 | jweiss | isn't that supposed to combine the ranges into [[1 5]]? |
| 14:17 | justin_smith | ahh, then you need to chang (> start e) to (> start (inc e)) |
| 14:17 | justin_smith | I think that should do it |
| 14:17 | jweiss | ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start (inc e)) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 2] [3 3] [4 5]]) |
| 14:17 | clojurebot | [[1 5]] |
| 14:17 | jweiss | sweet |
| 14:57 | rhg136 | and remember kids, don't hold on to the head of a seq |
| 15:17 | spuz | i have a long running process that reads from a lazy sequence |
| 15:17 | spuz | is it possible to log or print whenever a new item is read from that sequence? |
| 15:17 | dysfun | no |
| 15:18 | dysfun | there are ways to achieve a similar mechanism, but there is no automatic hook for reading |
| 15:20 | spuz | I was just looking for a way to adapt my existing lazy sequence |
| 15:20 | spuz | and I think this will work: http://stackoverflow.com/questions/24597228/how-to-observe-progress-while-consuming-a-lazy-sequence |
| 15:34 | macrolicious | why does (def x 0) (let [x (inc x)] x) => 1 ? I would think it would produce => 0 |
| 15:36 | dysfun | because a local binding shadows a namespace binding |
| 15:36 | dysfun | it's why you can't write a function with a parameter 'list' and then use the 'list' function inside it without messing about |
| 15:40 | rotcev | is there a way to 'name' y and ys as a single parameter in clojure or do i just need to do (cons y ys) to join them where i need it [[x & [y & ys]]] |
| 15:41 | dysfun | [y & ys :as all-ys] |
| 15:42 | rotcev | ty dysfun |
| 15:42 | rhg135 | ,(let [[a b :as c] [1 2 3]] [a b c]) |
| 15:42 | rhg135 | where did clojurebot go |
| 15:43 | dysfun | well trust me, it works |
| 15:43 | dysfun | even if clojurebot has gone off on one |
| 15:45 | justin_smith | ,(let [[a b :as c] [1 2 3]] [a b c]) |
| 15:45 | justin_smith | clojurebot: ? |
| 15:45 | dysfun | i thought we had a backup bot for emergencies like this? |
| 15:45 | dysfun | but i cant remember what the magic incantation to invoke it is |
| 15:46 | rhg135 | clojurebot was the backup afaik |
| 15:46 | dysfun | oh. right. |
| 15:48 | macrolicious | I can be the bot for now. |
| 15:51 | macrolicious | dj broken bot in the house |
| 15:52 | rhg135 | this is tragic |
| 15:53 | macrolicious | => Emilio Lizardo. Wasn't he on TV once? |
| 16:12 | WorldsEndless | Why doesn't this work? (-> "text" #(println %)) |
| 16:14 | justin_smith | WorldsEndless: macroexpand-1 will tell you |
| 16:14 | WorldsEndless | But it doesn't.... |
| 16:14 | justin_smith | ,(macroexpand-1 '(-> "text" #(println %))) |
| 16:14 | clojurebot | (fn* "text" [p1__25#] (println p1__25#)) |
| 16:14 | justin_smith | that's what -> is doing |
| 16:14 | WorldsEndless | ? Mine gives me a Runtime Exception |
| 16:14 | WorldsEndless | oh, the quote |
| 16:14 | justin_smith | you need to quote forms in order to macroexpand |
| 16:14 | justin_smith | yeah |
| 16:15 | justin_smith | so you see, #() expands to a call to fn, then "text" becomes the first arg to fn |
| 16:15 | WorldsEndless | what's the p1_25# business? |
| 16:15 | justin_smith | ,'#(foo) |
| 16:15 | clojurebot | (fn* [] (foo)) |
| 16:15 | justin_smith | ,'#(foo %) |
| 16:15 | clojurebot | (fn* [p1__74#] (foo p1__74#)) |
| 16:16 | justin_smith | it's a random parameter name that won't clash with anything else |
| 16:16 | justin_smith | (in fact generated in a way that ensures it can't possibly clash) |
| 16:17 | WorldsEndless | so, am I reading this right that "text" becomes the name of teh function, not a parameter? |
| 16:17 | spuz | woot. i got my sudoku algorithm down from over an hour to under a second |
| 16:18 | AimHere | Was the hour one just brute force? |
| 16:18 | spuz | they are both just brute force ;) |
| 16:19 | WorldsEndless | spuz: added threading? |
| 16:19 | spuz | nope |
| 16:19 | spuz | just must simpler and smarter validity checking |
| 16:19 | butters | I want to create a GUI app and am currently deciding on clojurescript and reagent. Is there something else that would be a better experience? |
| 16:19 | spuz | before I was creating a grid (vector of vectors) and then checking if that grid was valid |
| 16:20 | spuz | now I am simply picking a cell, and checking if the values 1-9 already exist in the rows/columns/squares that intersect it |
| 16:20 | spuz | i.e. no datastructure manipulation |
| 16:21 | spuz | actually, there is a bit of vector creation to get the columns and squares but somehow it's still pretty speedy |
| 16:21 | WorldsEndless | butters: I'm rather a fan of reagent/clojurescript |
| 16:42 | spuz | oh man, actually I found a really really stupid bug in my original implementation. I mixed up the x and the y coordinates which meant it was checking the wrong cells for validity |
| 16:42 | spuz | with that fixed, the original solution is almost as fast as the new onw |
| 16:44 | spuz | i guess this is why we write tests |
| 17:10 | xemdetia | maybe |
| 17:13 | dysfun | what's the go-to for reading edn in cljs? |
| 17:15 | justin_smith | dysfun: cljs.reader/read-string |
| 17:16 | devth | best way to get a range of items in the middle of a lazy seq? repeatedly call nth? |
| 17:16 | dysfun | justin_smith: ta |
| 17:17 | amalloy | devth: drop + take? |
| 17:17 | devth | amalloy: thx. it's a line seq. i wonder if nth would be any worse? |
| 17:17 | amalloy | a lot worse, if i understand your question |
| 17:18 | devth | i don't know whether or not line-seq is indexed |
| 17:18 | amalloy | no |
| 17:18 | amalloy | and even if it were that wouldn't help |
| 17:18 | devth | got it. ty |
| 17:18 | justin_smith | lazy-seqs are never indexed |
| 17:18 | devth | i guess that makes sense |
| 17:20 | devth | so every time you call nth it's iterating from the beginning, and forcing any unrealized values along the way |
| 17:22 | justin_smith | well, "along the way" sounds open ended, but lazy seqs are always realized in order, but yeah |
| 17:24 | phorse | Is there a document anywhere that talks about project.clj? I'm getting confused about profiles vs builds and where dependencies belong and how you configure them. |
| 17:24 | justin_smith | phorse: lein help example |
| 17:25 | justin_smith | also findable via google if you search for "leiningen sample project.clj" |
| 17:25 | justin_smith | phorse: oh, sorry, it's |
| 17:25 | justin_smith | "lein help sample" |
| 17:26 | phorse | Wow, this is a gem! |
| 17:26 | phorse | This should be more widely advertised, I think. |
| 17:26 | justin_smith | phorse: there are few things lein can do without a plugin that are not documented there |
| 17:27 | phorse | I might ask some more questions once I've read this, then, because I'm deep in the plugin weeds right now - mainly with figwheel but also with others. |
| 17:28 | justin_smith | plugins can do "anything" but typically either define a dev utility task launched by lein, or transform your deps somehow |
| 17:33 | phorse | So, plugins can specify their own keys and configuration in the project.clj, right? |
| 17:34 | justin_smith | phorse: they can ingest the whole project file and it's up to them which part they use and how |
| 17:34 | justin_smith | yeah |
| 17:34 | phorse | And these can all be profile specific, as configured under the :profiles key? |
| 17:34 | justin_smith | right, or they can be top level keys in the profile |
| 17:34 | justin_smith | depends on the plugin and how it is being used |
| 17:35 | phorse | Ok, I think that makes sens. |
| 17:36 | phorse | Do you use environ? Do the keys in profiles.clj correspond with the profile ids in :profiles in project.clj? |
| 17:37 | justin_smith | yes and yes |
| 17:37 | justin_smith | well wait, now |
| 17:37 | justin_smith | yes |
| 17:37 | phorse | ok! |
| 17:38 | justin_smith | environ lets me put less essential credentials for dev time in the project file, and prod configs in the env map on the server |
| 17:38 | justin_smith | s/less essential/less vulnerable/ |
| 17:38 | justin_smith | eg. password to a server that doesn't even have access from the net |
| 17:40 | phorse | So, in the case of a database connection, if I want to use one connection while in dev, but when I build an uberjar for prod use another database connection, I could specify that in the profiles.clj |
| 17:41 | justin_smith | well, in prod you wouldn't have a profiles .clj would you? |
| 17:41 | justin_smith | in prod environ can read from an environment variable from the system |
| 17:41 | phorse | No, but doesn't it merge the maps when uberjarring? |
| 17:42 | justin_smith | phorse: none of those profiles are available at deployment unless you seek them out and parse them by hand, they are build time / dev time config |
| 17:42 | phorse | Ahh, I was confused then. |
| 17:42 | justin_smith | lein stuff is not for app config, it is for build config (but there is definitely a tendency to try to scope creep there...) |
| 17:43 | justin_smith | but fundamentally it's a build tool |
| 17:43 | justin_smith | phorse: this is actually why environ is good - it can find a value in project.clj, in a java system property, or a shell environment variable, and your code will look the same |
| 17:43 | justin_smith | it just looks until it finds one |
| 17:44 | phorse | I'll have to play around with it - that could really simplify our process |
| 17:44 | rhg135 | it's funny how short and simple the code is |
| 17:45 | justin_smith | rhg135: yeah, kind of hilarious actually - it takes more characters to explain how to use it and why it is useful than it takes to implement it |
| 17:45 | rhg135 | indeed. |
| 17:46 | rhg135 | like most of the seq functions without optimization |
| 18:35 | WorldsEndless | I'm trying to specify the separator for a data.csv output to be a tab char, but it can't receive strings. How do I specify a tab char, since \t is a plain "t"? |
| 18:39 | ToxicFrog | WorldsEndless: \tab or \u0009 |
| 18:39 | ToxicFrog | WorldsEndless: http://clojure.org/reference/reader#_literals |
| 18:39 | WorldsEndless | Ah! Thanks! |
| 19:14 | justin_smith | ,(first "\tanother method") |
| 19:14 | clojurebot | \tab |
| 19:16 | justin_smith | ,(iterate pr-str "\\") |
| 19:16 | clojurebot | ("\\" "\"\\\\\"" "\"\\\"\\\\\\\\\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\"\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" ...) |
| 19:17 | justin_smith | wow, that blows up fast |
| 19:17 | justin_smith | ,(drop 5 (iterate pr-str "\\")) |
| 19:17 | clojurebot | ("\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\... |
| 19:19 | amalloy | should be exponential, right |
| 19:19 | justin_smith | yeah, I guess so |
| 19:20 | justin_smith | ,(map count (iterate pr-str "\\")) |
| 19:20 | clojurebot | (1 4 10 22 46 ...) |
| 19:20 | justin_smith | ,(map count (drop 5 (iterate pr-str "\\"))) |
| 19:20 | clojurebot | (94 190 382 766 1534 ...) |
| 19:26 | Glenjamin | ,(map count (drop 5 (iterate pr-str "\\\""))) |
| 19:26 | clojurebot | (126 254 510 1022 2046 ...) |
| 19:27 | Glenjamin | that didn't have as much of an impact as i'd have hoped |
| 19:27 | justin_smith | powers of 2 - 2 ! |
| 19:28 | justin_smith | while mine is a little less clear |
| 19:28 | Glenjamin | exponential growth! |
| 19:28 | Glenjamin | yours is x2 + 2 |
| 19:29 | Glenjamin | oh, they both are |
| 19:29 | Glenjamin | just different start point |
| 19:31 | justin_smith | Glenjamin: yours is (2^n)-2, but I'm not seeing the formula for mine |
| 19:32 | Glenjamin | hrm, i need a repl |
| 19:32 | Glenjamin | or a spreadsheet |
| 19:35 | justin_smith | ,(def n (map count (iterate pr-str "\\"))) |
| 19:35 | clojurebot | #'sandbox/n |
| 19:35 | justin_smith | ,(map - (rest n) n) |
| 19:35 | clojurebot | (3 6 12 24 48 ...) |
| 19:35 | justin_smith | so we have a series of doubled differences |
| 19:35 | justin_smith | ,n |
| 19:35 | clojurebot | (1 4 10 22 46 ...) |
| 19:36 | Glenjamin | n1 = n0 * 2 + 2 |
| 19:36 | justin_smith | yeah, sounds right |
| 19:36 | Glenjamin | i've forgotten the maths to turn that into a function of i |
| 20:33 | hxegon | Trying to get node-host working with neovim for paraedit. Anyone know why I wouldn't have a bundle/node-host folder after :PluginInstall? |
| 20:36 | hxegon | nevermind... had a .vim folder and it was going off of that |
| 20:48 | Somelauw | In Python I would create a startup file .pythonrc that contains lines like import re, import math, etc to have them immediately available when I start a repl. How would I achieve something similar in Clojure? |
| 21:00 | rhg135 | The python repl is a lie! But AFAIK clojure does none of that magic |
| 21:01 | rhg135 | Well, it will load user.clj on the classpath |
| 21:24 | lockdown | Somelauw: create an namespace with the ns macro and put what you need there, then in the repl switch to that nswith in-ns |
| 21:34 | Somelauw | lockdown: that's what I'm doing |
| 21:52 | kenrestivo | is there any guarantee of the order that tests are run with clojure.test? |
| 21:52 | kenrestivo | reason being: i'm seeing on one machine, foo.bar-test is being run first, on another machine foo.baz-test is being run first |
| 21:56 | rhg135 | I think the runner uses a map, but I may be wrong |
| 22:01 | kenrestivo | thanks, that'd make sense. key order not guaranteed. |
| 22:59 | cortexman | teach me something about clojure |