#clojure log - Jun 16 2013

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:01 ambrosebs: Is it possible to nest prefix lists in a require?

0:01 tomjack: nope

0:01 ambrosebs: thanks

0:15 wei_: How do I get the string name of a function (not symbol)? this doesn't work (let [f filter] (name f))

0:17 tomjack: you should probably consider that impossible

0:18 the var has a .sym but that's not really public ##(.sym #'filter)

0:18 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Var is bad!

0:20 wei_: ok, thanks. just wanted a way to turn a list of functions into strings. i guess i can go the other way then, using resolve

0:22 tomjack: you can ##(.getName (class filter)) but..

0:22 lazybot: ⇒ "clojure.core$filter"

0:25 dobry-den1: off the top of the head any elegant way to merge vectors: [1 2 3] into [0 0 0 0 0] => [1 2 3 0 0]

0:28 akhudek: ##(let [a [1 2 3] b [0 0 0 0 0]] (into a (subvec b (count a))))

0:28 lazybot: ⇒ [1 2 3 0 0]

0:28 akhudek: assuming a is always smaller than b, and you want to overwrite b

0:32 dobry-den1: akhudek: nice, thanks.

0:41 amalloy: tomjack: .sym on vars is silly: if you actually have a var, rather than a function, you can use the :name in its meta

0:42 tomjack: nice, and then you can get the ns via ns-name

0:42 thanks

0:42 I thought there was no public way

1:25 samrat: how do I get cond to print something then recursively call a function: https://www.refheap.com/15823

1:30 tomjack: ~helpme

1:30 clojurebot: A bug report (or other request for help) has three parts: What you did; what you expected to happen; what happened instead. If any of those three are missing, it's awfully hard to help you.

1:33 samrat: tomjack: if that was for me, I'm doing (do (println something) (monte-carlo ...)) and I get the printed text only when I interrupt the execution

1:37 tomjack: hmm

1:38 samrat: tomjack: oh, wait. looks like it is working. I was just being impatient. Sorry

1:39 tomjack: the timeout bit doesn't make sense to me

1:41 it's supposed to test whether calculating the new score during a single step takes longer than the timeout?

1:42 I guess what seems strange is that it's not really a 'timeout' - if it took 30s and the timeout was 1s, you'll find out that it 'timed out' after 30s

1:43 samrat: tomjack: the function is supposed to dedicate only some limited time for a cipher

1:43 after that, if its not performing well, then stop it and try "improving" upon a new cipher instead.

1:44 noonian: http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#currentTimeMillis()

1:44 samrat: tomjack: I'm translating this from racket: http://blog.jverkamp.com/2013/01/25/an-optimal-alphabetizing-cipher/

1:45 tomjack: in that case, shouldn't the 'timer' val get passed down, rather than being recomputed every step?

1:45 noonian: it doesn't guaruntee to return ms, which could explain it taking longer

1:46 tomjack: the racket example seems to pass timer down

1:47 noonian: ah, that makes sense, (> (- (System/currentTimeMillis) timer) (* timeout 1000)) is not likely to be true because timer is the previous call to currentTimeMillis and the code will execute faster than your timeout

1:48 you could use a loop/recur form here and have timer be a passed in

1:49 you want timer to only be called once at the beginning since that is how you are calculating elapsed time

1:50 tomjack: well, you want what's there in every case except the :else branch of the cond

1:50 when the timer should be preserved

1:51 samrat: tomjack: ah, thanks. It is working faster now.

1:51 noonian: the recursive call is the problem, (let [timer (System/currentTimeMilis) ...) is called in every recursive step, so you are calculating elapsed time since the last recursion instead of when you called the function in your code

1:53 actually, each step is the time between the let and the cond case and not relating to the previous step

1:54 samrat: noonian: I'm passing the timer in the :else clause now.

1:56 for the other cases, I do want to reset the timer.

1:58 noonian: you can just create a new timer and pass that in instead of the old one when you call monte-carlo in those cases

1:59 just pass in the result of a new call to currentTimeMillis

2:03 samrat: noonian: hmm, would that be more "correct" than calling currentTimeMillis from the let block?

2:03 noonian: that is what the racket code does too, but I'd assumed it was the same thing

2:05 tomjack: you added a timer arg to the fn but still have a let for timer?

2:05 noonian: I dont understand this syntax, do you call their version with any arguments?

2:05 (define (solve/monte-carlo [guess (random-key)]


2:06 samrat: tomjack: now I don't

2:07 noonian: yes. you can see it called there: (solve/monte-carlo (random-key) -inf.0 timeout (current-seconds))

2:08 noonian: those are the default values.

2:08 in the (define ...), I mean

2:09 noonian: samrat: I see, in the other version it isn't using a let, they are just the default values

2:12 basically, you wan't the current ms in the first 2 cases, and you want the snapshot of the ms when the function was first called in the else case

2:13 by binding timer in the let it gets bound to the new ms every recursive call and the else case always has the most recent time

2:14 notice that he calls (solve/monte-carlo) from the repl to test the output

2:14 with no args

2:16 tomjack: that's kinda neat

2:17 guess I could make a macro for default args

2:18 murtaza52: how do I write this java code in clojure - > FileSystems.getDefault().getPath("logs", "access.log");

2:20 tomjack: (.getPath (FileSystem/getDefault) "logs" (into-array String ["access.log"]))

2:22 variadic java methods are just syntax sugar for passing an array

2:22 syntax sugar we don't have in clojure..

2:26 noonian: samrat: in r5rs scheme, I would use a named let to achieve what hes doing, in clojure that is similiar to a loop/recur form. Basically you bind your default values in the loop form and change your calls to monte-carlo to calling recur

2:29 samrat: noonian: I'm going to try that. I got a StackOverflow after running the current version for a while.

2:30 noonian: yeah, racket guarantees to optimize tail calls, whereas clojure will not so you have to use loop/recur or higher order functions

2:33 zRecursive: loop/recur ensures "tail recursive" ?

2:37 noonian: zRecursive: yep

2:38 zRecursive: not direct though

2:39 maybe it is due to JVM

2:39 noonian: I expect clojure will get automatic tail call optimization whenever java gets gets it, >= 1.8 probably

2:40 zRecursive: if so, that will be great

3:04 tomjack: ,((promise) 42)

3:04 clojurebot: #<core$promise$reify__6310@1211162: 42>

3:04 tomjack: ,(def x ((promise) 42))

3:04 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

3:04 callen: tomjack: surely you knew the def wasn't going to work?

3:04 tomjack: I thought clojurebot was wide open

3:05 result is java.lang.AbstractMethodError in clojure.lang.Compiler$InvokeExpr.eval

3:05 because promises don't implement applyTo

3:06 SNBarnett: Hi, why does (= java.lang.String (class "a")) return true but (case (class "a") java.lang.String true nil) return nil?

3:08 amalloy: tomjack: promises aren't "publicly" IFn anyway, so...?

3:09 tomjack: oh, I didn't know the IFn part was supposed to be hidden. but my point was really more: warning, this is what can happen when you don't implement applyTo

3:09 &(case 'java.lang.String java.lang.String true)

3:09 lazybot: ⇒ true

3:20 SNBarnett: tomjack: cheers, any idea why the other form doesn't work?

3:21 tomjack: because the String class is not the symbol 'java.lang.String

3:21 you can't match a class with case

3:23 SNBarnett: tomjack: ah ok, thanks.

3:23 noonian: ,(if java.lang.String true false)

3:23 clojurebot: true

3:24 tomjack: "All manner of constant expressions are acceptable in case, including numbers, strings, symbols, keywords, and (Clojure) composites thereof."

3:24 noonian: you're using case like a cond

3:26 ,(case java.lang.String java.lang.String true "something" "a string" "default")

3:26 clojurebot: "default"

3:26 noonian: hmm

3:26 tomjack: interesting https://www.refheap.com/f1c14b6df75de1e49da485e92

3:27 SNBarnett: noonian: was trying to follow this example http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure

3:28 noonian: SNBarnett: yeah, I was wrong

3:28 ,(case (class "a") java.lang.String true false)

3:28 clojurebot: false

3:30 tomjack: that's just wrong

3:30 ambrosebs must not have tested it? :)

3:30 hiredman: java.lang.String is read is a symbol and eval'ed as a class

3:30 ,(case 'java.lang.String java.lang.String true false)

3:30 clojurebot: true

3:30 hiredman: case treats each possiblity has a constant (no eval)

3:32 amalloy: tomjack: using #class to sneak eval into case will probably break if you AOT

3:32 noonian: yeah, case's doc states that test-constants must be compile time literals

3:33 and it looks like user written classes aren't compile time constants

3:38 tomjack: amalloy: doesn't look like it

3:39 well, at least, https://www.refheap.com/5bdb722fbaa0fa22dbfa970f9 seems to work

3:41 amalloy: tomjack: well, if you delete the .clj file and just run from the .class, i think it fails because the code generated by case assumes hashcodes are consistent

3:43 tomjack: I ran with java -jar on an uberjar

3:43 but I think I see how it's evil

3:45 hiredman: the java.lang.String class always seems to have the same hashcode (must be a class loading order thing) but, for example, clojure.lang.RT doesn't

3:45 tomjack: ah, interesting

3:45 hiredman: across jvm runs it has different hashcodes

3:46 tomjack: hmm, I'm always getting 1268575826

3:46 amalloy: hiredman: lazybot and clojurebot return different hash codes for String right now

3:46 hiredman: here String is always 1051225362

3:46 tomjack: here String is 1145768891..

3:46 hiredman: amalloy: yeah, I bet it is a lod order thing, so different jvm versions might be different

3:46 tomjack: so yeah, really evil :)

3:46 hiredman: load

3:48 so for a given jvm the hashcode is always the same because the initialization of the jvm happens in a deterministic way, and the string String class is always loaded at the same time, but across jvm versions class deps change ect, so the initialization order may change

3:48 tomjack: &(.hashCode (java.net.URI. "/"))

3:48 lazybot: ⇒ 47

3:49 tomjack: &(.hashCode #inst "2012")

3:49 lazybot: ⇒ -1768894156

3:49 tomjack: cool

3:51 &(.hashCode (java.util.UUID/fromString "b3da40ec-cbe2-4637-a0fa-de66b1293896"))

3:51 lazybot: ⇒ 1777066027

3:55 SNBarnett: So the best way to get around this is to just use cond?

3:57 tomjack: is it bad to close over an access to an :unsynchronized-mutable?

3:58 I guess at best I'll get the old value

3:59 yep

4:05 amalloy: SNBarnett: or one of the many features intended for use in class-based polymorphism

4:06 interfaces, protocols, multimethods...

4:09 SNBarnett: amalloy: thanks for the suggestions

4:52 john2x: i'm having a hard time understanding loop and recur.. so recur's arguments need to match let's bindings?

4:53 *loop's bindings

4:58 noonian: yes, you can think of loops bindings as default values

5:00 er, initial values

5:05 you can use recur without loop to that will call the actual function

5:10 john2x: these are at least conceptually the same, https://gist.github.com/lore17/7ea7af0218894405fab2

5:20 tomjack: if we require an implementation of equality for our values, maybe "you can put it in a map" is a good description

5:20 the example makes the "in practice, they're not values" for fns make sense to me

5:51 mindbender1: Is it possible to tell cljsc where to look for macros, say via options?

5:56 tomjack: mindbender1: I have this hack for that https://www.refheap.com/6540b2904cb1b419c22dcda05

6:19 mindbender1: tomjack: I saw your hack. Good. But I was looking for a way to do it while in the repl. Say tell it to look here for macros. Because I'm passing in a bunch of files which it is compiling correctly but halts because the path where cljs-macros is located is not on classpath(deliberately for partability reasons). So I want it to look 'here'(a specific path) for the macros.

6:20 tomjack: dunno what you're talking about, I thought cljsc was a shell script

6:21 mindbender1: *portability

6:22 I was referring to cljs.compiler

6:27 berdario: Hi, about the error I stumbled upon yesterday

6:27 I just wrote a message to the clojurescript mailing list

6:28 I reproduced it with my clone of the clojurescript repo, and with the repl sample

6:28 https://github.com/clojure/clojurescript/tree/master/samples/repl

6:28 the message hasn't been approved yet

6:29 but if there's anyone who has experience with cljs, that can help me understand what is going wrong, I'd appreciate

6:33 tomjack: mindbender1: ah.. macros are just require'd with require iirc, so no

6:45 greywolve: is there any way to restart the reload the brepl namespaces without having to completely restart the repl everytime you make code changes?

6:46 Eucoo: hi

6:46 mindbender1: greywolve: (require *ns* :reload)

6:47 berdario: mindbender1: are you using clojurescript with a repl in the browser?

6:47 Eucoo: how do you guys manage long let bindings declaration? is it some kind of bad pattern?

6:47 greywolve: thanks ill try that ;p

6:47 mindbender1: berdario: yep

6:48 berdario: mindbender1: do you know of any common roadblocks? I spent hours trying to get it running, but nothing works

6:48 the only instance in which I got the repl working, is with the lein-cljsbuild advanced sample... but that needs a ring server

6:48 greywolve: berdario

6:48 whats the problem?

6:49 mindbender1: I don't like and I don't use lein-cljsbuild workflow

6:49 greywolve: the brepl is pretty simple to setup

6:49 berdario: the repl doesn't get connected

6:49 it just stays there... after I opened the page with the code for the connection

6:49 greywolve: https://github.com/magomimmo/modern-cljs

6:49 berdario: I try some simple forms... like (+ 1 1) but the repl is completely unresponsive

6:49 greywolve: try following those tutorials

6:50 mindbender1: berdario: you have to refresh the page

6:50 greywolve: hmm did you add the cljs code to connect to the brepl?

6:50 mindbender1: so that it hooks into the hung repl

6:50 greywolve: mindbender1: whats your cljs workflow? i'm still trying to find a good one

6:50 berdario: mindbender1: I tried to refresh a dozen times

6:50 greywolve: that seems to require ring

6:51 greywolve: no it doesn't

6:51 you can use any web server

6:51 berdario: oh, good

6:51 mindbender1: cljs1 or more recently pedestal

6:51 greywolve: but ring is convenient if you are also building a server side api for your app

6:52 i want to try out pedastal

6:52 mindbender1: do you use the brepl at all?

6:53 berdario you can quickly test using python SimpleHTTPServer aswell

6:53 berdario: yes, I usually use python3's http.server

6:53 btw, I just noticed right now that I have a server somewhere stuck on port 8000

6:54 mindbender1: greywolve: more specifically I try to work with cemerick.piggieback

6:54 berdario: I thought I killed all of the server I opened previously... and I have no other shell open

6:54 greywolve: make sure your cljs code that connects to the repl, and the brepl server are the same port ;p

6:54 that could be the prob then

6:54 mindbender1: it provide a repl-env that plays nicely with nrepl

6:54 greywolve: mindbender1: i'm using that atm, but :cljs/quit doesn't work for me lol

6:55 mindbender1: for :cljs/quit to work you have to be able to have evaluated an expression

6:56 if you're were using nrepl.el with emacs then you could send an interupt to the process

6:57 I'm not familiar with sending an interrupt outside emacs nrepl

6:57 berdario: greywolve: I always used port 9000, that shouldn't be it... I'm compiling the cljs now btw

6:59 mindbender1: In most cases you just have to keep pushing and tweaking to really be familiar with things

6:59 greywolve: mindbender1: ah ok, but you can just reload the namespaces and that works for you?

6:59 berdario: greywolve: the modern-cljs tutorial doesn't work

6:59 same problem as before

7:00 greywolve: weird! im doing it right now and its working fine ;p

7:00 mindbender1: In brepl, you use load-file or load-namespace

7:01 berdario: it's really frustrating... I hoped to use cljs instead of resorting to the same old javascript

7:01 but I can't see a way forward, if even the tutorials aren't working

7:01 greywolve: so if i have a namespace like mod.login in a file login.cljs, and i make changes to it, can i just go (load-namespace 'mod.login) without having to restart the brepl?

7:01 mindbender1: yes

7:01 greywolve: berdario: what os are you on?

7:02 nice... i wish these things were better documented ;p

7:02 berdario: ubuntu 13.04

7:02 finishingmove: I've got this using Compojure: (def app (handler/site app-routes)) . How would I add (handler/api api-routes) to that?

7:02 mindbender1: load-namespace is documented somewhere

7:02 greywolve: berdario: push your code to git a repo and ill try it on my side

7:02 finishingmove: do i need to do a (def api ...) ?

7:03 greywolve: yeah "somewhere"

7:03 lol

7:03 berdario: greywolve: I'm just using a clone of modern-cljs I just got... no changes whatsoever

7:03 greywolve: oh dear

7:03 then it should definitely work

7:03 mindbender1: https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure

7:03 greywolve: thanks

7:03 ;)

7:04 does (js/alert "hello") also hang?

7:04 berdario: greywolve: yes

7:05 mindbender1: https://github.com/clojure/clojurescript/wiki/The-REPL-and-Evaluation-Environments

7:05 greywolve: also did you check the network tab in dev tools (in chrome at least) to see if its connecting to the brepl?

7:05 berdario: greywolve: uhm, I'm not using brepl, I'm just using the cljsbuild repl

7:06 greywolve: oh

7:06 then thats even stranger, that should be a snap to setup ;p

7:07 berdario: greywolve: there're 2 requests

7:07 one gets back a 200

7:07 the other is pending

7:07 the pending one, gets back 13 byte

7:07 bytes

7:07 gosh, now it works

7:08 greywolve: lol nice

7:11 berdario: greywolve: well, thank you... I tried just now in my project, and I've been able to get it working there

7:12 greywolve: berdario: i didn't do much to help ;p haha glad its working though

7:12 berdario: I really have no clue what could've been going wrong... I literally tried dozen times with all kind of samples... at the beginning I wasn't using a server to serve the html

7:13 so surely that could've been the problem at first... but with the latest attempts, I used it, and so there was something else amiss

7:13 finishingmove: I want to be able to send / receive JSON with Compojure. Do I need some external libraries? And what would you recommend

7:14 berdario: greywolve: btw, I fear that this might not be enough for me... what I was trying to do was a clojurescript local application with node-webkit (the same technology used by lighttable)

7:14 there's a node-webkit-cljs project... but to debug the functions made available by node-webkit, I'd need to run it through it

7:15 and obviously, if I run the repl through node.js, there's no way I can see to access the dom

7:16 so, I'd need to run the repl without having a separate server, other than the cljsbuild repl listener

7:16 do you know of any way to get what I want?

7:16 greywolve: whats your overall goal ?

7:16 i mean just in terms of what you are trying to build

7:18 berdario: some simple application to load html/css, ideally at the end it should be used for the layout of different kind of documents, not just web pages

7:18 I thought that using node-webkit was the easiest way to go, since this way I could directly have the content rendere in the page (maybe as an iframe?)

7:19 and yet, I could access the disk, save data locally and, etc.etc.

7:19 right now I'm just experimenting around... nothing serious... it's sunday after all :)

7:20 (obviously, I can access the disk from a plain web page application, localstorage, indexeddb and such... but I was thinking of doing that latter)

7:21 greywolve: wow this the first time ive seen node-webkit, looks awesome, but yeah using it from clojurescript i have no idea, its already hard enough just using clojurescript normally (for me anyway cause i'm new to it ) ;p

7:21 berdario: yeah, the same... :)

7:22 btw, it's kinda hard to use node-webkit with plain javascript imho

7:22 for example, I started to work with some samples, and apparently the behavior of node-webkit when parsing the package.json changed

7:22 greywolve: https://github.com/Flamefork/node-webkit-cljs looks like your best bet like you said, maybe you can help add some of the other missing api pieces

7:22 plain js is always hard i guess haha ;p

7:23 berdario: moreover, you can't use nodejs's require freely... since many libraries try to access the document and window object upon startup.... but when inside nodejs's require, those aren't available...

7:24 so if I'd have used plain javascript, I'd have to hardcode the path to the js libraries in the html (like I've seen done in the various example)... something I looked to avoid by using clojurescript :D

7:24 greywolve: agreed, unfortunately, to contribute to that I'd need to understand clearly how to access the objects that node-webkit makes avaialble

7:25 greywolve: perhaps that would be good experience for you ;)

7:25 berdario: (aside from compiling some simple cljs files, this is the first time for me that I used clojurescript) so, I hoped to get a repl working working inside that

7:26 I wonder if flamefork avoided the repl, and just kept compiling/running to try to see if it works

7:26 greywolve: is lighttable being developed in plain js or clojurescript?

7:26 berdario: greywolve: clojurescript

7:26 unfortunately, it isn't open source (not yet at least) afaik

7:26 greywolve: maybe ask chris what he thinks then ;p

7:27 yeah the repl really speeds things up, compiling everytime is quite slow

7:28 berdario: greywolve: on top of that, you have to package the things inside a .zip to run them in node-webkit

7:28 greywolve: geez

7:28 berdario: I was planning to add that command to the repl-launch command as soon as I'd got it working

7:28 greywolve: i like a very rapid feedback cycle

7:38 murtaza52: tomjack: how do I write this one - java.nio.file.Paths.get("myPath", "subPathA", "subPathB"); - in clojure

7:38 (.get java.nio.file.Paths "myPath" "subPathA" "subPathB") - this didnt work

7:44 berdario: murtaza52: this works, but is ugly as hell

7:44 (java.nio.file.Paths/get "myPath" (into-array java.lang.String '("subPathA" "subPathB")))

7:44 you have to use /get, because it's a static method

7:45 the into-array, is because the rest of the arguments is a vararg

7:45 pisketti: berdario: Do you explicitly have to use array when the java method takes varargs?

7:46 berdario: pisketti: it's the first time I stumbled upon a vararg :) I don't know if there's a cleaner way

7:46 maybe there's a macro somewhere for it... but at the end, under the hood I think there's no way around using an array

7:46 murtaza52: berdario: why leave the first arg out, and only apply into-array to the other two args

7:46 pisketti: How about just calling them as varargs like you would in Java or in clojure ( & xs)

7:47 It doesn't work out of the box like that?

7:47 berdario: murtaza52: this is the java signature: get(String first, String... more)

7:47 the first argument is required

7:48 this is relevant... but I haven't finished to read it yet https://groups.google.com/forum/?fromgroups#!topic/clojure/ZLIKz3bitoc

7:53 murtaza52: FileSystems.getDefault().getPath("logs", "access.log"); - how do I translate this to clojure ?

8:11 pisketti: murtaza52: without testing it, I'd say (.getPath (FileSystems/getDefault) "logs" "accessLog")

8:14 murtaza52: that works thanks

8:16 pisketti: np

8:28 Okasu: ,'#=(apply * '#=(range 2 10))

8:28 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

8:28 Okasu: Meh.

8:28 &'#=(apply * '#=(range 2 10))

8:28 lazybot: java.lang.IllegalStateException: clojure.lang.LispReader$ReaderException: EvalReader not allowed when *read-eval* is false.

11:51 uris77: what is the right way to use apply with reverse?

11:51 piranha: cemerick: friend doesn't do any salting for passwords, right? Or bcrypt does that by itself?

11:51 uris77: for example (apply reverse [5 4 3 2 1])

11:51 cemerick: piranha: bcrypt salts automatically

11:51 uris77: that doesn't work. Im a newbie :)

11:51 piranha: cemerick: ok, thanks

11:52 hyPiRion: uris77: It's just ##(reverse [5 4 3 2 1])

11:52 lazybot: ⇒ (1 2 3 4 5)

11:53 hyPiRion: reverse takes a single sequence as input

11:53 kmicu: ## *clojure-version*

11:53 hyPiRion: &*clojure-version* ;-)

11:53 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

11:53 hyPiRion: ,*clojure-version*

11:54 clojurebot: {:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"}

11:54 hyPiRion: oh, clojurebot is bleeding edge

11:54 kmicu: very bleeding

11:54 Mingqi: I'm trying to write a web application use clojure. anybody can suggest a configuration solution in clojure?

11:55 borkdude: Mingqi take a look at Luminus or Pedestal

11:55 hyPiRion: Mingqi: http://pedestal.io/ is a tool set/configuration for web apps

11:56 kmicu: If you are not familiar with clojure stack, pedestal is not a good choice IMHO

11:56 Mingqi: Michiel, thank you. I'm looking...

11:57 borkdude: Mingqi you looked up my first name? ;)

11:57 Mingqi: Yes, I got your full name

11:58 hyPiRion: Oh, you're working for NSA?

11:58 * hyPiRion shows himself out.

11:58 borkdude: haha

11:59 Mingqi: it's very simple. Just click your name and freenode will show your information: Michiel Borkent, London, UK ...etc

11:59 by the way, i'm using http://webchat.freenode.net/

11:59 borkdude: I'm glad NSA thinks I'm in Londen

11:59 London

12:00 hyPiRion: borkdude: aren't there any Dutch freenode servers?

12:00 I vaguely recall you're from there

12:00 Mingqi: which client you are using on Mac, I download a colloquy but doesn't work

12:01 borkdude: hyPiRion I don't think so, but I actually don't care which server I'm using

12:01 Mingqi Textual

12:01 pdk: iirc there's a mac port of irssi

12:02 borkdude: Mingqi if you build it yourself using Xcode it is free

12:02 pdk: i never got why xchat does that too

12:02 hyPiRion: fair enough. For some strange reason I thought latency would be critical for IRC just now.

12:02 pdk: they're like "pay for the official build but you can still compile the same thing for free!"

12:03 then everyone just turns around and uses 3rd party enhanced builds for free anyway

12:04 borkdude: Mingqi I used to use erc in emacs also

12:05 one thing that annoys me about Textual: it autojoins channels I visited before, I wonder if I can turn that off

12:05 I know how to turn off the autojoin, but it should not do it by default

12:08 Mingqi: oh, damn! Textual also doesn't work. I believe it's China government block freenode.

12:10 borkdude: Mingqi hmm. or you are behind some firewall that blocks the irc port?

12:10 Mingqi if the china government would block freenode, then why don't they block webchat as well

12:11 Mingqi: Yes, It's a BIG firewall built by China government, we call it GFW, great fire wall.

12:11 borkdude: Mingqi funny

12:12 Mingqi: http://en.wikipedia.org/wiki/Great_Firewall_of_China

12:16 uris77: i wanted to write a function that takes 2 functions and some args, and applies those 2 functions to the args. That is why I was asking about (apply reverse [5 4 3 2 1])

12:18 borkdude: uris77 is the result of f1 an arg to f2, or do you want to apply f1 and f1 to the same args?

12:19 uris77: f2 should be applied to the result of (f1 [args])

12:19 i thought i could just use apply with any function to do this, but hit a wall with functions like reverse and rest

12:19 borkdude: uris77 use comp

12:20 uris77: oh, nice

12:20 thanks alot

12:20 borkdude: uris77 or simply write (f2 (f1 [args]))

12:27 Mingqi: Hi Michiel, both of Luminus and Pedestal you suggest are web framework. but I need a library to resolve my configuration problem: support structure data, like list, dictionary, just like json, but I also want to difference configuration for dev and production environment

12:28 do you other suggestions for that?

12:31 clj_newb: Hi, I've been looking for a while but I haven't found anything regarding clojure debugging with vim at all. Is it even possible? Can the current alpha release of light table debug?

12:33 kmicu: @google clojure debugger

12:34 hyPiRion: $google clojure debugger

12:34 lazybot: [Debugging in Clojure? - Stack Overflow] http://stackoverflow.com/questions/2352020/debugging-in-clojure

12:35 kmicu: So many prefixes in so many channels.

12:36 clj_newb: sorry I should have express my question better. I meant more like setting breakpoints and the like, specifically for vim, but thanks anyway

12:38 kmicu: $google clojure debugging vim

12:38 lazybot: [dgrnbrg/vim-redl · GitHub] https://github.com/dgrnbrg/vim-redl

12:39 kmicu: "This plugin integrates Vim with a running Clojure JVM. It provides a repl that supports breakpoints..."

12:40 clj_newb: I saw that, thanks kmicu, I guess it is the only option, but it forces me to change my vim clojure setup. Well thanks kmicu

12:42 * kmicu have no idea how good is nrepl + ritz + vim

12:44 cemerick: OK, what is the incantation to get an external javascript library folded into the gclosure compilation output? I've tried :libs, :foreign-libs, and even :externs just for laughs, with no results.

12:45 the lib in question is http://davidbau.com/encode/seedrandom.js FWIW

14:11 Denommus: Hi

14:20 seancorfield: Hi Denommus

14:20 (just to prove there are some live folks here on a quiet sunday)

14:21 Denommus: Today I may start writing about COA

14:55 seancorfield: COA?

15:05 kmicu: Probably CoA - clj on android

15:08 jouiswalker: is there a way to specify that lein should just grab the latest release of a library?

15:11 kmicu: LATEST

15:12 maio`: my first clojar https://clojars.org/fun_migrations :)

15:12 what's the "promote" button @ clojars?

15:13 kmicu: jouiswalker: but you should read http://nelsonmorris.net/2012/07/31/do-not-use-version-ranges-in-project-clj.html

15:14 jouiswalker: kmicu: thats really helpful. thanks!

15:18 borkdude: I read that in C you can mark a function 'pure' so the compiler can optimize. Is there any such thing in Clojure?

15:18 (I guess not)

15:20 xeqi: maio`: clojars doesn't require signed artifacts, but they are prefered. there is some work being done to make a repository of only signed artifacts. "promote" is currently a way to say make my jar available in the new repo

15:21 it should become automatic eventually

15:21 amalloy: no, but clojure's functions are much more powerful. if you want to avoid repeated calls to a function, just memoize it

15:21 jouiswalker: borkdude: I didnt know you could do that in c o_o

15:21 borkdude: amalloy I guess in Haskell such a thing is going on a lot, without having to memoize anything

15:22 amalloy: jouiswalker: it's not in the standard, it's an extension that some compilers add

15:22 well, in haskell every function is pure, so the hinting is implicit

15:25 maio`: xeqi: ok thanks

15:32 jouiswalker: wow, this is really cool:

15:32 http://nakkaya.com/2011/01/04/duck-hunt-experiment/

16:37 tomjack: consider a type where equality is decidable, but may take arbitrarily long to compute, regardless of the input 'size'. value or not? :)

16:38 seems we want not just decidable equality but efficient equality..

16:39 gfredericks: are we talking about comparing functions again?

16:40 tomjack: not functions, since that's undecidable. my point is that 'decidable equality' may not be enough

16:40 gfredericks: because it might be unbounded

16:41 I can imagine regexes being tough to compare :)

16:41 tomjack: that makes me wonder if there is an Eq instance for (->) t with some finiteness constraint on t

16:42 apparently it's decidable for true regular expressions?

16:42 gfredericks: right

16:42 always have to distinguish CS regexes from real-world regexes :)

16:43 * gfredericks suggests the term "Proper Regular Expression"

16:45 gfredericks: the most remarkable thing I know about PRE's is that you can efficiently index all matching strings

16:45 laliluna: 2

16:46 tomjack: presumably the logarithm of the regular expression type is a character?

16:46 * gfredericks has never taken the logarithm of a type

16:55 hyPiRion: gfredericks: what do you mean by efficiently? :p

16:55 in terms of space or storage?

16:57 gfredericks: you could efficiently in every practical sense implement something such as (nth #"foo(bar|baz{3,4})*bar" 999999999999999)

16:57 assuming the regex there is a PRE

16:58 * gfredericks fumbles through his github

16:58 hyPiRion: gfredericks: isn't that multibranching?

16:58 gfredericks: hyPiRion: I have no idea what that means

16:58 hyPiRion: gfredericks: there are multiple solutions to that answer

16:58 do you want one or all of them?

16:59 gfredericks: no there's one answer

16:59 hyPiRion: huh. Then I'm not sure if I get what that indexing is.

16:59 gfredericks: I'm saying there's an ordering of all the distinct matches to that regex that is also efficiently indexable both ways

16:59 the nth given up there can be implemented as well as its inverse

16:59 hyPiRion: ah alright

17:00 yeah, that makes sense

17:00 gfredericks: relatedly, given a regex I can return an (infinite?) lazy seq of all distinct matches

17:00 https://github.com/fredericksgary/ranguages/blob/master/src/ranguages/counting.clj#L104

17:01 hyPiRion: gfredericks: now do it with shared structure

17:01 gfredericks: haha

17:01 hyPiRion: gfredericks: oh right, you're a core.logic guy. How come (run* [q] (== q #{1 2})) completely blows my stack?

17:02 gfredericks: I don't think it oughta

17:02 unless sets are forbidden

17:02 they must be :)

17:03 I don't know that they're explicitely supported

17:03 hyPiRion: wahh, there goes my idea

17:03 Oh well

17:03 gfredericks: haha

17:03 my expectation is that there's no obvious way to naively support them fully, same with maps

17:04 hyPiRion: Oh right

17:04 gfredericks: unbound tails and all that

17:04 hyPiRion: (fresh [x y] #{x y})

17:04 gfredericks: I think there's been work on maps but haven't been following it

17:04 hyPiRion: Well

17:05 that implies (!= x y)

17:05 gfredericks: oh that's an interesting point as well

17:05 tomjack: CLP(Set) isn't implemented

17:05 sets no longer implement even IWalkTerm

17:06 hyPiRion: I was struggling since I didn't understand why (membero x some-set-here) crashed everything, and then I converted it into a vec it worked just fine

17:07 Interesting that different data structures actually gives an implicit constraint on the lvars

17:07 gfredericks: membero is terrible for perf

17:07 at least if your collection is ground

17:08 hyPiRion: gfredericks: so e.g. (membero x [1 2 3]) is horrible perf-wise?

17:08 gfredericks: exactly

17:08 that by itself might be okay

17:09 but e.g., if you did that to 20 vars you'd be out of memory

17:09 hyPiRion: oh no

17:09 that totally destroys my idea

17:09 gfredericks: don't worry! there is a solution!

17:10 hyPiRion: oh, what is this solution you're talking about?

17:10 gfredericks: https://www.refheap.com/15830

17:11 tomjack: sweet

17:11 I have a ground coll that is the signature of my language and memberos all over the place

17:12 hyPiRion: oh great, now I'll happily use that because I have no idea why membero is slow and why that is faster

17:12 gfredericks: membero is slow because it uses conde

17:12 which does interleaving

17:12 hyPiRion: oh right, I see

17:12 gfredericks: which is not necessary when the clauses are short and finite, like unifying with a ground value

17:12 so e.g., if you (membero x1 [1 2]) ... (membero x20 [1 2])

17:12 then you effectively have a binary tree of depth 20

17:13 and conde will helpfully search the whole thing in parallel

17:13 before finding a single solution

17:13 futile: happy father's day to anyone relevant

17:13 gfredericks: happy belated fathers day to anyone relevant in the eastern hemisphere

17:15 hyPiRion: Humm. So in https://www.refheap.com/15831, would my horribly-named `compatiblo` be slow?

17:15 And yeah, it's not efficient compared to another solution I'm keen on writing right after this

17:15 tomjack: you can't use == on sets

17:15 I think?

17:15 hyPiRion: tomjack: Well, it works perfectly fine over here!

17:16 gfredericks: well if t1 and t2 are both non-ground...

17:16 hyPiRion: All the sets are ground anyway, so could I replace it with something else?

17:16 gfredericks: yeah, they're both non-ground

17:16 gfredericks: hyPiRion: yeah if p1 and p2 are sets and not logic vars you could (if ... s# u#) or something like that

17:17 hyPiRion: Oh, okay, I'll have to read up on that I suppose

17:17 gfredericks: I'm confusing myself trying to reason about when it's okay to skip conde

17:17 so I'm going to stop

17:17 futile: so apparently The Incredible Machine relied heavily on the CPU's own speed

17:17 so, playing it now in dosbox, it runs ridiculously too quick

17:18 oh wait that's not related to Clojure

17:18 sorry

17:19 tomjack: oh, == will just fallback to = if it doesn't know how to deal with something?

17:19 hyPiRion: gfredericks: well, I'll read up on it anyway

17:20 gfredericks: hyPiRion: if you watch the youtube of the last hangout it'll all get gone over in detail :)

17:20 hyPiRion: Oh, awesome

17:21 tomjack: ah yes https://www.refheap.com/86578ea53616bd29063e8a914

17:22 gfredericks: tomjack: huh weird; so (fresh [x] (== x (Object.))) always fails?

17:22 or wait I mean the other way around?

17:22 time to test it

17:23 hrm no both succeed

17:23 that I don't understand

17:23 oh unless that code you pasted doesn't run if either arg to == is an lvar

17:24 tomjack: seems relevant https://www.refheap.com/90aa9118ff169b3ebfdf257ac

17:24 it will do the lvar unify-terms instead I guess, which causes a substitution?

17:24 gfredericks: right

17:31 hyPiRion: gfredericks: so what could I replace (== #{} ground-set) with? I naively tried (= ...), but it seems like it want a fn

17:31 (And I'm a bit tired to dig more into core.logic right now so I just lazily ask you)

17:33 gfredericks: hyPiRion: (if (= #{} ground-set) s# u#)?

17:33 tomjack: why replace it?

17:33 gfredericks: good point I guess tomjack just proved it should work

17:33 if by "ground set" you mean "an actual set" rather than an lvar with a value

17:34 tomjack: should work even with an lvar, yes?

17:34 hyPiRion: gfredericks: a set with ground values

17:34 well yeah

17:35 works for me!

17:35 gfredericks: then I won't bother figuring out what you meant :)

17:35 tomjack: hmm, wait, what?

17:35 https://www.refheap.com/5550cbeb9859316c1819ca13b

17:36 hyPiRion: tomjack: oh yeah, I did that too

17:36 dnolen said in #minikanren that he removed support for sets completely

17:36 tomjack: this was why I thought "you can't use == on sets"

17:36 but I don't understand now why it doesn't work

17:36 gfredericks: I'm guessing you can (== aset anotherset) but not (== an-lvar a-set)

17:37 hyPiRion: tomjack: well, I'm not doing any unification at all, I'm essentially comparing two sets

17:37 tomjack: gfredericks: that appears to be the case

17:37 hyPiRion: two sets without any lvars in them

17:37 gfredericks: should be fine then

17:37 it's just regular =

17:38 * hyPiRion accepts this as a fact.

17:38 tomjack: I see, sets are tree terms

17:38 and walk is identity on sets

17:38 so walk* blows the stack..

17:39 wonder if there should be a check there whether walk actually did anything

17:40 no, I guess we'd just need an IWalkTerm for sets

17:40 gfredericks: tree term is some flag protocol?

17:40 tomjack: yes, but also all coll? are tree terms

17:41 gfredericks: ah ha

17:45 tomjack: please someone do CLP(Set) :)

17:49 gfredericks: if I attempted anything it'd probably be CLP(Q)

17:50 but I'm a little worried about that drop-one function

17:50 weavejester: Just released Ring 1.2.0-RC1

17:51 * gfredericks mutters "Honest sir, I ain't been jestin' no weaves" to himself

17:51 weavejester: Next Ring version is going to have a much shorter development cycle :/

17:51 gfredericks: 3

17:51 akhudek: weavejester: why the :/ ?

17:51 weavejester: akhudek: Because I just checked when I released Ring 1.1.0 :)

17:53 cemerick: weavejester: nice, looking forward to rolling with it. Might just peg friend 0.2.0 against ring 1.2.0 and save everyone a bunch of trouble. :-)

17:55 weavejester: cemerick: Doesn't Friend already depend on the 1.2.0 beta?

18:05 hyPiRion: weavejester: you've been on fire recently, props to that

18:20 akhudek: hmm, https://clojars.org/zip-visit what went wrong?

18:22 well, lein deps :verify works

18:29 tomjack: hmm, should IEnforceableConstraint not be empty/

18:29 once we've no longer "hard coded force-ans"

18:39 seems like the ckanren way is to run all defined enforce fns

18:43 direct translation would seem to be an atom in clojure.core.logic with a map of enforce-fns, and other namespaces swap! their enforce-fn in

18:43 which seems.. weird

18:46 ianeslick: Anyone aware of a Clojure datatype that provides an immutable view over traditional databases? Something like an Index or Table abstraction that works with DynamoDB, HBase, Cloudbase, etc.

18:46 I'm writing something like this; but wanted to make sure I'm not re-hashing old work.

18:47 The principle motivation is that none of the built-in abstractions really deal well with the notion of complex indexing or extracting ranges from a Collection based on something other than a numeric index.

18:49 Hierarchy: Peer/Connection (encapsulates a connection to a database), returns a Store object which you use to generate new versions of an Index. Similar to Datomic, except that we add the Store type to capture a table type that has a fixed schema for how keys/values are mapped to storage.

18:50 Only reason to do this vs. Datomic, other than cost perhaps, is that other stores provide the ability to better control data layout for queries and computational patterns of moving compute to data (map-reduce, etc)

21:27 murtaza52: I have a fn which is returning a lazy seq, and something is causing it throw away the first element

21:27 I just dont understand whats happening ?

21:27 gfredericks: me neither

21:29 murtaza52: what code is troubling you ?

21:29 gfredericks: yours

21:29 murtaza52: :)

21:29 gfredericks: but you haven't told me much more about it so there's not much I can do about it :)

21:31 perhaps you could share your code?

21:31 murtaza52: yup posting the url - just a sec

21:31 https://github.com/murtaza52/clj-nio2/blob/master/src/nio2/watch.clj

21:32 The watch-seq fn at the end is giving trouble

21:33 its suppose to watch over a dir, and report any change events - like file creation, modification, deletion

21:33 it just doesnt report the first event immediately. It reports it along with the second

21:34 gfredericks: side note, apply concat can probably replace your flatten

21:34 ~flatten

21:34 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

21:35 gfredericks: murtaza52: so your issue is not that the return value is incorrect, just that it's not timed the way you would expect?

21:36 murtaza52: yup

21:36 here is a gist of using it in an repl - https://gist.github.com/murtaza52/5794159

21:36 so once this code is run, it basically blocks

21:37 gfredericks: well I'm curious if maybe flatten was the actual issue

21:37 murtaza52: and then prints whenever an event happens

21:37 why would that be so ?

21:37 gfredericks: it might interact more strangely with laziness; it's too complicated for me to guess at

21:38 try apply concat and see if that helps

21:38 murtaza52: yes it could be, I think it most probably is, bcoz it was working correct before

21:41 gfredericks: fascinating

21:41 (dec flatten)

21:41 lazybot: ⇒ -1

21:41 murtaza52: apply concat also gives same behaviour

21:41 what is dec flatten

21:41 gfredericks: that was just me publicly criticizing flatten

21:42 murtaza52: oh ok :) newbie to irc

21:44 gfredericks: I have no further guesses

21:45 murtaza52: it works properly if I dont use apply concat or flatten, however then the signature of the fn changes. It is a forked repo I am trying to work with

21:45 gfredericks: o_O that's curious

21:46 ,(take 3 (concat [1 2 3] (lazy-seq (Thread/sleep 3000))))

21:46 clojurebot: (1 2 3)

21:46 gfredericks: concat you ain't so lazy is you

21:47 ,(take 3 (concat [1 2 3] (lazy-seq (Thread/sleep 3000))))

21:47 clojurebot: (1 2 3)

21:47 gfredericks: oh nevermind

21:47 false goose herring

21:47 chase

21:48 murtaza52: do I have any other ways to flatten a seq

21:48 (apply identity [:as])

21:49 (apply identity [:as :b]) - an identity that will also work for a seq

21:49 gfredericks: I know of no reason why concat should have this effect

21:49 murtaza52: bcoz its a lazy seq concatenated to a lazy seq

21:50 gfredericks: sure but concat should not realize the second lazy seq at all until you need that part

21:50 and the test I did above confirms that it seems to be working properly

21:50 murtaza52: u know one curious thing I noticed - if I used flatten two times, e evaled the fn and then concat it to the whole,

21:50 then my timing was off by two events

21:51 so the more lazy constructs I am using the more the timing is getting off !!

21:51 gfredericks: ,(take 3 (flatten [[1 2 3] (lazy-seq (Thread/sleep 9000))]))

21:51 clojurebot: (1 2 3)

21:51 gfredericks: ^ suggests flatten works fine too

21:52 VFe: Curious if anyone understands why this is, I have a simple luminous web-app, configured with friend. and a relatively simple route (GET "/account" []

21:52 (friend/authorize #{::user} (layout/render "account.html"))) if I put it inside my test-routes in handler.clj, it works fine, but it I put it in any other defroute, it tells me I don't have access to the resource after logging in.

21:54 callen: VFe: do you really need the full workflow stuff of Friend, or are you just doing the essentials of web app auth?

21:55 VFe: This is just a side project for learning, not really for anything serious.

21:56 murtaza52: gfedricks: (flatten [(read-events ws) (repeatedly #(read-events ws))])

21:56 callen: VFe: https://github.com/bitemyapp/neubite/blob/master/src/neubite/middleware.clj https://github.com/bitemyapp/neubite/blob/master/src/neubite/routes/admin.clj

21:56 VFe: using tools you don't understand will get you into trouble in a hurry.

21:56 murtaza52: gfredericks: the above one returns the first event immediately, but then clubs the second and third one

21:57 so its the use of flatten with repeatedly

21:58 gfredericks: ,(take 3 (flatten [[1 2 3] (repeatedly #(Thread/sleep 10000))]))

21:58 clojurebot: (1 2 3)

21:58 gfredericks: repeatedly is pretty innocent

21:59 VFe: Aye, I'm seeing that, that's why I'm trying to figure it out. Thanks for the information though, I always get a lot from new examples :)

21:59 tomjack: &(time (doall (take 3 (flatten (repeatedly #(do (Thread/sleep 1000) [:foo]))))))

21:59 lazybot: ⇒ "Elapsed time: 4011.374677 msecs" (:foo :foo :foo)

22:00 tomjack: does that make sense?

22:00 murtaza52: nope sorry :)

22:00 gfredericks: oh hm

22:00 tomjack: &(time (doall (take 3 (repeatedly #(do (Thread/sleep 1000) [:foo])))))

22:00 lazybot: ⇒ "Elapsed time: 3010.309 msecs" ([:foo] [:foo] [:foo])

22:00 ddellacosta: hmm, all of a sudden clojurescript 1830 complaints in project…anyone know what the scoop is?

22:01 gfredericks: &(time (doall (take 3 (apply concat (repeatedly #(do (Thread/sleep 1000) [:foo]))))))

22:01 lazybot: ⇒ "Elapsed time: 4012.558563 msecs" (:foo :foo :foo)

22:01 tomjack: ddellacosta: are you writing a macro? did you print something during macroexpansion? that's my only guess

22:02 gfredericks: murtaza52: well I guess that reproduces it. I'm not sure what the difference is with what I was doing, or why it's behaving that way at all

22:02 ddellacosta: tomjack: sorry, should be more explicit: I can't even load up repl/start project all of a sudden today, which smells like it's bringing in a new dependency all of a sudden.

22:02 tomjack: no clue then

22:02 murtaza52: gfredericks: sorry I am missing the point

22:02 ddellacosta: thought maybe I missed something, but poking around on the CLJS mailing list yields no clues

22:02 hmm

22:03 gfredericks: murtaza52: the timings of ~4000ms should ideally be ~3000ms

22:03 ddellacosta: must be some dependent library being sneaky

22:03 gfredericks: i.e., it's realizing one step too far

22:03 murtaza52: how so, its returning only 3 values ?

22:03 ddellacosta: I miss lein pedantic's stern but loving touch

22:04 gfredericks: murtaza52: I don't know _why_ it's doing it, I just know that it _is_, due to the fact that it took 4000ms

22:05 murtaza52: i.e., this seems to be the same issue you're dealing with

22:05 and I can now investigate it without having to go through you

22:05 if tomjack knows what's up I'd be terribly interested

22:06 murtaza52: yup it makes sense

22:07 I will be away for 20 mins, so please ping me if anything comes up

22:07 ddellacosta: nevermind, looks like it was my fault for using piggieback 0.0.5-SNAPSHOT.

22:09 gfredericks: this is getting much weirder

22:09 &(time (doall (take 1 (apply concat (repeatedly #(do (Thread/sleep 1000) [:foo]))))))

22:09 lazybot: ⇒ "Elapsed time: 4012.168009 msecs" (:foo)

22:09 gfredericks: ^ (noting the `take 1`)

22:09 tomjack: :)

22:11 I guess apply concat will always realize 4 things

22:11 [x y & zs] gives two

22:11 gfredericks: I've been staring at the concat code and have no idea why that would be the case

22:11 oh hm

22:12 tomjack: yeah I dunno either

22:12 gfredericks: so it has to walk the arg seq to know which clause of concat to execute

22:12 tomjack: if you look at the stack inside the repeatedly fn it goes back to RT.boundedLength

22:12 dunno if that's relevant

22:12 can't tell what the bound is

22:13 gfredericks: &(time (doall (take 1 (reduce concat (repeatedly #(do (Thread/sleep 1000) [:foo]))))))

22:13 tomjack: yeah I guess it makes sense

22:13 lazybot: Execution Timed Out!

22:13 gfredericks: oh

22:13 yes of course that would not work

22:14 * gfredericks tries to figure out what he was thinking

22:14 tomjack: I think it's that (next zs)

22:14 gfredericks: but it's all inside the lazy-seq thunk

22:14 I guess that doesn't matter

22:15 tomjack: hmm, yeah, I don't get it

22:15 gfredericks: interesting. okay so anyhow the solution ought to be a replacement for apply concat

22:15 tomjack: I think if this is a problem, you're probably doing something wrong :)

22:16 gfredericks: really? You're getting a lazy seq of groups of things and want to flatten that lazily?

22:16 seems reasonable to me

22:16 tomjack: if you care about whether one or two extra things are realized I mean

22:16 it shouldn't matter

22:17 gfredericks: in the case of listening for events though

22:17 you think using lazy seqs at all is bad?

22:17 (for that use)

22:18 tomjack: I don't understand the watch.clj code really

22:18 but apparently it's bad, because this is a problem :)

22:19 looks like it's lazy IO basically? yeah, bad

22:20 gfredericks: this is a new idea to me. I feel like modeling external events as a lazy seq is an oft-used example of the utility of lazy seqs

22:20 tomjack: that seems odd

22:20 gfredericks: in any case this seems to fix it: (defn concats [s] (lazy-seq (concat (first s) (concats (rest s)))))

22:21 tomjack: lazy seqs are pull-based, 'external events' suggests push

22:21 gfredericks: murtaza52: ^, modulo tomjack's higher level criticisms

22:21 tomjack: so it only makes sense if the "pull" doesn't block prohibitively?

22:22 tomjack: well it could still make sense that way

22:22 gfredericks: I think this is a pull

22:22 tomjack: as long as pulling doesn't cause something to happen in such a way that depending on how/when you pull, you get different results

22:23 gfredericks: and the issue is that if the second pull is going to block for a while then you're not seeing the first results because concat is waiting for the second batch before it gives you anything

22:24 tomjack: hmm

22:24 s/well it could still make sense that way//

22:25 gfredericks: okay. so the lesson is don't use lazy seqs when you're dependent on clojure.core being maximally lazy

22:25 tomjack: my opinion is probably worthless, I have developed the view that lazy seqs are fundamentally broken

22:26 the cases where you don't notice that they're broken are the cases where it's OK to use them :)

22:26 gfredericks: ha

22:32 admittedly there are two levels of laziness going on here

22:32 I think concat does fine with not realizing anything extra within the seqs you pass it

22:32 it's the fact that he's relying on the arg list itself being lazy that concat didn't expect

22:32 I think the signature of concat is maybe weird

22:32 tomjack: yeah, in retrospect it's not surprising

22:32 gfredericks: or at least the alternative should exist

22:32 I bet the majority of my uses of concat are with apply

22:32 tomjack: dunno what it would even mean for apply to be lazy in the seq

22:32 gfredericks: yeah that's not really feasible

22:32 but concat doesn't have to be written variadically

22:32 and I think this illustrates that a non-variadic version (like the one I pasted above) could be valuable

22:32 dnolen: ddellacosta: hmm, I just tried 1820 in a project everything seems fine here

22:33 ddellacosta: dnolen: yeah, it was totally a false alarm, my apologies--I had a snapshot version of Piggieback and it was somehow pulling in 1830 for some reason

22:33 dnolen: ddellacosta: you must mean 1820?

22:33 AlexE: Hi all - I'm having a weird problem in emacs paredit where typing a "(" adds an extra space in front of the opening parens

22:34 ddellacosta: dnolen: well, this may illuminate the error. I didn't look into it deeply, but it was clearly complaining about "1830." Let me take a closer look, maybe is something I should let cemerick know about

22:34 AlexE: Is anyone else seeing this? I causes problems for reader functions like: # ()

22:35 gfredericks: AlexE: not I

22:35 cemerick: ddellacosta: whoops; that's a build on my local machine :-/

22:36 Some vars in the cljs analyzer changed on master, which that snapshot is tracking.

22:36 ddellacosta: cemerick: ah, haha…was wondering what was up with that. ;-) I should have known better than to use 0.0.5-SNAPSHOT anyways, I don't remember why I had it in there…but moving back down to 0.0.4 solved it, so I forgot about it and moved on.

22:36 AlexE: gfredericks - thanks, so you don't get an extra space in front when using paredit.el?

22:36 gfredericks: AlexE: nope, I've never seen that

22:36 ddellacosta: gotcha

22:36 gfredericks: I'm probably not up-to-date though

22:37 tomjack: gfredericks: incidentally, concats is join, huh? :)

22:37 AlexE: hmm - it's definitely a paredit thing because disabling the mode solves the problem… but that's a very inefficient :-/

22:37 gfredericks: tomjack: is that a haskell name?

22:37 AlexE: ...workaround

22:38 tomjack: yeah

22:38 gfredericks: I guess it is then

22:38 I would have guessed haskell just had a one-arg function called `concat`

22:38 but you'd probably know better than me

22:39 tomjack: it has that too for lists

22:39 gfredericks: oh join is on a typeclass?

22:39 monoids?

22:39 * gfredericks conjectures wildly

22:40 gfredericks: this is monads isn't it

22:40 I've never had the names of the monadic functions too solidly in my head

22:40 tomjack: yeah

22:40 gfredericks: in fact the strongest evidence I can muster without googling is that core.logic uses the name `join` so it must be about monads :P

22:41 tomjack: if you read about monads outside haskell usually they're formulated in terms of join

22:41 gfredericks: no wai

22:41 t

22:41 the core.logic word I'm thinking of is bind I think

22:41 tomjack: bind is the.. other.. way :)

22:42 * gfredericks defenestrates a heap of comonads

22:43 tomjack: I always felt a little weird about #(apply concat %1)

22:43 gfredericks: is this worth proposing on clojure-dev?

22:43 tomjack: #(mapcat identity %) would be a suitable concats, yes?

22:44 gfredericks: mapcat uses apply concat

22:44 tomjack: :'(

22:46 &(first (mapcat (constantly [:foo]) (repeatedly #(println "foo"))))

22:46 lazybot: ⇒ foo foo foo foo :foo

22:46 tomjack: delightful

22:46 gfredericks: :)

22:48 tomjack: so with a recursive mapcat thingy might you end up looking further and further ahead?

22:49 or is the over-eagerness bounded at least

22:49 I say 'thingy' because I have no idea what I'm talking about

22:52 gfredericks: tomjack: you mean the current impl of mapcat?

22:52 should just be 4 args

22:54 tomjack: yeah I'm wondering if you can get yourself into situations where you're 4 elems too eager, then 8, then ...

22:55 gfredericks: okay so you're talking about a hypothetical different impl of mapcat?

22:55 tomjack: no a hypothetical use of current mapcat

22:55 gfredericks: unless you're calling it more than once somehow...

22:55 which I guess is what you meant by "recursive"

22:56 tomjack: yeah, though I really have no clue what that hypothetical use might be

22:57 just seems like a potential eagerness-leak waiting to happen

22:57 cemerick: dnolen: should I wait for you to vet my latest patch before suggesting yet more changes I'd like to make to the cljs REPL(s)? :-P

22:57 dnolen: cemerick: feel free open enhancement tickets for stuff you have in mind

22:57 gfredericks: tomjack: so if there were a decent name for it besides join then we could propose that function gets added to core and mapcat gets rewritten

22:58 dnolen: cemerick: one question - on the async bit - I'm not sure why this isn't surmountable given how browser REPL works in the first place

22:58 cemerick: dnolen: you mean re: reflect stuff?

22:58 dnolen: cemerick: yes

23:00 cemerick: dnolen: not sure it can be, easily. e.g. (doc 'whatever) is entirely disconnected from the R-E-P loop, insofar as what it does is an out-of-band callback

23:00 murtaza52: tomjack:, gfredericks: great analysis. so maybe its not working bcoz concat is expecting two realized elements, while one is lazy and blocking.

23:01 gfredericks: murtaza52: yeah, did you see my impl of `concats`?

23:01 dnolen: cemerick: I don't see why this matters if all the calls are forced to sync

23:01 forced to be sync

23:01 sync call to browser, sync call to server, return value to REPL

23:01 murtaza52: however shouldnt this work - (apply concat [] (repeatedly #(read-events ws))) - the second element to concat will be realized when a system event happens. however this also behaves the same way

23:01 no let me try that.

23:02 dnolen: cemerick: again, I don't know for sure, I'm just curious why this issue doesn't affect the normal REPL

23:02 cemerick: dnolen: perhaps; I don't know the goog xhr/channel APIs at all.

23:02 gfredericks: murtaza52: apply concat realizes 4 arguments when you first force it, so I guess (apply concat [] [] [] [] ...) would work

23:02 dnolen: cemerick: I do recall the reflect stuff uses xhr instead of the CrossPageChannel

23:03 cemerick: dnolen: because the browser-repl is enforcing response ordering on the channel

23:03 dnolen: cemerick: xhr can be forced to be sync

23:03 murtaza52: why is that so, why 4 elements

23:03 dnolen: cemerick: in anycase, it's an enhancement not a big deal

23:03 cemerick: just wondering if you dug into much, but it sounds like not - no problem

23:03 cemerick: i.e. all the add-in-order business through an agent, etc

23:03 gfredericks: murtaza52: eh, it's details; anyhow I just tested it and you can't escape one extra realization by simply adding more args

23:03 dnolen: cemerick: k

23:04 gfredericks: murtaza52: but my concats should solve it for you

23:04 cemerick: dnolen: not really, just trying to bring everything forward as it was; that said, I'm pretty sure no one actually uses the reflect stuff, given the output it was producing...?

23:04 murtaza52: concats

23:04 tomjack: gfredericks: join is not good because it's taken by clojure.string/join?

23:04 gfredericks: tomjack: or just suggests that

23:05 dnolen: cemerick: likely

23:05 gfredericks: _or_ suggests monads

23:05 I'm not 100% opposed. maybe it's good.

23:05 dnolen: cemerick: thanks much for this anway, can't wait to see this stuff get hooked up to tools

23:07 cemerick: dnolen: FWIW, I think getting the reflective stuff out of the actual REPL will be less fragile / more capable in the end. Wouldn't be a function, but I think that's a small price now that I've gotten a fuller tour.

23:07 dnolen: yeah, been using it for a long time myself. Invaluable IMO. Always-instant cljs REPL, etc.

23:07 dnolen: cemerick: like just special forms for everything?

23:09 murtaza52: gfredericks: it works ! however now I dont know why it works !

23:09 why did it solve the problem :)

23:10 cemerick: dnolen: Dunno. Depends on just how much you want to jam in the REPL proper. Even pushing e.g. doc lookup through a dedicated nREPL op makes so much more possible w.r.t. customizable/localized experience -- more complicated things like macroexpansion and symbol lookup only get better. The line-by-line textual REPL is a *really* narrow keyhole.

23:10 dnolen: cemerick: hum, I don't have strong opinions about it and you're messing around with this stuff a bit more.

23:11 cemerick: it just seemed like it would make tooling more awkard not having these things be first class - but perhaps the concern was misplaced.

23:12 cemerick: dnolen: I'm actually a bit behind what technomancy and co. are doing.

23:13 The point is, one-off stuff like `doc` makes sense to have around, just because it's convenient, and generally works well in a terminal. Macroexpansion, symbol lookup, call-trace display/visualization, etc. etc....not so much.

23:13 tomjack: &(apply (fn [x y & zs]) (repeatedly 100 #(println "foo")))

23:13 lazybot: ⇒ foo foo foo foo nil

23:13 tomjack: murtaza52: ^

23:13 in other words, it's just a quirk of (apply concat ..)

23:14 cemerick: All these things are why Dr. Racket and Lispworks are awesome, in addition to textual REPLs.

23:14 dnolen: Anyway, once the patch makes it through safely, I'll see what I can do about making reflect stuff synchronous.

23:15 gfredericks: tomjack: murtaza52: http://dev.clojure.org/jira/browse/CLJ-1218

23:15 dnolen: cemerick: k

23:15 murtaza52: in the above example, shouldnt it print it 100 times ?

23:15 gfredericks: murtaza52: no because repeatedly is lazy

23:15 dnolen: cemerick: in other news, your core.match bugs are getting crushed

23:15 tomjack: one might argue that it should print 0 times

23:15 dnolen: very quickly

23:15 gfredericks: but the function signature forces several realizations

23:16 tomjack: (well, 0 times wouldn't make sense in clojure, but..)

23:16 cemerick: dnolen: yeah, I saw you got a second wind :-) Very excited to get back to the bits I have that use it, though I'm about 12 layers too deep at this point :-/

23:16 tomjack: I still don't understand why it's 4 though

23:16 dnolen: cemerick: heh, yeah it needed 15 hours of focused hacking to get out of the bog

23:16 cemerick: dnolen: I thought match had gotten passé for you? :-P

23:17 dnolen: cemerick: we're all clear now, it's been really smooth sailing. Was far too obsessed with premature optimization two years - some embarassing stuff got purged.

23:17 two years ago

23:18 tomjack: gfredericks: I think my position is still "if you require maximal laziness, you're doing it wrong" and would be surprised if the clojure team doesn't echo this cop-out :)

23:18 cemerick: dnolen: heh, so your "fixed" comment was just you adding a testcase verifying the fix you actually made however long ago? :-)

23:18 gfredericks: yeah that wouldn't bother me too much

23:19 tomjack: in any case, I'm headed off. Thanks for learning me a clojure.

23:19 murtaza52: so its apply that causes a lazy seq to realize 4 times

23:19 gfredericks: ...sorta

23:20 not that apply could really do anything different

23:20 tomjack: &(apply (fn [x y z w v & us]) (repeatedly 100 #(println "foo")))

23:20 lazybot: ⇒ foo foo foo foo foo foo foo nil

23:20 dnolen: cemerick: heh yeah the "fix" wasn't really one thing, a lot of refactoring and simplifying

23:21 murtaza52: it realizes it the number of times its needs args, thats why the non vaiadic version works

23:21 I mean the times the fn needs args

23:22 dnolen: one nice outcome is that seq pattern matching can be salvaged

23:22 was going to give it the boot, but now it an vector matching can peacefully coexist

23:26 cemerick: dnolen: with all the same notation, etc?

23:27 dnolen: cemerick: it just works, no backtracking weirdness

23:27 cemerick: sweet

23:27 dnolen: cemerick: however vector patterns still only work on *vectors*

23:27 cemerick: sounds fine to me

23:27 murtaza52: gfredericks: so shouldnt this also realize just 4 elements

23:27 ,(apply concat (repeat [:a]))

23:27 clojurebot: (:a :a :a :a :a ...)

23:27 cemerick: dnolen: sorry, wasn't meaning to be coy w/ 521 :-P

23:28 dnolen: cemerick: I'll probably change that, but I'd rather get out solid release that doesn't have so many bugs before thinking about enhancements again.

23:29 cemerick: dnolen: didn't think it was possible efficiently? I mean, once you're matching seqs generally, the general case is linear time, yes?

23:30 dnolen: cemerick: it's not possible efficiently, but given a culture of destructuring seqs I'm not sure it matters much :P

23:30 murtaza52: tomjack: why doesnt this version also block, doesnt it need atleast two elem to concat, why does it immediately return the first event, without waiting for the second event also to realize

23:30 (defn concats [s](lazy-seq (concat (first s) (concats (rest s)))))

23:30 dnolen: cemerick: again it's not something I fully decided something to stew on

23:31 cemerick: sure

23:31 ddellacosta: dnolen, cemerick: just saw you folks talking about CLJS repl, I would love to help. I use it a lot via piggieback, and would be using it every day if I could get some of the kinks out. namespace stuff, connecting already existent project to repl are pain points for me. But not sure where to start with contributing.

23:31 tomjack: murtaza52: in that case the first element of (concats foo) can be gotten from (first foo)

23:31 cemerick: ddellacosta: clarify those pain points, please?

23:31 tomjack: concats and rest are both lazy so..

23:32 and (concat x y) won't realize y until necessary

23:32 it's just (apply concat foo) that's a bit funny

23:33 murtaza52: so it will return (concat x []) or x, as y is not realized ?

23:33 ddellacosta: cemerick: sure. 1) I have an existing project with browser connect code on the test build. When I open a piggieback session and then open the project w/connect CLJS in a browser, sometimes I have to hit reload a dozen times before the browser syncs up with the repl. This could just be my ignorance, but at least I'd love to help documenting the process.

23:35 cemerick: 2) I want to have a testing flow like my clojure.test/midje flows, where I test in the repl, and reload the namespaces to call run-tests again. I started investigating how to integrate tools.namespace but not sure where to begin with this one. As it is, I end up re-compiling my tests every time and running via `lein cljsbuild test`. It's not as fast or nice as my clojure workflow.

23:35 tomjack: &(take 3 (concat (lazy-seq (println "foo") [1 2 3]) (lazy-seq (println "bar") [4 5 6])))

23:35 lazybot: ⇒ (foo1 2 3)

23:35 tomjack: &(take 4 (concat (lazy-seq (println "foo") [1 2 3]) (lazy-seq (println "bar") [4 5 6])))

23:35 lazybot: ⇒ (foo1 2 bar3 4)

23:35 ddellacosta: anyways, that's my wishlist…heh.

23:36 cemerick: ddellacosta: I did some serious surgery to the browser REPL that should make all that a lot easier. Pending dnolen's stamp of approval at the moment. :-) You can try out the 'browser-repl' branch on my cljs fork if you want.

23:36 s/easier/more reliable

23:36 well, and easier, too :-P

23:37 dnolen: cemerick: sounds awesome, will take a look soon, just want to wrap up a few more core.match things

23:37 ddellacosta: cemerick: okay, I think in fact you sent that to me via IRC a few weeks ago, and while it was super smooth to get going in a brand new browser env., I couldn't figure out how to sync it up to my existing codebase. Will take another look.

23:37 cemerick: dnolen: sorry, wasn't trying to rush you :-)

23:38 ddellacosta: That's more clojurescript.test than piggieback or the REPL, I think: https://github.com/cemerick/clojurescript.test

23:39 I don't use tools.namespace or midje, so perhaps my frame of reference is a bit off. But, I drive a lot of my testing through the REPL, and the above brings 98% of clojure.test to a CLJS repl.

23:40 ddellacosta: cemerick: yeah, I'm using clojurescript.test (thanks, I use so much of your code every day these days!), but that first issue I was talking more just about connecting a running CLJS browser session (by that I mean my app up and running in a browser) to a repl, rather than testing it

23:41 murtaza52: tomjack: gfredericks: thanks !

23:41 ddellacosta: I guess maybe what I can help most with at this point is testing and adding documentation. But we are still in a very early period I guess with integrating CLJS into a real workflow, so I don't want to codify anything prematurely, if that's the right way to put it.

23:41 cemerick: ddellacosta: you mean, after you've been fiddling with the app in the browser for a while, and then you have trouble connecting it to the browser-REPL?

23:42 ddellacosta: cemerick: yeah, I mean, so often I'll load up my app in the browser, and I'll want to test the current state of some variables or how something behaves, or attach an event listener dynamically (for example)

23:43 cemerick: and so I'll start up a piggieback session, and load up a copy with the browser/repl connect code compiled in

23:43 and it can be hit-or-miss.

23:43 and in general it's just a pain to reload the code and have to re-set-up the cljs/repl connection

23:44 cemerick: oh, so you're still connecting at load time, etc

23:44 ddellacosta: yeah, I mean, I have this kind of hack-y flow worked out

23:45 cemerick: I'm afraid I've been running my own patched build of cljs for so long, I've forgotten all the little nuances of the original browser-repl.

23:45 ddellacosta: 1) load piggieback in repl 2) reload browser 3) type (.log js/console "connected?") in repl 4) if it doesn't connect right away, reload browser until it kicks in and "connected?" gets dumped out in my browser console.

23:45 cemerick: hrm

23:46 ddellacosta: any chance you're attempting to run multiple browser-repl sessions from a single Clojure runtime?

23:47 ddellacosta: cemerick: well, I'm definitely not calling cemerick.piggieback/cljs-repl more than once (just one repl running) if that's what you mean, but I'm not sure what the effects of reloading the browser are.

23:49 started to dig into the cljs browser/repl code one day, and I didn't get far before I got distracted by higher priority stuff. I think I just need to sit down and really try understanding all the sub-systems involved, then maybe I can contribute more. But I'd really love to get this tooling nicer, as I think it would help the eco-system in general.

23:50 cemerick: I'm afraid to speculate, as my memory is a bit hazy about the failure modes at the moment. :-|

23:50 ddellacosta: For sure, there's a ton of work to be done around getting ClojureScript and its associating tooling up to snuff. *very* early days, as you said.

23:51 ddellacosta: haha, no worries. Yeah, at this point it's all kind of "good enough for now, look into it when I have time." But when I saw you folks talking about it I thought I'd pipe up as I am happy to contribute, just not sure where to start.

23:51 cemerick: ddellacosta: oftentimes, neither do I ;-P

23:51 ddellacosta: haha

23:52 well, I'll read through your browser REPL code and see what I can learn.

23:54 cemerick: I think once the browser-repl is settled down, that'll make things a lot more pleasant all around. Esp. if your tools have multisession nREPL support, you should end up being able to load code into either your Clojure backend or currently-connected cljs browser effectively without needing to think about which is which too much.

23:55 callen: seancorfield: so have you just not needed to-sql-time yet or what?

23:55 ddellacosta: cemerick: that would be fantastic. Another thing we were tossing around was the idea of a browser plugin which would just pop open a running CLJS repl for you, within the current namespace of the running CLJS loaded

23:55 callen: seancorfield: you're importing java.sql.Timestamp, is there some problem I should be aware of?

23:55 ddellacosta: namespace -> environment I should say

23:56 cemerick: The really hard part will be getting all of the Clojure-supporting tools to support analogous cljs nREPL ops and such so that things more sophisticated than eval and load-file work the same way.

23:56 That's mostly political though, not technical.

23:56 ddellacosta: ah. Yeah, I stumble on namespace issues a lot in the cljs REPL

23:57 callen: cemerick: I make an excellent Political Commissar for ensuring the comrades stick to the party line.

23:57 cemerick: I can provide my forged letters of recommendation from university if you like.

23:57 cemerick: ddellacosta: like, an actual Plugin, i.e. rev up a jvm and such?

23:58 callen: alexbaranosky1: is there some documentation on dates/times and Korma that exists but I haven't discovered/

23:58 ddellacosta: cemerick: yeah, it wasn't too thought out, but was more pie-in-the-sky, "wouldn't that be nice?" I had only thought of it on Mac OS X honestly, as you could trigger Terminal, and I'm not sure what you would need on Windows/Linux.

23:58 cemerick: callen: I think perhaps a softer touch is called for. ;-P

23:59 ddellacosta: sounds a bit crazy :-) I think using the self-hosting cljs fork is probably more realistic.

23:59 callen: cemerick: is good. I can strangle with velvet just as well as rope.

23:59 cemerick: maybe even give vodka before.

23:59 cemerick: ddellacosta: Which perhaps isn't saying much?

23:59 ddellacosta: cemerick: yeah, perhaps too much…heh. ;-)

Logging service provided by n01se.net