#clojure log - Nov 10 2012

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

0:05 XPherior: Who's awake?!

0:06 twobitsprite: you

0:06 XPherior: Haw.

0:47 brainproxy: Sgeo: https://gist.github.com/4050049

0:48 I'm working on monad transformers, and discovered by experiment that the algo.monads implementation and the protocol-monads (my fork) implementation are giving different answers

0:49 for monadic plus in the context of the list/sequence transformer applied to the set monad

0:49 but which one is "correct"?

0:49 having a hard time consulting the haskell wiki as the notation is hard for me to follow

0:50 Sgeo: Is there a difference between the "set" monad concept and the list monad?

0:50 What happens if you try these examples, converting to the list monad?

0:50 brainproxy: so, sequence/list transformer over the list-monad?

0:51 Sgeo: Hold on, I'm not thinking this through

0:51 brainproxy: okay, thanks for your time, I actually need to step away for a little bit, but I appreciate your input

0:51 should be back in 25 min or so

0:52 Sgeo: Are you sure that the inputs you're giving to the function are effectively similar enough for the question to make sense?

0:52 imeredith: brainproxy: i dont get clojures syntax well, but are you basically trying to do something like ... Set(1 2) + Set(3 4) ?

0:52 brainproxy: Sgeo: yes, they're the same inputs

0:52 effectively, i mean

0:52 well... I have a high degree of confidence they are

0:52 Sgeo: Because the first one is giving am/m-plus a bunch of sets that themselves contain a list

0:53 amalloy: imeredith: no, he's doing something pretty obscure; i wouldn't worry about it

0:53 Sgeo: And the second is giving... not entirely sure about that list-t stuff, but looks like just a bunch of lists?

0:53 brainproxy: the first one is asking to carry out monadic plus on the set-list monadic values

0:53 and the same for the second

0:53 imeredith: amalloy: k, i was going to see what scalaz did, but i cant grok clojure well :)

0:54 brainproxy: imeredith: thanks for thinking about it :)

0:54 Sgeo: (set-list 1 2) is effectively the same as #{(1 2}

0:55 amalloy: as a fun aside, brainproxy and Sgeo, have you tried to provide an instance of Monad for Set in haskell?

0:55 brainproxy: amalloy: i don't know a lick of haskell, yet

0:56 Sgeo: istr that one of the problems in attempting to do so is that Sets require a typeclass constraint (forgot if that's the term), and thus >>= for sets would have to be (Ord a, Ord b) => Set a -> (a -> Set b) -> Set b

0:57 amalloy: Sgeo: right on the nose

0:57 Sgeo: And you can't write that instance, since >>= is not supposed to have that constraint

0:57 brainproxy: okay, well let me try with list transformer over list monad

0:57 and see how results compare in the two librarier

0:57 Sgeo: But that's irrelevent to Clojure

0:57 amalloy: although i didn't know Set had that constraint; i thought it was just the union function

0:57 brainproxy: *libraries

0:57 Sgeo: amalloy, hmm, hold on'

0:57 amalloy: well, that's why i said "as a fun aside"

0:58 Sgeo: amalloy, um, I think it's that >>= would need to use a function that requires Ord... I don't really remember

0:58 I do recall that using constraints in the data declaration is recommended against, so that they're not needed everywhere.

0:58 It's been a while

0:59 So probably not that Set requires it, but some operation that >>= needs would require it

0:59 imeredith: Sgeo: amalloy, at worst dont sets just require equals?

0:59 amalloy: Sgeo: yes

0:59 Sgeo: imeredith, in theory, but an efficient implementation needs some ordering, even if it's arbitrary

0:59 imeredith: of course

1:01 brainproxy: Sgeo: https://gist.github.com/4050099

1:02 similar result

1:03 Sgeo: > msum [[[1, 2, 3]], [[]], [[3, 4]]]

1:03 => [[1,2,3],[],[3,4]]

1:03 Still not entirely sure of what you're inputting for the second one

1:03 What's the list-t used for here?

1:04 brainproxy: list-t is the list transformer

1:04 imeredith: oh

1:04 brainproxy: applying it to the list monad

1:04 Sgeo: This seems like it's likely to be a different operation from just putting a list in a list

1:06 I'm not certain, because I don't understand monad transformers too well, and especially not in the context of Clojure

1:06 brainproxy: https://github.com/clojure/algo.monads/blob/master/src/main/clojure/clojure/algo/monads.clj#L610

1:06 imeredith: i really wish multibot was going

1:06 brainproxy: i think I understand the docstring more clearly now

1:09 Sgeo: thanks, it looks like algo.monads has it right and the protocol-monads have a subtle implementation problem

1:09 Sgeo: You're... welcome, but I still wish I entirely understood what is going on

1:09 brainproxy: that is, given that haskell's msum and algo.monads m-plus are doing the same thing

1:09 Sgeo: Are you certain that trying something closer to the equivalent in protocol monads won't give you the same result?

1:10 brainproxy: well I'm not sure I do either, I'm learning what it all means by banging around with the two libraries, and grok'ing what I can from haskell-related discussions

1:11 but the idea is that the list monad has been composed with the list monad, and there are rules for how to to deal with that when you want to do monadic operations on the compound monad

1:11 Sgeo: @(m/m-plus [(list (list 1 2 3)) (list (list)) (list (list 3 4))])

1:11 muhoo: i don't think i've ever seen a monad in clojure code in the wild.

1:11 Sgeo: brainproxy, maybe compare it with ... oh, I see, you are

1:11 Oh, I don't know if the Haskell code I pasted actually corresponds properly

1:13 brainproxy: okay

1:13 imeredith: brainproxy: so basically whats going on is that the list transformer gives you access to the inner stuff, hense you are combining your inner lists into on

1:13 e

1:13 then it unwraps it into the outer bit which is a list

1:14 brainproxy: imeredith: close

1:14 but that's the basic idea

1:14 imeredith: brainproxy: try using an option instead of a list, and i think it should become clearer

1:15 brainproxy: option?

1:15 imeredith: err

1:15 maybe

1:15 oh

1:15 brainproxy: like maybe monad?

1:15 imeredith: brainproxy: sorry, i see the subtle difference

1:15 brainproxy: yeah, im just saying, i think you are being confused by it being a list-t of lists

1:16 brainproxy: dang... I wish I knew how to express this in haskell, need to learn some more stuff

1:16 imeredith: sorry i cant express stuff in clojure

1:16 brainproxy: it's okay

1:17 my problem is I've been learning monads by studying source of algo.monads and protocol-monads and reading related tutorials

1:17 imeredith: in scala i would go ListT(Some(List(1,2,3))) which would have the type ListT[Option, Int]

1:17 Option = Maybe in this case

1:17 brainproxy: gotcha

1:18 shachaf: Is someone expressing something in Haskell?

1:18 imeredith: brainproxy: im biased, but i do think that static typing will help you learn this stuff heh

1:18 not that im an expert :(

1:18 brainproxy: imeredith: right, that's actually one of the nice things about jim duey's protocol monads

1:18 is they give you a way to reason about the types

1:19 Grozhnabev: shachaf, you hold no power over me here, you evil man.

1:19 brainproxy: whereas algo.monads is purely interface driven

1:19 Grozhnabev: Freedom shall carry on.

1:21 imeredith: brainproxy: how do they give you a way to reason over types?

1:22 brainproxy: because the bind and result are implemented as protocol methods

1:22 as well zero and plus

1:22 imeredith: brainproxy: honestly the types thing is one of the main reasons i havent gotten into clojure more, i started down the monad track at the same time i was looking into clojure, and now i cant even imagine doing it without static typing

1:22 * imeredith looks up protocol methods

1:22 shachaf: Please stop changing your nick, Grozhnabev.

1:22 It's just annoying. :-(

1:22 brainproxy: imeredith: see https://github.com/michaelsbradleyjr/protocol-monads/blob/examples/src/monads/core.clj

1:23 Grozhnabev: shachaf, "freedom annoys those who seek to oppress others" - Virgil, 0231 CE

1:23 brainproxy: that's my fork of duey's library, and I've been paying a lot of attention to type-related issues

1:23 there's even a "return type checker"

1:23 which is purely optional

1:24 meant to help the developer reason more carefully about the steps in his monadic computations

1:24 imeredith: brainproxy: so when does the type stuff kick in? when you load the code?

1:24 brainproxy: no, if you bind *throw-on-mismatch* to true

1:25 then if you have a mismatch between a bound monadic value and the return of a monadic function

1:25 you get an exception

1:25 imeredith: at runtime?

1:25 brainproxy: yeah

1:25 imeredith: i guess you then rely on tests to pick up any problems?

1:25 Sgeo: imeredith, one of the notable things in Haskell that you can't do in Clojure due to the differnt type systems is polymorphism on the return type

1:26 brainproxy: imeredith: well, the checker is meant itself as a way to identity subtle errors during development

1:26 Sgeo: That is, can't really do a return :: (Monad m) => a -> m a

1:26 imeredith: brainproxy: right

1:26 Sgeo: in clojure you cant?

1:26 oh

1:26 Sgeo: core.algo.monads works around it by sort of supplying the information in a dynamically-scoped way

1:26 imeredith: i see

1:26 Sgeo: I think protocol-monads does it by not actually supplying a return function, but not entirely sure

1:27 brainproxy: Sgeo: what do you mean?

1:27 imeredith: how do you get by without return?

1:27 Sgeo: brainproxy, let's try a simpler example than return. Haskell has a value called maxBound

1:27 If used where an Int is expected, maxBound is the maximum Int value

1:28 imeredith: do-result isnt return?

1:28 Sgeo: If used where a Char is expected, maxBound is the maximum Char

1:28 etc. etc.

1:28 imeredith, erm, it probably is, but ... hold on

1:28 imeredith: I take it MonadZero is Monoid too

1:29 Sgeo: Note that do-result takes an argument that it ignores

1:29 brainproxy: note on the thing I just linked to on github, the transformer sections are still being adjusted w.r.t. to the type checker stuff I implemented

1:29 and so there are / are probably things wrong with them

1:29 but up to that section, everything is pretty solid

1:30 Sgeo: That argument is not needed in Haskell, because the type system effectively supplies that information

1:30 imeredith: brainproxy: no reader monad? :(

1:30 brainproxy: imeredith: not yet

1:31 imeredith: Kleisli/ReaderT is my favourite monad trnasformer atm - probably because its the only one i really understand

1:31 :)

1:32 Sgeo: Protocol monads keeps calling "monads" what I would term "monadic values" :(

1:32 Although in protocol monads, you can get the information about the monad from a monadic value

1:32 brainproxy: right

1:32 Sgeo: So, I guess it sort of makes sense

1:33 brainproxy: so when you do (m/bind [1 2 3] (fn [x] ...))

1:33 the monad is the vector monad

1:33 since the monadic value is a vector

1:35 i've worked to flesh out the test suite a good bit

1:36 which helped me to think about what everything actually does ... just that I've hit a wall w/ transformers since I don't have the knowledge to begin with know whether the lib is implementing them correctly

2:13 Sgeo: just realized I could simplify bind and plus for the ListTransformer, revealing an "inner plus" at work

2:13 https://github.com/michaelsbradleyjr/protocol-monads/blob/examples/src/monads/core.clj#L728

2:52 muhoo: i suspect, as a complete gut hunch, that monads are only necessary to get around limitations created by haskell, i.e. its strict type checking. the same way that things like design patterns are necessary to get around limitations in oop.

2:56 amalloy: muhoo: nobody would bother porting them to clojure if that were true

3:01 monads capture a common pattern that is useful in a lot of contexts. for example, clojure's for macro is a special-cased version of the list monad

3:02 shachaf: That's silly. "Monad" is just the name of a generic API that a lot of different types in Haskell expose.

3:02 amalloy: shachaf: sorry, which is silly?

3:02 shachaf: You can perfectly well write Haskell code without ever using this API, but it's a nice abstraction to recognize.

3:02 "necessary to get around limitations created by haskell"

3:03 Sgeo: bound-fn bothers me a little. What if I have a macro that expands into an fn form, but where I'm using the macro I'd rather it expand into bound-fn

3:03 amalloy: well, he's presumably thinking of IO, which is in some ways what he's claiming

3:03 Sgeo: Am I just out of luck?

3:04 shachaf: amalloy: The way IO is done in Haskell has nothing to do with type checking.

3:04 tomoj: Sgeo: bound-fn* ?

3:04 shachaf: It has everything to do with purity, and if you had a dynamically typed pure language, you could do the exact same thing.

3:04 tomoj: not sure what you mean

3:05 Sgeo: tomoj, suppose I am using future

3:05 But I want the code inside my future block to see some dynamic variable

3:05 How do I make it use bound-fn or bound-fn* instead?

3:06 amalloy: shachaf: yes. i don't think it's unreasonable for him to think those are the same thing, right? the haskell type system prevents you from performing IO except in functions which deal in IO. type safety and purity seem pretty related to me

3:06 tomoj: futures already have binding conveyance

3:06 shachaf: amalloy: That has nothing to do with the type system.

3:06 It could work precisely the same way in a dynamically-typed language.

3:06 IO String isn't a "tagged" String which the type system keeps apart from String; it's a completely different kind of value.

3:07 tomoj: I guess you might mean (future-call (bound-fn* f)) ? but that could only make sense if you called bound-fn* in some other dynamic scope

3:07 I think?

3:07 shachaf: 00:05 <lambdabot> shachaf says: getLine :: IO String contains a String in the same way that /bin/ls contains a list of files

3:10 * Sgeo imagines a Clojure in which all functions that take one or more arguments were required to be referentially pure, and only 0-argument functions could do side-effects such as I/O

3:10 Sgeo: (println "Hello") could return a 0 argument function, which I then call to actually print "Hello"

3:11 ((println "Hello")).. except I don't do that, rather, I build up a huge 0-argument function out of several pieces, and tell the compiler where it is

3:43 raek: Sgeo: I think 'future' itself already acts as a 'bound-fn'

3:44 bbloom: ,(source bound-fn)

3:44 clojurebot: Source not found

3:44 Sgeo: So, in my own code, if I want to output an fn based off code passed into the macro, I should likely use bound-fn?

3:44 Blah

3:45 bbloom: works locally

3:45 ,(doc bound-fn)

3:45 clojurebot: "([& fntail]); Returns a function defined by the given fntail, which will install the same bindings in effect as in the thread at the time bound-fn was called. This may be used to define a helper function which runs on a different thread, but needs the same bindings in place."

3:45 bbloom: ,(doc bound-fn*)

3:45 clojurebot: "([f]); Returns a function, which will install the same bindings in effect as in the thread at the time bound-fn* was called and then call f with any given arguments. This may be used to define a helper function which runs on a different thread, but needs the same bindings in place."

3:45 raek: if you want the current value of some dynamics vars, perhaps you could just let them

3:45 bbloom: ,(doc with-bindings)

3:45 clojurebot: "([binding-map & body]); Takes a map of Var/value pairs. Installs for the given Vars the associated values as thread-local bindings. The executes body. Pops the installed bindings after body was evaluated. Returns the value of body."

3:46 tomoj: I don't think you can do that

3:46 brainproxy: Sgeo: okay, figured it out

3:46 https://gist.github.com/4050099

3:46 tomoj: the macro returns code, how are you going to get the bindings in there?

3:47 brainproxy: with a flag, the algo.monads version will implement the same op as protocol-monads

3:47 tomoj: oh

3:47 I think I misunderstood you

3:47 raek: (defmacro foo [] `(let [x# (quote ~*x*), y# (quote ~*y*)] (defn ... x# ... y# ...)))

3:48 I find dynamic vars hard to use

3:53 bbloom: raek: let is lexical, you want binding

3:53 ,(doc binding)

3:53 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

5:23 nicl: how do I check the case of a character in a string?

5:24 basically, I would like to filter a string by case

5:34 ajmccluskey: nicl: I'm really new to clojure, so there's probably better ways, but my first thoughts would be something like (defn is-upper-case? [c] (= (clojure.string/upper-case c) c))

5:34 nicl: ajmccluskey: ah yes, don't know why I didn't think of that?!

5:35 ajmccluskey: thanks

5:35 ajmccluskey: nicl: no worries. Just glad I could help someone else for a change :)

5:42 Raynes: er

5:42 &(Character/isUpperCase \x)

5:42 lazybot: ⇒ false

5:42 Raynes: &(Character/isUpperCase \X)

5:42 lazybot: ⇒ true

5:42 Raynes: nicl: ^

5:43 ajmccluskey: nicl: I think Raynes has a far better answer

5:44 Raynes: Your answer was clever.

5:45 Don't feel bad because you haven't memorized the java standard library. :)

5:46 nicl: Ragnes: thanks!

5:46 Raynes: ah sorry, got your name wrong.

5:46 Raynes: thanks. Was thinking there would be something like that

5:47 ajmccluskey: Haha, thanks. Using already working code is cleverer though :p.

5:50 nicl: ajmccluskey: I agree with Raynes though - you're solution was solid common sense

5:50 which is to be applauded!

6:09 daniel__: is there an easy way of debugging what takes a long time to load when including a namespace i.e. (use 'backend.core) (REPL)

6:24 ivan: daniel__: reloading via tools.namespace or by using eval-defun repeatedly in Emacs with nrepl

6:24 the general idea is to keep your JVM running

6:30 daniel__: thanks ivan

6:31 im also having a problem serializing a protobuf-dump (byte array) to a string if anyone can help there?

6:31 it works in some cases and not in others, i need a reliable way of going from protobuf-dump -> string

7:11 ithildin: Hey, not sure who's around this early. I'm new to clojure (and linux, double whammy) and I'm wondering what my options are for writing something with a GUI

7:11 Is there much there outside of Swing?

7:12 In case it wasn't too clear, that's GUI options for clojure in linux

7:19 ChongLi: ithildin: you could write your GUI in opengl

7:20 that's a big undertaking though

7:20 ithildin: yeah, that seems like overkill to get some buttons and text on the screen

7:21 ChongLi: seesaw

7:21 it's a DSL built on swing

7:21 https://github.com/daveray/seesaw

7:21 ithildin: I have seen seesaw when I've searched.

7:22 so it would be nicer than normal Swing. but I've not had good experiences with swing

7:22 granted, that was years and years ago

7:22 maybe things have gotten better?

7:22 ChongLi: probably

7:22 the number of users of swing is pretty staggering

7:23 ithildin: Yeah, that's the advantage. Coming from web development or iOS development (or Delphi or VisualWhatever) it seemed really annoying though

7:24 scottj: ithildin: there's GUIFTW that supports SWT (eclipse)

7:24 ChongLi: the other advantage is the fact that clojure is a lisp

7:24 allowing library writers a lot of liberty in building nice DSLs with macros

7:24 ithildin: hmm I'll have to check that out as well scottj

7:25 scottj: ithildin: https://github.com/santamon/GUIFTW it hasn't been updated in a year so unless you really don't want swing I'd go with seesaw which is very actively developed

7:25 ithildin: ah, ok

7:26 yeah, not a good sign when the readme says "It's in alpha stage" and then it hasn't been updated for a year

7:27 ChongLi: yeah it's always a shame when things are seemingly abandoned

7:28 ithildin: ha, apparently I don't know the keyboard shortcuts in xchat

7:29 daniel__: How do i serialize a protobuf-dump when i have it as a byte array?

7:29 I'm sending it as a string with ZeroMQ

7:34 raek: another thing that happens a lot is that the readme says "It's in alpha stage" but the project is actively used by hundreds persons and is actively maintained

7:35 people should bump up their versions from 0.x.0 to 1.0.0 more often

7:39 rodnaph_: raek: +1 if it's not some big commercial offering then "usable" should be 1.0

7:40 (though i am guilty of not doing this too)

7:46 daniel__: i have a print inside a function that isnt printing to the repl

7:46 maybe its because its in a try block, maybe because its within a while loop?

7:47 raek: daniel__: is it in another thread?

7:48 try and while shouldn't affect it

7:49 rodnaph_: is it part of some lazy evaluation that hasn't been realised?

7:49 daniel__: i dont think so https://gist.github.com/4050976

7:50 line 7

7:55 any ideas?

7:58 just noticed my try block isnt properly formed

7:59 andrewmcveigh: daniel__: the "future" is spinning up another thread.

7:59 ah, sorry... your println is not involved.

7:59 daniel__: yeah its outside the future

8:00 the second deref should be cached as well shouldnt it?

8:01 added a modification, this is how my try should be isnt it? https://gist.github.com/4050976

8:02 andrewmcveigh: daniel__: no, you had the try block right the first time.

8:02 daniel__: should it be (try expr (finally ..)

8:02 clojurebot: Cool story bro.

8:03 andrewmcveigh: yeah

8:03 daniel__: shouldnt it*

8:03 raek: daniel__: println-str prints to a string and returns it. but it is not passed out from the while form

8:03 daniel__: try changing it to 'println'

8:03 daniel__: raek, i tried with print as well

8:03 ok

8:04 andrewmcveigh: in the first example, dont i have (try expr1 expr2 (finally .. ?

8:04 raek: or if it clojure data structures, use 'prn'

8:04 ,(doc while)

8:04 clojurebot: "([test & body]); Repeatedly executes body while test expression is true. Presumes some side-effect will cause test to become false/nil. Returns nil"

8:04 daniel__: im hoping its a string, but thats why i want to print it

8:04 raek: println-str does not print

8:05 andrewmcveigh: daniel__: yes, that's fine.

8:05 raek: it behaves as 'format', but adds a newline

8:05 daniel__: no but i mean, im not sure if its a clojure data structure or not, i want to verify what it is

8:05 raek: daniel__: what happens if you use 'prn' instead of 'print-str'?

8:05 daniel__: let me just test it

8:06 raek: also, do you call (server ..) directly in the repl?

8:06 daniel__: ok :) with println it works :D

8:06 raek: daniel__: do you understand the difference?

8:06 daniel__: im sure i tried with (print before , shouldnt they be the same except for a (newline)

8:06 raek: yes

8:06 daniel__: raek, yeah i call it directly

8:07 the difference between prn and print i dont know

8:07 i will investigate

8:07 raek: between println and println-str

8:07 daniel__: oh, println-str prints to a string and then returns that string

8:07 and the while wasnt returning anything

8:07 raek: ,(pr '[foo "foo bar"])

8:07 clojurebot: [foo "foo bar"]

8:07 raek: ,(print '[foo "foo bar"])

8:07 clojurebot: [foo foo bar]

8:08 daniel__: print prints to *out*

8:08 raek: daniel__: exatctly

8:08 daniel__: im just puzzled why it didnt seem to work when i tried it with print before

8:09 raek: pr/prn/pr-str turns clojure data into strings so that they can be read again

8:09 print/println/str turns stuff into strings in random ways

8:09 daniel__: i see

8:11 wingy: how can i check the path of the current file?

8:11 daniel__: *file* wingy

8:12 includes the filename

8:12 wingy: daniel__: hmm Light Table returns nil

8:12 daniel__: its nil in the repl

8:12 not sure how light table works

8:13 wingy: nil in the repl as well?

8:14 damn i have a file opened but i dont know where its located

8:14 raek: wingy: a repl is not really in a file. (it is in a namespace though)

8:14 oh, maybe this was a light table specific thing

8:14 wingy: raek: yes

8:21 used grep to find it instead

8:32 darq: Hi. How can someone help me how to negate (membero 2 [1 2 3]) in core.logic? Instead of the goal to succed i want it to fail

8:36 daniel__: Does anyone have any advice for handing ctrl+c in the repl? I have a function running in a (while true .. which i sometimes want to break out of with ctrl+c .. the problem is, the next time i launch the function the repl crashes

8:36 i need to make sure i execute the finally block on ctrl+c

9:03 Neurus__: Hi, I'm starting with Clojure.

9:04 whats the sharp (#) sign? (map #(+ 10 %) [ 1 3 5 7 ])

9:04

9:05 andrewmcveigh: Neurus__: #(+ 10 %) is shorthand for (fn [a] (+ 10 a))

9:06 Bronsa: ,'#(+ 10 %)

9:06 clojurebot: (fn* [p1__27#] (+ 10 p1__27#))

9:06 Neurus__: tks andrewmcveigh , Tried googling but didn't find it :(

9:08 andrewmcveigh: Neurus__: np. It's not easy googling for #

9:18 Neurus__: really enjoing 4clojure.com

9:22 andrewmcveigh: Neurus__: yeah, it's a cool site.

9:58 ambrosebs: brainproxy: you might be interested in my work in statically typing algo.monads https://github.com/frenchy64/typed-clojure/blob/master/test/typed/test/monads.clj#L278

9:58 brainproxy: I saw your protocol monads fork with type related debugging

11:22 ebaxt: Is it possible to add login hooks when using friend?

11:36 hcumberdale: cemerick ..?

11:37 I'm trying to get started with friend

11:37 I like to use compojure

11:38 But I do not understand how the samples on https://github.com/cemerick/friend are connected to each other?

11:39 cemerick: hcumberdale: compojure

11:39 gah

11:39 hcumberdale: Hi cemerick

11:39 cemerick: hcumberdale: compojure is mostly just some routing and helpers around ring handlers, so the ring-only examples are equally applicable to handlers produced by compojure fns and macros

11:40 hcumberdale: And how does the "(friend/authenticate {:credential-fn " stuff work?

11:40 cemerick: hcumberdale: perhaps looking at the mock app used in friends tests would be helpful: https://github.com/cemerick/friend/blob/master/test/test_friend/mock_app.clj

11:40 hcumberdale: Do I need friend/authenticate when I use friend/wrap-authorize ?

11:40 cemerick: well, the map provided to friend/authenticate is configuration for the friend middleware

11:41 Yes

11:41 hcumberdale: Ahh, that's a bit disconnected to the compojure sample

11:41 cemerick: well, it's not a compojure sample per se, just a sample focused on authorization that happens to use compojure routes

11:42 hcumberdale: Ahh! ;)

11:42 cemerick I'm currently using sandbar

11:42 I forked it to fix the issue that it can not work with numbers as password

11:43 compojure/context & friend/wrap-authorize should be similar to a regex like "/user*" :user right?

11:45 cemerick: wrap-authorize (and everything else in friend) is entirely ignorant of whatever you're using for routing

11:45 hcumberdale: Does friend store the session in the default ring session store? So is it possible to stay with "(wrap-stateful-session {:store (session-store :sessions)})" ?

11:46 cemerick: Yes, friend presumes the use of ring sessions.

11:49 hcumberdale: So "friend/authenticate" does not mean that there is actually authentication?

11:50 It just means, it is there if authorize is used?

11:50 authorize or authenticated ...?

11:51 ebaxt: cemerick: Is it possible to add login hooks when using friend?

11:52 cemerick: hcumberdale: I'm not clear on your question...

11:52 ebaxt: login hooks?

11:54 hcumberdale: friend/authenticate does nothing if there is neither authorize or authenticated used?

11:56 cemerick: it establishes the scope within the app within which (a) a user may become authenticated, and (b) an authorization error will be automagically (i.e. by redirection to a login page, etc)

11:57 ebaxt: cemerick: a function called after login before redirecting. Or do I have to write a custom workflow?

11:57 hcumberdale: So friend/authenticate is like a "wrap-authentication-context"

11:57 cemerick: ebaxt: or add the hook to your credential fn

11:57 bbl

12:01 hcumberdale: Is there a html-form example for interactive-form ?

12:20 clojure.lang.ArityException: Wrong number of args (2) passed to: friend$authenticate$fn

12:20 mhhh

12:42 SrPx: Can you give help about clojurescript?

12:42 I am getting 'cannot set property error of undefined' when trying to run the compiled js of a simple hello world.

12:54 );

13:04 wink: hey, any clues how to get (let [x '(+ 2 3)] (+ 1 x)) work? (I know, taking off ' just works, but I happen to have a function call that I want to completely use as an argument, then call it)

13:06 malcolmsparks: (let [x '(+ 2 3)] (+ 1 (eval x))) ??

13:06 lazybot: malcolmsparks: Uh, no. Why would you even ask?

13:07 dspp: ,(let [x '(+ 2 3)] (+ 1 ~x))

13:07 clojurebot: #<IllegalStateException java.lang.IllegalStateException: Attempting to call unbound fn: #'clojure.core/unquote>

13:08 dspp: ,(let [x '(+ 2 3)] (+ 1 (eval x)))

13:08 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

13:09 _tca: what's the reason you want to use it as an argument also wink

13:10 does it need to be a list?

13:12 wink: _tca: well maybe it can be done more elegantly, but I basically have some wrapper function and I'm passing a block of (clojure.java.jdbc/update-or-insert-values) into it, so at the moment there's no db connection yet

13:19 malcolmsparks: wink, could you may be wrap your function in a delay, and then deref it once you have the db connection?

13:21 or just wrap it in a function?

13:22 wink: malcolmsparks: thanks, I didn't know about delay, works perfectly

13:23 Sgeo_: Is there a delay* ?

13:23 hcumberdale: friend :unauthorized-handler does not work ! ;(

13:24 malcolmsparks: I think that's an overblown solution, I'm regretting mentioning it because it should be possible to simply wrap in a function

13:24 eg.

13:25 hcumberdale: https://www.refheap.com/paste/6524

13:25 malcolmsparks: (let [x (fn [] (+ 2 3))] (+ 1 (x)))

13:25 ie. so that evaluation is delayed until the db connection is in scope

13:25 hcumberdale: https://www.refheap.com/paste/6525

13:26 malcolmsparks: delays have extra semantics (memoization) that you don't need

13:27 but delays are useful to know about - I use them for somewhat expensive operations (eg. looking up a static value in a database that won't change)

13:27 where I don't want to pay for the database query until the value is actually needed

13:27 and when I know it won't change so don't want to visit the database each time the value is required

13:28 wink: hm, yeah

13:28 malcolmsparks: thanks, used fn now :)

13:29 malcolmsparks: is this the right channel to ask core.logic questions? or is there a dedicated irc channel for that

13:29 wink: I still don't really get why in one direction it's like this: (1 2 3) => cannot execute function named "1", but on the other hand I can't call something like '(1 2 3)

13:30 malcolmsparks: '(1 2 3) is a list (data) because you're quoting it

13:30 (1 2 3) is the function '1' with two arguments (2 and 3)

13:31 since '1' isn't a function, you get an error

13:31 wink: yes

13:31 malcolmsparks: as soon as you present the special form (a ...) to clojure it gets excited and tries to apply it immediately

13:32 btw. 'apply' means run the function named in the first item of the list with the arguments in the rest of the list

13:33 wink: wait, that works?

13:36 malcolmsparks: I'm not sure how that would work besides: (def x ["str" "a" "b"]) (apply (eval(read-string (first x))) x)

13:41 malcolmsparks: wink, I'm not sure what you're asking

13:41 can you rephrase?

13:42 wink: malcolmsparks: I'm not asking this time, I'm questioning " 'apply' means run the function named in the first item of the list with the arguments in the rest of the list"

13:44 SrPx: Anyone has an idea why clojurescript is not working here ? http://stackoverflow.com/questions/13324490/getting-cannot-set-property-error-of-undefined-when-trying-to-run-the-js-outp#comment18177550_13324490

13:45 malcolmsparks: Here's a list: (1 2 3) - but if it isn't quoted Lisp sees this as a 'special form' and evaluates it, that's all I meant. The rule for evaluation is to consider the first item of the list (a) to be the function, and it is given b and c as arguments.

13:45 (a b c)

13:46 wink: yes of course, but core/apply takes 2 arguments. not one, even if it's a list. or am I mistaken?

13:50 malcolmsparks: ah, I see the confusion, I didn't mean core/apply when I used the word 'apply'

13:50 tomoj: SrPx: maybe try putting [org.clojure/clojurescript "0.0-1535"] in your dependencies

13:50 malcolmsparks: clojure.core/apply takes 2 args yes, the first is the function, the second is the list of args

13:50 tomoj: SrPx: and run lein cljsbuild clean I guess..

13:51 kinda strange to me that cljsbuild magically includes a cljs dependency

13:52 SrPx: tomoj: :dependencies [[org.clojure/clojurescript "0.0-1535"]] , with the double [[]] right

13:52 tomoj: yeah

13:53 SrPx: tomoj: thanks but nothing. ):

13:53 tomoj: I know some nodejs problems were fixed recently, can't remember if your error was one of them

13:53 SrPx: Just downloaded it today ;/

13:54 Wait actually, I'm not sure. Can I redownload the :plugins [[lein-cljsbuild "0.2.9"]] ?

13:54 tomoj: no need

13:55 SrPx: Hmm. Perhaps it's node.js's fault?

13:57 Wow it workeeeed.

13:57 Can't believe (: just ran "lein deps"

13:58 Oh and lein cljsbuild clean as you said

13:58 probably was that

13:58 tomoj: huh..

13:58 I tried it and got a similar but different error

13:58 SrPx: What?

13:58 clojurebot: What is @

13:58 SrPx: Which*

13:59 tomoj: uncommenting `:optimizations :simple` made it almost work

13:59 which is odd - I thought the cljs compiler defaulted to :simple for node

14:00 but then I also needed https://www.refheap.com/paste/2cdbc41ebdb9771ae45bfaad7

14:01 to avoid a different error

14:01 SrPx: 'almost work'?

14:02 tomoj: well 'almost work' in that unless I set! *main-cli-fn*, I still get an error

14:02 which is expected

14:03 strange though, even if cljsbuild told the compiler to use :whitespace, I'd thought it would still use :simple

14:04 SrPx: hmm

14:04 (:

14:05 tomoj: I'm surprised (js/console.log "hello") works - I always do (.log js/console "hello")

14:11 amalloy: Sgeo: delay*? wouldn't that just be fn?

14:13 or maybe identity, since i assume delay* would be passed a function rather than an expression body

14:14 tomoj: memoize?

14:15 amalloy: maybe

14:16 mudge: just curious what people's favorite clojure books are

14:16 tomoj: I guess memoize might still execute the function more than once?

14:17 &(let [f (memoize (fn [] (do (println "called!") 42)))] (future (f)) (future (f)))

14:17 lazybot: java.lang.SecurityException: You tripped the alarm! future-call is bad!

14:19 tomoj: delay's mechanism for ensuring the fn is only called once seems magic

14:20 oh, guess not. deref is synchronized

14:22 SrPx: Why it wouldn't work?

14:23 I don't understand clojruescript's approach. 20k lines? Why not just compile to readable javascript? Is it impossible? Or because this way it is optimized?

14:33 amalloy: tomoj: yeah, memoize can call twice. it's a fun little exercise to write a version that never does (but it comes out to be substantially slower than memoize, so presumably the tradeoff was made on purpose)

14:36 hcumberdale: SrPx what are you doing with clojurescript?

14:36 Have not tried it,...

14:37 SrPx: At the moment nothing special, just learning how it works

14:37 I'm trying to get parenscript to work now , to compare them

14:38 Drakeson: is there a straighforward bridge between a dialect of scheme and javascript?

14:40 hcumberdale: SrPx what is a possible usecase for clojurescript?

14:40 replace jquery? ;)

14:45 cmn: sure, or the power goes out, or your cat stays too long on your laptop's power button

14:45 sorry, wrong window

14:49 SrPx: hcumberdale: program things ?

14:49 hcumberdale: not replace jquery, you'll probably use it with clojurescript

14:50 hcumberdale: clojurescript is just a language that compiles to javascript and people using it are probably those who don't like javascript's syntax and stuff and prefer to code in a better language

14:51 Drakeson: that's what I was wondering too

14:51 Drakeson: if you find something please tell me, but it doesn't seem to be the case

15:03 jamii: http://i.imgur.com/6g8Fh.jpg

15:03 Clearly working hard here...

15:07 tomoj: amalloy: shit

15:07 I used memoize wrongly

15:07 amalloy: eh?

15:07 tomoj: I knew it felt fishy at the time

15:08 (fn id-factory [part] (memoize (fn [& args] (datomic.api/tempid part))))

15:09 only one thread touches that right now, but that could've been hell later..

15:11 I wonder thought whether that is a dangerous use of memoize or a bad idea generally

15:46 zackzackzack: If I want to shush log4j when I am running lein tests, where should I put the log4.properties file?

15:48 darq: Hi. (run 3 [q] (without [:a :b :c] [:a] q)) => (:b :c) ? is there a way in core.logic to get ([:b :c]) so that the result is in a vector

15:52 dakrone: zackzackzack: you should be able to put it anywhere in your resource path, you can either set :resource-paths in lein2, or put it in the 'test' folder so it'll only take effect while testing

15:54 zackzackzack: dakrone: Haha! Into the test folder it goes

16:13 amalloy: (list (vec (run ...)))

16:14 tomoj: &(assoc {} 1 2 3)

16:14 lazybot: ⇒ {3 nil, 1 2}

16:14 amalloy: pffft

16:16 raek: hrm, I have a problem with aleph (or gloss, more specifically). when I try to read lines from a socket using :delimiers ["\r\n" "\n"], lines don't "get through" until the next line is sent...

16:16 when I use :delimiers ["\n"] it works correctly

16:17 amalloy: raek: i assume you're spelling delimiters right in your real code?

16:19 tomoj: not being able to use your own libraries in a transaction fn seems cumbersome. I'm tempted to try to macroexpand on the peer that defines a fn, but that seems.. bad

16:19 raek: amalloy: yeah

16:22 amalloy: raek: https://github.com/ztellman/gloss/blob/0.2.2/src/gloss/data/bytes/delimited.clj#L48 looks like it might be relevant. i can't see the details, obviously, but it looks like it might be saying "the largest delimiter i might find is size 2, therefore i need two bytes to start looking for a delimiter"

17:04 tomoj: warning, if you accidentally say :db.type/ref when you mean :db.type/long, datomic will happily oblige

17:05 Cubic: Why does loop need to be a special form? Couldn't it have been a macro that evaluates to a fn?

17:07 amalloy: just performance. let could be a macro too, but even scheme isn't that wasteful

17:11 augustl: how do I create a multimethod that dispatches on whether an arg is a string or a function?

17:12 (class (fn [])) is "user$eval952$fn__953", not sure how to write a defmethod that dispatches on that..

17:14 Cubic: Dispatch on keywords :string and :function, and then just check in the dispatch function for string? or function?

17:14 ,(doc string?)

17:15 clojurebot: "([x]); Return true if x is a String"

17:15 Cubic: ,(doc fn?)

17:15 clojurebot: "([x]); Returns true if x implements Fn, i.e. is an object created via fn."

17:15 augustl: hmm

17:15 amalloy: augustl: IFn

17:19 Cubic: amalloy: I guess that depends on whether he wants ifn? or fn?

17:19 amalloy: sure

17:21 augustl: ended up just doing an if/else ;)

17:22 getting "signing failed: No secret key" when trying to deploy to clojars with leiningen, is the process of "lein deploy clojars" documented somewhere?

17:22 amalloy: http://www.antiifcampaign.com/ always makes me laugh

17:23 tomoj: use objects to build a code!

17:24 bosie: vim (vimclojure) question: closing the vimclojure window with ^c screws with it as i can't seem to reopen it. it always throws a "cannot find my window" exception

17:28 nvm, found it

17:40 yedi: is chris granger still streaming?

17:53 muhoo: mudge: i like clojurebook.com, if you're coming from a web-dev, non-fp background

17:54 mudge: muhoo: does it teach the fp way to program?

17:55 muhoo: mudge: it's more "here's how to use clojure (and fp) to Do Stuff".

17:55 mudge: muhoo: cool

17:55 muhoo: very practical. it certainly does use idiomatic, clojure/fp ways of doing stuff, but the focus is on practical tasks

17:56 Raynes: First of all, monads are like burritos.

17:56 You'll be fine now.

17:56 muhoo: Raynes: the morning after, not so much.

17:56 * muhoo burps

17:57 mudge: *farts*

17:58 muhoo: Raynes: i haven't messed with haskell much, but monads smell a bit to me like something that had to be invented to get around haskell's BDSM type system, much the way design patterns had to be invented to get around limitations in OOP

17:59 Raynes: muhoo: Get out of my internet.

17:59 muhoo: hehehe

18:00 amalloy: muhoo: you made that statement yesterday, but i don't think you listened to or noticed any of the counterarguments

18:00 muhoo: don't think i saw them, actually. must scroll back.

18:01 amalloy: it's like saying that parens had to be invented to fit the ludicrous requirements imposed on lisp by macros

18:01 Raynes: muhoo: Monads weren't actually created for Haskell, right? It was Opal.

18:01 amalloy: Raynes: for mathematicians first :P

18:02 Raynes: Yeah, but mathematical monads are different, right?

18:02 amalloy: naw

18:02 Raynes: Wikipedia says they "are not identical"

18:02 amalloy: well. i'm not an expert on category theory by any means

18:03 Raynes: muhoo: Why do you hate the Haskells?

18:04 It's so much fun.

18:04 I've been writing random crap in it just for the sake of it.

18:04 muhoo: i don't. i'm sure i'll learn it at some point.

18:04 amalloy: thanks, the discussion happened after i was AFK, and looks very informative.

18:38 augustl: should I ever do the transient/persistent thing when building collections without first making sure it's actually a performance reason to do it in my system? :)

19:06 Cubic: augustl: what thing?

19:48 Awesome. Just spend two hours fixing a bug that happened because I thought that '(start)==(list start) for some reason (I kinda knew it wasn't, but that slipped past me right now)

19:55 hughfdjackson: Cubic: painful experiences make for better programmers :D

19:55 hopefully..

19:57 Cubic: I guess. Made me realize that I could use a vector just as well as a stack as a list.

21:02 XPherior: So I've been messing around with this concept of seeding a database without knowing the concrete types. Does this make sense to anyone else? http://michaeldrogalis.github.com/dibble/

21:12 fluke777: Hi everybody. I have a problem with proxy. I am using this code https://gist.github.com/4053357 to call a visitor which create AST as it goes. For testing purposes I just change the state once I enter the method visitMetricExpr. What baffles me is that when I run it in REPL (nrepl) it always return 3. When I package to a jar use reply to run the exact same code it returns one. I am kinda lost not really sure where to look. Can anyone take a look and maybe

21:12 something completely stupid that I am doing?

22:51 augustl: any suggestions for option parse libraries other than clojopts? It seems to not handle operands at all

22:52 hmm, seems that the actual problem is that it doesn't support --foo 123, only --foo=123

22:53 amalloy: augustl: really? it uses the java port of gnu getopt, which i thought accepted both

22:53 i wrote clojopts but haven't touched it in over a year; there's a contrib lib that's probably more maintained

22:53 augustl: a http://pubs.opengroup.org/onlinepubs/9699919799/ compliant jvm option parser would be nice :)

22:54 I not sure if gnu getopt is posix compliant

22:54 the biggest problem is ambiguities really, -bar can mean -b -a -r and -b=ar

22:54 and so on

22:55 already wrote one, but for Node.js ;) https://github.com/busterjs/posix-argv-parser

22:55 amalloy: i don't think that's an ambiguity; you just have to define whether b accepts a value, and whether a/r are valid options, after which there's a nonambiguous parse

22:56 augustl: indeed, as long as it's possible to define it beforehand it should be all good

22:57 here's my code, https://www.refheap.com/paste/6533, running that with "lein run --port 4224" prints {:clojopts/more (4224), :port nil} for `opts`

22:57 but --port=4224 works

22:57 interestingly enough -p4224 doesn't, even though the help output says it does :)

22:58 uh nvm I did --p4224

23:00 http://commons.apache.org/cli/ looks pretty good

23:00 amalloy: augustl: if you say the arg's value is optional, then --port 4224 isn't attaching the value

23:01 if you switch from optional-arg to with-arg, i think those both parse the same

23:02 afaict that's how getopt in c behaves also, if you say the arg is optional

23:05 augustl: amalloy: ah, I see

23:12 the apache commons lib worked just like I wanted :) https://www.refheap.com/paste/6534

23:16 brainproxy: looking to switch some deftype things over to defrecord, but upon doing so I'm getting exceptions in the REPL re: print-method

23:16 that is, as a multi-method it's not sure which dispatch to prefer

23:17 what I'd really like is to have the same print-method impl that deftype gives me

23:20 devth: when using :keys in a fn's args list, can you do additional destructuring? e.g.: (defn f [{:keys [a]}] a), then i call: (f {a: [1 2 3]}) and i only care about 3.

23:21 seems like i'd have to do another separate round of destructuring in a let form - just making sure i'm not missing something.

23:22 amalloy: no. just don't use the :keys shortcut

23:23 (let [{[_ _ x] :a} m] ...)

23:26 augustl: did that fix your problem?

23:27 devth: amalloy: ah, hadn't thought of that. ty

23:29 augustl: amalloy: yup!

23:30 jamii: Turns out you can just wing emacs list - https://gist.github.com/4053713

23:30 Seems to work

Logging service provided by n01se.net