2009-08-10
| 00:17 | rlb | Does clojure have an rfc-822 date parser? |
| 00:19 | arbscht | doesn't java have a class for that? |
| 00:19 | LauJensen | yep |
| 00:20 | arbscht | java.text.SimpleDateFormat, I suppose |
| 00:25 | rlb | Sure, though it looked like that might require multiple patterns. I had just wondered if clojure already had something simpler. Anyway, thanks. |
| 00:26 | LauJensen | It might - Just not something that I know of. Check clojure.org under libraries maybe |
| 00:27 | rlb | I saw the email lib -- perhaps it provides access to the date parser. |
| 00:28 | rlb | nevermind, that's just for sending |
| 00:34 | Anniepoo | clojurebot: paste |
| 00:34 | clojurebot | lisppaste8, url |
| 00:34 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 00:49 | lisppaste8 | Anniepoo pasted "with-foo" at http://paste.lisp.org/display/85108 |
| 00:51 | hiredman | binding |
| 00:51 | Anniepoo | probably a very simple question, but I nee dto know what the buzzword is for this |
| 00:51 | Anniepoo | Thanks! |
| 00:51 | hiredman | ,(doc binding)_ |
| 00:51 | 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." |
| 00:51 | Anniepoo | ah, sweet |
| 00:51 | Anniepoo | ok, thanks |
| 00:51 | Anniepoo | that's what I wanted |
| 00:51 | hiredman | anyway, binding is for dynamic binding |
| 00:51 | Anniepoo | yah, what about concurrancy? |
| 00:52 | hiredman | threadlocal |
| 00:52 | Anniepoo | ok, cool |
| 00:52 | Anniepoo | 8cD Clojure continues to amaze and delight |
| 00:53 | LauJensen | (and it'll keep doing it for a while) |
| 01:23 | d2dchat | How can I make a function repeat 2 or any number of times I specify? |
| 01:23 | d2dchat | twice* |
| 01:23 | d2dchat | like the equivalent of times.do in ruby |
| 01:23 | d2dchat | I tried (repeat 2 (my-recursive-function)) |
| 01:23 | LauJensen | ~(take 10 (repeat 2)) |
| 01:23 | clojurebot | Gabh mo leithscéal? |
| 01:23 | d2dchat | but that didn't work |
| 01:24 | d2dchat | hmm what does take do? |
| 01:24 | LauJensen | When you say repeat, do you mean execute in sequence? |
| 01:24 | d2dchat | it doesn't matter the order, as long as it repeats the function twice |
| 01:25 | d2dchat | executes twice |
| 01:25 | LauJensen | (dotimes [i 2] (my-func)) |
| 01:26 | d2dchat | LauJensen: ah! That worked beautifully |
| 01:26 | d2dchat | how come repeat doesn't work? |
| 01:26 | LauJensen | I have no idea, it works locally |
| 01:26 | LauJensen | ~(repeat 2) |
| 01:26 | clojurebot | It's greek to me. |
| 01:26 | LauJensen | ~(doc repeat) |
| 01:26 | clojurebot | Excuse me? |
| 01:26 | Fossi | d2dchat: repeatedly |
| 01:26 | Fossi | repeat repeats a value |
| 01:27 | Fossi | ,(doc repeat) |
| 01:27 | clojurebot | "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs." |
| 01:27 | d2dchat | well for whatever reason repeat didn't execute the function twice |
| 01:27 | d2dchat | and dotimes did |
| 01:27 | d2dchat | not sure why |
| 01:27 | LauJensen | But repeat is not what you want |
| 01:27 | LauJensen | I thought you wanted a data sequence |
| 01:27 | LauJensen | But may I ask why you're executing something twice? |
| 01:27 | Fossi | repeat repeats a value |
| 01:27 | d2dchat | well it could be variable.. depends on arity |
| 01:28 | Fossi | it does not call a function |
| 01:28 | d2dchat | Fossi: gotcha |
| 01:28 | d2dchat | LauJensen: my function generates functions randomly based on arity :) |
| 01:28 | hiredman | ,(doc repeatedly) |
| 01:28 | clojurebot | "([f]); Takes a function of no args, presumably with side effects, and returns an infinite lazy sequence of calls to it" |
| 01:29 | d2dchat | hmm, my function has args |
| 01:29 | hiredman | d2dchat: wrap it in a thunk |
| 01:30 | Fossi | thunkamajunk |
| 01:30 | hiredman | ,(take 2 (repeatedly #(+ 1 2))) |
| 01:30 | d2dchat | thunk? :) |
| 01:30 | clojurebot | (3 3) |
| 01:30 | hiredman | ~google thunk |
| 01:30 | clojurebot | First, out of 1370000 results is: |
| 01:30 | clojurebot | Thunk - Wikipedia, the free encyclopedia |
| 01:30 | clojurebot | http://en.wikipedia.org/wiki/Thunk |
| 01:30 | LauJensen | d2dchat: Sounds awesome |
| 01:31 | d2dchat | hopefully it will be.. Genetic Programming is fun :) |
| 01:31 | LauJensen | If you can program a hamster which brews coffee, please let me know |
| 01:31 | d2dchat | LauJensen: I'm on it! |
| 01:31 | d2dchat | ;) |
| 01:32 | d2dchat | Will call is Javaster |
| 01:32 | LauJensen | Clamster |
| 01:32 | d2dchat | Beanster |
| 01:33 | d2dchat | now I have to learn how to preserve state across functions.. do I just pass a parameter around? |
| 01:34 | d2dchat | well |
| 01:34 | d2dchat | it's the same function |
| 01:34 | d2dchat | I will experiment :) |
| 01:34 | LauJensen | To be truely functional you have to pass everything around |
| 01:34 | Anniepoo | look at 'let' |
| 01:34 | d2dchat | Is it better to pass it around? |
| 01:35 | LauJensen | http://en.wikipedia.org/wiki/Functional_programming |
| 01:35 | LauJensen | Skim that |
| 01:35 | d2dchat | Right, I know some erlang |
| 01:35 | d2dchat | just wanted to know clojure conventions because it's a hybrid |
| 01:35 | d2dchat | but I guess opt for immutability ! |
| 01:56 | d2dchat | How come this isn't allowed? |
| 01:56 | d2dchat | user=> (defn blah [something] (something)) |
| 01:56 | d2dchat | #'user/blah |
| 01:56 | d2dchat | user=> (blah ()) |
| 01:57 | d2dchat | I'm assuming there is a better way to push an empty list to a function :) |
| 01:57 | d2dchat | user=> (defn blah [something] (something)) |
| 01:57 | d2dchat | #'user/blah |
| 01:57 | d2dchat | user=> (blah ()) |
| 01:57 | d2dchat | java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) |
| 01:57 | Fossi | you call something |
| 01:58 | hiredman | you are trying to call the empty list as a function |
| 01:58 | hiredman | it isn't |
| 01:58 | hiredman | so surprisingly you get an exception |
| 01:58 | d2dchat | Sure, makes sense, is there a way to test that? |
| 01:58 | hiredman | lists == function application |
| 01:59 | LauJensen | The empty list is '() not () |
| 01:59 | hiredman | ,(list? ()) |
| 01:59 | clojurebot | true |
| 01:59 | hiredman | LauJensen: the empty lists doesn't need quoting |
| 01:59 | hiredman | ,() |
| 01:59 | clojurebot | () |
| 01:59 | LauJensen | oh |
| 01:59 | LauJensen | Old habit then |
| 02:00 | hiredman | ,((fn [something] (something)) 1) |
| 02:00 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 02:00 | d2dchat | hmm I think what I want is to create an expression on the fly |
| 02:01 | d2dchat | without it evaluating quite yet |
| 02:01 | hiredman | that function will give you an exception if you call it with anything that does not implement IFn |
| 02:01 | d2dchat | right, make ssense |
| 02:01 | LauJensen | ,(def f (fn [x] 5)) |
| 02:01 | clojurebot | DENIED |
| 02:01 | d2dchat | :) |
| 02:02 | d2dchat | is it possible to execute [+ 5 6] ? |
| 02:02 | hiredman | d2dchat: you seem not to have read any docs, I think it would help if you read some, tried out a few euler problems |
| 02:02 | hiredman | etc |
| 02:02 | hiredman | what the blip.tv videos |
| 02:02 | hiredman | watch |
| 02:13 | osaunders | I'm confused. Is Clojure object-oriented? How do I create an object? |
| 02:14 | hiredman | no |
| 02:14 | hiredman | clojurebot: rationale |
| 02:14 | clojurebot | rationale is http://clojure.org/rationale |
| 02:16 | osaunders | Still confused. There are multimethods but it's not object-oriented? |
| 02:16 | hiredman | osaunders: multimethods can dispatch on any function |
| 02:17 | hiredman | ~bliptv |
| 02:17 | clojurebot | Huh? |
| 02:17 | hiredman | ~blipt.v |
| 02:17 | clojurebot | It's greek to me. |
| 02:17 | hiredman | bah |
| 02:17 | hiredman | ~blip tv |
| 02:17 | clojurebot | I don't understand. |
| 02:17 | hiredman | ~blip.tv |
| 02:17 | clojurebot | blip.tv is http://clojure.blip.tv/ |
| 02:17 | hiredman | horrible |
| 02:17 | hiredman | anyway watch the videos, read the rationale |
| 02:18 | osaunders | I watched the ones for Java Programmers. |
| 02:18 | osaunders | Guess I should move on to the ones for LISP ones. |
| 02:20 | osaunders | "Systems that utilize runtime polymorphism are easier to change and extend. Clojure supports polymorphism at 3 levels. First, almost all of the core infrastructure data structures in the Clojure runtime are defined by Java interfaces." |
| 02:20 | hiredman | osaunders: did you see anything with objects and calling methods on objects in the video? |
| 02:21 | osaunders | No |
| 02:21 | osaunders | Should I? |
| 02:21 | hiredman | would you expect to see such in a video about an oop language? |
| 02:22 | hiredman | have you looked at the rationale page? |
| 02:23 | hiredman | there is a whole website beyond the page on multimethods |
| 02:23 | osaunders | Wow, you're almost berating me here. |
| 02:23 | hiredman | *shrug* |
| 02:25 | osaunders | Does Rich thing Smalltalk is a spaghetti code language? |
| 02:25 | osaunders | *think |
| 02:26 | Fossi | osaunders: dunno, maybe ask him? ;D |
| 02:26 | osaunders | Fossi: hiredman is having me look at the rationale as if that's going to explain the characteristics of the language. |
| 02:27 | Fossi | well, it kinda does |
| 02:27 | Fossi | at least it has some major points on there |
| 02:28 | osaunders | Hang on, let me read this fully http://clojure.org/runtime_polymorphism |
| 02:28 | Fossi | that being said i'd argue that clojure is mainly functional, but as a lisp, it can't keep you from coding in a OO style if you must |
| 02:28 | clojurebot | that is not what I wanted |
| 02:29 | hiredman | http://clojure.org/state is also good |
| 02:29 | Fossi | only that it would be awkward and prolly slow as well :) |
| 02:30 | Fossi | bbl |
| 02:49 | d2dchat | Is there a way to concatinate lists without evaluating them? |
| 02:49 | d2dchat | I have a loop that gives me (+) (5) and (6) |
| 02:49 | d2dchat | but I want to make it (+ 5 6) |
| 02:50 | hiredman | http://clojure.org/sequences |
| 02:52 | mikehinchey | concat |
| 02:53 | d2dchat | mikehinchey: isn't that just for vectors? |
| 02:54 | mikehinchey | no, most functions like that work on any seq |
| 02:54 | d2dchat | user=> (concat (5) (5) (5)) |
| 02:54 | d2dchat | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) |
| 02:55 | hiredman | d2dchat: lists are function application |
| 02:55 | mikehinchey | if you quote each (5), it will work '(5) |
| 02:55 | d2dchat | ahh OK |
| 02:55 | d2dchat | makes sense |
| 02:55 | hiredman | (5) tries to call 5 as a function |
| 02:56 | d2dchat | yup |
| 02:56 | d2dchat | user=> (concat '(5) '(5) '(5)) |
| 02:56 | d2dchat | (5 5 5) |
| 02:56 | d2dchat | grr |
| 02:56 | d2dchat | stupid mistake :( |
| 02:56 | hiredman | please read the url I pasted |
| 02:56 | hiredman | sequences and sequence functions are very import in clojure |
| 02:57 | d2dchat | reading through it |
| 04:16 | mikehinchey | What does #= do? I thought it was a reader macro for evaluation, but #=(if true 1 2) fails. |
| 04:17 | hiredman | read the exception |
| 04:17 | mikehinchey | "can't resolve if" |
| 04:17 | hiredman | the evaluation at readtime is very limited |
| 04:18 | hiredman | #=() is typically just used to call contructors |
| 04:18 | hiredman | ,#=(java.util.ArrayList. (1 2 3)) |
| 04:18 | clojurebot | #<ArrayList [1, 2, 3]> |
| 04:19 | hiredman | so you can have the reader read an ArrayList |
| 04:19 | hiredman | constructors |
| 04:19 | mikehinchey | ok, that's fine, it's not what I wanted then |
| 04:20 | hiredman | ,#=(System/exit 1) |
| 04:20 | clojurebot | System |
| 04:20 | hiredman | bah |
| 04:22 | mikehinchey | thanks |
| 05:42 | alrex021 | Is there any online paste that has clojure syntax highlight? |
| 05:43 | Chousuke | gist.github.com |
| 05:45 | alrex021 | thx Chousuke |
| 05:46 | alrex021 | I am trying to get my head around conditional flow in clojure. I have a following code snippet: http://gist.github.com/165113 |
| 05:47 | alrex021 | chat-view is meant to check if session has :login key, if not it must add it. After that it must continue on to return the html fragments |
| 05:47 | Chousuke | hm |
| 05:47 | Chousuke | then your problem there is that (layout... is the else branch |
| 05:48 | alrex021 | yup, exactly... |
| 05:48 | alrex021 | how do I setup a control flow so that (layout ... is always ran |
| 05:49 | Chousuke | you need (if-not pred then-branch nil) |
| 05:49 | Chousuke | or alternatively, (when-not pred then-branch= |
| 05:49 | Chousuke | )* |
| 05:49 | Chousuke | which is just a shortcut for the above :) |
| 05:50 | alrex021 | hmm, I am not following 100% :) .. what is wrong wih my if-not? |
| 05:50 | alrex021 | well...hmm layout falls in else part? |
| 05:50 | Chousuke | if-not requires both the then-form and else-form |
| 05:50 | Chousuke | and your layout is in the place where it expects the else-form |
| 05:52 | alrex021 | but my (layout ... part should be ran regardless of the if-not outcome... |
| 05:52 | Chousuke | btw, it looks like your session-assoc is a function containing a dosync... I think it's better style to not have dosyncs hidden in the actual "alter" functions |
| 05:53 | alrex021 | hmmm, its compojure's session-assoc which they advise to use |
| 05:53 | Chousuke | ah, hmm. in that case, I guess there's no helpong it :/ |
| 05:53 | alrex021 | and yes, it internally does an alter on the session ref |
| 05:54 | Chousuke | I just think one should keep most of the logic in pure functions. .) |
| 05:55 | Chousuke | eg. instead of a side-effecting function, I think it'd be better to have a pure function like (alter-session assoc :login whatever) designed to be wrapped in a dosync |
| 05:55 | arbscht | you could probably refactor that with the mutation in some kind of chat-login-controller function around chat-view |
| 05:55 | Chousuke | but I guess if it's the framework that's providing it to you, you should use it. |
| 05:55 | arbscht | a -view altering the session should ring bells, even in compojure |
| 05:56 | alrex021 | interesting |
| 05:57 | Chousuke | Anyway, you want to do (when-not guest (session-assoc ...)) (layout ...) |
| 06:01 | alrex021 | hhmm still doesn't seem right http://gist.github.com/165113 |
| 06:02 | alrex021 | prob is when (session-assoc ..) runs it doesn't bind it to guest in local block |
| 06:02 | alrex021 | that my guess |
| 06:03 | arbscht | oh, you want to use the updated session in chat-view |
| 06:04 | arbscht | that would need a new request |
| 06:05 | alrex021 | hmm, interesting... so I would need to exit the function and come back in? |
| 06:05 | alrex021 | would'n if-let help with this to maybe rebind guest to new value for new session :login |
| 06:06 | alrex021 | am I just making this look so difficult or is it really this difficult? |
| 06:06 | arbscht | you're conflating clojure flow with compojure+http flow :) |
| 06:08 | arbscht | hm, compojure docs are offline? :/ |
| 06:08 | alrex021 | what docs? :) |
| 06:08 | arbscht | oh, there was a secret site at preview.compojure.org |
| 06:08 | Chousuke | arbscht: ah, right. |
| 06:09 | Chousuke | arbscht: try (let [guest (or (session :login) (session-assoc :login (guest-account)))] |
| 06:10 | alrex021 | ok this worked....http://gist.github.com/165113 |
| 06:11 | alrex021 | for some reason I still think thats not really the cleanest way |
| 06:11 | alrex021 | So if-not guest, then add :login to session and then redirect back into the view via http call |
| 06:12 | arbscht | yes, that login check and redirect should go in a non-view function |
| 06:12 | Chousuke | yeah |
| 06:12 | alrex021 | I see, that makes sense....the mutable bit so then view would have no side-effects....does that sound right? |
| 06:13 | arbscht | right |
| 06:13 | Chousuke | and in general, doing non-view stuff in the view, mutable or not. |
| 06:14 | alrex021 | but would the view call this func that has side-effects...? |
| 06:14 | Chousuke | the other way around I think |
| 06:14 | arbscht | the router would dispatch to the -controller (or whatever), which would call the appropriate view after determining login etc |
| 06:14 | Chousuke | you write the function that checks the login, alters the session if needed, and then calls the view function. |
| 06:15 | alrex021 | oh I see...that makes very much sense...thx I'll give that a try quick |
| 06:43 | alrex021 | Ok I have a new working version that separates the pure function from one that alters the mutable data... http://gist.github.com/165113 |
| 06:44 | alrex021 | only question I have is....is it ok for the chat-view to still have a check on guest and then if required to redirect to login-controller to perform login then redirect to chat |
| 06:45 | arbscht | that's hard to make sense of without seeing the routes |
| 06:46 | alrex021 | sorry about that, I just added the routes.... http://gist.github.com/165113 |
| 06:47 | alrex021 | doesn't seem clean that my chat-view actually deals with login check |
| 06:48 | arbscht | right |
| 06:48 | arbscht | I'd suggest associating "/chat" with a controller, rather than a view, since it may affect the session state |
| 06:49 | alrex021 | so just anotherer level of indirection? |
| 06:49 | arbscht | essentially, yes |
| 06:50 | alrex021 | chat-controller ....checks login and takes you to chat-view |
| 06:50 | alrex021 | this way chat-view has no side-effects |
| 07:00 | alrex021 | arbscht: I have made the changes now and it looks much better. The chat-controller now holds the control logic and then delegates to chat-view pure function .. http://gist.github.com/165113 |
| 07:04 | arbscht | very good :) |
| 07:05 | arbscht | having the login-controller only redirect to "/chat" seems too specific. you could probably generalize it further somehow |
| 07:06 | alrex021 | yup, pass in :next param maybe |
| 07:06 | arbscht | that certainly cleaned up the view nicely, though |
| 07:07 | alrex021 | thx |
| 07:07 | arbscht | if session-assoc fails for some reason (say, disabled cookies), could you get caught in a redirect cycle? |
| 07:16 | alrex021_ | I added next-url param to login-controller so now its more generic... |
| 07:16 | alrex021_ | other controllers could redirect to it with next-url param that indicates where to go after login |
| 07:17 | alrex021_ | "f session-assoc fails for some reason (say, disabled cookies), could you get caught in a redirect cycle?" -> very good question....that is a big prob |
| 07:19 | alrex021_ | I'd hope that then an exception is raised or something to break the flow and then I could redirect to error page |
| 07:20 | alrex021_ | Again, this is just Simple Chat prog I;m building to learn more about clojure, conurracy api, ..etc |
| 07:22 | Chousuke | hm |
| 07:23 | Chousuke | well, it should be rather easy to check if session-assoc failed or not. |
| 07:23 | Chousuke | just try and see if the value you put there is present. |
| 07:24 | Chousuke | if not, redirect to an error page from the controller. |
| 07:24 | alrex021_ | yup, that makes sense.. |
| 07:25 | alrex021_ | so check (session :login) after assoc call |
| 07:25 | alrex021_ | if not there, well then cookies prob not enabled...so show error page |
| 07:39 | arbscht | sorry, what I mean is if the client rejects the session data in the response, it would be like a new visitor after the redirect |
| 08:43 | weissj | is there a way to define functions, etc in something other than the current namespace? seems strange to keep switching ns, doing a defn, switching again, etc |
| 08:46 | cark | i usually recompile the whole file, which has the ns form on top |
| 08:47 | weissj | cark: not sure i understand |
| 08:47 | cark | are you using emacs ? |
| 08:47 | weissj | no |
| 08:47 | cark | how are you developing ? |
| 08:47 | weissj | clojure-dev (eclipse) |
| 08:47 | cark | oh i see |
| 08:47 | cark | i can't help then =( |
| 08:48 | weissj | this question isn't an environment question, it's a clojure lang question |
| 08:48 | cark | well it's a about your developement process |
| 08:48 | weissj | my file has the ns form at the top, but i want to defn something in that file that goes in a different ns |
| 08:48 | cark | oh |
| 08:48 | cark | that seems strange |
| 08:49 | weissj | cark: yeah, it's using clj-record, which is like ruby on rails' ActiveRecord |
| 08:49 | weissj | it creates namespaces for each table and creates functions for them |
| 08:49 | weissj | using macros |
| 08:49 | smoonen | weissj -- does (intern) do what you want? |
| 08:50 | weissj | ,(doc intern) |
| 08:50 | clojurebot | DENIED |
| 08:50 | weissj | smoonen: yeah i think that's it, thanks! |
| 08:51 | weissj | smoonen: wait, maybe not. it creates vars, what about functions? |
| 08:53 | smoonen | weissj -- seems to work if I pass it a lambda |
| 08:53 | smoonen | (intern 'user 'f (fn [x] (inc x))) |
| 08:54 | weissj | smoonen: huh, ok, not quite how i imagined it would work, but i think that'll do it |
| 08:54 | weissj | i was expecting something more like "let" |
| 08:55 | weissj | sorta like (let-ns ns (block)) |
| 08:56 | weissj | in-ns switches ns, but does it permanently, it doesn't wrap anything |
| 08:56 | cark | you may use the binding form |
| 08:57 | cark | (binding [*ns* ..] |
| 09:00 | weissj | cark: ok let me give that a shot |
| 09:06 | cark | doesn't work =/ |
| 09:06 | cark | because it's a read-time thing instead of compile-time |
| 09:35 | slaney | is clojurebot a opensouce project that I can use myself? |
| 09:36 | arbscht | slaney: http://github.com/hiredman/clojurebot/tree/master |
| 09:36 | slaney | ah, great thanks |
| 09:48 | ericthorsen | What is the equivalent to memfn for static methods in a java class? |
| 09:50 | Chousuke | (doc memfn) |
| 09:50 | clojurebot | "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn." |
| 09:50 | Chousuke | hm. |
| 09:50 | ericthorsen | ...if I want to treat a static method as a first-class fn |
| 09:50 | Chousuke | I'd just use #(Foo/static %1 %2 %3...) |
| 09:52 | ericthorsen | Chouser: yes...that would work...too simple. I guess I was hoping Foo/static would just return something I could use. |
| 10:32 | weissj | is there something like "let" for namespaces (ie, execute this block in this namespace) |
| 10:33 | weissj | seems like the only option is to use in-ns which changes ns permanently (until you change it back) |
| 10:33 | Chouser | I've wondered the same thing. |
| 10:33 | smoonen | couldn't find anything. you could definitely write your own via macro. |
| 10:34 | weissj | so the macro would just save the value of *ns* and switch it back after the block runs? |
| 10:34 | Chouser | The most obvious interface to me would be just (defn other.ns/foo ...) but that appears to be explicitly unsupported |
| 10:34 | weissj | Chouser: yeah i tried that :) |
| 10:35 | weissj | i would have thought in-ns would have a different form for that |
| 10:43 | Anniepoo | wondering what constitutes real metadata |
| 10:44 | Anniepoo | I've got a bunch of code that shoves around vectors that represent 3D boxes |
| 10:46 | Anniepoo | the boxes have to actually come from a list with other info |
| 10:47 | Anniepoo | in a structmap. Eventually I'll want to get back to the structmap. Is it kosher to shove it into metadata? |
| 10:49 | Chouser | does it seem to anyone else that the questions in here keep getting harder? |
| 10:49 | Anniepoo | LOL |
| 10:50 | Anniepoo | we're learning! |
| 10:50 | Chouser | Anniepoo: I would imagine that's ok. |
| 10:50 | Anniepoo | ok, cool |
| 10:50 | Chouser | Using metadata like that is probably ok, I mean. Learning is unacceptible. |
| 10:50 | Anniepoo | I know from bitter experience with XML attributes that mixing metadata and data willy nilly is a bad thing |
| 10:51 | Anniepoo | I'm actually solving the knapsack problem at the moment. |
| 10:52 | Anniepoo | Chouser, can you solve the knapsack problem for me? ;c) |
| 10:58 | Chouser | 0-1 ? one constraint? |
| 10:59 | Anniepoo | I've got what actually isn't the knapsack problem (or I wouldn't be solving it), I need to exactly pack an AABB with |
| 10:59 | Anniepoo | AABB's drawn from a list. I also have available, fortunately, any sized AABB up to a certain maximum dimension on each side |
| 11:00 | Anniepoo | (AABB = axis aligned bounding box, a non rotated rectangular prism) |
| 11:01 | Chouser | 3D? |
| 11:01 | Anniepoo | yes |
| 11:02 | Anniepoo | the key is the variable sized one. I pack the thing with the biggest piece that will still fit, over and over, until the remaining chunks are under the limit of the rubber cube |
| 11:16 | lisppaste8 | cgrand pasted "microbenchmark: PersistenthashMap2$TransientMap" at http://paste.lisp.org/display/85126 |
| 11:21 | Chouser | cgrand: wow. care to summerize the difference, or should I just keep trying to read the code? |
| 11:26 | cgrand | Chouser: ideas from rhickey: no leave nodes and inner nodes aren't packed as soon as they are half full |
| 11:28 | Chouser | cgrand: version 3 will use new new? :-) |
| 11:30 | cgrand | maybe |
| 11:35 | cemerick | Chouser: welcome back :-) |
| 11:35 | cemerick | (if you had actually gone somewhere, that is) |
| 11:36 | Chouser | cemerick: thanks! family "vacation". |
| 11:37 | Chouser | cgrand: so ArrayNode instead of LeafNode? |
| 11:41 | cgrand | Chouser: ArrayNode instead of FullNode and BitmapIndexedNode now contains an interleaved array of keys and values (if the key is null then the value is an INode)) |
| 11:51 | duplo | Is there a webpage that explains "if-let" more than the clojure page? |
| 11:52 | drewr | duplo: not sure; what are you confused about? |
| 11:58 | duplo | drewr: The explanation just seems a little terse to me. |
| 11:59 | duplo | drewr: But maybe I need to read up a bit on macros for it to make more sence. |
| 12:04 | arohner | duplo: ,(source if-let) |
| 12:04 | drewr | duplo: it's a substitution for a common idiom (let [x true-or-false] (if x :foo :bar)) |
| 12:07 | duck1123 | I use it more often to test if the let contains something, or is nil |
| 12:09 | duck1123 | I just wish if-let would allow me to have multiple let statements. (perhaps with AND semantics for each statement) |
| 12:09 | Chousuke | that shouldn't be too difficult to implement. |
| 12:10 | Chousuke | would be a backwards-compatible change too |
| 12:11 | Chouser | are you sure 'and' is what you'd want? |
| 12:11 | duck1123 | not sure. that, or just like a normal let, with the if only applying to the last one |
| 12:14 | duck1123 | the latter is closer to how I've tried to use it, before I got the error |
| 12:15 | duck1123 | but in those cases, each statement in the original let was true anyway |
| 12:17 | Chousuke | I suppose it would be possible to have (if-let :any [x foo y bar] ...) |
| 12:18 | Chousuke | (and :all too) |
| 12:23 | duck1123 | Chousuke: would :last be the default then? |
| 12:23 | Chousuke | duck1123: maybe. |
| 12:25 | Chousuke | I'm still wondering whether it really makes sense, though. |
| 12:25 | Chousuke | to extend if-let like that I mean. |
| 12:25 | cemerick | I think not, if only because I'd expect :all to be the default. :-/ |
| 12:25 | cemerick | ...and others would expect :first |
| 12:26 | cemerick | and then someone would suggest a way to specify alternate schemes, like :alternating |
| 12:26 | cemerick | yeah, that was snark ;-) |
| 12:27 | duck1123 | I think :last is the best one truthfully. That's the one that fit's my use case when I ran into this yesterday |
| 12:28 | Chouser | this is all to avoid one more nesting of 'let'? |
| 12:28 | duck1123 | (let [a foo] (if-let [b bar] ... )) becomes (if-let [a foo b bar] ... ) but I can see how people might want :all as well |
| 12:50 | unlink | Where can I find a list of all the new transient methods? |
| 12:50 | Chousuke | hmm |
| 12:51 | Chousuke | find-doc transient will probably find you them all |
| 12:52 | unlink | Thanks. |
| 12:53 | unlink | So assoc! is how I mutate arrays? |
| 12:54 | Chousuke | vectors, and yes |
| 12:54 | unlink | right...transient vectors |
| 12:55 | tomoj | is this sane? (map #(vec [:foo %]) coll) |
| 12:55 | Chousuke | making a vector out of a vector is a bit weird :P |
| 12:55 | tomoj | that's what I thought |
| 12:55 | tomoj | but not sure how to do it without "vec" there |
| 12:56 | tomoj | since otherwise the map will try to call the vector as a function |
| 12:56 | Chousuke | you probably want to use a real lambda (map (fn [x] [:foo x]) coll) |
| 12:56 | tomoj | aha |
| 12:56 | tomoj | thanks |
| 12:57 | unlink | Do transients scream 'leaky abstraction' to anyone else? Persistent data structures enforce immutability, but transients come with a caveat -- don't bash in place -- which is not technically enforced and easy to get wrong |
| 12:57 | Chousuke | #(foo) is short for (fn [] (foo)), which trips people up sometimes. |
| 12:57 | tomoj | ah, I see |
| 12:57 | tomoj | there is no shortcut for (fn [] foo) I guess? |
| 12:57 | Chousuke | no |
| 12:57 | Chousuke | though you can do #(do foo) |
| 12:58 | tomoj | rather use a real lambda I think |
| 12:58 | Chousuke | unlink: I think it's possible it might become enforced at some point |
| 12:59 | Chousuke | though I suppose enforcing it would have to cost something |
| 13:00 | Chousuke | but I don't think it's a problem. Transients are supposed to be used carefully to begin with. |
| 13:00 | unlink | The second you start designing your programming language with warnings that a construct needs to be "used carefully", you have already failed. |
| 13:01 | Chousuke | well, I mostly meant that you should first design the algorithm with persistents, and then swap in transients if performance is a problem. |
| 13:02 | unlink | I agree that they should not be the go-to idiom for designing clojure programs, but the "incidental" mutability of transient values is a very real part of the API of clojure. |
| 13:02 | unlink | And no amount of warning will take that away. |
| 13:02 | unlink | (Unless technically enforced) |
| 13:03 | Chousuke | it'd help if the old values were invalidated, but I think that would cost too much in terms of performance. |
| 13:04 | Chousuke | you'd need a flag for every interim value to indicate whether it's been used or not. |
| 13:04 | tomoj | hmm.. I thought clojure was big on always enforcing immutability except through a few very specific APIs |
| 13:05 | tomoj | well, and all of Java |
| 13:05 | unlink | Which could kill cache locality. You're right -- it would negate part of the benefit of transients. As they stand, transients expose an enormous correctness abstraction leak. |
| 13:05 | unlink | however. |
| 13:06 | unlink | What makes this dangerous is that transients support the same read API as persistents. |
| 13:06 | Chousuke | hmm |
| 13:06 | Chousuke | I don't think that |
| 13:06 | Chousuke | ... will be a problem |
| 13:08 | unlink | Perhaps this correctness issue could be culturally enforced. I know however I would be more comfortable if there was a safety net that ensured that I could never be handed a transient value that could change under my feet and still read like a persistent without warning. |
| 13:09 | Chousuke | well, transients can't be used outside the thread they were created in. |
| 13:10 | Chousuke | so even if you happen to get a transient as input to a read-only function, it's not going to change between two reads unless you also write to it through the transient api. |
| 13:13 | unlink | Right, that is an essential safety measure. |
| 13:13 | Chousuke | hmm, I wonder if transients could cache the most recent value of "this" and check it upon edits. |
| 13:14 | Chousuke | wait, that makes no sense. |
| 13:20 | cemerick | would it really be bad if a flag were set on every transient instance that had been used as the basis of a mutation operation (assoc!, conj!, etc)? |
| 13:20 | cemerick | yeah, I guess it would. |
| 13:21 | Chousuke | some indirection could work :P |
| 13:22 | cemerick | but defeat the point, at least somewhat |
| 13:22 | Chousuke | yeah |
| 13:23 | cemerick | I'm happy enough to let the pitfalls be documented, and be done with it. |
| 13:23 | cemerick | you can't blame the rope when you hang yourself |
| 13:24 | cemerick | e.g. (let [a ..some transient..] (assoc! a :foo 5) (assoc! a :bar 6)) reflects some incredibly misguided thinking in general, so protecting against that is a tough order |
| 13:28 | cemerick | (I was called a 'lisp weenie' over the weekend. Maybe this is the kind of attitude that prompted that. :-P ) |
| 13:29 | Chousuke | I'm always wary of function bodies that contain more than one expression :P |
| 13:30 | d2dchat | How do you do the equivalent of && in a boolean expression? |
| 13:31 | Chousuke | use (and ...) |
| 13:32 | d2dchat | Chousuke: thx! I wonder why I couldn't find that in the API |
| 13:33 | Chousuke | well, and is not the easiest word to search for :P |
| 13:33 | Chousuke | rather, it's a bit too easy to find :) |
| 14:06 | kotarak | How can I parse xml files containing UTF-8 characters with clojure.xml/parse? The characters always turn to '?'. |
| 14:09 | gcv | what's the right way to determine the type of a Clojure value? I'm looking for an equivalent to (class x) which would return, e.g., :vector instead of clojure.lang.LazilyPersistentVector. |
| 14:11 | hiredman | gcv: why would anything return :vector |
| 14:12 | kotarak | gcv: quick hack http://paste.pocoo.org/show/133501 |
| 14:12 | tomoj | (count (filter ...)) is not good with laziness, is it? |
| 14:12 | kotarak | but why do you need it? |
| 14:12 | kotarak | tomoj: no |
| 14:12 | hiredman | tomoj: how could count be lazy? |
| 14:13 | tomoj | well, I mean, does it need to load the whole seq into memory at once, or not? |
| 14:13 | kotarak | obviously |
| 14:14 | tomoj | guess I need to write filter-count then |
| 14:14 | clojurebot | filter doesn't stop |
| 14:14 | gcv | kotarak: yeah, I was hoping to get a quick lookup... I'm working on writing Clojure values to Berkeley DB, and I need type tags, so I don't want to worry about the various vector types |
| 14:15 | kotarak | gcv: use multimethods with IPersistentMap etc, as dispatch values |
| 14:15 | hiredman | ,(ancestors []) |
| 14:15 | clojurebot | nil |
| 14:15 | hiredman | er |
| 14:15 | hiredman | ,(ancestors (class [])) |
| 14:15 | clojurebot | #{java.lang.Iterable java.lang.Runnable clojure.lang.Obj clojure.lang.IPersistentVector java.util.Collection clojure.lang.IFn clojure.lang.Seqable clojure.lang.Indexed java.util.List clojure.lang.AFn clojure.lang.Streamable java.lang.Object java.util.concurrent.Callable clojure.lang.IMeta java.util.RandomAccess clojure.lang.IObj clojure.lang.Sequential clojure.lang.IPersistentStack java.io.Serializable clojure.lang.Revers |
| 14:16 | gcv | ancestors! |
| 14:16 | gcv | hiredman: thank you, that's the function I needed |
| 14:16 | hiredman | clojure.lang.IPersistentVector msot likely what you want |
| 14:16 | gcv | hiredman: judging by the implementation of vector?, yes it is |
| 14:17 | d2dchat | can someone help me figure out why expression is not evaluating properly? |
| 14:17 | d2dchat | http://pastie.org/private/kax4t0yrhw2caujppupa |
| 14:18 | hiredman | d2dchat: what do you mean "not evaluating properly" |
| 14:18 | d2dchat | I'm getting an exception at the very end |
| 14:18 | d2dchat | Exception in thread "main" java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn (darwin.clj:0) |
| 14:19 | hiredman | so somewhere you are trying to call a lazy-seq as a function |
| 14:19 | d2dchat | do (/ 5 6) expressions turn into lazy sequences if you are concat'ing them? |
| 14:20 | hiredman | sure |
| 14:20 | hiredman | but (/ 5 6) is also not a function |
| 14:20 | hiredman | so you cannot call it |
| 14:20 | d2dchat | but you can eval it ? |
| 14:20 | hiredman | sure |
| 14:21 | hiredman | d2dchat: I would really suggest you spend more time getting to know the language instead of just jumping and trying to write genetic algorithms |
| 14:21 | d2dchat | hehe |
| 14:21 | d2dchat | I learned a lot from this exercise, but I agree ;) |
| 14:21 | d2dchat | I think I got far though! |
| 14:24 | d2dchat | hiredman: can you explain to me why when I (println expression) on line 39, I get my desired output |
| 14:24 | d2dchat | but when I try to println outside of that context on line 48 it throws an exception? |
| 14:25 | d2dchat | isn't it just passing that around? |
| 14:25 | Chousuke | btw, rather than quoting each of the inner lists, you can just quote the vector :P |
| 14:26 | hiredman | d2dchat: in the paste there are only 25 lines |
| 14:26 | d2dchat | I didn't think I was using any vectors... don't vectors use [] notation? |
| 14:26 | d2dchat | hiredman: whoops haha I have comments in my code |
| 14:27 | hiredman | are you for real? |
| 14:27 | hiredman | do you see all the [] in your code? |
| 14:27 | d2dchat | hiredman: Yes, but I'm using them for parameters? |
| 14:27 | d2dchat | hiredman: line 16 = line 39 |
| 14:27 | d2dchat | line 25 = line 48 |
| 14:28 | d2dchat | sry for the confusion |
| 14:28 | d2dchat | OOOHH |
| 14:28 | d2dchat | I see what you're saying |
| 14:28 | d2dchat | lol |
| 14:28 | d2dchat | Chousuke: thx :) |
| 14:29 | hiredman | d2dchat: somewhere you are trying to call a sequence like it is a function |
| 14:29 | d2dchat | Chousuke: made my API much nicer :) |
| 14:30 | d2dchat | Chousuke: hmm I get an exception now running with this: '[+ - / *] |
| 14:30 | hiredman | since you are building lists (I guess, I really don't want to step through this line by line) I imagine expression is a list/sequence |
| 14:30 | d2dchat | Exception in thread "main" java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn (darwin.clj:0) |
| 14:30 | Chousuke | I think it's in the rand-item |
| 14:30 | hiredman | on line 16 you try and call expression as a function |
| 14:31 | hiredman | is it? |
| 14:31 | d2dchat | hiredman: right, then I try to quote line 16 and it just returns (expression) |
| 14:31 | d2dchat | and when I try evaling that |
| 14:31 | d2dchat | it is like what?? |
| 14:31 | hiredman | … |
| 14:31 | hiredman | please learn clojure first |
| 14:31 | hiredman | please |
| 14:32 | d2dchat | lol, I didn't realize this room was reserved for complex questions.. sry.. I will do more research on my own :( |
| 14:33 | d2dchat | I understand that it can be annoying to answer the same questions all the time, but just thought I could get some quick reference |
| 14:37 | cemerick | d2dchat: simple questions are very welcome here, but trying to debug blobs of application code through irc isn't particularly easy |
| 14:38 | d2dchat | cemerick: agreed. I'm very appreciative of the help I received :) |
| 15:26 | weissj | does anyone know a way to add command history to the repl? |
| 15:27 | Chouser | I like rlwrap |
| 15:27 | smoonen | weissj -- I use http://utopia.knoware.nl/~hlub/uck/rlwrap/ |
| 15:27 | kotarak | there is jline (for completeness sake) |
| 15:27 | gcv | weissj: SLIME :) |
| 15:28 | weissj | hm ideally i could use it in eclipse, but i doubt that clojure-dev supports any of these |
| 15:28 | kotarak | And VimClojure Repl also does history |
| 16:43 | replaca | tomoj, kotarak: (count (filter #(...) ...)) isn't lazy, but it doesn't hold head either. So you can run it without blowing memory. |
| 16:44 | replaca | for example, (time (count (filter #(zero? (rem % 2)) (range 1000000000)))) runs without any problem, with java staying at about 210MB on the billion item list. |
| 16:44 | kotarak | replaca: depends on the second ... |
| 16:45 | tomoj | replaca: huh, and it's actually faster than the custom filter-count I wrote |
| 16:45 | tomoj | :) |
| 16:46 | kotarak | tomoj, replaca: (let [r (range 1000000000000)] (count (filter #(zero? (rem % 2)) r))) |
| 16:47 | tomoj | isn't that holding the head? |
| 16:48 | kotarak | tomoj: bingo. If you aren't charge of the seq you get, you cannot guarantee that (count (filter...)) does not blow up. |
| 16:48 | replaca | kotarak: that's cause you're holding head with the let |
| 16:49 | tomoj | luckily I'm in charge :) |
| 16:49 | replaca | that's just always a problem with lazy seqs! |
| 16:50 | kotarak | tomoj: and you buy that with computing time. If you want to use the actual seq again without count, you have to recompute it again. |
| 16:51 | tomoj | I don't :) |
| 17:28 | Anniepoo | clojurebot: paste |
| 17:28 | clojurebot | lisppaste8, url |
| 17:28 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 17:35 | lisppaste8 | Anniepoo pasted "optional element in list" at http://paste.lisp.org/display/85162 |
| 17:35 | Anniepoo | silly style question |
| 17:36 | Chousuke | hm |
| 17:37 | Chousuke | maybe syntax-quote could help you? |
| 17:38 | Chousuke | ,`(1 2 ~@(do nil) 4) |
| 17:38 | clojurebot | (1 2 4) |
| 17:38 | Chousuke | ,`(1 2 ~@(do '(3)) 4) |
| 17:38 | clojurebot | (1 2 3 4) |
| 17:38 | hiredman | depends what you mean by "build a list" |
| 17:39 | hiredman | you mean just have a list literal that conditionaly includes some element? |
| 17:39 | Anniepoo | well, I'm calling a bunch of functions in order and surrounding them with list |
| 17:39 | hiredman | :( |
| 17:39 | hiredman | sounds horrid |
| 17:40 | Anniepoo | well, I'm interacting with an imperative system I can only talk to over http in 2K chunks\ |
| 17:40 | Anniepoo | and can't use more than 64K memory |
| 17:40 | hiredman | ,(for [x [#(inc 1) #(inc 3) #(inc 4)]] (x)) |
| 17:40 | clojurebot | (2 4 5) |
| 17:42 | hiredman | so you know which element you want to conditionally include? |
| 17:42 | Anniepoo | ,(list "foo" (if (< 3 7) "maybe") "bar") |
| 17:42 | clojurebot | ("foo" "maybe" "bar") |
| 17:42 | Chousuke | ,(for [x [inc dec not identity] :let [z (x 1)] :when z] z) |
| 17:42 | clojurebot | (2 0 1) |
| 17:43 | Anniepoo | but that's broken for |
| 17:43 | Anniepoo | ,(list "foo" (if (< 8 7) "maybe") "bar") |
| 17:43 | Anniepoo | ,(list "foo" (if (< 8 7) "maybe") "bar") |
| 17:43 | clojurebot | ("foo" nil "bar") |
| 17:44 | Anniepoo | expecting ("foo" "bar") |
| 17:44 | kotarak_ | ,(concat (list 1 2) (when false (list 3)) (list 4)) |
| 17:44 | clojurebot | (1 2 4) |
| 17:44 | hiredman | :( |
| 17:44 | hiredman | concat |
| 17:44 | Anniepoo | yah, that looks more right |
| 17:45 | Anniepoo | make a sublist for each piece and concat them |
| 17:45 | hiredman | what is the issue with filter? |
| 17:45 | Anniepoo | not one |
| 17:45 | hiredman | ,(remove nil? (list "foo" (if (< 8 7) "maybe") "bar")) |
| 17:45 | clojurebot | ("foo" "bar") |
| 17:46 | Anniepoo | this just felt 'horrid' and un-clojure-like |
| 17:46 | Anniepoo | ah, cool |
| 17:46 | hiredman | well, it isn't |
| 17:47 | Anniepoo | this one seems closest to expressing the idea of the code |
| 17:47 | Anniepoo | ,`(1 2 ~@(do nil) 4) |
| 17:47 | Anniepoo | ,`(1 2 ~@(do nil) 4) |
| 17:47 | clojurebot | (1 2 4) |
| 17:48 | hiredman | sure, but are you using a literal or not, and willyou always be using a literal? |
| 17:49 | hiredman | if the list of strings is built, it is possible to put the logic in the function that builds the list |
| 17:49 | Anniepoo | no, I'm not using literals, I'm calling a different function for each element |
| 17:49 | hiredman | the other thing to keep in mind is: |
| 17:49 | hiredman | ,(str nil) |
| 17:49 | clojurebot | "" |
| 17:49 | kotarak_ | For strings when should be sufficient |
| 17:49 | kotarak_ | ,(str "a" (when false "b") "c") |
| 17:49 | clojurebot | "ac" |
| 17:50 | hiredman | ,(apply str (list "foo" (if (< 8 7) "maybe") "bar")) |
| 17:50 | clojurebot | "foobar" |
| 17:50 | Anniepoo | wanted ("foo" "bar") |
| 17:50 | hiredman | Anniepoo: but the list, not the elements of the list, is the list a literal or constructed |
| 17:50 | Anniepoo | hmm... maybe I'm not understanding that question |
| 17:51 | Anniepoo | I'm calling list |
| 17:51 | hiredman | (list (foo 1) (bar 2)) or (somefunction-that-produces-a-list some-input-data) |
| 17:52 | hiredman | do you think you will always produce the list that way? is it possibly you might switch to some other list producing function in the future (pull the list from a database, or over the network, or whatever) |
| 17:52 | Anniepoo | the first |
| 17:53 | Anniepoo | no |
| 17:53 | hiredman | filter/remove will work for both cases (list …) and a list produced via some other method |
| 17:53 | Anniepoo | the list represents a series of commands to the external system |
| 17:53 | Anniepoo | I'm writing a compiler for that system |
| 17:55 | Anniepoo | this is the convert-sane-representation-to-sequence-of-cmds-that-instantiates-it-on-what-amounts-to-hardware |
| 17:57 | hiredman | I think anything you do will reimplement filter |
| 17:57 | Anniepoo | ok, cool |
| 17:57 | hiredman | you want to conditionally remove items from a list |
| 17:58 | Anniepoo | just wondered if there was an idiomatic way |
| 17:58 | Anniepoo | rich hickey said at one point to try to stay close to expressing the idea of the code |
| 17:59 | hiredman | something like (remove nil? (list "foo" (if (< 8 7) "maybe") "bar")) |
| 17:59 | Anniepoo | and the idea here in English is 'if 3 < 7 then add the third item' |
| 17:59 | hiredman | using when instead of if |
| 17:59 | Anniepoo | yah, looks like it |
| 17:59 | Anniepoo | thanks |
| 17:59 | Anniepoo | hi Mike! |
| 17:59 | mikehinchey | hi Annie |
| 18:00 | hiredman | if you make whatever recieves the list tolerant of nils in someway (silently ignore them?) then you don't need the remove |
| 18:00 | Anniepoo | true |
| 18:01 | Anniepoo | if I do that, what I should do is some 'flatten' operation |
| 18:01 | hiredman | ,(doc flatten) |
| 18:01 | clojurebot | "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil." |
| 18:01 | tomoj | anyone heard anything about continuation-based web dev in clojure? reading an old thread from december, but it died |
| 18:02 | Anniepoo | yah, oddly, that's the solution here |
| 18:04 | Anniepoo | ,(flatten ("foo" '() "bar")) |
| 18:04 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn |
| 18:04 | tomoj | ,(flatten '("foo" () "bar")) |
| 18:04 | clojurebot | ("foo" "bar") |
| 18:04 | Anniepoo | ,(flatten '("foo" () "bar")) |
| 18:04 | clojurebot | ("foo" "bar") |
| 18:04 | Anniepoo | thanks tom |
| 18:04 | Anniepoo | whoo hoo, that's right |
| 18:04 | Anniepoo | glad I asked |
| 18:05 | Anniepoo | thanks all |
| 18:46 | prospero_ | what allows *print-length* to be changed via set! |
| 18:46 | prospero_ | if I try to change a def of my own, I get a "can't change root binding with set" error |
| 18:47 | hiredman | prospero_: the repl is executed inside a binding |
| 18:48 | prospero_ | yes, but if I call "set! *print-length* 10" outside the repl, it doesn't throw an exception |
| 18:49 | prospero_ | it doesn't do anything either, I know, but I'm just wondering why it doesn't throw an exception |
| 18:50 | hiredman | it's possible that the binding is created by the compiler |
| 18:50 | hiredman | *shrug* |
| 18:50 | hiredman | I never use set! |
| 18:51 | prospero_ | well, maybe you can suggest a decent way to handle this: |
| 18:51 | prospero_ | I'm trying to handle memory management on the gpu |
| 18:51 | hiredman | Oh |
| 18:51 | prospero_ | and I want to be able to define a threshold, above which it collects unused textures |
| 18:52 | prospero_ | this should be a global setting, not necessarily within a binding |
| 18:52 | prospero_ | so set! seems like a decent candidate |
| 18:52 | hiredman | uh |
| 18:52 | prospero_ | but maybe not? |
| 18:52 | hiredman | have you read the docs on set! ? |
| 18:53 | prospero_ | maybe not as carefully as I should have |
| 18:53 | hiredman | set! only works on threadlocaly bound vars, which are generally setup via binding |
| 18:53 | prospero_ | I was more going on how it's used with *print-length* |
| 18:53 | Anniepoo | prospero, it might make sense to make it an atom. You're trying to make something mutable |
| 18:53 | hiredman | prospero_: http://clojure.org/vars#toc1 |
| 18:53 | prospero_ | anniepoo: that makes sense, it just seemed cleaner if it weren't wrapped in an atom or ref |
| 18:54 | Anniepoo | (def texture-mem-threshold (atom 7500000)) |
| 18:54 | osaunders | How do I split a string into characters? |
| 18:54 | _mst | would alter-var-root be an option maybe? |
| 18:54 | Chousuke | osaunders: calling seq on it will return a seq of characters |
| 18:54 | _mst | I've never seen it used much in the wild so I'm unsure... |
| 18:54 | prospero_ | hiredman: making it thread-local would be fine, actually |
| 18:54 | Chousuke | ,(seq "foo") |
| 18:54 | clojurebot | (\f \o \o) |
| 18:54 | prospero_ | I'll take a second look at the docs |
| 18:54 | hiredman | prospero_: so then use binding |
| 18:54 | osaunders | Chousuke: Thanks :) |
| 18:55 | Anniepoo | somebody explained to me, when I asked similar question, that the @mem-threshold had a salutary effect of warning that it's mutable |
| 18:55 | Anniepoo | because of the @ |
| 18:55 | Chousuke | if you use binding, it's not really mutable. |
| 18:55 | prospero_ | hiredman: fair enough |
| 18:55 | Chousuke | it can just vary depending on the dynamic environment. |
| 18:55 | hiredman | Chousuke: tell that to set! |
| 18:56 | Chousuke | hiredman: set! is evil and shall be ignored. |
| 18:56 | hiredman | :D |
| 18:56 | hiredman | that's what I like to hear |
| 18:57 | Anniepoo | Chousuke has a set of tights and a cape with a no-@ symbol and calls himself immutable man 8cD |
| 18:57 | prospero_ | ok, so I guess I'll leave set! to *print-length* |
| 18:57 | clojurebot | count |
| 18:57 | Chousuke | but really, set! is for setting stuff at the repl, and for java fields :) |
| 18:58 | hiredman | ,(macroexpand '@x) |
| 18:58 | clojurebot | (clojure.core/deref x) |
| 18:58 | hiredman | no @ needed |
| 18:58 | hiredman | deref should yeild immutable values anyway |
| 18:59 | Chousuke | though my syntax-quote macro uses a thread-locally bound var as a "mutable". |
| 18:59 | Chousuke | but it's not shared between syntax-quote calls so it's fine. |
| 18:59 | hiredman | :( |
| 19:00 | Chousuke | in fact, an atom wouldn't work since I'd have to take care of resetting it, and then you couldn't use the syntax-quote macro in two threads at the same time :/ |
| 19:02 | Chousuke | I'm not using set! though. |
| 19:02 | Chousuke | it kept throwing exceptions and after a while I got alter-var-root to do what I needed. |
| 19:05 | Chousuke | actually, I wonder |
| 19:05 | Chousuke | now that I tested it, it's not doing what I want :( |
| 19:12 | Chousuke | and now it seems to work just right, when I changed it back to using set! ... |
| 19:14 | hiredman | wonder if it would make sense to have an ur-clojure reader and compiler that work with ArrayList and HashMap for bootstrapping cinc |
| 19:15 | Chousuke | ... |
| 19:15 | Chousuke | I think I will just stop trying to be clever with vars and pass down the autogensym map as a parameter... |
| 19:15 | hiredman | if all the Persistent collections are written in clojure |
| 19:16 | Chousuke | well, the old clojure reader will probably work? |
| 19:19 | hiredman | I guess |
| 19:20 | hiredman | I guess LispReader.java isn't that bad |
| 19:24 | Chousuke | gahh |
| 19:24 | Chousuke | it was laziness that was causing the trouble. |
| 19:25 | hiredman | clojurebot: laziness? |
| 19:25 | clojurebot | Pardon? |
| 19:25 | hiredman | clojurebot: laziness is what will save us all |
| 19:25 | clojurebot | Alles klar |
| 19:26 | Chousuke | now it all works beautifully |
| 19:26 | Chousuke | clojure.core> (syntax-quote (foo# ~@(list 1 2 3) foo#)) |
| 19:26 | Chousuke | (foo__auto__7666 1 2 3 foo__auto__7666) |
| 19:26 | hiredman | nice |
| 19:26 | Chousuke | I just have to get my reader into somewhat usable state too. |
| 19:27 | Chousuke | currently, it can read itself! |
| 19:27 | hiredman | that is syntax-quote as a macro? |
| 19:27 | Chousuke | yes |
| 19:27 | Chousuke | (producing, unfortunately, not quite correct output ;() |
| 19:27 | Chousuke | (the reader, that is) |
| 19:28 | Chousuke | syntax-quote seems to be working |
| 19:28 | hiredman | what does the macroexpand to? |
| 19:28 | Chousuke | (clojure.core/first (clojure.core/list (clojure.core/concat (clojure.core/list (quote foo__auto__7676)) (do (list 1 2 3)) (clojure.core/list (quote foo__auto__7676))))) |
| 19:29 | hiredman | :( |
| 19:29 | Chousuke | that's what syntax-quote does anyway :) |
| 19:29 | Chousuke | just read-time, so you never see it. |
| 19:29 | hiredman | yeah |
| 19:30 | Chousuke | the (first (list ..)) at the start could probably be done away with, but it simplifies the implementation. |
| 19:30 | hiredman | I think it is a good idea to keep computation in the same place it was before |
| 19:30 | hiredman | read → compile → run |
| 19:31 | hiredman | I guess it doesn't make a huge difference |
| 19:34 | Chousuke | http://github.com/Chousuke/clojure/tree/clojure-reader here's what I have now (probably easiest to look at the commits page) |
| 19:34 | Chousuke | it's not usable yet at all, and I may destroy the branch at any time, but it's there if you're curious :P |
| 19:36 | jwhitlark | Is there anyway to create an interface other than gen-interface? I need to dynamically create and pass an interface (not a class) to a function. |
| 19:39 | Chousuke | I'm not aware of any dynamic way of creating interfaces :/ |
| 19:39 | Chousuke | would the function use reflection or something to figure it out, then? |
| 19:40 | jwhitlark | kinda. It's for the java lib for dbus. You need to pass in an interface that tells what the remote object implements. |
| 19:40 | jwhitlark | Of course, dbus provides that information, but I've not found a way for the java lib to use that to create the object. |
| 19:40 | jwhitlark | yet. |
| 19:41 | jwhitlark | perhaps a better approach would be to cast the resulting object against a proxy which implements the interface, but I'm not sure it that would work. |
| 19:42 | jwhitlark | (can't test it at the moment, I'm on the wrong machine) |
| 19:42 | Chousuke | hm :/ |
| 19:43 | Chousuke | I have no idea. And I'm off to get some sleep. Good night :) |
| 19:43 | jwhitlark | Thanks for trying, anyway. Good night. |
| 21:00 | ataggart | is there a way to make the following work properly? (defmacro foo [] `(defn bar [s] (println s))) |
| 21:01 | ataggart | right now when I call (foo), I get "java.lang.Exception: Can't use qualified name as parameter: user/s" |
| 21:02 | arbscht | (defmacro foo [] `(defn bar [s#] (println s#))) |
| 21:03 | ataggart | hmm, though I tried that |
| 21:03 | ataggart | *thought |
| 21:04 | ataggart | thanks |
| 21:59 | rabidsnail | Why does clojure.zip/children not return a seq of nodes, but instead a seq of the data at the nodes? |
| 22:00 | hiredman | a seq of nodes would be pretty useless |
| 22:00 | hiredman | well |
| 22:00 | rabidsnail | (clojure.zip/branch? (first (clojure.zip/children (clojure.zip/vector-zip [1 [2 [3 [4 5]]]])))) --> java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0) |
| 22:01 | hiredman | ,(-> [1 [2 [3 [4 5]]]] zip/vector-zip) |
| 22:01 | clojurebot | [[1 [2 [3 [4 5]]]] nil] |
| 22:01 | hiredman | ,(-> [1 [2 [3 [4 5]]]] zip/vector-zip zip/children) |
| 22:01 | clojurebot | (1 [2 [3 [4 5]]]) |
| 22:01 | hiredman | ,(-> [1 [2 [3 [4 5]]]] zip/vector-zip zip/children first) |
| 22:01 | clojurebot | 1 |
| 22:01 | hiredman | ,(-> [1 [2 [3 [4 5]]]] zip/vector-zip zip/children first zip/branch?) |
| 22:01 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 22:01 | hiredman | ~def clojure.zip/vector-zip |
| 22:02 | gjahad | /join #sa-website |
| 22:02 | hiredman | weird |
| 22:03 | rabidsnail | Could it be a bug? |
| 22:03 | hiredman | oh |
| 22:03 | hiredman | it is not a bug |
| 22:03 | tomoj | what exactly does the fact that watches are "Experimental" mean? |
| 22:04 | tomoj | they might not work right? or they might change/disappear in the future? |
| 22:04 | hiredman | no, I think just the exact interface has not solidified yet |
| 22:04 | tomoj | ah, ok |
| 22:05 | hiredman | rabidsnail: you are call branch? on something that is not a zipper structure |
| 22:05 | hiredman | just the exception is not very helpful because of the coding style used in branch? |
| 22:06 | rabidsnail | Why doesn't children return zipper structures? next, up, down, etc. do, right? |
| 22:07 | hiredman | rabidsnail: because the zipper is immutable, children would have to return new zipper structures for each child |
| 22:08 | rabidsnail | Isn't that what up down left and right do? |
| 22:08 | rabidsnail | Why shouldn't children do that? |
| 22:09 | hiredman | rabidsnail: yes, but neither returns more then one zipper structure |
| 22:10 | hiredman | rabidsnail: why do you want children to return zipper structures? |
| 22:10 | rabidsnail | So that I can recurse by mapping through them |
| 22:10 | hiredman | haha |
| 22:11 | hiredman | you can use something like (iterate zip/left zipper) |
| 22:14 | hiredman | or, for that matter, you can just call vector-zip on each child |
| 22:14 | hiredman | (via map) |
| 22:15 | rabidsnail | that's true |
| 22:15 | alphaeus | How would you do (for [a1 (range 2) a2 (range 2) ... a40 (range 2)] [a1 a2 ... a40]) without writing all the a variables? |
| 22:15 | hiredman | I can only imagine you must be doing this for side effects |
| 22:16 | hiredman | alphaeus: I wouldn't |
| 22:16 | hiredman | ,(doc nth) |
| 22:16 | clojurebot | "([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences." |
| 22:16 | hiredman | actually |
| 22:16 | hiredman | map vector |
| 22:16 | hiredman | ,(map vector (range 10) (range 10 20) (range 20 30)) |
| 22:16 | clojurebot | ([0 10 20] [1 11 21] [2 12 22] [3 13 23] [4 14 24] [5 15 25] [6 16 26] [7 17 27] [8 18 28] [9 19 29]) |
| 22:18 | Anniepoo | clojurebot: paste |
| 22:18 | clojurebot | lisppaste8, url |
| 22:18 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 22:24 | alphaeus | hiredman: I don't understand how that code is a substitute for using for |
| 22:25 | alphaeus | ,(count (for [i (range 10) j (range 10 20) k (range 20 30)] [i j k])) |
| 22:25 | clojurebot | 1000 |
| 22:25 | hiredman | oh, right |
| 22:25 | hiredman | *that* |
| 22:27 | hiredman | *shrug* write a macro to generate the for expression for you |
| 22:30 | lisppaste8 | Anniepoo pasted "multimethods oopsie" at http://paste.lisp.org/display/85172 |
| 22:30 | Anniepoo | this is my first multimethod - I'm clearly having some noobie problem, but I can't see it |
| 22:31 | Anniepoo | (scroll to bottom before doing painful code reading) |
| 22:34 | arbscht | alphaeus: see clojure.contrib.combinatorics/cartesian-product |
| 22:35 | hiredman | Anniepoo: something is trying to call a method on nil |
| 22:35 | tomoj | aw man |
| 22:35 | hiredman | so look for nils |
| 22:35 | arbscht | (count (apply cartesian-product [(range 10) (range 10 20) (range 20 30)])) => 1000 |
| 22:36 | Anniepoo | nils are my life |
| 22:36 | tomoj | alphaeus: https://gist.github.com/1df4bbae8b2685b02826 |
| 22:36 | tomoj | my first macro in clojure :) |
| 22:37 | tomoj | but use contrib |
| 22:39 | tomoj | are you really going to use 40?? |
| 22:39 | tomoj | ..really big seq |
| 22:44 | alphaeus | arbscht: thanks |
| 22:44 | alphaeus | tomoj: I wish I could but I don't think I have enough cpu or patience for it to evaluate |
| 22:44 | tomoj | I did (count (n-bits 40)) and then I thought about what I just typed a bit... |
| 22:52 | arbscht | Anniepoo: I don't follow what's going on in lsl-type. is "^x" a typo? is meta-type a function? |
| 22:53 | Anniepoo | it's the metadata for x |
| 22:54 | Anniepoo | I need to ensure that things get uploaded as the proper type in the external system |
| 22:54 | Anniepoo | so I tag my data with it's type in the external system |
| 22:55 | hiredman | Anniepoo: start add println's and look for the source of the nil |
| 22:55 | Anniepoo | it's that line |
| 22:55 | Anniepoo | that is, it's the multimethod call |
| 22:56 | Anniepoo | it's not getting to any of the multimethod cases that I can see |
| 22:56 | Anniepoo | though I can trip a breakpoint in lsl-type |
| 22:56 | hiredman | Anniepoo: that means it is the dispatch function |
| 22:56 | arbscht | can you explain what meta-type is? |
| 22:56 | hiredman | so something in the dispatch function is calling a method on nil |
| 22:57 | hiredman | possibly x is nil |
| 22:57 | hiredman | ,^nil |
| 22:57 | clojurebot | nil |
| 22:57 | hiredman | bah |
| 22:57 | hiredman | ,(let [x nil] ^x) |
| 22:57 | clojurebot | nil |
| 22:57 | Anniepoo | this system is a GUI that lets the user draw stuff onscreen, then sends it by an arcane system to the Second Life virtual world |
| 22:57 | Anniepoo | meta-type is the type the data will have in Second Life |
| 22:58 | hiredman | oh |
| 22:58 | arbscht | in cond, you're invoking it as a function |
| 22:58 | Anniepoo | lsl-type extracts the type |
| 22:58 | hiredman | yeah |
| 22:58 | Anniepoo | the metadata is authoritative |
| 22:58 | hiredman | ,(nil) |
| 22:58 | clojurebot | java.lang.IllegalArgumentException: Can't call nil |
| 22:58 | Anniepoo | but it's often obvious from the clojure type |
| 22:58 | Anniepoo | aaargh! |
| 22:58 | hiredman | Anniepoo: you are call meta-type as a function |
| 22:58 | Anniepoo | you're right |
| 22:58 | Anniepoo | thanks |
| 22:59 | Anniepoo | I meant to just check if it was nil |
| 22:59 | hiredman | well it was |
| 22:59 | Anniepoo | LOL |
| 22:59 | Anniepoo | odd, wonder why it's nil |
| 23:01 | rabidsnail | Is there a reverse operation for seq-zip? |
| 23:02 | hiredman | uh |
| 23:03 | hiredman | what? |
| 23:03 | rabidsnail | (reverse-operation (seq-zip thing)) == thing |
| 23:03 | hiredman | ,(doc zip/root) |
| 23:03 | clojurebot | "([loc]); zips all the way up and returns the root node, reflecting any changes." |
| 23:04 | rabidsnail | when I do that I get a bunch of stuff added. |
| 23:04 | hiredman | http://clojure.org/other_libraries#toc5 |
| 23:04 | rabidsnail | vectors and maps and such |
| 23:05 | hiredman | that means you are changing the zipper |
| 23:05 | hiredman | if you want to keep the original, you should hang on to it before you start editing |
| 23:06 | rabidsnail | I don't want the original, I wan a clean chaned version that doesn't have maps with :pnodes and :ppath and such |
| 23:06 | rabidsnail | changed |
| 23:06 | rabidsnail | rather |
| 23:07 | hiredman | uh |
| 23:07 | hiredman | you are doing something wrong |
| 23:08 | hiredman | the :pnodes stuff is part of the editing, once you call root it should be there, if it is, that means you messed up a call somewhere and broke the zipper |
| 23:08 | hiredman | ,(-> [1 2 3 4] zip/vector-zip zip/next) |
| 23:08 | clojurebot | [1 {:l [], :pnodes [[1 2 3 4]], :ppath nil, :r (2 3 4)}] |
| 23:08 | hiredman | ,(-> [1 2 3 4] zip/vector-zip zip/next zip/root) |
| 23:08 | clojurebot | [1 2 3 4] |
| 23:08 | rabidsnail | oh |
| 23:22 | Anniepoo | in this example are the commas significant? |
| 23:22 | Anniepoo | (let [{a :a, b :b, c :c, :as m :or {a 2 b 3}} {:a 5 :c 6}] |
| 23:22 | durka42 | no |
| 23:23 | durka42 | commas are always whitespace |
| 23:23 | Anniepoo | thanks |