#clojure logs

2011-04-27

00:48mreynoldsHmm, problem 15 doesn't like #(* % 2), says it's being passed the wrong number of args
00:49Clintegerproblem 15?
00:49mreynoldshttps://www.4clojure.com/problem/15
00:49mreynoldsSorry, was stuck on a while back when they posted this site into the chat room
00:49Clintegerah. perhaps try #4clojure ;)
00:49mreynoldsOH
00:49mreynoldsRight
00:49mreynoldsthanks
01:11seancorfield__it's even got it's own channel now??
01:11Clintegersmall in comparison to this channel, but yes lol
01:16lancepantzyeah, so check this one out
01:16lancepantzjava.lang.RuntimeException: java.lang.Exception: No such var: clojure.core/if (NO_SOURCE_FILE:0)
01:16lancepantzhow screwed does that mean i am?
01:17hiredmanif is a special form, no var
01:18lancepantzdoes that imply i'm calling it outside of parens somethere?
01:18lancepantz*where
01:18hiredman#'clojure.core/if
01:18hiredman,#'clojure.core/if
01:18clojurebotjava.lang.Exception: Unable to resolve var: clojure.core/if in this context
01:19hiredman,(ns-resolve 'clojure.core 'if)
01:19clojurebotnil
01:19lancepantzright
01:19lancepantzguess i'll keep lookin
01:19hiredmansomething like that
01:20lancepantzthanks dude
02:52prkchp_sndwchhello, I'm trying to set up overtone using the command "lein repl". how do I have the repl load a clojure file I've written?
02:57seancorfield__(load-file "path/to/file.clj")
03:07prkchp_sndwchthanks sean
03:31justinlillyhttp://pastebin.com/2f9w2JqR -- does anyone have a better way to write this seemingly simple function?
03:41seancorfield__(zero? left) instead of (= left 0)
03:41seancorfield__otherwise i guess it's fine... i can't remember what i did for that problem :)
03:48avyskIf you don't want to use repeat, you can do with (for [_ (range i)] item) :)
03:49justinlillyis there sugar for doing (= myvar '())
03:49justinlillyempty? doesn't work as it throws an exception if it gets something like an int.
03:54BelafHello everybody! I've got a question about using clojure.contrib.logging together with clojure.test: is there an easy way (e.g. by binding some special variable) to redirect the logging coming from tests to a different logfile ?
03:55seancorfield__just fyi, in 1.3.0 c.c.logging has become https://github.com/clojure/tools.logging
03:57Belafallright, thanks, but I'm still on 1.2.0. Maybe there will be some way only in 1.3.0?
03:58seancorfield__i haven't looked at c.c.logging yet, sorry
03:58seancorfield__avysk: nice use of for!
04:00BelafI've found some "java level" way of switching to a different logfile, I'll try that one, waiting for something better :)
04:06raekBelaf: don't know any solution to the redirection problem, but you can use clojure.tools.logging in 1.2.0 or 1.2.1 just fine
04:07BelafYou mean it's already there? Going to check it, thanks!
04:08raekyup. [org.clojure/tools.logging "0.1.2"]
04:08BelafOh, now I got it, for 1.2.0 it's a separate package.
04:10raekthe version of tools.logging does not follow the clojure versioning
04:12fliebelSo, how do projects actually get into the new contrib?
04:13raeksomething like this http://groups.google.com/group/clojure-dev/browse_thread/thread/12e9f47aa54bc969
04:13fliebeloh, okay
04:22solar_seaHi. How do I alias a namespace within another one ? I've tried (ns my-ns (:require [clojure.contrib.math :as math])), but then math/ doesn't resolve. Fully quallified - it works.
04:23BelafAny advantage in using "clojure / tools.logging" vs "clojure.contrib.logging", except maybe being ready for clojure 1.3.0 ?
04:58mrBlissJust got my copy of The Joy of Clojure in the mail!
05:06KerrisI wish some projects would take donations. :(
06:49clgvI want to use the latest stable version of Incanter but no frequently updated snapshot. what do I supply to leiningen's project.clj? only 1.2.2 without the "-SNAPSHOT"?
06:53clgvok that seemed to have worked
07:07raekclgv: these are the versions available on clojars: http://clojars.org/repo/incanter/incanter/
07:07raek1.2.3 seems to be the latest non-snapshot
07:13clgvraek: oh ok thanks. I did try to find out the version number on their homepage ;)
07:15clgvI would love a standalone jar of it. it really spams my lib directory ;)
07:33mholmqvistHi, I'm trying to use java.util.ServiceLoader to load a service that is implemented in Clojure using :gen-class. I get a ServiceConfigurationError with cause: Provider could not be instantiated: org.foo.Bar java.lang.ExceptionInInitializerError
07:34mholmqvistI have read that Clojure uses the context classloader and that I should set it before trying to load Clojure classes as in http://dev.clojure.org/jira/browse/CLJ-260
07:36mholmqvistThe implemented service is in an external jar-file and I use a URLClassLoader to load the jar. Anyone got any hints?
07:38mholmqvistFurther down is: java.io.FileNotFoundException: Could not locate org/foo/Bar__init.class or org/foo/bar.clj on classpath.
07:42mholmqvistAH! Never mind. I used the wrong ClassLoader when calling Thread.currentThread().setContextClassLoader. It's working now.
07:42clojurebotPaul Graham is the creator of the other new lisp
07:44KerrisArc?
07:44clojurebotPOLO! nya nya you can't see me
07:44Kerrisoh, it's clojurebot. =_=
07:49ilyakhi *
07:49ilyakWhy does (print "a") (print "b") differs from (map print ["a" "b"]) in ccw?
07:55thorwililyak: not just in ccw
07:59thorwililyak: map takes and evaluates to a seq. whereas the first is too separate forms
07:59thorwil s/too/two/
08:00thorwilhow to use Enlive's text? it should return the content of a node, but i need it inside of a transfomation ...
08:29ilyakI have a mystical problem
08:30ilyakI have a transient {} for which I do a lot of (assoc! it key (+ increment (get it key 0)))
08:30ilyakand after I do some millions of that, it has only 8 keys - there should be like fifty
08:31ilyakWhich are, coincidentally, keys that would have the biggest values, but not in exactly sort order
08:41clgvilyak: minimal example?
08:42ilyakIt seems that after 8 keys I can no longer assoc! new keys
08:43ilyakwhen I assoc! key doesn't materialise in map
08:43ilyakI'll try to make one
08:44clgvI have a guess: do you use the result of assoc! to continue?
08:44clgvI was told that you need to and not doing so will only work in special cases
08:46ilyakWhat does it return? Should I?
08:46ilyakI think I'll paste my function
08:47ilyakhttp://pastebin.com/eBB8XujM
08:48clgv&(loop [lst [[1 2] [3 4] [5 6]] tm (transient {})] (if-let [p (first lst)] (recur (rest lst) (assoc! tm (first p) (second p))) (persistent! tm))
08:48sexpbot⟹ {1 2, 3 4, 5 6} ; Adjusted to (loop [lst [[1 2] [3 4] [5 6]] tm (transient {})] (if-let [p (first lst)] (recur (rest lst) (assoc! tm (first p) (second p))) (persistent! tm)))
08:51clgvilyak: seems like you do not use the return of assoc!
08:52clgvyou seem to want something like encapsulated mutable state. I have seen people doing that via atoms
08:52clgvso you could place your transient into an atom
08:52raekilyak: transients should be use the same way as the ordinary ones. they might change *some* things in place (this is just an optimization), but you should not rely on that it changes anything in place
08:53ilyakraek: So I have to write it using ref?
08:54clgvilyak: no. an atom will suffice
08:54raekif you want something that mutates, you need to use a ref, atom, var or agent
08:54raekatoms and vars are pretty lightwight
08:55clgvilyak: maybe like that: http://pastebin.com/t1TqbfUt
08:55raeksometimes, even a loop/recur can be an alternative to mutation
08:56raekah, now I saw your code.
08:56raekan atom here is a very good fit, as clgv suggested
08:57ilyakclgv: thanks I'll look into it
08:58clgvilyak: you may have to correct a paranthesis or two ;)
09:00raekilyak: http://pastebin.com/nGm3QRXu
09:01raekyeah, don't trust the parenthesis balance in mine too... :)
09:02raekchanges: removed transients and changed swap expression to (swap! counts update-in [major] (fnil + 0) (count listens))
09:03clgvraek: hmm well you are right - no need for transient anymore since its calling schedule isnt that tight anymore
09:08fortxunis Rich Hickey around?
09:08clgv$seen rhickey
09:08sexpbotrhickey was last seen quitting 1 week ago.
09:08fortxunahh
09:10fortxun$help
09:10sexpbotYou're going to need to tell me what you want help with.
09:10fortxun$help message
09:10sexpbotTopic: "message" doesn't exist!
09:12clgv$help msg
09:12sexpbotTopic: "msg" doesn't exist!
09:13clgv$help /msg
09:13sexpbotTopic: "/msg" doesn't exist!
09:13clgvah you might mean "mail"?
09:14clgv$help mail
09:14sexpbotclgv: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.
09:17jamesswifttired and blind to why this isn't working, can anybody point out the obvious to me? http://pastebin.com/rBT4809Y
09:17jamesswift*gets ready to slap forehead*
09:18clgvjamesswift: what exactly are you trying to do?
09:18jamesswifttrying to get the value of :menuName from the map
09:19jamesswiftclgv: but I'm getting nil
09:19clgvwhere do you construct the map?
09:19clgvfor a short example: ##(let [map {:menuName "hello2"}] (map :menuName))
09:19sexpbot⟹ "hello2"
09:20jamesswiftclgv: it's actually passed in a request (compojure route) ... er. I think I realise why i'm stupid. it's strings in ring requests not keywords. I knew I just had to say it 'out loud' to realise why i was stupid. thanks for listening :)
09:21jamesswiftclgv: I think I forget this at least once a month
09:22jamesswift##({"menuName" "hello"} "menuName")
09:22sexpbot⟹ "hello"
09:52clgvis there an abbreviation for (reduce #(reduce + %) mat) on matrices?
10:04cemerickclgv: (def msum (partial reduce #(reduce + %))) ?
10:05clgvcemerick: lol. I thought there might have been something built-in for matrice like structures ;)
10:05cemerickclgv: no need when you can define msum yourself :-)
10:06cemerickThough I'll bet there are at least a couple of matrix op libraries floating around.
10:06clgvis that the shortest way to convert a double matrix? ##(map seq (make-array Double/TYPE 3 3))
10:06sexpbot⟹ ((0.0 0.0 0.0) (0.0 0.0 0.0) (0.0 0.0 0.0))
10:17choffsteinDoes anyone have some 'production' code where they use protocols that I can look at. I've read lots of 'gentle introductions' to them, and while I think I get the general gist of them, I don't really know a practical example of where I would use them in my code.
10:19jlfchoffstein: maybe http://blog.higher-order.net/2010/05/05/circuitbreaker-clojure-1-2/ ?
10:19choffsteinI'll give it a read. Thanks :)
10:20jlfnp
10:26clgvchoffstein: one case where use them is when you want functions that have a lot of state so that using partial gets ugly
10:26clgvand for having real java-interfaces
10:26choffsteinclgv: not quite sure if I follow. What do you mean functions that have a lot of state?
10:27clgvchoffstein: hm I guess you can rewrite that: if you need objects similar to those in java (but in general immutable)
10:28choffsteinHmmm, I see. I'll keep poking around. I feel like i'm going around the answer in circles ... eventually i'll understand it
10:30clgvI use them for my configuration object and for the specification objects
10:30clgvI think the case with the specification objects is the most fitting
10:31clgvThe protocol has a method that creates a function. internally the function is provided with "constant" parameters via partial.
10:32clgvthe specification has a hierarchy with different specification types for different purposes, but all do create functions
10:33clgv$findfn 0.12345 0.12
10:33sexpbot[]
10:39choffsteinhmmmm
10:39choffsteinthat ... confuses me more :D
10:46clgvok, simpler then: one interface (= protocol) with different implementations^^
11:25clgv&(- 0.0)
11:25sexpbot⟹ -0.0
11:25clgvthat feels odd
11:42TimMcclgv: Floating point is like that.
11:42clgvTimMc: yeah. but it makes no sense ;)
11:43TimMc,((juxt pos? zero? neg?) [1 0.0 -0.0 -1])
11:43clojurebotjava.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number
11:43TimMcbah
11:43TimMc,(map (juxt pos? zero? neg?) [1 0.0 -0.0 -1])
11:43clojurebot([true false false] [false true false] [false true false] [false false true])
11:44clgvlike expected
11:48TimMcI have actualy used negative zero vs. positive zero on occasion.
12:02manutter,(= 0.0 -0.0)
12:02clojurebottrue
12:02manutterfascinating
12:05sritchiedoes anyone have any experience with thrift serialization, for java?
12:14choffsteinAnyone aware of any component based web frameworks for Clojure like SmallTalk's Seaside or Ruby's Wee?
12:15TimMc,(== 0.0 -0.0)
12:15clojurebottrue
12:21thorwilchoffstein: afaik there doesn't exist any ready-for-action non-spartan web framework for clojure
12:21choffsteinfigured :)
12:24thorwilchoffstein: if that changes or changed, something might appear on http://clojure-libraries.appspot.com/category/27 or http://clojars.org/search?q=web
12:25choffsteinokay. thanks
12:43amalloysritchie: i do
12:44sritchieamalloy: I just figured out my issue -- I had been using backtype's thrift jarfile from clojars, which had an earlier version of thrift than I'd been using to generate my java source
12:46sritchiejust pushed 0.5.0 to clojars -- http://clojars.org/redd/thrift
12:48TimMcAny recommendation for writing CLojure shell scripts?
12:48TimMc("Don't" is an acceptable answer.)
12:49amalloyTimMc: jark?
12:49manutterTook the words right out of my mouth
12:49amalloyi haven't tried it, but it claims to be for this purpose
12:50manutterI've played with it a little, looks promising
12:51manutterhttp://icylisper.in/clojure/jark.html
13:13TimMcMore specifically, can I just drop a shebang onto a .clj file?
13:14RaynesTimMc: Yes, you can. Check out the cake README (the part about shell scripts) and/or jark's documentation about it.
13:14amalloyTimMc: i think there's some kind of limitation about how long the shebang line can be, though, bizarrely, which doesn't play nice with the bloated command lines java uses
13:15amalloy(a limitation in the shell, not in clojure)
13:15TimMcRaynes: Nice, thanks.
13:17justinlillyamalloy: you should be able to easily fix that with another command somewhere. `echo "./big-java-program" > ~/bin/java-prog` then add #!/path/to/java-prog at the top.
13:34TimMcHrm. Running with the cake shebang does not preserve the working directory.
13:35amalloyTimMc: java hates working directories
13:35TimMc:-(
13:35amalloythe jvm has a cwd, which doesn't change after jvm launch
13:35RaynesTimMc: There isn't really anything that can be done about that. Can't change the working directory at runtime.
13:36amalloyso with eg cake, which has a persistent jvm, the cwd will always be wherever the jvm was launched from
13:36dnolenTimMc: but cake preserves it's own cwd
13:37amalloyi imagine jark will do something like detect where you are when you invoke jark, and pass that as a parameter to the script you want to run
13:37dnolenTimMc: I got them to add that feature a while back
13:38TimMcI'd be happier with explicit cwd anyway.
13:40TimMcI'll stick with this shitty Bash script for now.
13:42david`any of you guys using emacs on os x?
13:42dnolendavid`: yup
13:43david`do you use emacs or aquamacs?
13:45david`dnolen: still at nyu
13:47dnolendavid`: Cocoa Emacs, http://emacsformacosx.com/. No teaching at nyu at the moment, but perhaps again in the future.
13:47david`I went to Gallatin
13:48david`NYU was a lot of fun
13:48dnolendavid`: cool! agreed.
14:07TimMcoh my god how can bash be this fucked up
14:08amalloyTimMc: whiner. i don't like programming in bash, but for shell-related stuff it's pretty powerful
14:08choffsteinI'm running into an issue where it seems like data is being treated lazily and then an error is cropping up later in my program in a totally "unrelated" section. In on part of my program, I am dividing one number by another. About 100 lines later, when I try to print this data, I get a divide by zero error. Is there any way to force evaluation of the thunks?
14:09TimMcamalloy: I just changed the start of my iteration from 1 to 0, and my file renumbering script stopped working -- apparently because an arithmetic operation returning 0 is an error code or something.
14:09technomancychoffstein: sure; doall will do that
14:09choffsteinokay, thanks
14:10amalloyTimMc: "apparently...or something" tends to be a complaint associated with "i don't understand what is going on", not "what is going on is clearly wrong". just sayin', seems wrong to leap to the assumption that bash is doing something crazy
14:11TimMcamalloy: Yeah, I know. BUt seriously, all I changed was the initial value of a counter.
14:14markomani have a strange problem with saving datastore on appengine magic. it seems its not possible to save inside for loop
14:17amalloylazy?
14:17clojurebotlazy is hard
14:18amalloyclose enough, clojurebot
14:18markomanok, i solved it. cant do (for (save (new ...))) but need to do (save (for (new ...)))
14:19TimMcamalloy: The built-in "let" arithmetic command gives a non-zero exit value on a zero result. :-(
14:21amalloyTimMc: huh. i've never used let. i agree it seems kinda weird
14:21TimMcANyway, that interacted poorly (and mysteriously) with my use of set -o errexit
14:23TimMcand I use *that* because bash takes a "let's keep going anyway and see what happens!" approach to error handing by default.
14:42amalloyTimMc: && and ||?
14:44amalloythat is, i don't even know what errexit is, so take this with a grain of salt, but it sounds like swatting a fly with a bulldozer, while && and || would give you more fine-grained control
14:52TimMcamalloy: When I write scripts that bash (hah!) on the filesystem, I prefer to have unexpected error cases stop the program entirely.
14:53amalloyTimMc: right. that's what && is for?
14:53amalloycreatenewfile && mv newfile oldfile
14:54TimMcHow would you apply that to `for f in *.jpg ; do ... done` ?
14:55TimMcAnyway, I solved my specific issue with `let "n = i * 2" || true`
14:56amalloyTimMc: use while instead of for, i think
14:56amalloybut i dunno
14:56amalloyi don't do a lot of scripting really
14:56TimMchmm
14:56TimMcI try to avoid it.
14:57TimMcI'll check out while, though.
15:23raekamalloy: what was the variable called for custom 2-space indented forms in clojure-mode?
15:34sritchiehey all -- I've got a function that works great, until I add a single entry to the let statement, after which it fails
15:34sritchiehttps://gist.github.com/945001
15:35sritchieif i insert a println, it looks like it hits the else statement for the first four loops and does fine, when throws this exception when it has to travel down the second path in cond
15:35bulterssritchie: I'm no expert, but iirc in a normal let pos is not directly available
15:36bulterssritchie: But that could've been some other lisp :P
15:36sritchie,(let [x 5 y (inc x)] y)
15:36clojurebot6
15:37sritchiemaybe the fact that it's inside the loop is the issue, though
15:37raeksritchie: if you reload the namespace with (require 'the-ns :reload), you will get line numbers in the stack trace
15:38bulterssritchie: then consider my remark not typed ;-)
15:39sritchieraek: hmm, I didn't see a change
15:39hiredmansritchie: offset is nil
15:39sritchieI think it's zero
15:39raekmaybe 'pos' could be nil
15:40sritchieoh, yeah
15:40hiredmansritchie: I think you are wrong
15:40sritchieno, offset is zero -- pos becomes nil on the recursion when the list empties out
15:41sritchiethat's the issue! good stuff
15:46amalloyraek: clojure-defun-indents iirc
15:46amalloybut it's under the clojure-mode group, so you can find it that way too
16:08raekamalloy: thx
18:02lackerhi all. i am having a problem with leiningen. when I run my project with `lein run` it works fine, but when I run an uberjar I get a "Could not find the main class: mo.core. Program will exit."
18:02technomancylacker: probably missing :gen-class?
18:02lackerah yes, that token is nowhere in my code. where should that go?
18:03technomancyit goes in the ns form of the namespace containing -main
18:03technomancylein help tutorial under Uberjar shows it
18:03lackerok cool thanks. is that generated by `lein new` and I deleted it at some point, or is it just a step that I have to do?
18:04technomancyit's not included by default
18:05lackerwhere is this tutorial you refer to? sorry for asking noob questions here when I should be reading docs
18:07technomancyjust run "lein help tutorial"
18:08SomelauwI wonder whether you can create a game and program it is functionally as possible.
18:09brehautSomelauw: with 'as possible' : yes
18:09lackerthanks technomancy
18:10technomancysure
18:11SomelauwBut wouldn t games have a lot of mutable state?
18:12SomelauwLike objects disappearing and character doing attacks and such?
18:12brehautit depends?
18:12brehautyou'll have to have some mutable state
18:12brehautlike any real program*
18:12brehaut*bag of caveats im sure
18:14SomelauwYes, but that makes me wonder to what extend you should use immutable state and at which point you should stop using it.
18:15SomelauwSince technically you can pass a list of all games object in a recursive function, but that is probably to painful.
18:15raekSomelauw: you might find this interesting: http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/docs/sweeny.pdf
18:15raekespecially slide 52
18:15raekand then there's http://prog21.dadgum.com/23.html
18:15raek"Purely Functional Retrogames"
18:20raekfrom the retrogame series: "When I first mused over writing a game in a purely functional style, this had me stymied. One simple function ends up possibly changing the entire state of the world? Should that function take the whole world as input and return a brand new world as output? Why even use functional programming, then?"
18:21raekI believe that for programs that has essensial state, making the whole part functional might not be the most convenient way to do it
18:22raekone of the powers of Clojure is that it lets you hande state in a well-defined and pretty way, when you need it
18:23brehaut(inc raek)
18:23sexpbot⟹ 8
18:23no_mindif I have to iterate over a sequence without any side-effects. Which language construct is the fastest ? doseq or for ?
18:23hiredmanwithout?
18:25raeka purely functional core, and a layer for managing state on top of that, seems to be the pattern I have seen so far
18:26raekbut where to draw the line between the purely functional part and the state managing part is the real question... :)
18:30SomelauwYes, but maybe your website will explain it.
18:31SomelauwI was thinking that mutable state might be good when modelling something that has mutable state in reallife.
18:42no_mindany AI based application written in clojure yet ? Looking for some application based on agent to be precise
19:11TimMcno_mind: doseq is intended for side effects, for is intended to collect results
19:43mecCould someone take a look at my persistent double linked list code? remove-node, add-before, and add-after share too much structure but I'm not sure how to refactor them. https://github.com/mecdemort/mec/blob/master/double_list.clj
19:51SomelauwHmm, I know something about functional programming, but I really should learn how to write an actual application in a fp language.
20:13mecDoes implementing Associative assume constant time lookup?
20:47scottjin slime when there's an error during C-c C-k anyone have the error window with details stop opening/displaying in the last few months? not sure if it's a bug in my setup
20:48hiredmanI've seen the issue with clojure 1.3, maybe if you upgrade your swank-clojure?
20:48hiredmanI haven't played with 1.3 + swank for sometime, so I dunno if it still happens
21:00sritchieamalloy: if you have a second, I had a quick question about thrift -- if I declare a field in a struct that takes a list of values, say, list<FireTuple> series, inside of a struct called TimeSeries
21:00sritchieis (TimeSeries. [(FireTuple. 0 0) (FireTuple. 1 2)]) the right way to populate that list?
21:00sritchietimeseries doesn't seem to care what's inside that list
21:00sritchies/list/vector
21:00sexpbot<sritchie> timeseries doesn't seem to care what's inside that vector
21:03amalloysritchie: dunno. you asked about thrift in java, not in clojure :P
21:04sritchiehaha, fair point
21:05sritchieamalloy: what's the answer in java?
21:05sritchiecan a struct take any sort of collection, to populate a list?
21:05amalloysritchie: turns out i actually don't know that either. i haven't really worked with very complex types - i just declared a struct that groups together some basic data types
21:06amalloybut i don't know what constructors get created. i'd do more like (doto (TimeSeries.) (.setSeries [(FireTuple. 0 0)...]))
21:06amalloysince i know it creates setters
21:09sritchieamalloy: interesting, you're right, here -- looks like the constructor doesn't typecheck
21:10sritchiebut using (doto (TimeSeries.) (.addToSeries (FireTuple. 0 0))) works out
21:18hiredman,(doc instance?)
21:18clojurebot"([c x]); Evaluates x and tests if it is an instance of the class c. Returns true or false"
21:35scottjhiredman: does a description of your compilation errors open? what version of swank-clojure are you using?
22:02SergioTapiahello
22:03SergioTapia$karma hiredman
23:24chrissbxHow do you append strings in clojure? Once again I'm at a loss searching for the right docs...
23:25chrissbxFor example the cheatsheet doesn't mention that, even though it's got two sections about strings.
23:25jdmmmmmchrissbx: (str "a" "b")
23:26jdmmmmm,(str "a" "b")
23:26clojurebot"ab"
23:26chrissbxhum. I wonder what's the logic about this name?
23:26chrissbxWell I'll just eat it.
23:27jdmmmmmI think it just makes a string out of anything you pass in.
23:27jdmmmmm,(str "ab" 12 '[:a :b])
23:27clojurebot"ab12[:a :b]"
23:28chrissbxyeah, that's what I expected, kind of a constructor.
23:29chrissbxBut to take two of them and make a new one... (shrugs)
23:29jdmmmmmalong the lines of vec
23:29chrissbxWell I haven't learned about that yet :)
23:29jdmmmmmJava strings are immutable; making new ones in inevitable.
23:36chrissbxIs there a rule which ops do automatic conversions of types, btw?
23:36chrissbxLike, is it only these constructor-like ops like str, vec?
23:36chrissbxwell, forget about vec already, that won't convert I guess.
23:36jdmmmmmvec will:
23:37jdmmmmm,(vec '(:a :b :c))
23:37clojurebot[:a :b :c]
23:37jdmmmmmOf course, it's not really "converting" -- it's creating a new one.
23:39chrissbxHu, but unlike str which also takes single characters, vec doesn't take single elements to make up a vector.
23:39chrissbxThat'd be "vector".
23:40chrissbxah "vec" actually doesn't take multiple arguments.
23:40chrissbx(That's what I thought when you said str was along the lines of vec.)
23:40amalloychrissbx: most operations implicitly convert their arguments to a seq
23:41amalloybecause that's how first/rest work
23:43chrissbxIs there a "reduce" that folds from the right?
23:44chrissbxcalled fold-right or foldr in some languages
23:44amalloychrissbx: not a built-in
23:45amalloyas i understand things this is because foldl can process elements from a seq on demand, but foldr would have to realize the whole seq all at once and build up a deep stack to evaluate even the first fold
23:46chrissbxI want something like (reduce (fn[r v] (cons (str v "=") (cons v r))) '() '(a b c))
23:46chrissbxbut output ("a=" a "b=" b "c=" c) instead of ("c=" c "b=" b "a=" a)
23:47chrissbxWhat you say seems the wrong way around: fold-right can process the input lazily, fold-left can't.
23:47amalloychrissbx: usually you can get that sort of thing by using a vector and conj instead of a list and cons
23:47chrissbxAssuming that we're talking about lazy linked lists where the first cell is the left-most
23:47jdmmmmm,(map #(str % "=" %) '(a b c))
23:47clojurebot("a=a" "b=b" "c=c")
23:48chrissbxBut I need two cons for each element; one stringified, the other not.
23:48amalloychrissbx: maybe you can explain to me how foldr can process inputs lazily. i saw that in a haskell text but can't really understand it
23:48chrissbxSo I can't use map.
23:48jdmmmmm,(mapcat #(list (str % "=") %) '(a b c))
23:48clojurebot("a=" a "b=" b "c=" c)
23:50chrissbxamalloy: say the output looks like ("a=" a "b=" b "c=" c); if you take "first", it will have to evaluate as far as getting the element "a" from the input list.
23:51chrissbxBut say the output looks like ("c=" c "b=" b "a=" a), which is what reduce gives, taking "first" will need the input till the last element, c.
23:51chrissbxThat's the short answer; the longer would be to go through each step of the evaluation.
23:52chrissbxIn an eager language, reduce (or fold-left) doesn't need stack, because it can build the output while walking the input in forward direction.
23:53amalloy&(reduce #(conj %1 (str %2 "=") %2) [] '(a b c))
23:53sexpbot⟹ ["a=" a "b=" b "c=" c]
23:53amalloyfwiw
23:53chrissbxWhereas in the same eager language, fold-right needs to build up a stack of intermediate results while walking the input.
23:53chrissbxBut that's not what you suggested was happening here.
23:55amalloychrissbx: that is what's happening here. clojure is an eager language at its root, but with lots of laziness options built on top
23:56chrissbxHm you said "as i understand things this is because foldl can process elements from a seq on demand,"
23:57amalloyits input seq
23:57chrissbxI concentrated on the "on demand" part, meaning lazy eval of the input
23:58chrissbxWhat I want to say is: if you prefer solutions in terms of "efficiency", then in an eager language, fold-left could be preferrable because it doesn't need stack,
23:58amalloyseancorfield: bad news: two more 4clojure problems
23:58chrissbxwhereas in a lazy language (lazy input seq) fold-right would be preferrable because in this case it *doesn't* need stack and in addition doesn't evaluate the input more than required for the part of the output that's needed.