#clojure log - Apr 04 2014

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

2:18 haole: if I have a function that returns other functions, what is a good word to give it a "type"? generator? factory?

2:18 I don't know what to call my "foo" function generator :D

2:18 what suffix to use or something like that

2:18 arrdem: haole: partial? :P

2:19 haole: or you could just leave a comment with a type signature of the retuned function... :P

2:19 haole: arrdem: partial is perfect... forgot about it :)

2:19 thanks

2:45 clojure is really impressive, btw... I've managed to implement a proof of concept of something that was entirely theorical so far in 50 lines of clojure, and the previous attempts of doing it were using thousands of lines of (badly written) Java

2:45 \o/

2:46 ssafejava: yeah, clojure is a fun language, hard to believe it sits on the jvm sometimes

2:46 TEttinger: haole, proof of what concept, I wonder?

2:49 haole: TEttinger, adaptative automatons

2:49 TEttinger: like cellular automatons?

2:49 haole: there are implementations, but none of them of a second degree adaptative automaton, which is what I was talking about

2:49 no... from computer science

2:49 sorry

2:49 automata

2:49 lol

2:50 weird plural from latin

2:50 and I'm sleepy :)

2:50 TEttinger: yep I have no idea what those are

2:50 haole: TEttinger: do you know state machines?

2:52 TEttinger: think state machines that can add/remove states/transitions on every transition activation

2:52 TEttinger: yeah, just scanned the wikipedia article on automata theory :)

2:52 oooh

2:52 haole: it's supposed to be useful for AI

2:52 that's what my group is studying right now

2:52 TEttinger: so sorta non-finite FSMs?

2:53 haole: yeah, but you have a finite set of "adaptative" rules

2:53 it's not complete chaos :D

2:53 rule = what adds/removes stuff on a transition

2:53 TEttinger: sure

2:54 that can't be purely theoretical can it? I guess the second degree is that part?

2:59 well that's great that you wrote an order of magnitude less code and got a better result!

3:00 oh he quit

3:03 arrdem: thoughts on these last two fns? I'm trying to decide if I'm doing something evil here or not...

3:03 https://github.com/arrdem/geri/blob/master/src/geri/aspects.clj#L98

3:03 this sort of multiple inheritance is nice... but it leaves a bad taste in the mouth.

3:09 amalloy: arrdem: i mean, while i won't comment on levels of evil because i can't figure out what this is intended to do, that macro should just be a function

3:10 extend is a function, not a macro, and you're evaluating all of your args exactly once in an ordinary context. you're not using any features of macros

3:11 oh, but you have this fnmap thing, i guess

3:11 arrdem: yeah but fnmap is also just normal eval with no need for syntax gen

3:12 amalloy: the idea here is that if I use defaspect above, it kicks out a protocol which is nice to work with.

3:13 I'd like to be able to do inheritance by composition, so this function turned macro is just a tool for being able to wrap the implementation of a aspect with a partial evaluation to extract a member field.

3:14 so really it's just shorthand for punting the implementation to the appropriate member.

3:14 which already has one, presumably.

3:30 ddellacosta: when the channel that a mult was created from is closed, does that close all the taps and wipe out the mult?

3:31 Viesti: hum, any recomendations for doing authentication with ring (found cemerick's friend)?

3:33 ddellacosta: I would start with Friend, in my opinion there's not much else out there unless you want to wrap up some Java solutions (Shiro, for example)

3:42 Viesti: ddellacosta: thanks

3:43 ddellacosta: Viesti: sure thing

5:14 tuft: is there an alternative to (into {}) for constructing a map without specifying concrete type?

5:25 clgv: tuft: what do you mean by "without specifying concrete type"?

5:42 xsyn: morning

5:42 (just)

5:48 ddellacosta: xsyn: morning, or, evening from Asia. ;-)

6:54 kras: :key is a keyword, what is this ::my_key

6:55 noidi_: a namespaced keyword

6:55 kras: does it belong to the current namespace?

6:55 noidi: yes

6:56 it gets expanded to :my.namespace/my_key

6:56 kras: (equal *ns*/:my_key ::my_key)

6:57 noidi: and if you have other.namespace aliased as o, you ::o/key is expanded to :other.namespace/key

6:57 kras: thanks noidi

7:26 djpowell: So... om. If I want to pass a value down to a sub component I can either use init-state or grafts?

7:27 Are grafts more suited to values? But I can't use grafts with build-all?

7:30 Or should I be using :opts

7:35 ambrosebs: anyone used tools.analyzer to scan inside jar files? It seems to completely ignore .clj files in jars.

7:36 trying to figure out how to get a list of directories inside a given jar

7:45 Bronsa: ambrosebs: use io/resource

7:45 clojure.tools.emitter.jvm> (clojure.java.io/resource "clojure/core.clj")

7:45 #<URL jar:file:/home/bronsa/.m2/repository/org/clojure/clojure/1.6.0/clojure-1.6.0.jar!/clojure/core.clj>

7:47 ambrosebs: Bronsa: I was using clojure.tools.namespace.dir/scan which needs a sequence of directories to scan.

7:48 apparently it's foiled by jars

7:50 Bronsa: ambrosebs: dunno, it works in eastwood, let me look at how Andy implemented this

7:52 mh nevermind, clojure namespaces don't run through tools.namespace

7:55 ambrosebs: Bronsa: there's something weird going on with resolving classes after analysing them in core.typed https://groups.google.com/d/msg/clojure-core-typed/Y9TpTeexarg/D4dRJjcvmjMJ

7:55 I think this is similar to something I mentioned to you before

7:55 Haven't looked further

7:57 probably some weird classloader issue

7:57 Bronsa: definitely a classloader issue

7:58 I'll try to see if I can reproduce a minimal case

7:58 ambrosebs: thanks!

8:04 Bronsa: ambrosebs: I think I see where the problem is

8:04 https://github.com/clojure/core.typed/blob/master/src/main/clojure/clojure/core/typed/check.clj#L4995-L4997

8:05 ambrosebs: that Class refers to a stub class used by tools.analyzer.jvm to reflect on it

8:06 after the evaluation, that class is overridden in the classloader by the compiled one

8:06 so clojure.reflect/reflect complains that it cannot find it on the classpath because it's been replaced with the new one

8:07 ambrosebs: Bronsa: so I should always get a new one before reflecting?

8:07 Bronsa: yeah

8:08 ambrosebs: cool. Rushed through :deftype*, didn't really understand what was happening.

8:08 Bronsa: ambrosebs: I'm not 100% sure that this is what's causing the exception Sean is having but it would make sense

8:08 you can see from the stacktrace that's choking on clojure.core.typed.check/deftype-method-members

8:10 ambrosebs: Bronsa: so class-name is always a class?

8:10 Bronsa: yes

8:11 irctc: I'm new to this. Can I ask literally anything here?

8:11 Bronsa: ambrosebs: https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/jvm.clj#L328 just added a comment :P

8:13 ambrosebs: Bronsa: is :name the full class name?

8:13 irctc: I have a question, can I get help here?

8:13 yotsov: irctc: I am new here as well, but from what I have seen, any clojure-related questions are just fine here, so just go ahead :)

8:13 Bronsa: ambrosebs: no, just call (.getName ^Class class-name)

8:13 irctc: I am trying to deploy a webapp to heroku, but I don't know why it won't deploy. I think it might have something to do with the database connection settings

8:14 ambrosebs: Bronsa: so (-> class-name u/Class->symbol u/symbol->Class) is pretty much what I want?

8:14 Bronsa: ambrosebs: yeah, that should do it I think

8:14 ambrosebs: cool

8:15 Bronsa: ambrosebs: in some future t.a.j release I might stop generating stub deftype classes and just add a hook in the reflector

8:15 irctc: I get this error: 2014-04-04T11:49:42.457401+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path=/favicon.ico

8:15 Bronsa: doing this would mean having to make all :class fields symbols, like clojure.reflector does though

8:16 pyr: hi guys, running into something that's a bit more of a java issue but I thought I might ask

8:17 i have to read in double data from a bytestring that is serialized in C by just writing out the address space for the double

8:17 yotsov: irctc: have you added a favicon to your webapp? does heroku expect you to have one?

8:18 pyr: so I have two questions: 1. are double stored the same way in memory on the JVM and in C, 2. is there a way for me to read in a bytestring or byte-array to a double ?

8:19 irctc: I don't know what a favicon is. What is it? and how do you do that signal when you respond to me?

8:19 clgv: pyr: there is a distinction between primitive doubles and double objects on the JVM

8:19 pyr: clgv: so primitive doubles will be similar to C doubles and double objects will be something else entirely I suppose

8:19 clgv: pyr: yes

8:20 pyr: java.nio has so called Buffers where you can easily switch from byte to double

8:20 yotsov: irctc: http://en.wikipedia.org/wiki/Favicon regarding second question, depends on your irc client, in my case I just doubleclick on your name

8:21 pyr: clgv: ok, will look into this, thank you

8:21 clgv: ok, got it, if storage is the same, this will be a breeze, cheers

8:23 irctc: okay you are helping me out. So it is crashing on the get for a favicon, which is a little 16X16 graphic that I am supposed to provide on that request?

8:23 wtf haha

8:24 I've deployed other apps on heroku and never had this problem

8:27 yotsov: irctc: surprising indeed, it might be some other problem in disguise. Such as, your webapp might be crashing on any request, and the favicon request might happen to be the first one incoming. Hard to tell

8:29 PeakCode: I believe the app is already crashed when the request for /favicon.ico comes in.

8:30 falsetto: I'm trying to recall a tool I saw about a year ago that's probably most similar to make. It allows one to write a script to transform data through a discrete number of steps and is implemented in Clojure. Anyone know what I'm talking about?

8:30 yotsov: falsetto: Storm ?

8:31 falsetto: sorry, that's not similar to make

8:31 falsetto: Thanks though :)

8:31 I remember what the page looked like and everything. Dammit. Should have used Delicious :(

8:33 Found it! Yay :) https://github.com/Factual/drake

9:14 AeroNotix: long shot but is anyone using authorize.net?

9:59 oinksoft: i'm using leiningen w/ checkouts. I can require the checkout out project, but I get "could not find artifact foo:projname:jar:VERSION in clojars". the project is checkout out to ./checkouts/projname. the dependency is [foo/projname "SOMEVERSION"]

10:00 but if I comment out the dependency line, i can run `lein repl` and require things from the checkout out library

10:04 jph-: i wonder if there's like a message-queuing system, but just for one app's consumption... ala sqlite

10:04 likewise an sqlite-like redis

10:05 mdrogalis: jph-: Redis isn't exactly a queueing system.

10:05 jph-: mdrogalis, no, but i also look at things like sidekiq that kinda do what i'm looking into

10:05 and that uses redis as backend

10:06 it was more about having something redis-like that wasn't a full-blown network service

10:06 ie how sqlite isn't a full blown database server

10:06 mdrogalis: jph-: You can always run a lightweight queue

10:06 Got'cha.

10:06 jph-: im beginning to discover that queuing is a big topic area

10:06 heh

10:06 i started with core.async and lamina and then started looking further afield

10:07 the rabbitmqs, the sidekiqs

10:07 looking at how this stuff is done in different places

10:07 ie if i want to look inside a queue, persist a queue, modify a queue

10:07 mdrogalis: jph-: Maybe https://github.com/Factual/durable-queue ?

10:07 jph-: oh that looks lovely

10:08 i shall star it right away

10:08 this is kind of where clojure-toolbox lies to me... or rather, if i dont see it on the toolbox, i assume something like it doesnt exist

10:09 i was beginning to consider things like sqlite or in-memory datomic for something queuey

10:09 this looks really nice, thank you

10:09 (inc mdrogalis)

10:09 lazybot: ⇒ 4

10:09 mdrogalis: Anytime

10:10 Aww yeah up to 4 :P

10:11 jph-: this is for queuing trading api requests

10:11 so something reliable is necessary

10:12 mdrogalis: jph-: Reliable as in highly available? Strongly consistent?

10:12 I can help you pick something if you're clear about your reqs.

10:12 jph-: if you throw 100 API requests at it, and any fail, you know which failed and can do something about them

10:13 rootex: couchdb

10:13 jph-: and if you throw 1000 and something changes, you can flush the queue, or otherwise halt processing

10:13 hrmm

10:13 i've done some work with couchdb but i havent thought about it in that context

10:14 * jph- puts on his thinking cap

10:14 mpenet: jph-: durable-queue from factual comes to mind

10:14 jph-: mpenet, you were pipped to the finish line, already recommended :)

10:14 mpenet: ah :)

10:15 jph-: what's the idiomatic way of specifying configuration options to a clojure library you're using?

10:15 mdrogalis: jph-: HornetQ supports transactions.

10:15 Might be worth looking at.

10:15 jph-: mdrogalis, i'll have a look

10:17 durable-queue looks like a lightweight sidekiq/resque in a library

10:17 in other words, rather neat

10:22 mdrogalis: I feel like being able to performance tune one strong queuing system and one database for write throughput are hella valuable skills.

10:22 It's just nice to have that immediately sometimes.

10:34 jph-: hrmm

10:54 oskarth: I'm having issues with clj-http and java / Startcom ssl cert leading to a "unable to find valid certification path" error when calling an external API. 1. Would this be solved using http-kit? (others have hinted at this) 2. Is there something else I can do?

10:55 dakrone: oskarth: can you gist a full stacktrace?

10:55 oskarth: dakrone: can I pm link to you?

10:56 dakrone: oskarth: sure

10:56 jcromartie: oskarth: you need to add the cert to a truststore

10:58 jph-: oskarth, i had exactly the same issue

10:58 from memory it was a oracle java7 issue

10:59 oskarth: jph-: so it was on the java installation level? using openjdk

11:00 jph-: yep, i think i have some bookmarks from last time

11:00 oskarth: I found this thinghttp://www.ailis.de/~k/uploads/scripts/import-startssl

11:00 http://www.ailis.de/~k/uploads/scripts/import-startssl *

11:00 was it somethign like this that you did?

11:01 insamniac: you should be able to use keytool to import the cert, and pass the truststore location as a java option

11:01 jph-: oskarth, yes that exact script

11:01 also https://stackoverflow.com/questions/4302686/import-startcom-ca-certificates-in-windows-jre

11:01 oskarth: okay cool, I'll give it a shot. Thanks all :)

11:01 insamniac: oh i see, that's what that script does!

11:02 jph-: i encountered it trying to get jitsi (jabber client) to talk to servers using startcom certs

11:02 oskarth: does anyone have any good resources for grokking SSL? I really don't have a good mental picture of it all and what is causing what and where

11:02 jph-: you shouldnt have to, that's the problem

11:03 it's incredibly complex and libraries should do the work for you

11:03 oskarth: right, guess java is failing in that regard? :p

11:03 jph-: your problem is due to one cert provider not getting their CA added to java cert store

11:03 no, the cert provider

11:03 same problem happened recently with a godaddy CA

11:03 oskarth: oh. Is this specific to my "cert tree" and not a general problem?

11:03 ddellacosta: oskarth: https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet

11:04 oskarth: I don't understand who's vetting who and why really, like where does this Startcom business come in

11:04 ddellacosta: thanks

11:04 jph-: oskarth, this is due to something missing in your cert store, that the provider should have ensured was present

11:04 oskarth: jph who's the provider?

11:05 jph-: oskarth, startcom

11:05 since they didnt get their CA certs into the cert store, your apps dont trust them

11:05 oskarth: I see, so I can blame then then!

11:05 jph-: yes

11:05 its the same as encountering a self-signed SSL cert in the wild

11:05 jcromartie: in Ruby, you would just ignore all SSL errors :)

11:06 https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html

11:06 jph-: well with http-kit i use insecure? false

11:06 so i dont get that choice

11:08 after looking at durable queue i kind of want a durable-queue-like backed lamina

11:08 heh

11:08 or persistent lamina channels

11:22 mpenet: probably easy to do, aleph a someting a bit similar with redis

11:23 lgs32a: cemerick: Do you have a hint what the reason could be when emacs suddenly decides to shiver while I am running a piggieback session? company-complete was disabled

11:24 cemerick: lgs32a: "shiver"?

11:24 mpenet: jph-: https://github.com/ztellman/aleph/blob/master/src/aleph/redis.clj#L115-L134

11:25 one way though

11:25 jph-: mpenet, i was just chatting with someone about the async lamina queue i was testing

11:25 https://gist.github.com/jphackworth/9976671

11:25 https://gist.github.com/jphackworth/9976727

11:26 lgs32a: cemerick: emacs starts using the cpu around 30%, jvm around 10% without any particular reason, emacs mode line starts slightly shivering, only workaround is to restart the cider session

11:26 jph-: doesn't do the persistent stuff, or retries, but the client can find out the result of their queued job

11:26 cemerick: huh

11:26 lgs32a: never seen that

11:26 lgs32a: reall?

11:26 cemerick: lgs32a: AFAICT, eldoc sometimes causes bad things to happen on a ClojureScript session, but I've never seen "shivering"

11:27 lgs32a: i have eldoc disabled as well

11:27 i had the problem with older emacs/nrepl combinations as well

11:31 cemerick: lgs32a: perhaps some other modes conflicting / causing problems. Yours is the first report I've heard.

11:32 lgs32a: cemerick: I'd love to debug. can you give me a hint where I can log all ops that are received by piggieback?

11:33 cemerick: lgs32a: it'd require a top-level middleware that dumps requests and responses somewhere. I've actually written it 10 different times, but never kept it around. :-/

11:35 jph-: mpenet, i havent tried aleph before, but i like the look of that redis/aleph combo

11:36 lgs32a: cemerick: thanks, I'll try something like that.

12:38 pdk: what's the verdict on clojure cookbook

12:38 bjorkintosh: cook it first.

12:44 bbloom: meanwhile, in #ruby, there is a guy who consistently tries to write "bbl" but accidentally writes "bbloom: ", so when I come back to my desk, I get to see the ongoing conversation about people who can't find a bug bug in production, but everybody assumes it's related to the fact that he's monkey patching the date time class

12:45 ambrosebs: haha

12:46 justin_smith: the foolishness of trying to tab-complete a tla

12:47 bbloom: it had not occured to me before that your nick could be parsed as "be back later, out of memory"

12:47 bbloom: justin_smith: haha, awesome

12:48 justin_smith: I guess bbloom would be an apropriate acronym for ruby users "shit, better start quitting random apps, memory is gone again"

12:48 * gfredericks patches test.check to expose the current most-shrank value for transparency during shrinking marathons

12:49 technomancy: justin_smith: that's big talk for someone whose runtime uses utf-16 =P

12:49 bbloom: ambrosebs: try to type check this, punk! https://github.com/marcel/aws-s3/pull/14

12:49 * bbloom does not miss ruby, especially when he has to use it for a client

12:50 ambrosebs: :)

12:50 TimMc: technomancy: OH SNAP

12:50 bbloom: ambrosebs: wow, that was 4 years ago... time flies when you're const_missing

12:50 justin_smith: technomancy: yeah, but the jvm has an arbitrary upper limit that makes it crash, which is like much better, right?

12:51 TimMc: http://static.fjcdn.com/gifs/Guuurl_a72cd9_2202093.gif

12:51 technomancy: riiiiight

12:51 http://p.hagelb.org/ram-gone.png

12:58 mikerod: ,(instance? String)

12:58 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/instance?>

12:59 mikerod: weird. the repl is letting me do that and returning nil

12:59 ambrosebs: mikerod: which version of clojure are you on?

12:59 mikerod: I must have something messed up..

12:59 {:major 1, :minor 5, :incremental 1, :qualifier nil}

12:59 ,*clojure-version*

13:00 clojurebot: {:major 1, :minor 6, :incremental 0, :qualifier nil}

13:00 ambrosebs: mikerod: I seem to remember this issue. Something to do with inlining.

13:00 mikerod: ambrosebs: it gave me a sneaky bug

13:00 not sure if it existed outside the repl env though

13:00 bbloom: mikerod: try (apply instance? String [])

13:00 pyrtsa: mikerod: My Clojure 1.5.1 REPL returns false. Wow, didn't know of that bug.

13:01 mikerod: bbloom: I get: ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)

13:01 TravisD: technomancy: That is my favourite picture of yours

13:01 mikerod: pyrtsa: it snuck up on me

13:01 bbloom: this is what happens when inlining is hacked by hand rather than properly integrated with the compiler... which is what happens when you write your compiler in java and then invent clojure, making you never want to write java again

13:01 mikerod: I had an `(if (instance SomeClass) "then part" "else part")`

13:01 I always got the "else part" and I didn't realize my arity issue

13:02 bbloom: hah, so this is a known issue addressed in 1.6?

13:03 what is the scope of the issue too? I'd be interested to read up on it, but I guess I could just go trace through it and see if I can understand it. :)

13:03 seangrove: dnolen_: Just got a request in #sfcljs to create an Om users group

13:03 bbloom: mikerod: seems so based on what we're seeing & what ambrosebs said

13:03 ambrosebs: probably http://dev.clojure.org/jira/browse/CLJ-1171

13:03 seangrove: dnolen_: Time for you to pare Om down into something that doesn't require a users group ;)

13:04 mikerod: ambrosebs: oh nice

13:04 so this may just relate specifically to instance? perhaps; that's a bit better.

13:04 pyrtsa: mikerod: Another funny little thing is that instance? and isa? have their arguments in different order: (instance? Object "") vs (isa? String Object)... :)

13:05 ambrosebs: mikerod: correct

13:05 mikerod: pyrtsa: I agree, that confuses me

13:05 just have to look at the signature closely

13:05 ambrosebs: thanks for the link/info

13:05 TimMc: nigh unto PHP-like

13:05 bbloom: (doc isa?)

13:05 clojurebot: "([child parent] [h child parent]); Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy"

13:06 bbloom: weird. isa? seems backwards to me

13:06 technomancy: bbloom: srsly

13:06 pyrtsa: bbloom: Compared to, say the comparison operators?

13:06 TimMc: No, that one makes sense to me.

13:06 pyrtsa: I think isa? makes sense indeed.

13:06 bbloom: pyrtsa: < makes perfect sense if you just read it as if it were spelled "asc"

13:06 TimMc: (< a b) is a < b; (isa? a b) is a isa? b

13:06 pyrtsa: What TimMc said.

13:07 technomancy: when most people use "X is a Y" in english, they're actually talking about instance?, not isa?.

13:07 justin_smith: we just need a prefix-verb-only natural language and these things will all be cleared up

13:07 TimMc: &(isa? () [])

13:07 lazybot: ⇒ true

13:07 technomancy: isa? actually tells you "all Xes are Ys", which is just messed up

13:07 pyrtsa: ,(-> String (isa? Object))

13:07 clojurebot: true

13:07 bbloom: TimMc: no, it should read this way: (isa? a b); ((partial isa? a) b)

13:08 TimMc: yeah, yeah

13:08 stain: to me, living in UK ,"isa" is a tax-free savings account

13:08 bbloom: technomancy: isa? also depends on hierarchies, which don't have an interface or protocol

13:08 stain: or something JarJar Binks would say

13:09 bbloom: i assume hierarchies are from the same era as clojure.zip, where rich was exploring how far and in what direction to push the data + metadata - types approach

13:10 justin_smith: Heirarchies just seem like a weird useless corner of the language to me. This is probably ignorance. I think this is related to me not grokking friend also.

13:10 bbloom: does friend use hierarchies?

13:11 justin_smith: I think so, but I could be wrong about that too for all I know

13:11 stain: (dear-sir-would-you-mind-checking-for-me-if-this-type-might-possibly-be-a-specialization-of-this-other-type? java.util.HashMap java.util.Map)

13:11 pyrtsa: I'm just happy that (core.typed'less) Clojure usually avoids the further complications the inheritance-based type system brings, which are covariance and contravariance.

13:11 arrdem: stain: plz no

13:11 stain: y u do dis

13:12 gtrak: justin_smith: I went a couple years without ever writing a multimethod, either.

13:12 justin_smith: bbloom: https://github.com/cemerick/friend#hierarchical-roles-ht-derive-isa-et-al

13:12 yeah, it uses heirarchies

13:12 which I think is related to me just not getting it

13:12 bbloom: heh

13:13 ambrosebs: I had fun with hierarchies as my first exposure to Clojure http://clojure-doc.org/articles/tutorials/growing_a_dsl_with_clojure.html

13:13 gtrak: justin_smith: but multimethods use the hierarchies

13:13 stain: we face the same challenge in the world of ontologies.. people mix up Classes and Instances all the time. I've seen people define ontologies with say :StianSoilandReyes rdfs:subClassOf foaf:Person, [ a owl:Restriction; owl:onProperty "foaf:name" owl:value "Stian Soiland-Reyes" ] .

13:13 intead of just: :StianSoilandReyes a foaf:Person ; foaf:name "Stian Soiland-Reyes"

13:14 first case would be good if there were many clones of me (and they all had the same name!)

13:14 ambrosebs: when I wrote that, technomancy said "why doesn't this guy just admit he's writing a compiler". Cos I had no idea.

13:14 bbloom: ambrosebs: i want predicate dispatch so bad

13:14 justin_smith: gtrak: yeah, I have done very little with defmulti; it could very well be that clojure heirarchies will be a a revelation that vastly improves my code when I grok the situation

13:14 arrdem: ambrosebs: :D

13:14 gtrak: it hasn't been that way for me, but it's been convenient occasionally.

13:14 the 'clojure-in-action' book tries to use them extensively for domain modeling.

13:15 but I didn't really 'get it'

13:15 justin_smith: gtrak: cool, I may have to check that out and see what I am missing

13:15 * arrdem has never used a higherarchy for anything useful

13:15 ambrosebs: bbloom: I always forget what predicate dispatch is.

13:15 justin_smith: the anarchists of #clojure

13:16 gtrak: justin_smith: I wasn't impressed with it, I just noticed it cared a lot about the hierarchies :-)

13:16 bbloom: ambrosebs: think multimethods, but instead of a hierarchy, methods are matched by arbitrary predicates

13:16 mathematica has one of the least-bad predicate dispatch systems out there, give it a try

13:16 ambrosebs: bbloom: yes I will

13:17 bbloom: usually, predicate dispatch systems are tied to the pattern systems too

13:19 stain: for instance imagine you have different kinds of memberships and subscriptions to a service (e.g. Spotify). You can have :free :premium and :professional - both :premium and :professional specialize :paid Then you can have :ondemand :monthly and :yearly and create the actual plans as say [:free :monthlyPremium :yearlyPremium :monthlyProfessional :yearlyProfessional]

13:20 but now in your "can you play this silly song" code all over the place you don't need to code in all of those, you just check against the higher levels of the hierarchy

13:21 so you have a hierarchy, here of subscription types, but it could be anything like your status or ranking (think Stack Overflow badges), regions and cities, languages and formats..

13:21 justin_smith: stain: fair enough. Though my first instinct with something like that would to make sets of keywords and test membership of the sets.

13:21 which for all I know is what derive based heirarchies are doing under the hood

13:21 stain: so quite powerful and useful to adapt without having to build big object structures like in Java, because really you don't have any further data or methods to attach to those

13:22 yes.. that is why you tend to use the ::private keywords so that you don't inadvertedly mix in a different hierarchy

13:22 arrdem: function from a finite list to its infinite repetition... gah.

13:22 justin_smith: :semi/private

13:23 stain: but the confusion arrises because of the innovation of using this also to check Java subclasses.. which have a split between classes and instances

13:24 arrdem: there we go. clojure.core/cycle.

13:24 justin_smith: stain: from a rudimentary category theory perspective I envision the classes as having the heirarchy, and the checks are all based on a mapping of instance to class

13:24 though that is likely simpler than the semantics of isa? instance? etc. etc.

13:25 bbloom: justin_smith: what? you haven't upgraded your brain to homotopic spaces yet? c'mon now

13:25 justin_smith: bbloom: I tried but it turns out my brain is not smooth and I nearly burst a vessel

13:26 arrdem: (inc justin_smith)

13:26 lazybot: ⇒ 31

13:26 ptcek: I am trying to use bidi (for bidirectional routing) and got stucked. I create a ring handler from the routes, my routes contain resources (handlers) and my resources need routes to get urls to other resources == circular dependency... Any suggestion how to approach this differently?

13:28 sritchie: ptcek: I know, so annoying

13:28 ptcek: (circular dependency in namespaces, as I want resources and routes to be in separate namespaces)

13:28 sritchie: ptcek: the circular dep thing is becoming a real problem

13:29 arrdem: if only we had a real compiler that wasn't order sensitive.. oh did I say that out loud?

13:29 jcromartie: shot fired!

13:29 rasmusto: fired shot!

13:29 rootex: is defrecord and deftype pervasive in clojure code?

13:29 * arrdem chambers the next one

13:30 jcromartie: rootex: I would say no

13:30 justin_smith: arrdem: as long as the repl has time machine so the interactive version has the same semantics as the version loaded from a file

13:30 hiredman: rootex: it really depends

13:30 tuft: ,(map Integer/parseInt ["1" "2"])

13:30 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer, compiling:(NO_SOURCE_PATH:0:0)>

13:30 tuft: hmm

13:30 ,(Integer/parseInt "2")

13:30 clojurebot: 2

13:31 cbp: Whenever you have a circular dep you can usually solve it by adding a 3rd namespace

13:31 justin_smith: tuft: that is not a function so it is not first class

13:31 rasmusto: ,(map #(Integer/parseInt %) ["1" "2"])

13:31 clojurebot: (1 2)

13:31 justin_smith: tuft: you can put it in a #() though

13:31 hiredman: rootex: at the single project level, some projects use them a lot, others not at all, so it is kind of a mix

13:31 justin_smith: like rasmusto did

13:32 jcromartie: rootex: yeah they tend not to be exposed at the boundaries

13:32 justin_smith: rootex: I use them (and reify) when I want protocols

13:32 jcromartie: rootex: protocols on the other hand

13:34 rootex: ok, procotols do really get used much?

13:34 justin_smith: they are very useful, for example if you have code that should be specialized by an end user

13:35 ptcek: cbp: can you be a bit more specific?

13:35 rootex: justin_smith: to expose APIs?

13:35 technomancy: rootex: protocols are fast, but they are not nearly as flexible as multimethods, and they introduce difficult-to-debug problems around reloading.

13:35 sritchie: cbp: yeah, but that can be a serious pain in the ass

13:36 cpb: for example, I have a user that can use coupons, and coupons that can list all of their users

13:36 cbp: sure, I can make a third namespace for user/coupon interactions,

13:36 cbp: but then I have a namespace for every edge...

13:36 and it just gets uncomfortable

13:36 justin_smith: rootex: pretty much yeah - you write your code to the protocol, and the user provides something implementing that protocol

13:37 or some lib is implemented around a protocol, and you define something implementing it, etc.

13:37 rootex: justin_smith: like java interfaces?

13:37 cbp: ptcek: if ns `a` requires ns `b` and viceversa. put the functions that cause the circular dependency in an ns `c`

13:37 rootex: technomancy: what do you mean by reloading?

13:37 justin_smith: rootex: yeah, that's pretty much what protocols are actually

13:38 and that's the one case where I end up using defrecord or reify

13:38 cbp: ptcek: sometimes that requires you to actually extract and write those functions

13:39 sritchie: Yes I guess it can be a pain although I'm not very convinced that if circular deps were allowed that the result would be well designed code

13:39 justin_smith: sritchie: conversations converging, if you have protocol namespaces defining coupon and user, then the implementations fleshing out those protocols can use each other via the protocols, it can work very nicely

13:39 technomancy: rootex: just recompiling during development.

13:39 tuft: justin_smith: ok thanks

13:39 sritchie: justin_smith: I ended up doing that for the data structure definitions

13:39 justin_smith: and extracted data schemas to cljx, actually

13:40 tuft: justin_smith: still feels strange that it's not a function when you can call it like one

13:40 justin_smith: sritchie: yeah that's pretty much how I would do it

13:41 tuft: yeah, that is a little awkward, but there are lots of things like that in clojure - keywords, maps, vectors, symbols, methods - all can be called as if functions

13:41 sritchie: tuft: it is a function, really - it just looks up the type of the first argument and picks an implementation

13:41 imagine a function with a big hashmap of type -> another function

13:41 rootex: technomancy: so you would avoid protocols for multimethods whenever you can?

13:42 Does Joy of Clojure book touches these topics deeply, like when to use them or best cases for them? (macros, datatypes/protocols, multimethods)

13:43 technomancy: rootex: well, in general the need for user-defined polymorphism in clojure is very rare to begin with, but yeah, I have never written any code where the extra overhead of multimethods was an actual problem in practice.

13:43 bbloom: technomancy: you keep making that claim, yet all my programs are loaded with polymorphism...

13:44 llasram: ditto

13:44 tuft: justin_smith: seems like those examples behave like functions in this context, though. e.g.

13:44 ,(map :hi [{:hi 2} {:hi 3}])

13:44 clojurebot: (2 3)

13:44 llasram: I do generally prefer multimethods, but I use protocols pretty freely too because of the ability to `reify` them

13:44 arrdem: I'm writing an AI that does some major dispatching via multimethods.. I'll let you know in a few weeks if it's too slow :P

13:44 tuft: justin_smith: well, that one does anyway =)

13:44 gtrak: does pulling functions out of hash-maps count as polymorphism?

13:44 bbloom: arrdem: generally, the slow part of multimethods is 1) the lack of call site caching and 2) the isa mechanism

13:45 tuft: sritchie: makes sense for resolution of java overloads. still don't see why that couldn't be a regular function value, though -- compiler details?

13:45 arrdem: gtrak: I'd say so...

13:45 gtrak: barely

13:45 sritchie: tuft: yup, prob

13:45 gtrak: heh, it's so vague to me.

13:45 bbloom: arrdem: i've considered extending my dispatch-map library to support explicit call site caches. ie you'd create a "call-cache" and then it would implement IFn

13:45 gtrak: polymorphism...

13:45 a particular arrangement of branch instructions.

13:46 arrdem: gtrak: it's totally unstructured polymorphism, but under the hood it's what we all rely on the hardware to do to actually _implement_ polymorphism.

13:46 so...

13:46 I guess it counts.

13:46 arrays of function pointers FTW...

13:46 gtrak: in that case, I have a lot of 'if' statements, my code has so much polymorphism :-)

13:47 cbp: pft polymorphism is just a way to reduce my 300 line functions into 20 line chunks

13:47 gtrak: and the bytecode implements IFn.. that's polymorphic too!

13:47 I guess we're just talking about it as an intentional construct

13:49 seangrove: cemerick: I tried playing around with double-check in cljs last week, was a bit painful (the readme example had the wrong namespace, etc.), curious if any of the recent cljs releases have made it a bit smoother?

13:49 justin_smith: cbp: and if I recall you are quite fond of the 300 line version

13:50 cbp: justin_smith: =P just too lazy to break it down

13:50 cemerick: seangrove: I haven't given the docs a buff yet, so that's no different. What were your other issues?

13:50 * cbp needs an emacs macro to turn a giant cond into multimethods

13:51 arrdem: cbp: when you write it, be a good chap and throw it in the clj-refactor lib plz

13:52 rootex: do guys feel less productive on a laptop than on a desktop computer? ;)

13:52 cbp: all i do on my desktop is play video games so i guess not

13:52 technomancy: as long as I have a mechanical keyboard I'm happy

13:52 justin_smith: rootex: is that an emacs dig?

13:52 rasmusto: who doesn't have a compute farm?

13:52 * arrdem has a supercomputer

13:53 gtrak: rootex: I overclocked my desktop to 4.4GHz, but I haven't really used it in months.

13:53 cemerick: seangrove: going offline now, please do file any issues you hit; the cljs releases shouldn't affect anything

13:53 gtrak: haven't played games in a while either

13:53 but it has the potential to run faster than a laptop for a lower price, which saves time, that's for sure.

13:54 rasmusto: http://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Beowulf.jpg/449px-Beowulf.jpg

13:54 TimMc: gtrak: That's pretty fast.

13:54 gtrak: TimMc: it's hard to notice the difference really, except when it isn't.

13:54 technomancy: you can always SSH into more CPU and disk space. you can't SSH into a better keyboard and display.

13:54 rasmusto: cat /proc/cpuinfo | grep processor | wc -l => 64

13:55 gtrak: SSD makes the biggest difference by far.

13:55 plus just having enough memory

13:55 TimMc: gtrak: The last time I heard of something running that fast, it was cooked with liquid nitrogen. https://www.youtube.com/watch?v=ZF8S3Nn7mTQ

13:55 *cooled ha

13:55 gtrak: TimMc: ha, the core i5's are pretty sweet

13:55 maybe it's at 4.2, I don't remember really, but around there.

13:56 arrdem: apparently multimethods are recursive datastructures... 0/5 would not pprint again

13:56 TimMc: The LN2 is actually at 5 GHz.

13:56 rootex: justin_smith: :)

13:56 technomancy: true

13:57 gtrak: yea, I used to be into all that before I became a real programmer :-). Now I don't have patience for it anymore.

13:57 I just do the quick wins.

13:57 rootex: I guess the laptop strains more the back and the neck but haven't really feel any symptons yet :)

13:58 gtrak: no even for setting up your linux distro? ;)

13:58 gtrak: rootex: yup, used to run arch, now I can't stand tweaking stuff anymore :-)

13:58 rasmusto: arch is ez pz

13:58 gtrak: it is.

13:58 but, I have more than one computer.

13:59 arrdem: arch iz osum

13:59 rootex: yeah, arch is a bit high maintenance

13:59 gtrak: and I'd forget to look at relnotes for breaking changes

13:59 * rasmusto runs sudo-git-unstable

14:00 rasmusto: I did have a few pacman -Syu's that broke grub, but that's all fixed now :D

14:00 arrdem: rasmusto: my hat's off to you... I like having an Arch that marginally works :P

14:00 yedi_: how would you count the occurrences of a word in a string?

14:00 TimMc: rasmusto: That combination of words makes me nervous.

14:00 Bronsa: I don't bother with updating my Arch anymore

14:00 gtrak: yedi_: split, frequencies

14:00 TimMc: length of re-seq?

14:01 Bronsa: it works fine now, I'm not going to do anything to make that change.

14:01 rasmusto: you have every right to feel nervous

14:01 TimMc: gtrak: I think frequencies is not what you want.

14:01 rasmusto: arch is so much easier than gentoo prefix, though. So I feel pretty comfortable

14:01 * katratxo runs `pacman -Syu` every day

14:01 justin_smith: rootex: my laptop strains my back because it is monstrously huge. But I like having 32 gigs of ram and 8 cpus so I won't complain

14:01 (plus big screen and keyboard)

14:02 arrdem: I'd do my inc counter thing to count members of the arch master race... but lazybot kills it every time :c

14:02 yedi_: gtrak: well more like the occurences of "\n" in a string like "\n\nand\n\n\n\nsome\nwords\n"

14:03 gtrak: yedi_: ah, first thing I'd try would be (count (filter

14:03 unless there's some built-in string method that's faster.

14:04 justin_smith: ,(get (frequencies "hello\nworld\n\n!!!\n") \newline) ; yedi_

14:04 clojurebot: 4

14:05 TimMc: yedi_: So... character, not word?

14:05 rasmusto: (doc frequencies)

14:05 clojurebot: "([coll]); Returns a map from distinct items in coll to the number of times they appear."

14:06 justin_smith: re-matches is likely better if it is not a single char

14:06 yedi_: yea the \newline character, i think i was getting confused by the representation of it within a string

14:08 gtrak: ,(count (filter (partial = \newline) "hello\nworld\n\n!!!\n"))

14:08 clojurebot: 4

14:08 justin_smith: ,(re-seq #"\n" "hello\nworld\n\n!!!\n") ; the more general case

14:08 clojurebot: ("\n" "\n" "\n" "\n")

14:09 justin_smith: ,(count (re-seq #"\n" "hello\nworld\n\n!!!\n")) ; the more general case*

14:09 clojurebot: 4

14:09 rasmusto: ,(count (filter #{\newline} "hello\nworld\n\n!!!\n"))

14:09 clojurebot: 4

14:10 justin_smith: rasmusto: yeah that one is better than frequencies for the single character case

14:10 rasmusto: is it essentially the same as (partial = \newline)?

14:10 tuft: what's the most straight forward way to filter nils? is it really (filter (comp not nil?) foo)?

14:11 rasmusto: (remove nil? foo)

14:11 justin_smith: rasmusto: yeah, though a little slower iirc

14:11 AimHere: For 1.6, isn't (not (nil?)) now 'some?'

14:11 justin_smith: tuft: there is also (complement nil?)

14:12 rasmusto: (filter some? foo) is confusing to me

14:12 justin_smith: AimHere: how does that behave for false?

14:12 AimHere: I think the whole purpose of it is to behave differently from false and nil

14:12 Otherwise (filter identity foo) would be fine

14:12 justin_smith: ,(filter some? [false false false])

14:12 clojurebot: (false false false)

14:12 justin_smith: cool

14:12 AimHere: ,(filter some? [false nil '()])

14:12 clojurebot: (false ())

14:13 rasmusto: some? messes me up because I associate it with some, which consumes a colleciton

14:13 collection*

14:13 tuft: ah some? is nice

14:13 fits with some-> and some->>

14:13 justin_smith: (some? :pig)

14:13 rasmusto: ,(some some? [true false nil])

14:13 clojurebot: true

14:15 danneu: Can anyone recommend a simple/minimal crossplat html5 audio library?

14:16 justin_smith: danneu: what do you need beyond the spec?

14:20 michaniskin: danneu: https://github.com/mathias/hum

14:21 cbp: rasmusto: hehe so terse and pithy!

14:22 rasmusto: concise, meaningful and sexpual

14:22 bbloom: ,(assoc {})

14:22 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/assoc>

14:22 gtrak: rasmusto: my first reaction is 'ew gross'

14:22 bbloom: bah!

14:22 rasmusto: ,(>)

14:23 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/>>

14:23 bbloom: ,(apply assoc {} []) ; burns me every time

14:23 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/assoc>

14:23 verma: just wondering if people here do this differently? -> (if (empty? p) "default-val" p)

14:23 rasmusto: ,(apply < [])

14:23 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/<>

14:23 amalloy: bbloom: yes, one of several functions that are dangerous to call apply on for no good reason

14:24 rasmusto: verma: what are you expecting p to be when its not empty?

14:24 bbloom: amalloy: surely somebody must have submitted a patch for this....

14:24 rasmusto: bbloom: I think I was reading the PR about < and > yesterday

14:24 bbloom: rasmusto: < and > are a little more questionable

14:25 rasmusto: (doc <)

14:25 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums are in monotonically increasing order, otherwise false."

14:25 justin_smith: ,(< Double/NaN)

14:25 clojurebot: true

14:25 justin_smith: lol

14:25 bbloom: is no-args monotonically increasing?

14:25 rasmusto: its undef, return a nil maybe? hmm

14:25 verma: rasmusto: (let [first-part (if (empty? p) "." p)] ...) basically I want a default value of "." for p if its empty

14:27 amalloy: bbloom: as much as one arg is

14:27 rasmusto: verma: yea, I mean that should work. But turning an empty p into a "." seems a little roundabout. I guess it depends on what you're doing with p afterwards

14:27 amalloy: (ie, yes, obviously so: for all i,j, xs[i] < xs[j])

14:27 er

14:27 for all i xs[i] < xs[i+1]

14:27 rasmusto: there exists i,j xs[i] > xs[j] would be false, yea?

14:28 bbloom: amalloy: yeah, i think this is like that 0^0 thing that was just going around

14:28 0^0 is 1... why? b/c math.

14:28 amalloy: bbloom: except 0^0 is undefined, isn't it?

14:28 rasmusto: nopes

14:28 gfredericks: no

14:28 verma: rasmusto: https://gist.github.com/verma/9980396

14:28 amalloy: welp, guess it's been too long since math class

14:28 bbloom: amalloy: http://www.askamathematician.com/2010/12/q-what-does-00-zero-raised-to-the-zeroth-power-equal-why-do-mathematicians-and-high-school-teachers-disagree/

14:28 gfredericks: ,(apply * (repeat 0 0)) ; also in clojure

14:28 clojurebot: 1

14:28 rasmusto: amalloy: no, math class told you wrong

14:28 amalloy: rasmusto: right, because that's almost the negation of my for-all

14:28 bbloom: gfredericks: heh, clever

14:29 gfredericks: there are some fundamental definitions that use similar concepts. I think the standard series definition of e starts with 0! = 1

14:29 ,(apply * (range 1 1))

14:29 clojurebot: 1

14:30 rasmusto: verma: I'd personally use (= p "") instead of (empty? p), since you're explicitly looking for strings

14:30 DaReaper5: Anyone familiar with clj-xpath? How do i check if a node exists?

14:31 bbloom: amalloy: anyway, i think we discussed this before

14:31 storme: is there anything in clojure similar to the .inspect method in ruby?

14:31 verma: rasmusto: sounds good :)

14:31 bbloom: amalloy: in short, somebody needs to corner alex/rich and push these things through

14:32 DaReaper5: Co-worker (who is unavailable) said to do "xmlexists( '/parent_node/the_node' passing parent_node) " but I am not sure how to translate this into somthing usable

14:32 gtrak: storme: what are you trying to inspect?

14:32 bbloom: storme: you want prn-str

14:32 storme: alternatively, prn to just print it directly

14:33 storme: double alternatively, use clojure.core/pprint or fipp.edn/pprint

14:33 tos9: 7/7

14:34 storme: gtrak bbloom: I'm trying to look at a clojure.lang.IteratorSeq

14:34 bbloom: storme: and what's the problem?

14:34 justin_smith: storme: maybe you want clojure.repl/source ?

14:35 bbloom: justin_smith: not for a java class

14:35 DaReaper5: Anyone familiar with clj-xpath?

14:35 justin_smith: oh yeah, oops

14:35 gtrak: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IteratorSeq.java

14:36 if you want the actual values in the class, that's harder :-)

14:36 the object, rather, but usually I'll try 'bean' and see what happens, not relevant in this case.

14:38 justin_smith: gtrak: there is always clojure.reflect if you want to really get into the rabbithole

14:38 gtrak: yes, yes there is :-)

14:38 storme: I'm using yokogiri to scrape, and I want the contents in div that I am targeting

14:38 gtrak: I made a type-checking new+ with clojure.reflect once :-)

14:39 storme: (#<HtmlDivision HtmlDivision[<div class="grid_11">]>)

14:39 is what I'm being returned

14:39 gtrak: https://github.com/gtrak/interop/blob/master/src/interop/core.clj#L70

14:39 haven't used it for anything, but it was fun.

14:43 DaReaper5: Anyone familiar with clj-xpath? How do i check if a node exists?

14:43 (last time)

14:47 verma: can a keyword have spaces??

14:47 lazybot: verma: What are you, crazy? Of course not!

14:47 gtrak: verma: yes and it shouldn't

14:47 verma: ,(keyword "hello world")

14:47 clojurebot: :hello world

14:47 verma: dafuq :(

14:47 gtrak: keywords should just round-trip through the reader at dev-time :-).

14:48 i guess it'll never happen

14:48 verma: ,(= (keyword "hello world") (keyword "hello world"))

14:48 clojurebot: true

14:49 verma: ,{ (keyword "hello world" 10 }

14:49 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: }>

14:49 verma: ,{ (keyword "hello world") 10 }

14:49 clojurebot: {:hello world 10}

14:50 verma: ,((keyword "hello world") { (keyword "hello world") 10 })

14:50 clojurebot: 10

14:50 gtrak: ,(keyword "")

14:50 clojurebot: :

14:50 verma: oh shit :)

14:50 gtrak: it's a fun game

14:50 verma: so wow keywords

14:51 gtrak: ,(= (keyword "s/b") :s/b)

14:51 clojurebot: true

14:51 gtrak: ,(= (keyword nil "s/b") :s/b)

14:51 clojurebot: false

14:51 gtrak: ,(keyword nil "s/b")

14:51 clojurebot: :s/b

14:52 jcromartie: wat

14:52 ,(namespace (keyword nil "foo/bar"))

14:52 clojurebot: nil

14:52 jcromartie: you filthy liar

14:52 verma: (clojure-version)

14:52 ,(clojure-version)

14:52 clojurebot: "1.6.0"

14:55 michaniskin: ,(symbol "123")

14:55 clojurebot: 123

14:55 michaniskin: ,(symbol "1 2 3")

14:55 clojurebot: 1 2 3

15:04 verma: doing map over a hash-map converts the hash-map into a list, is there a way to apply a function just to the keys of a map and get a map back? or do I have to do it manually?

15:05 akhudek: verma: manually or via a function for that that someone already wrote

15:05 verma: e.g. prismatic’s plumbing library has a map-vals function, but not a map-keys

15:05 technomancy: it is a strange omission from clojure.core

15:06 verma: TIL about plumbing, nice! :)

15:07 justin_smith: verma: I always end up just filling in the blanks in (into {} (fn [[k v]] .. [k' v']) {...})

15:08 verma: justin_smith, nice! didn't know about into either :)

15:10 justin_smith: ,(into {} (map (fn [[k v]] [(str k k) (* v 2)]) {"a" 0 "b" 1 "c" 2 "d" 3}))

15:10 clojurebot: {"dd" 6, "aa" 0, "bb" 2, "cc" 4}

15:10 justin_smith: I missed the call to map in my previous example btw

15:14 verma: justin_smith, yeah I figured that, thanks

15:17 amalloy: justin_smith: into/for is generally more readable than into/map

15:17 justin_smith: amalloy: yeah, fair enough

15:18 verma: wasn't too hard once I learnt about into: https://gist.github.com/verma/9981313

15:18 for, huh, never even used it ever :)

15:19 justin_smith: ,(into {} (for [[k v] {"a" 0 "b" 1 "c" 2 "d" 3}] [(str k k) (* v 2)])) ; yeah, much clearer

15:19 clojurebot: {"dd" 6, "aa" 0, "bb" 2, "cc" 4}

15:19 verma: nice

15:23 with for: https://gist.github.com/verma/9981313

15:23 thanks guys, learning something new everyday

15:25 justin_smith: verma: that was just the first version again

15:27 verma: I added a comment to it

15:27 oh

15:27 now I did, sorry

15:55 sveri: Hi, I am currently playing around with OM and I wonder if its possible to call a javascript function which creates its own dom (I am looking to call canvasjs like this: http://canvasjs.com/docs/charts/chart-types/html5-line-chart/) The examples I saw only draw text into the dom, so is this even possible?

15:58 dnolen_: sveri: you cannot construct your own DOM, however you can target the DOM React created via refs which usually good enough for many JS libs

15:59 sveri: dnolen_: Ok, so I get that I cannot do it, but I dont understand your proposed solution I am afraid

15:59 dnolen_: if you have an example I would happily go through it

16:01 dnolen_: btw. OMs concepts are awesome and nice you gave that talk at the clojure conf, it convinced a friend of mine to try it out :-)

16:02 se_: I'm trying to stub a function from a different ns using provided in midje, but it seems I'm not able to override external functions. Any tips on this? example: (fact "foo uses bar" (foo) => "blah" (provided (bar) => "blah")) .. (defn foo [] (bar)) .. where bar is required from another ns

16:08 justin_smith: se_: I don't know midge, but is this something with-redefs would help with?

16:08 ,(doc with-redefs)

16:08 clojurebot: "([bindings & body]); binding => var-symbol temp-value-expr Temporarily redefines Vars while executing the body. The temp-value-exprs will be evaluated and each resulting value will replace in parallel the root value of its Var. After the body is executed, the root values of all the Vars will be set back to their old values. These temporary changes will be visible in all threads. Useful for mockin...

16:08 se_: justin_smith: i believe provided uses with-redefs under the hood, but i will look into that, thanks

16:09 justin_smith: se_: it could be you need to require the ns with an alias and use the ns alias, or use the full ns name

16:10 otherwise it likely wants to create bar in the current ns

16:10 se_: justin_smith: good point, ill give that a try

16:10 dnolen_: sveri: this is an Om thing, it's a React thing. I don't have an example handy. But read up on React refs and look around for React examples that need to interop with mutable JS libraries and you'll see what I mean. Om approach looks almost exactly the same.

16:10 "this is not an Om thing" I mean.

16:11 sveri: dnolen_: I think I get it, thank you very much :-)

16:11 justin_smith: se_: also if that is the issue, it is just more evidence that :use is evil and :require should be used instead

16:38 ghadishayban: Are there any examples of inline caches in the clojurescript compiler?

16:38 blake__: Given a function "fn example[x y] (if (= x y) y (example x (rand-int (inc x))))", how do I make this return all the values of y instead of just the final one?

16:39 I know I could pass a seq along and add to it with each iteration but I think that's the long way 'round?

16:40 amalloy: blake__: just cons a value onto the recursive call: (cons y (example ...))

16:40 and then the base case needs to be (list y) instead of just y

16:41 blake__: Riight. Still struggling with that one. I don't need to pass the list because I'm building it...

16:42 amalloy, thanks!

16:43 amalloy: blake__: try thinking of it this way: imagine that your example function already does what you want: it returns a list of all the values of y. now, how can you use that to return one more value? easy: you cons onto it. and then all that remains is to make the base case work: if there's only one "final" value, how do you return a list of it?

16:44 blake__: *nod* Yeah...the whole "call this trusting that it will eventually do what you want" thing is a trip.

16:45 guns: recursion fairy

16:45 amalloy: i woulc appreciate a recursion fairy

16:45 blake__: heh

16:46 You leave a pair of blank parentheses under your pillow and in the morning, it's replaced with a realized function!

16:46 justin_smith: collects stack frames from under your pillow and leaves behind optimized tail calls

16:46 rasmusto: hah

16:46 tcooth fairy

16:46 justin_smith: ouch

16:46 ((juxt inc dec) rasmusto)

16:47 rasmusto: yeah, I deserved that

16:47 llasram: (inc rasmusto)

16:47 lazybot: ⇒ 5

16:48 llasram: I wish to do my part to encourage such behavior :-)

16:59 justin_smith: or perhaps it goes around putting pillows under peoples pillows

17:03 TimMc: I like that.

17:04 blake__: (but only if they look)

17:05 arrdem: I've never been graced with a visit from the tcooth fairy.. I spend my weekends hunting the eater of socks T_T

17:07 http://en.wikipedia.org/wiki/Discworld_gods#Other_personifications

17:07 rasmusto: ,:Glingleglingleglingle

17:07 clojurebot: :Glingleglingleglingle

17:08 justin_smith: I can reliably find the Oh God of hangovers if I go looking

17:08 arrdem: I went looking for him once... the next day he came calling and I haven't searched again.

17:27 cYmen_: I was just reading this https://github.com/magomimmo/modern-cljs/blob/master/doc/tutorial-04.md

17:27 Does anybody know why one would make an ajax call to validate the user input before registering the user?

17:27 It seems like it could simply be done with a single call.

17:28 justin_smith: cYmen_: to avoid having to navigate back to the same page, and instead let them know they need to change something before leaving the page?

17:29 being taken back to refill a form because one field was bad is really annoying

17:30 cYmen_: uh yeah but why not just do it all in javascript?

17:30 you know make a call that tries to register and then redirect the user if it was successful

17:35 coventry`: Is there a way for a leiningen project to access its own project.clj map?

17:38 technomancy: coventry`: you need a plugin; the design of lein is that projects shouldn't know when they're running under it vs independently

17:39 hyPiRion: coventry`: https://www.youtube.com/watch?v=uXebQ7RkhKs#t=1051

17:39 justin_smith: coventry`: and also, based on my experiences with similar lines of thought, consider what your app should do if run from an uberjar

17:39 hyPiRion: It's possible to use :injections to do that.

17:41 technomancy: yeah, better to add in what you actually care about (via injections or the classpath) than expose the whole map

17:43 coventry`: Thanks, guys. injections looks like a good way to do it, and only sending the info I need makes a lot of sense, too.

17:46 aedon: when I run lein repl, what should I expect my current directory (clojure.java.io/resource ".") to be? is there a way to set it via project.clj?

17:47 coventry`: Also, this is only for dev config, so it shouldn't be too hard to make it compatible with uberjarring.

17:47 hyPiRion: aedon: it should be the root directory

17:47 justin_smith: aedon: I don't think the JVM supports setting the current directory

17:47 definitely not portably

17:47 aedon: hyPiRion: root = dir with project.clj? I'm finding that it's my src/ directory instead

17:47 justin_smith: aedon: better to have a distinctive path in the classpath to the resource you need

17:48 aedon: io/resource does not find things relative to current dir, but relative to classpath. That's the point of io/resource

17:50 aedon: justin_smith: hrrrm, interesting. ok makes sense. so the classpath from a standard project.clj standpoint is going to be :source-paths + jars required by dependencies?

17:50 justin_smith: plus resource-paths

17:51 aedon: ahhh. there's what i'm missing, I assume. thanks

17:51 hyPiRion: aedon: yeah, it should be where the project.clj

17:51 technomancy: there's (System/getProperty "user.dir") but that's totally different

17:51 lemonodor: aedon: for those times you actually do want to access an in-project file as opposed to a resource (e.g. tests on code that is meant to access files), i found the easiest thing was to do (io/file (io/resource "test.data.foo)) or whatever

17:51 but maybe there’s a better way

17:52 (where io=clojure.java.io)

17:52 antonv: hi, how do you develop with multi-file projects, where files require each other

17:53 when I open one of the files and do cider-jack-in (cider is a emacs client for nrepl)

17:53 aedon: Thanks, all of you. God, I love what I'm reading about om and FRP and core.async, but god it's still 'exciting' to setup an environment to develop in.

17:54 antonv: when I execute (ns ... (require my.other.file) ) in one of the files which requires another, clojure throws java.io.FileNotFoundException

17:55 because my.other.file is not compiled I think

17:55 how to make it aware that the file can be loaded from source in my project directory?

17:56 is there are way to ask leingen to load all my files?

17:56 justin_smith: antonv: if the ns is in the classpath there is likely some other problem

17:56 antonv: or setup clojure to load the sources?

17:56 justin_smith: require should cause recursive loading as far as possible

17:57 antonv: justin_smith: even if the file is not compiled? I mean will it load .clj file?

17:57 coventry`: Does the snippet from xeqi's talk, `[(spit "resources/project.clj" ~(prn-str project))], require any further configuration to make it work? I'm getting "Unable to resolve symbol: project" from it.

17:57 justin_smith: also I assume that is (:require ...) and not (require )

17:57 antonv: .clj files are found and compiled

17:57 antonv: clojure always compiles as part of loading

17:57 antonv: justin_smith: right, thanks

17:58 I will investigate wheterh cider-jack-in includes my project source directory into classpath

17:58 amalloy: justin_smith: (require) works fine in ns forms; (:require) is just conventional

17:59 justin_smith: antonv: make sure that if your ns has a - in it that becomes a _ in the file name, and that the directory structure follows the ns structure

17:59 amalloy: oh, I had no idea, thanks

17:59 amalloy: antonv: paste a real stacktrace to gist.github.com, or refheap.com or something - the problem is too vague, as you can see by justin_smith listing all the things that can ever go wrong in a namespace

18:00 justin_smith: amalloy: I thought I was mentioning the most common ones

18:00 amalloy: maybe. but my point is if he told you what's actually wrong you could just mention the actual problem

18:01 justin_smith: of course

18:01 antonv: justin_smith: yes, thanks, my namspace is test-db, it has -

18:02 justin_smith: common culprit, changing it to _ should fix the issue

18:02 (in the file name that is)

18:03 hyPiRion: ,(munge "test-db")

18:03 clojurebot: "test_db"

18:05 justin_smith: &(munge "☃🐈❄☺")

18:05 lazybot: ⇒ "☃🐈❄☺"

18:06 antonv: justin_smith: now everything works OK, thanks again

18:06 justin_smith: np, glad I could help

18:07 AmandaC: Is there any minimal lein templates for a cljs project?

18:07 I mean, it’s somewhat trivial to convert a normal Clojure one, but I’d rather let a machine do that for me. :p

18:07 TimMc: justin_smith: Fun fact: JVM don't care.

18:08 Unicode snowman is a pefectly valid classname.

18:08 justin_smith: awesome to know

18:08 coventry`: "lein new om-starter myproject"

18:08 Well, that's for om, not just for cljs.

18:08 justin_smith: &(munge " ; does this mean EOF is also a valid class name?

18:08 lazybot: ⇒ ""

18:09 coventry`: Should work fine if you just ignore the om stuff though, I guess...

18:10 AmandaC: Hrm, I guess I can make this project an experiment into playing with om also. :p

18:10 * AmandaC uses that to get started

18:11 justin_smith: &(Character/isJavaIdentifierStart \)

18:11 lazybot: ⇒ false

18:11 justin_smith: &(Character/isJavaIdentifierStart \☃)

18:11 lazybot: ⇒ false

18:11 coventry`: The first part of dnolen's om tutorial is very good. (The rest probably is, too, I just haven't read it yet.)

18:13 amalloy: ,(defprotocol ☃ (❄ [this]))

18:13 clojurebot: ?

18:13 amalloy: silly clojurebot doesn't seem to have his character encoding right?

18:14 justin_smith: yeah, that's why I switch to lazybot for anything unicode related

18:14 xpera: amalloy: have you tried -Dfile.encoding=UTF-8

18:14 amalloy: huh? i'm just talking about clojurebot. i can't change his startup parameters

18:15 xpera: amalloy: oh, I didn't know who controls him/her/it

18:16 TimMc: justin_smith: Now, whether *Java* allows arbitrary unicode is another matter.

18:17 justin_smith: oh right, so that method is a different story

18:21 &(let [ 12

18:21 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

18:22 justin_smith: hey no fair

18:22 ,(let [ 12

18:22 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:22 justin_smith: wtf, works in my repl

18:22 cbp: wat

18:22 justin_smith: ,(let [ 12

18:22 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:22 xpera: justin_smith: yeah, because it waits for moer

18:22 justin_smith: it is eating

18:23 oh, I see - I had a ^C in there, which it seems that erc refuses to send

18:23 though

18:24 amalloy: there's a ^C for you

18:25 justin_smith: ,(let [  12

18:25 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:25 justin_smith: &(let [  12

18:25 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

18:25 rasmusto: clojurebot is a space case

18:25 justin_smith: that one displays right, and works in my repl, but it seems IRC messes with it

18:29 guns: TimMc: Java supports unicode identifiers

18:30 justin_smith: guns: in that case what is up with Character/isJavaIdentifierStart - it just doesn't like some unicode at the start of the identifiers?

18:30 guns: justin_smith: hmmm, let's see

18:31 amalloy: justin_smith: identifiers start with [a-zA-Z0-9_$], as i recall

18:32 guns: justin_smith: it supports all Unicode _letters_

18:32 amalloy: well, the javadoc claims they can start with anything that's alphabetic

18:32 guns: ,(Character/isJavaIdentifierStart \α)

18:32 clojurebot: true

18:38 justin_smith: &((juxt count rand-nth)(filter #(Character/isJavaIdentifierStart %) (map char (range 32767))))

18:39 AmandaC: coventry`: got a link for that tutorial? Google’s being a bit unhelpful. :p

18:39 lazybot: Execution Timed Out!

18:39 justin_smith: locally that returnd [25454 \㒈]

18:39 so most of unicode in the 0 to 32767 range at least

18:40 abp: AmandaC: https://github.com/swannodette/om/wiki

18:41 AmandaC: ah

18:41 thanks

18:42 justin_smith: for the full range of char, 48529/65535

18:47 xpera: ,(->> 100000 range (mapcat #(range % (+ % 5))) distinct count time)

18:47 clojurebot: "Elapsed time: 1082.362801 msecs"\n100004

18:48 xpera: ,(->> 1000000 range (mapcat #(range % (+ % 5))) distinct count time)

18:48 clojurebot: Execution Timed Out

18:48 xpera: ,(->> 10000 range (mapcat #(range % (+ % 5))) distinct count time)

18:48 clojurebot: "Elapsed time: 67.691173 msecs"\n10004

18:49 xpera: was curious about how distinct performs. seems roughly linear in my REPL

18:50 any tips on how to see how memory (or objects) are created? in the REPL, maybe? or do I have to do a full profiler?

18:50 ^how many^ / size

18:51 cbp: use something like criterium for benching

18:51 xpera: cbp: yeah, it is great for execution time. i was wondering about memory usage.

18:51 cbp: jconsole

18:51 xpera: things like set/union

18:52 justin_smith: xpera: jvisualvm makes it easy to look at heap usage, and what object types are using heapspace

18:52 xpera: cbp, justin_smith thanks

18:53 justin_smith: including snapshotting, histograms, etc. with graphing. I hear yourkit is good too but jvisualvm comes with the jdk and suffices for me

18:53 it should be in the same bin directory java is in if you have the jdk

18:54 xpera: justin_smith: surprisingly, it just worked to incant its name

18:54 justin_smith: cool deal


18:58 arrdem: justin_smith: you have way to much fun using glyphs in channel

18:58 cbp: i need to copy and paste them outside of emacs heheh

18:58 justin_smith: I can't help it, I'm easily amused by unicode

18:58 cbp: M-x describe-char

18:59 amalloy: justin_smith: don't forget, 'a' is unicode too :P.

18:59 arrdem: I just enjoy being able to do eˣponₑnTΣ and general latex :D

19:01 justin_smith: ⏰ gtg

19:02 cbp: gdammit

19:03 cYmen_: lein cljsbuild complains about unknown build identifier

19:03 I am pretty sure I added that identifier, what could I have done wrong?

19:04 cbp: paste project.clj + command? =P

19:05 cYmen_: ugh nevermind

19:05 my map was so messed up it is surprising one of the builds worked

19:20 xeqi: coventry`: you have to put that in a task or middleware or such, someplace the project gets passed to

19:21 coventry`: but I think this has already been packaged into a plugin somewhere

19:21 xpera: any recommendations for good screencasts or walkthroughs for using the profiling tools in clojure?

19:35 amalloy: xpera: the profiling tools in clojure are just the java profiling tools. there's not really anything specific to clojure

19:36 xpera: amalloy: ok, i was just hoping to see a recommended order: start the profiler? then sample? then filter to your app's namespace. I was stumbling around.

19:37 various questions like that... and how long should instrumentation take... what happens when it seems to hang? etc.

20:03 yedi: in om: i have a list of elements somewhere in my appstate, i'm mapping an om/build call, however the component i'm mapping doesn't get a cursor like i'd expect. it just gets the actual element

20:04 is there a way to map across a list somewhere in the app state and have (map) pass in cursors instead of the actual data?

20:05 not sure if that makes sense...

20:05 i have this line: (map (partial om/build combo-view) (get-in data [:analysis]))

20:05 and (combo-view) seems to not be getting a cursor

20:27 abp: yedi: I think you don't need map, just om/build-all, what's in :analysis, a collection of primitives?

20:27 yedi: yea a collection of maps

20:28 that will get updated in the subcomponent

20:28 abp: yedi: Oh that's strange then.

20:28 yedi: yea the type of data is ending up as: cljs.core/PersistentHashMap

20:35 abp: same issue with om/build-all just btdubs

20:37 abp: yedi: Yeah, was just a tip to drop some code. Primitive js values can't be cursors, I think, can't help further.

20:37 yedi: ok thanks

20:37 abp: that's why I asked about :analysis

20:40 yedi: yea -- (map type (get-in @app-state [:analysis :analysis])) returns a list of cljs.core/PersistentHashMap

20:41 dunno if that's expected behavior or what

20:41 abp: yedi: if you deref the cursor I'd think so

20:43 yedi: oh right

20:44 om converts your app-state atom into a cursor when used inside an om rendering loop?

20:46 abp: yedi: I think more like you give the atom to root and om provides you cursors into it, but they're derefable just like the atom

20:48 yedi: and converts an initial app-state into an atom if you don't provide one

20:48 yedi: (print (type data)) ; (print (type (get-in data [:analysis])))

20:48 so i put these lines at the top of the problematic component

20:48 and got:

20:49 om.core/MapCursor

20:49 cljs.core/List

20:49 i guess get-in on a cursor might not return a cursor?

20:50 abp: yedi: that would be strange since i guess cursors just implements Associative protocols

20:51 yedi: that's what i thought and is how i've been using it thus far so im also confused

20:51 abp: yedi: seems like map-cursor implements no get-in

20:51 yedi: i just tried (:analysis data) and it's stil just return List as the type

20:52 s/return/returning

20:52 abp: yedi: ah and it doesn't need to.. sorry I'm quite tired

20:54 yedi: can you paste the code on refheap.com or as a gist?

20:55 yedi: https://gist.github.com/yedi/9985991

20:57 abp: yedi: try printing in render

20:59 yedi: printing in render shows the same results

20:59 abp: yedi: then I can't see enough from that code, app-state and how it get's to there is most likely what's wrong

21:02 ddellacosta: yedi: get-in should work fine on a cursor

21:03 abp: ddellacosta: yeah I wrote faster then realizing that it's implemented on associative ;)

21:03 ddellacosta: abp: yep

21:04 abp: ddellacosta: mostly rubber ducking here

21:05 yedi: ddellacosta: yea so i don't really understand what my issue is

21:05 i wonder if there are any gotchas for how you construct or update app-state that might result in odd cursor issues

21:06 ddellacosta: yedi: well, one thing I was doing wrong at one point was inserting lazy seqs.

21:07 abp: ddellacosta: Heh, that's subtle.

21:07 ddellacosta: abp: yeah, I didn't pick it up until dnolen clued me in on the list

21:09 yedi: ddellacosta: interesting, i'lll look into that

21:10 ddellacosta: yedi: and there are in fact gotchas when constructing your data structure--cursors are going to be "flat" (won't generate cursors recursively) if they are sets, for example

21:10 yedi: just a limitation of how much has been implemented so far.

21:12 yedi: your list may be the problem here, try passing in a vector instead. I don't believe you can get an IndexedCursor from a list.

21:12 yedi: ddellacosta: thanks, will see if that works

21:18 abp: ddellacosta: I should read the source instead of just glancing into it sparingly.

21:18 ddellacosta: abp: believe me, I've been ducking in and out of it without really digging into it up until now

21:19 abp: I only really read through sections when I'm absolutely stumped

21:19 abp: but gotta do the same

21:26 abp: ddellacosta: Well, I didn't know about the data restrictions imposed by cursors but planning on doing a project with om soon.

21:27 So really understanding what I get into seems appropriate.

21:28 ddellacosta: abp: yeah, I've realized recently you really do have to understand how it works past a certain point

21:31 abp: ddellacosta: Yeah and react as well as writing much more things to get a feeling for architecture.

21:55 `szx: does anyone have any suggestions/ideas on how to implement tweens in clojure?

21:56 i'm working on a little game and i have a nested world atom, which i update-in on every frame

21:57 i guess i could centralize tweens, keep a list of the paths i'm tweening and update them on every frame as well

21:57 not sure if that's the best way to go about it though

22:05 Frozenlock: I'm having some troubles with lein-droid. I get stuck at "Installing APK..." on my device. Any advice?

22:18 `szx: Frozenlock: i've never used lein-droid but to the best of my knowledge once it gets to that stage it's adb's territory

22:18 so sounds like an android issue rather than a lein-droid/clojure issue

22:21 Frozenlock: `szx: makes sense, I'll check for problems on the android side. Thanks

22:45 Woohoo, success!

22:45 Repl running on an Android device :-)

22:57 amalloy: `szx: the only meaning i know for the word "tween" is http://www.qwantz.com/index.php?comic=230 - others may have similar experience, in which case you can get a better answer by explaining what you really mean

22:59 `szx: haha, got it

23:00 $google tweening

23:00 lazybot: [Inbetweening - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Inbetweening

23:00 `szx: that would probably do a better job of explaining it than me

23:01 i'm basically looking for a way to gradually change values over time

23:01 suppose i have a circle with radius 5, i might want to interpolate that radius to 10 over 500ms

23:03 the way it's usually done is your "tween manager" keeps a list of references/pointers to every variable that needs tweening. on every frame you would call update on it and it would go through the list and mutate values directly

23:04 obviously not how you would want to do it in clojure

23:14 amalloy: `szx: i don't have a lot of experience in that area, but you could have something like: (defn tween [from to, start-time duration] (fn [current-time] (...do math on all those things...))). then when you want to start tweening you create this tween function, and call it with the current time to find out what the intermediate value should be

23:15 `szx: amalloy: interesting

23:15 amalloy: there's some not-insignificant bookkeeping work to, to make these things cohabitate with ordinary values and not confuse the types

23:15 but it seems like a viable approach

23:15 `szx: amalloy: so you're saying you would assoc this fn to the :radius etc

23:16 amalloy: right

23:16 `szx: makes sense, and i guess my non-tweening values could be (constantly val)?

23:17 i guess that wouldn't take an argument

23:18 anyway, i'll give it a try

23:18 thanks

Logging service provided by n01se.net