#clojure logs

2015-11-26

00:29kenrestivologging change?
00:29kenrestivo~java logging
00:29clojurebotjava logging is clown shoes
00:33arrdemthe bojth
00:39tolstoyHow many story points for "Log when the user logs in?" Get out your cards!
00:48arrdemheh
01:42didibusI'm trying to create a map from a vector as such: [:a "a" :b "b"] would give me a {:a "a" :b "b"} is there a method for that?
01:44scottjdidibus: (apply hash-map [:a "a" ...])
01:45didibushey, hadn't thought of that
01:54douglarek, (apply hash-map [:a "a" :b "b"])
01:54clojurebot{:b "b", :a "a"}
01:55douglarek, (hash-map :a "a" :b "b")
01:55clojurebot{:b "b", :a "a"}
03:23jonathanjis there an enlive selector that matches a nonexistent element?
03:23jonathanjfor example if i want to add a child to the "head" element, if it doesn't exist then i want to create it
03:23jonathanjit's not obvious how you achieve this with enlive
03:37wafflejockif anyone can tell me how to translate this to a terminal command (or just explain the steps of what's going on) I'd be grateful http://paste.ubuntu.com/13513071/
03:37wafflejockSo far I tried but it appears my base64 encoded output is longer than the actual passwords in the DB
03:37wafflejockecho -n SECRETSALTtest | sha1sum | awk '{print $1}' | base64
03:38wafflejockbasically inherited this code and trying to figure out how I can verify the passwords using the current method but in another language
03:38opqdonutsha1sum outputs the sum as hex
03:38opqdonutpassing that to base64 sounds weird
03:38opqdonutwhat's "encode" in that snippet?
03:39opqdonutoh it's probably https://github.com/clojure/data.codec/blob/master/src/main/clojure/clojure/data/codec/base64.clj#L230
03:39wafflejockjust made a more full version of the paste and just sanitized the salt value http://paste.ubuntu.com/13513085/
03:40jonathanjugh, learning about enlive is a painful process
03:40wafflejockthink that's it yeah but I have a tough time reading clojure let me know if you need me to search for anything else int he code
03:40jonathanjthe documentation is awful
03:40opqdonutwafflejock: something like "sha1sum | awk '{print $1}' | xxd -r -p | base64" is what you want
03:41opqdonutwafflejock: you want to base64-encode the raw output of sha1, not the hexadecimal representation
03:41opqdonutwafflejock: xxd -r -p takes in hex and outputs binary
03:41wafflejockopqdonut: okay will give that a go thanks for the help
03:41opqdonutwafflejock: and even that might be wrong due to byte order issues
03:43wafflejockopqdonut: nope you got it, so this is doing a sha1sum which outputs hexadecimal then that goes to xxd that converts to binary then base64 encodes?
03:44wafflejockthanks again for the help too, wasn't likely I was going to stumble on that myself
03:44opqdonutwafflejock: yes, which is what the clojure code does too
03:44opqdonutno worries
03:52jonathanjargh
03:52jonathanji can't figure out how to select a <head> element only when it doesn't exist with enlive
04:08jonathanjthis can't possibly be the best way to insert a <link>, and a <head> if necessary, surely? https://pb.codehash.net/ec8a2b65ef2c4f83a3f82451d0d96000
04:42muhuksuppose you're doing a fold (or reduce) and what happens inside has not clear description, perhaps just massaging data structures. But you still want to call the function you pass something. I'm using folder/reducer as generic names. Do you have a better name for this thing? (suppose I define these functions within some letfn inside another fn)
07:07visofhi guys
07:15the_nona1hey
07:41ainuciao
07:41poweredhow to make function f such that : (f [:a :b :c :d :e] 1 3 4) = [:a :c :d] ?
07:41wmealinglater
07:42justin_smith,(map [:a :b :c :d :e] [1 3 4]) ; powered
07:42clojurebot(:b :d :e)
07:42justin_smithhmm...
07:43justin_smith,(map [:a :b :c :d :e] (map dec [1 3 4]))
07:43clojurebot(:a :c :d)
07:43jeayejustin_smith: How's that working?
07:43justin_smith,(map (comp [:a :b :c :d :e] dec) [1 3 4])
07:43clojurebot(:a :c :d)
07:43justin_smith,([:a :b :C :d :e] 2) ; jeaye
07:43clojurebot:C
07:44jeayejustin_smith: So vectors, when invoked, behave like nth?
07:44poweredvector as a function, cool
07:44justin_smithjeaye: just like hash maps
07:44jeayeHandy.
07:44justin_smithwell, hash maps are get as a function, and get on a vector does nth
07:44jeayeRight.
07:44justin_smithsee also keywords and symbols which become get as functions
07:45justin_smith,('foo '{foo bar baz quux})
07:45clojurebotbar
07:46justin_smithjeaye: it can also lead to really weird results...
07:46jeayeYeah, I've seen this sort. Never with vectors though.
07:46justin_smith,('foo nil :huh) - if you didn't know this was calling get
07:46clojurebot:huh
07:46justin_smithor - even weirder
07:46justin_smith,((get get get get) nil :wat)
07:46clojurebotnil
07:47justin_smith,((get get get get) "anything" :umm :wat)
07:47clojurebot:wat
07:48justin_smithget can be used as (fn [a b c] c)
07:48justin_smith(as long as a isn't ILookup)
07:58phaseNi@seen onlineperson
07:58phaseNiwhoops
07:58phaseNiwrong channel
07:59mavbozo,(instance? clojure.lang.IFn [])
07:59clojurebottrue
07:59mavbozo,(instance? clojure.lang.ILookup [])
07:59clojurebottrue
08:00mavbozo(,satisfies? clojure.lang.IFn [])
08:01mavbozo,(satisfies? clojure.lang.IFn [])
08:01clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.core$instance_QMARK___4118 invokeStatic "core.clj" 144]}]\n :trace\n [[clojure.core$instance_QMARK___4118 invokeStatic "core.clj" 144]\n [clojure.core$find_protocol_impl invokeStatic "core_deftype.clj" 511]\n [clojure.core$satisfies_QMARK_ invokeStatic "core_deftype.clj" 544]\n [clojure.core$...
08:01mavbozo,(satisfies? clojure.lang.ILookup [])
08:01clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.core$instance_QMARK___4118 invokeStatic "core.clj" 144]}]\n :trace\n [[clojure.core$instance_QMARK___4118 invokeStatic "core.clj" 144]\n [clojure.core$find_protocol_impl invokeStatic "core_deftype.clj" 511]\n [clojure.core$satisfies_QMARK_ invokeStatic "core_deftype.clj" 544]\n [clojure.core$...
08:01justin_smith,(doc satisfies?)
08:01clojurebot"([protocol x]); Returns true if x satisfies the protocol"
08:02justin_smithmavbozo: I think the issue here is that IFn and ILookup are interfaces, not protocols
08:03mavbozo,(doc instance?)
08:03clojurebot"([c x]); Evaluates x and tests if it is an instance of the class c. Returns true or false"
08:04mavbozoso, something can be a instance of a interface
08:04justin_smithyes
08:08mavbozo,(satisfies? CollReduce [])
08:09clojurebot#error {\n :cause "Unable to resolve symbol: CollReduce in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: CollReduce in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: Col...
08:36newbie75for systems created with nodejs it is a rather common pattern to hotswap JS source files on a running server. this is also possible with Clojure, but I know that most folks are very concerned about security and Clojure apps usually come as jars
08:36newbie75is there anything that holds me from hotswapping Clojure code?
08:37justin_smitheven with a jar deployment, you can still load code at runtime if you want things to work that way
08:37noncomyeah, i know, i actually did that already
08:37noncombut otherwise, why is not it so common in this community?
08:37noncomor is it?
08:39justin_smithnoncom: in terms of knowing the code works, there's a lot less to go wrong if you can be sure the exact code that was verified on staging can be run on production
08:39justin_smithand with hot-swapping there's a lot more ways for that to go wrong
08:39noncomthat seems to me so too. so the nodejs people are simply more reckless?
08:41noncomyeah, probably there's not much more to it..
08:41Glenjaminerlang is the only language i know where people really hot-swap in prod
08:41Glenjaminor maybe some lispers
08:41Glenjaminnode & JS swapping in general is generally only a dev tool
08:42justin_smithGlenjamin: but for every dev tool, you'll find some dev impatient enough to try it on production
08:43Glenjaminand so they should, as long as they let us know how it went
08:43Glenjaminerlang has been hot-swapping code in prod for decades
08:43noncombecause erlang simply does not care if anything fails
08:45justin_smithsee also php, which also cares not (for different reasons)
08:45justin_smithsounds like a joke - but the reason is the program is restarted for every request
08:46justin_smithwith mirage, the vm loads so fast you can load up a new vm instance for a request
08:46justin_smithas in, OS level vm
08:50anejava, or well, the jvm, also has had hot-swapping for ages
09:02mpenetprismatic/schema question anyone knows if it's possible to have custom err message when using "pred" (it must be generated from the result of the predicate actually)?
09:03mpenetsince it catches everything it's currently not possible (the pred throws, and is caught by "schema" internals and thrown away...)
09:07justin_smithmpenet: what about using s/check instead of s/validate?
09:07mpenetI guess I ll have to implement the Schema protocol
09:07mpenethmm didn't try but I dont' think it makes any difference, "pred" will return the same (and still swallow the exception)
09:08justin_smithmpenet: check isn't supposed to throw is it?
09:08justin_smithit just returns a true/false
09:08justin_smithmpenet: I use check when I want to report that something isn't expected, but continue anyway
09:09justin_smithmpenet: see, no throw, just an informative return value https://github.com/Prismatic/schema/blob/master/src/cljx/schema/core.cljx#L136
09:09mpenetyeah but it's not what I want, I need to get to the exception thrown by my predicate used with "pred", right not it just says "the pred foo errored" in short.
09:11mpenetThe predicate basically compiles a string input (SQL like language) into an AST, and I need to get to that error so that I can show it to the user (it has line/col info etc).
09:12mpenetanyway, I think I know how to do this, but it feels a bit convoluted, I hope I am not reinventing a wheel here
09:14justin_smithmpenet: if a function assumes that it can report a state to the top level of the code via a thrown exception, is that really a predicate though?
09:15mpenetit's not, but I can change it to return a value, I don't think it makes any difference. the pred must return non nil, rest is ignored
09:15mpenetor maybe I am not using the right fn from their api, I ll re-check
09:16justin_smithmpenet: right, sounds like what you have shouldn't be a predicate, it should be a custom validator with custom error output
09:16mpenetyeah, that's also my conclusion
10:19poweredis there a faster way to concatenate a whole bunch of strings together than : (reduce str coll) ?
10:20muhukpowered: use a StringBuffer maybe
10:24justin_smithpowered: apply str will use a StringBuilder, which is faster than what reduce will do
10:25justin_smithpowered: see here https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L517
10:32poweredapply str was more than 500 times faster than reduce str
10:33justin_smithwow, I knew it would be faster, but that's a LOT faster :)
10:33justin_smithpowered: how many items were being combined?
10:33poweredjust 11408
10:34poweredwith about 250 characters per string
10:35tdammersreduce is forced to concatenate strings one at a time; str can use a hanoi towers style algorithm
10:35tdammersthe difference is sth like O(n^2) vs O(n) or sth
10:36justin_smithtdammers: also, reduce is generating 11407 immutable objects, while apply str uses one builder
10:50zactshi clojurists
10:51zactshow does clojure compare to haskell?
10:51zactswhen would I want to use clojure, and when would I want to use Haskell?
10:51zactsClojure
10:52poweredclojure is more dynamic and practical, but I haven't used Haskell so I don't know
10:52dnolenzacts: Haskell has a very powerful type system
10:52dnolenthis is going to have a big effect on the way you write programs
10:52anethey are two different beasts
10:53dnolenin terms of prioritizing value oriented programming however they are very much the same
10:53anei agree, there's lots of common ideas
10:53dnolenzacts: other things, Clojure has a more complete full stack story as it has a good mature compile to JavaScript story
10:55zactsok
10:55zactsI know I do find Overtone interesting (the music processing system for Clojure)
10:55zactsand I think it's more mature for this purpose than anything Haskell offers afaik
10:56zactscan you metaprogram clojure via lispy () syntax tricks?
10:56zactsI know that Haskell doesn't use parenthetical syntax
10:56zactsso perhaps clojure would lend itself well to certain metaprogramming techniques better than haskell would?
10:58anebeing a lisp, that is a given
10:58anesomeone wrote a structured haskell editor mode for Emacs, but it's a bit... wobbly
10:58ARM9clojure almost has common lisp meta programming (just missing custom reader macros)
10:58anehaskell is not a lisp, it's descended from ML and Miranda
11:10justin_smithzacts: clojure does runtime metaprogramming like lisp, though it's not as common in normal clojure code. haskell supports compile time metaprogramming via template haskell, but I don't think it has runtime metaprogramming
11:11zactsI see, neat
11:12zactshow is clojurescript coming along these days?
11:12justin_smithI use it at work, it's good - the toolchain is a little awkward to set up
11:13zactsah ok nice
11:13justin_smithbut it is definitely usable, and it is very easy to migrate functionality between server and browser (since of course the backend is jvm clojure)
11:13zactsoh nice
11:13zactsso Clojure and Clojurescript interop is pretty good for most common tasks?
11:14justin_smithzacts: figwheel makes cljs development pretty amazing - you have a clojurescript repl, and the code you do in the repl immediately takes effect in the running browser
11:14zactsnice
11:14justin_smithzacts: I don't know about "interop" - eg the way you can directly use js in cljs, or directly use the jvm in clojure
11:14justin_smithbut they communicate nicely, and you can share or migrate code between them very reasily
11:49ARM9any reason why some? isn't some ?
11:49ARM9since every? is [pred coll]
11:51dnolenARM9: some isn't a predicate
11:51dnolenthat is, doesn't return boolean value
11:52phaseNiDoes anyone know a good example of using aleph to create a line based tcp connection?
11:52ARM9some does return a boolean or nil
11:52dnolen,(some #{:foo} [:foo :bar])
11:52clojurebot:foo
11:52dnolenARM9: ^
11:52ARM9you're right
12:08juanjohi
12:08juanjohow can i replace the last newline of a string by a space?
12:08juanjolike trim-newline but adding a space
12:13broquaintjuanjo: (clojure.string/replace "foo bar\n" #"\n$" " ")
12:14perplexa+
12:14juanjoif i want \n or and \r? the same that trim-newline does?
12:15broquaintUse moar regexp :) e.g #"[\n\r]+$" that could be fancier but it'll do the job
12:16juanjothanks
12:16juanjoim really new to clojure
12:46juanjoim using enlive
12:53augustlwhen I run "lein uberjar", the next clojure.tools.nameslace.repl/refresh fails with errors about namespaces it doesn't find
12:54augustlanyone know why that might be? Is it related to aot compilation maybe?
12:58justin_smithaugustl: yeah, if you move the uberjar out of the target directory, then use lein clean, then the next refresh should not get an error
12:58augustlthanks! Will try that
12:58justin_smithaugustl: I think it's the cached compilation artifacts (class files and such) made by uberjar that cause the problem
12:58justin_smithof course if you don't move the jar before running lein clean you lose the jar
13:10augustlah, right :)
13:41hlolli,(def map-with-fn {:a (fn [[x y]] (+ x y))})
13:41clojurebot#'sandbox/map-with-fn
13:41hlolli,((:a map-with-fn) [2 2])
13:41clojurebot4
13:42hlolli,(def map-with-values {:a [2 2]})
13:42clojurebot#'sandbox/map-with-values
13:42hlolliMy question is, what is a good syntactic sugared way to apply functions from one map to values of another map that share the same keyword?
13:46justin_smith,(apply apply (map :a [map-with-fn map-with-values]))
13:46clojurebot#error {\n :cause "Wrong number of args (2) passed to: sandbox/fn--26"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: sandbox/fn--26"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 36]\n [clojure.lang.AFn applyToHelper "AFn.java" 156]\n [clojure....
13:46justin_smithergh
13:47justin_smithif your fn had just been plus that would have worked
13:47hlollihmm
13:47justin_smith,(apply apply (map :a [{:a +} {:a [2 2]}]))
13:47clojurebot4
13:47hlolli,((:a map-with-fn) (:a map-with-values))
13:47clojurebot4
13:49justin_smith,((fn [[f & args]] (apply f args)) (map :a map-with-fn map-with-values))
13:49clojurebot#error {\n :cause "Wrong number of args (0) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: PersistentVector"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [clojure.lang.AFn applyToHelper "AFn.java" 152]\n [cloj...
13:49hlolliwell, Im seeing if I can make my code cleaner by storing functions in a map and call them with another map, each function of course expects different input type.
13:49justin_smith,((fn [[f & args]] (apply f args)) (map :a [map-with-fn map-with-values]))
13:49clojurebot4
15:15kenrestivoi have a trivial question: why was there a plushy cthulhu on the podium at the conj?
15:52waamaralalso, where can I get one?
16:15beakyany reason to use lsits over vectors?
16:20beakyi guess lists are more efficient when i want stack-like behavior?
16:20beakyand lists are the way to go for macros
16:20beakyand thats it?
16:40justin_s1ithbeaky: just about any clojure function that goes through a collection and generates results one by one will return a lazy-seq, which is like a list but lazy
16:41justin_s1ithbeaky: often it's a question of what you had to do with the input - and often there's no strong reason to make a vector again later
16:45beakywow my use of multimethods has gone out of hand
16:46beakyive got multimethods dispatching via multimethods and invoking other multimethods
16:46beakyhow do you limit use of multimethods
16:52elvis4526I'm pretty sure the answer is yes, but is a uberjar generated on one server can be used again on another server?
16:52elvis4526If the JRE is the same version & architecture
16:52justin_s1ithelvis4526: yes, and with very few exceptions, the OS shouldn't even matter
16:53justin_s1ithand most of the time you just need the JRE to be 1.6 or newer, no other restriction
16:53elvis4526that's even better, that's really cool thanks
16:53justin_s1ithversions don't need to match
16:53justin_s1ithoh man my nick got changed
16:54justin_smithmuch better
17:57m1dnight_Hmm, I finally decided to fix the cider warning that cider-nrepl is not installed but none of the fixes i found online work. I have added it as :repl in my profiles.clj file and even as :plugin, but I still get the warning in emacs.
17:58m1dnight_I have updated all my emacs packages and updated leiningen as well.
17:59m1dnight_(ERROR: CIDER's version (0.10.0-snapshot) does not match cider-nrepl's version (not installed). Things will break!)
18:07justin_smithm1dnight_: you need the cider-nrepl plugin (usually added through profiles.clj)
18:08justin_smithm1dnight_: can you share your profiles.clj on maybe refheap?
18:08justin_smith[/win 3
18:12m1dnight_I seem to have set it up atm.
18:12m1dnight_But now `cider-restart` is broken :<
18:12m1dnight_to the google-copter
18:14m1dnight_All those different version numbers are so confusing. Am I on 0.10 or on .2.12 or what?
18:14m1dnight_https://www.refheap.com/112118 <- profiles.clj
18:15m1dnight_lein repl gives me: REPL-y 0.3.7, nREPL 0.2.10
18:15m1dnight_but leiningen version is 2.5.3
18:16m1dnight_and according to clojars 0.10.0-snapshot is the latest.
18:20m1dnight_Or is this just a bug in the cider.el (or whatever it is)?
18:20m1dnight_Seems like it as it is an emacs-level error.
18:21justin_smithm1dnight_: leiningen and nrepl are two different projects
18:21justin_smithand cider is a third - cider requires both the others though
18:21m1dnight_okay
18:21m1dnight_so if I get it right, nrepl is a leiningen plugin?
18:21m1dnight_like lein-ancient
18:22m1dnight_so that can be upgraded seperately of all the rest.
18:22justin_smithno, cider-nrepl is a middleware for nrepl
18:22m1dnight_oh
18:22justin_smithnrepl is provided by lein, though cider might want lein to use a different version of nrepl
18:22m1dnight_But the error I get now in emacs is "CIDER requires Nrepl .2.12 (or newer) to work properly"
18:23m1dnight_I dont mind that, but what I do mind is that it really crippled my emacs. Somehow. Im guessing the newest cider package? Because C-c C-k is broken, `cider-restart` throws "wrong type argument: stringp, nil"
18:24justin_smithm1dnight_: package.el compiles el files to elc, but cider is not binary compatible between upgrades, so at the very least you have to delete all your old .elc files
18:24justin_smithyou can optionally recompile them, that helps emacs start up faster, but it's not a requirement for things to work
18:25justin_smiths/binary-compatible/api-compatible
18:27m1dnight_I have versioncontrolled my entire emacs and setup to autoinstall on boot. so I just did that.
18:27m1dnight_Reinstalling everything as we speak :p
18:28justin_smithm1dnight_: you don't need to reinstall
18:28justin_smithin fact, reinstalling won't help
18:28justin_smithyou need to delete the elc files
18:28m1dnight_well, reinstalling emacs == rm -Rf .emacs.d && git clone .emacs.d :p
18:28m1dnight_so that does help
18:29justin_smithoh, and no .elc files in your git?
18:29m1dnight_no
18:29m1dnight_okay lets see
18:29justin_smithok, so that's just a roundabout way of deleting the elc files then :P
18:29m1dnight_it is :>
18:30m1dnight_still the error, though
18:32m1dnight_Oh, but it seems like it is meant to throw those.
18:32m1dnight_so all is well.
18:32m1dnight_now back to what I wanted to do an hour ago.. :p
19:43ChristopherSI'm confused about something and am having trouble finding info online. How can I run an application, interact with it in a repl while it's running, and also make changes to the source and have them update in real time? I feel like I've seen things that say Clojure can do this, but I'm having a lot of trouble actually figuring out how.
19:51bhajanaChristopherS: do you use leiningen?
19:53rufoaanybody familiar with cljs-ajax? It seems if I perform the same ajax.core/GET request several times in a row, only the first one actually causes an XHR to occur? is there e.g. memoization or something going on?
19:58ChristopherSbhajana: yep, I use leiningen!
19:59justin_smithChristopherS: this doesn't require leiningen actually - you can start your program from inside a repl, and use (require some.ns :reload) to load the newest version of a namespace
19:59justin_smiththough some editors have bindings to automate that based on the file you are editing
20:03ChristopherSThat makes sense! So let's say I wanted to do something like add a route to an already running compojure server. How would I run the server to allow me to do that, and then how would I do that (load in the new changes without stopping the server)?
20:04justin_smithChristopherS: when you pass the routes to the function that starts your server, pass in the var so that when you change the var it sees the new value
20:04justin_smithI assume you are either setting a handler in project.clj or using run-jetty ?
20:13ChristopherSHmm should I be using run-jetty? I've been doing `lein ring server`, but I'm pretty new to this
20:15rufoathere's also http-kit which works like run-jetty
20:15justin_smithChristopherS: with lein ring server, you set the handler function in your project.clj - that is the other option I mentioned
20:16justin_smithChristopherS: so in your project.clj, where it refers to the handler, what you can do is change some-ns/handler-name to #'some-ns/handler-name and this will pass the var to the http server, so that new values are used when it is redefined
20:23kenrestivothere are no apropos vars on async-shell-command to make it stop throwing a window up every time it runs. i want it to run in the background, is there a hook i can use to bury it before it shows?
20:24kenrestivooops wron channel
20:27kenrestivowhat i was going to ask here is: is there any way to convert a nested map into a zipper? i.e. {:foo {:bar 1 :baz 2} ?
20:28kenrestivoit's hard to determine the answer to the predicates that zip/zipper requires in a nested map like that
20:29justin_smithkenrestivo: a good predicate is coll?
20:29justin_smith,(coll? [])
20:29justin_smith,(coll? {})
20:29clojurebottrue
20:29clojurebottrue
20:29justin_smithand then seq to get the individual entries, of course
20:36kenrestivohmm ok will try
21:27douglarek, (= ((fn [x y] (keep-indexed #(if (not= 0 (rem (inc %) y)) %2) x)) [1 2 3 4 5 6 7 8] 3) [1 2 4 5 7 8])
21:27clojurebottrue
21:27douglarek, (= ((fn [x y] (keep-indexed #(if (not= 0 (rem (inc %) y)) %2) x)) [1 2 3 4 5 6 7 8] 3) '(1 2 4 5 7 8))')
21:27clojurebottrue
21:27douglarek, (= ((fn [x y] (keep-indexed #(if (not= 0 (rem (inc %) y)) %2) x)) [1 2 3 4 5 6 7 8] 3) '(1 2 4 5 7 8)))
21:27clojurebottrue
21:28douglarek= can be used between seq and vec,
21:28douglarekamazing!
21:31justin_smithdouglarek: it's called structural equality
21:38douglarekjustin_smith: thanks, any detail ?
21:39justin_smithdouglarek: I rich hickey talks about his reasoning for structural equality in one of his videos, I forget which one
21:39justin_smithmy version of he summary is that when you have immutable data, often what you want to know is if the shape of two collections matches, even if the exact type and instances are different
21:40justin_smithdouglarek: for example, you expect (int 4) to be equal to (long 4) - same contents, different classes, right?
21:42douglarekyeah,
21:43douglarekso '(1 2) will share same structure with [1 2]?
21:43justin_smithdouglarek: not on a literal sense of existing in the same place in ram
21:44justin_smithbut they obviously have equal elements in each place
21:44justin_smithjust as (int 4) and (long 4) are equal, but are not referring to the same object
21:44douglarekjustin_smith: ok, i must try to understand it
21:45justin_smithdouglarek: if you have "the joy of clojure" in hardback, and I have the same edition in paperback, we still say we have the same book
21:45justin_smithbecause what's in them is the same
21:46douglarekvery vivid
21:46douglarekis it a value equality
21:47justin_smithright - they are equal by value, despite having different identity and class
21:47douglarekjustin_smith: thanks a lot, Every time you help me all about it
23:44kenrestivostuart's talk on debugging was great, but he left out the most important debugging technique:
23:45kenrestivo"copy/paste the error message into google"
23:45kenrestivoi think that's how 99% of problems are solved
23:47justin_smithkenrestivo: I swear one of these days I am going to make a website with the most common clojure error messages and what they usually mean
23:55elvis4526You should - most exceptions i encounter when using Clojure aren't terribly useful on their own. In general, would core.typed help against NullPointerException? Is it worth it?
23:57justin_smithelvis4526: it seems pretty cool, I have not tried core.typed though. I have tried prismatic/schema which is useful for runtime assertions about the shape of data in your inputs / outputs