2012-07-28
| 00:02 | teurastaja | if i dont know java, should i learn it before learning clojure? i know scheme |
| 00:04 | emezeske | teurastaja: Knowing some java basics will probably make your life easier |
| 00:06 | arohner_ | let's say you have a datastructure, that's a (ref {}). In general, you do you write defns that take the ref, or the deref'd map? |
| 00:06 | teurastaja | what features does someone who uses clojure and doesnt know java misses |
| 00:06 | teurastaja | ? |
| 00:07 | arohner | teurastaja: don't bother "learning" java. Just write what you want to write, and learn java lazily |
| 00:08 | emezeske | teurastaja: Well, for one thing, the error messages you will get from the clojure compiler are just java stack traces |
| 00:08 | teurastaja | can one write a metacircular interpreter in clojure alone? |
| 00:08 | arohner | yes |
| 00:09 | teurastaja | does it have continuations? |
| 00:09 | teurastaja | can it do systems programming? |
| 00:10 | arohner | no |
| 00:10 | teurastaja | no for which? |
| 00:10 | arohner | both, on the JVM |
| 00:11 | arohner | you can use JNA or JNI to load and call C libraries, but it wouldn't be useful for embedded systems, or interrupt handling |
| 00:11 | teurastaja | so what are clojures strengths |
| 00:11 | teurastaja | ? |
| 00:11 | arohner | It's a practical lisp |
| 00:12 | arohner | a lot of people use it for web stuff, and map reduce kinds of things |
| 00:13 | arohner | and it's good anywhere you'd use java, python or ruby |
| 00:14 | teurastaja | clojure vs common lisp vs scheme...? |
| 00:16 | arohner | clojure has much better multi-threading support. The UI bindings are good enough. It can be trivially embedded in any existing java program |
| 00:16 | arohner | probably bigger community at this point |
| 00:19 | arohner | you get to use JVM web servers and JVM DB drivers, so you can 'steal' from existing java libs when needed |
| 00:20 | teurastaja | java is not really an argument for me but its goode to know |
| 00:21 | teurastaja | what networking protocols does it support? |
| 00:22 | Raynes | * |
| 00:23 | emezeske | teurastaja: You want an exhaustive list? |
| 00:24 | arohner | java is good in the sense that there's usually an available library for interacting with the outside world. If you're just going to be doing project euler, then yeah, you probably don't need it |
| 00:27 | teurastaja | just want to be sold clojure so i know if its good for me |
| 00:28 | arohner | what are you looking to do with it? |
| 00:34 | teurastaja | things i cant do easily with scheme |
| 00:34 | teurastaja | i dont know exactly |
| 00:58 | Raynes | If you can't easily do something in Scheme, it's usually related to there not being a library for it. |
| 02:15 | jestinepaul | Why is my membership to clojure-dev google group still pending? I have already sent my CA last week. |
| 10:17 | xumingmingv | I know that there is a function named assoc-in to put something into a nested structure |
| 10:17 | xumingmingv | why there is no corresponding function to remove something from the nested structure? |
| 10:18 | xumingmingv | user=> (swap! x assoc-in [:handlers :lst 0] "hello") |
| 10:18 | xumingmingv | {:handlers {:lst ["hello"]}} |
| 10:18 | xumingmingv | how do i remove the "hello" I just assoc-ined? |
| 10:20 | uvtc | xumingmingv: dissoc |
| 10:20 | xumingmingv | uvtc: I'd expect there is a dissoc-in |
| 10:20 | xumingmingv | but apparently there is no dissoc-in in clojure.core |
| 10:22 | uvtc | The clojuredocs for dissoc mention a dissoc-in in the legacy monolithic contrib... Is that now somewhere in the current contrib libs? |
| 10:24 | xumingmingv | just found the update-in, seems that's what I want |
| 10:24 | xumingmingv | maybe just because update-in is more useful than dissoc-in |
| 11:11 | bordatoue | could anyone tell me how to change a value of a variable within a loop , for example maininting a running total of sequence |
| 11:13 | augustl | bordatoue: pass it as an argument |
| 11:13 | augustl | (recur (inc i)) |
| 11:14 | bordatoue | is there any other option without using recur |
| 11:15 | augustl | bordatoue: what's wrong with recur? |
| 11:15 | uvtc | bordatoue: what in particular are you trying to do? |
| 11:16 | bordatoue | uvtc: augustl i want to konw if this possible using doseq |
| 11:16 | augustl | bordatoue: not that I'm aware, just recur it I guess :) |
| 11:17 | uvtc | bordatoue: If what's possible using doseq? |
| 11:17 | bordatoue | so what is purpose of doseq, |
| 11:17 | clojurebot | doseq is like for, but for side effects instead of values |
| 11:18 | bordatoue | okay, in py- for i in range(10): print i, i+10, i+=i , how do i do this in clojure using doseq |
| 11:18 | bordatoue | not recur |
| 11:18 | rlb | bordatoue: say you want a program that prints the integers, increasing, one per line -- doseq might be useful. |
| 11:18 | augustl | bordatoue: why do you have to use doseq? |
| 11:18 | augustl | bordatoue: you can use a ref or an atom or whatever, but that seems like a very bad idea |
| 11:18 | bordatoue | because doseq is like for , |
| 11:19 | augustl | but you can't do what you want to do with doseq |
| 11:19 | xumingmingv | we cannt remove an item from the middle of a vector or list, right? |
| 11:19 | rlb | (doseq [x (range)] (prn x)) |
| 11:19 | uvtc | &(doseq [i (range 10)] (let [j (+ i 10)] (println i j))) |
| 11:19 | lazybot | ⇒ 0 10 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 nil |
| 11:20 | uvtc | bordatoue: ^^ |
| 11:20 | bordatoue | uvtc: , would you be able to add the new value to i in your example using doseq |
| 11:21 | bordatoue | i+=i+10 |
| 11:21 | bordatoue | i+=10 |
| 11:21 | uvtc | Oh, right, you want to keep a running total. |
| 11:21 | bordatoue | yes, |
| 11:21 | bordatoue | i want to chang the binding within a loop |
| 11:22 | bordatoue | wihtout using recur |
| 11:22 | augustl | bordatoue: why is that? |
| 11:22 | bordatoue | augustl: swap function |
| 11:22 | rlb | bordatoue: are you saying "can I write a C style for loop in clojure"? If so, then no, not easily. |
| 11:22 | rlb | (and not efficiently) |
| 11:22 | bordatoue | if x>y then x=y |
| 11:23 | rlb | bordatoue: but there are other ways to accomplish whatever you're trying to do. |
| 11:23 | bordatoue | rlb: can you find a sloution using doseq |
| 11:23 | bordatoue | and let |
| 11:23 | craigbro | hola |
| 11:24 | bordatoue | rlb would you be able to find a max of a given range of number using doseq not using recur or max fn |
| 11:24 | thorwil | bordatoue: (min x y) ? |
| 11:24 | rlb | bordatoue: loop/recur *is* clojure's closest analog to for. |
| 11:24 | rlb | (C-style for) |
| 11:24 | rlb | doseq is not |
| 11:24 | bordatoue | rlb: in that case , when should we use doseq |
| 11:24 | augustl | bordatoue: doseq is for doing side effects on sequences |
| 11:24 | augustl | such as calling methods on java objects |
| 11:25 | rlb | bordatoue: whenever you want to traverse a sequence and produce side-effects. |
| 11:25 | craigbro | and not return anything? |
| 11:25 | rlb | (as the docs say) |
| 11:25 | rlb | Right |
| 11:25 | craigbro | like printing a list of strings |
| 11:25 | uvtc | bordatoue: you might be looking for `reduce`. |
| 11:25 | bordatoue | rlb: okay , then why can't you find max of a given range of numbers using doseq |
| 11:25 | craigbro | but I don't care about the return value |
| 11:26 | bordatoue | uvtc: i don't want to use other fn |
| 11:26 | ToxicFrog | bordatoue: because it's the wrong tool for the job, and you're asking the wrong question. |
| 11:26 | rlb | bordatoue: the same reason you can't do it with prn? |
| 11:26 | ToxicFrog | It's like asking "why can't I read a file using printf" |
| 11:26 | craigbro | boardatoue you could actually |
| 11:26 | ToxicFrog | craigbro: don't give him ideas, it's going to be ugly |
| 11:26 | bordatoue | if doseq helps to iterate a sequence then all that is left to swap a values |
| 11:27 | augustl | bordatoue: you don't seem to understand what a side effect is |
| 11:27 | craigbro | bordatoue: you would use a atom |
| 11:27 | bordatoue | craigbro: can you provide an example , i |
| 11:27 | augustl | bordatoue: since you're promtly ignoring that part :) |
| 11:27 | ToxicFrog | bordatoue: doseq is for when you have a lazy sequence and you need to force it to be evaluated because generating the sequence involves side effects that you care about. |
| 11:27 | bordatoue | augustl: i do know side effect, fn that are not pure |
| 11:27 | ToxicFrog | It is not a general purpose iteration construction. |
| 11:27 | rlb | bordatoue: and technically, yes, you *could* do it in clojure with an atom or simlar, but that would be "the wrong way" (and inefficient). |
| 11:28 | rlb | i.e doseq + let + atoms |
| 11:28 | augustl | bordatoue: here's an example of doseq https://www.refheap.com/paste/3855 |
| 11:28 | craigbro | bordatue: yah, let to bind an atom to a variable, and then inside your doseq you reference the atom and swap! the new max in |
| 11:28 | craigbro | bordatoue: but that's shitty |
| 11:29 | rlb | It's a complete misuse of clojure -- like using a file for the same purpose in C. |
| 11:29 | craigbro | bordatoue: specifically, you end up with alot of overhead for accessing the atom value and swapping the new value in |
| 11:29 | rlb | though it you're just interested in it for academic purposes, then yes, it'll work. |
| 11:30 | bordatoue | so if you are given a sequence and what to iterate it , then doseq isn't the right tool |
| 11:30 | augustl | scroll up ;) |
| 11:30 | craigbro | bordatue depends on the type of iteration you want, and what you want out of the iteration |
| 11:31 | craigbro | bordatoue: think of it like the old saying that eskimos have a hundred words for snow |
| 11:31 | bordatoue | augustl: i saw it , but is it wrong to do soemething like doseq [x (range 10)] |
| 11:31 | craigbro | bordatoue: lisps, have a half dozen ways to process a list. |
| 11:31 | craigbro | bordatoue: and the differences appeart sublte and unimportant at first |
| 11:32 | augustl | bordatoue: that's ok, if you're calling functions that have side effects and pass in x |
| 11:32 | bordatoue | so every time we are given a seq then it is loop and recur we need to use |
| 11:33 | craigbro | bordatoue: not really. you can use map, filter, reduce, select, doseq, or a loop/recur, just for starters |
| 11:33 | rlb | bordatoue: no, you'll probably more often want map/reduce/filter/etc. |
| 11:33 | rlb | bordatoue: or for. |
| 11:33 | bordatoue | i thought loop and recur should be rarely used as there are HOF functions |
| 11:33 | craigbro | bordatoue: hmm, never heard of that opinion before |
| 11:34 | augustl | HOF = higher order functions? |
| 11:34 | rlb | bordatoue: you can often use the other functions, but you'll still be using loop/recur reasonably often -- of course, depends on what you're doing. |
| 11:34 | augustl | I've never used them I think :) |
| 11:35 | craigbro | bordatoue: it might be helpful to think of these as tools for transofrming a list, or reducing a list |
| 11:36 | rlb | ...and I would be surprised if loop/recur is more common at first, for anyone coming from more strictly imperative languages. |
| 11:36 | rlb | s/would/wouldn't/ |
| 11:37 | rlb | bordatoue: often you can recast your problem to use the other functions (i.e. max. min, etc.) |
| 11:37 | bordatoue | (let [x 10] ... (let [x (+ x 10)] ...)) ,can anyone explain what happens with the stack allocation |
| 11:37 | bordatoue | basciall i have got one outer let with binding to x and inner let with binding to x |
| 11:38 | craigbro | in my 15k+ line app, loop is used 5 times |
| 11:38 | craigbro | and most of those are in code I have for walking tree-zipper data structures |
| 11:38 | craigbro | a naturaly "recursive" task |
| 11:38 | bordatoue | i just want to know if x ref to same object |
| 11:38 | rlb | bordatoue: no |
| 11:38 | rlb | bordatoue: the inner binding shadows the outer one. |
| 11:38 | craigbro | inner will shadow outer in the code that is lexically (typographically) inside the inner let |
| 11:39 | craigbro | they will not point to the same object |
| 11:40 | craigbro | also, letting something is not the same as saying "push this value onto the stack and let me refer to it as x" |
| 11:40 | ToxicFrog | Yeah, I have yet to use loop or recur at all |
| 11:40 | rlb | ...and the system is welcome to gc the outer bits iff they're no longer reachable, but I have no idea what clojure actualy does, implementation-wise wrt to that. |
| 11:40 | craigbro | in some lisp implementations it is close to that tho |
| 11:40 | bordatoue | craigbro: what happens during letting |
| 11:43 | rlb | bordatoue: conceptually, the inner x and the outer x are two different variables/names, bound to two different values. |
| 11:43 | bordatoue | thanks |
| 11:43 | rlb | code can only see the "nearest" binding |
| 11:45 | bordatoue | so if you are given a seq what is best way to iterate them lazily without using take,loop,first,rest,map,reduce, |
| 11:45 | ToxicFrog | ...why would you want to avoid using those? |
| 11:46 | craigbro | sorry, network bounce |
| 11:46 | bordatoue | i just want to know if it is possible to write a fn that would return a max of value in a given seq without using any high order funtions or loop and recur , also atom . just using let and doseq |
| 11:47 | antares_ | bordatoue: for but I see no reasons to avoid take, map, filter, reduce and so on |
| 11:47 | bordatoue | ofcourse no max or min |
| 11:47 | craigbro | bordatoue: sure, you can use doseq, and an atom |
| 11:47 | bordatoue | antares_: this is just for understanding what can be done with the language , |
| 11:47 | craigbro | bordatoue: an atom is a way to have mutable state in clojure |
| 11:48 | craigbro | bordatoue: avoiding HOFs in a lisp is not advised 8) |
| 11:48 | rlb | bordatoue: are you allowed to use fn? |
| 11:48 | bordatoue | so craigbro, what happens during atom operation does it use CAS |
| 11:48 | craigbro | CAS? |
| 11:48 | clojurebot | paredit screencast is http://p.hagelb.org/paredit-screencast.html |
| 11:48 | bordatoue | rlb: that is good way, acutally you could pass it as an argument |
| 11:49 | bordatoue | CAS compare and swap |
| 11:49 | craigbro | rlb: I end up doing that with macros alot, when I want a macro that binds a bunch of helper variables |
| 11:49 | rlb | bordatoue: and loop/recur is (more or less) just syntactic sugar for recursion (i.e. recursive fn calls). |
| 11:49 | craigbro | bordatoue: the atom itself doesn't give a fuck, but yah, you could compare and swap |
| 11:49 | craigbro | an atom is just a box |
| 11:49 | bordatoue | but jvm does not do a Tail call optims |
| 11:49 | craigbro | loop/recur handles that for you |
| 11:50 | bordatoue | is atom just a box like the var |
| 11:50 | ToxicFrog | bordatoue: no, but the clojure compiler does (by translating it into forms that the JVM can process in constant stack space) |
| 11:50 | rlb | but no, doeseq has *no way* to preserve state across sequence elements |
| 11:50 | craigbro | like a var, but you can change it, and the ways you change it handle synchronization and all that |
| 11:51 | rlb | bordatoue: doseq *can not do it*, by itself |
| 11:51 | craigbro | http://clojure.org/Atoms |
| 11:51 | rlb | (since you said "no atoms" above) |
| 11:52 | bordatoue | okay thanks everybody, very informative |
| 11:52 | craigbro | socratic method! |
| 11:54 | uvtc | I wonder why clojurebot pointed out that paredit screencast above... |
| 11:54 | uvtc | CAS? |
| 11:54 | clojurebot | paredit screencast is http://p.hagelb.org/paredit-screencast.html |
| 11:54 | uvtc | Hm. |
| 11:54 | craigbro | SCREE |
| 11:54 | craigbro | SCREE? |
| 11:54 | clojurebot | paredit screencast is http://p.hagelb.org/paredit-screencast.html |
| 11:54 | craigbro | PARE? |
| 11:54 | clojurebot | paredit tutorial is http://p.hagelb.org/paredit-outline |
| 11:54 | craigbro | OUTLINE? |
| 11:54 | craigbro | weird |
| 11:54 | uvtc | Didn't know about those pages. Nice. |
| 11:55 | duck1123 | that's why clojurebot told you, he knew you hadn't seen the paredit screencase |
| 11:55 | uvtc | The uncanny clojurebot. |
| 11:58 | casion | is there a page that has a list of common algorithms and/or tasks in clojure? |
| 11:58 | casion | i know of rossetta code, anything elsse? |
| 12:01 | uvtc | A cookbook, perhaps? |
| 12:01 | uvtc | casion: Maybe some at http://en.wikibooks.org/wiki/Clojure_Programming#Cookbook. |
| 12:02 | _zach | Is there a core fn that can convert a map of the form {index val} into a seq/vec where index corresponds to the index of the val in the new seq? |
| 12:03 | casion | uvtc: most othe stuff there is beyond me atm, but thank you :) |
| 12:03 | _zach | such that {0 :x 1 :y 3 :z} => (:x :y nil :z) |
| 12:05 | rlb | casion: for educational purposes, clojures own code for various operations can also be helpful. |
| 12:05 | rlb | s/clojures/clojure's/ |
| 12:06 | rlb | casion: and if you haven't seen them, there are links to the source in the documentation. |
| 12:06 | tmciver | ,(vals {0 :x 1 :y 3 :z}) ; _zach |
| 12:06 | clojurebot | (:x :y :z) |
| 12:06 | tmciver | nope, but close |
| 12:06 | casion | thanks rlb |
| 12:06 | _zach | tmciver: indeed, thanks |
| 12:07 | uvtc | _zach: Hm.. You might first start with `(vals m)` ... |
| 12:07 | rlb | i.e. http://clojuredocs.org/clojure_core/clojure.core/reverse#source |
| 12:07 | uvtc | Oh, wait. `map-indexd`. |
| 12:08 | _zach | uvtc: I think I have something figured out. I'll post my solution in a second. |
| 12:08 | _zach | there's likely a nicer way. |
| 12:08 | uvtc | &(map-indexed (fn [idx entry] [idx (val entry)]) {:a "aa" :b "bb" :c "cc"}) |
| 12:08 | lazybot | ⇒ ([0 "aa"] [1 "cc"] [2 "bb"]) |
| 12:09 | uvtc | _zach: er, though maybe I didn't read your question carefully enough. |
| 12:10 | _zach | uvtc: :) I have a map where index => val |
| 12:10 | _zach | so {3 :d 2 :c 0 :a 1 :b} should become (:a :b :c :d) |
| 12:11 | uvtc | _zach: Ok, so you want `(vals m)`, but you want them sorted by their keys in `m`. |
| 12:11 | _zach | uvtc: Exactly. |
| 12:12 | Bronsa | user=> (vals (into (sorted-map) {3 :d 2 :c 0 :a})) |
| 12:12 | Bronsa | (:a :c :d) |
| 12:12 | tmciver | _zach: but you also want indexes missing from the map to be represented as nil in the ouput, right? |
| 12:12 | _zach | tmciver: Yes. |
| 12:17 | uvtc | &(for [e (sort (fn [a b] (compare (a 0) (b 0))) (seq {3 :d 2 :c 0 :a 1 :b}))] (e 1)) |
| 12:17 | lazybot | ⇒ (:a :b :c :d) |
| 12:17 | uvtc | _zach: ^^ |
| 12:17 | uvtc | So, take a seq of the map to turn it into a list of entries, |
| 12:17 | Guest82661 | where do I find a core.logic binary(jar?) published? Sonatype or something? |
| 12:17 | uvtc | then sort those entries by their keys, |
| 12:18 | mich2 | here do I find a core.logic binary(jar?) published? Sonatype or something? |
| 12:18 | uvtc | _zach: and finally use `for` to just take the 2nd item of each entry. |
| 12:18 | _zach | uvtc: Thank you for this solution. I think Bronsa had another one as well, which is (vals (into (sorted-map) {3 :d 2 :c 0 :a 1 :b})) |
| 12:19 | Bronsa | ,(#(vals (into (into (sorted-map) (map vector (range (inc (reduce max (keys %)))) (repeat nil))) %)) {0 0 3 3 1 1}) |
| 12:19 | clojurebot | (0 1 nil 3) |
| 12:19 | Bronsa | this way you get also missing keys |
| 12:19 | _zach | Bronsa: Awesome! |
| 12:19 | Bronsa | I'm sure it can be done better but this is the first way that came to my mind |
| 12:19 | _zach | Bronsa: Thank you for your help. uvtc as well. |
| 12:20 | uvtc | _zach: Ah, missed that. ... Oooh, Bronsa's is nicer. :) |
| 12:28 | tmciver | _zach: here's another for good measure: ##(take 5 (map {0 :x 1 :y 3 :z} (range))) |
| 12:28 | lazybot | ⇒ (:x :y nil :z nil) |
| 12:29 | alex_baranosky | I'm trying to connect to clojure jack in, via M-x clojure-jack-in -- I have a project.clj file that I can use fine from lein repl. However when I try to use clojure-jack-in from Emacs it just says: "Starting swank server…" (and nothing else happens) |
| 12:29 | _zach | tmciver: I was just writing that same thing :). Thanks! |
| 12:30 | alex_baranosky | any ideas what might be the issue? |
| 12:31 | duck1123 | alex_baranosky: if you check the hidden buffers, there's probably one that has the output of the jack-in call |
| 12:31 | tmciver | alex_baranosky: I get that problem after I kill a previously running swank. |
| 12:32 | duck1123 | M-x slime-selector c (I think) |
| 12:38 | alex_baranosky | hmmm… my *swank* buffer had this message in it: "Process swank exited abnormally with code 127 |
| 12:38 | alex_baranosky | zsh:1: command not found: lein" |
| 12:39 | lnostdal | hi, (class (Long. (int 261))) ==> java.lang.Long but (class (Long. (Integer. 261))) ===> No matching ctor found for class java.lang.Long what's going on here? |
| 12:40 | alex_baranosky | I just reproduced it -- every time I redo M-x clojure-jack-in it is giving me an extra entry in the *swank* buffer |
| 12:43 | alex_baranosky | I think I've found the issue: Emacs isn't configured to get my PATH from my .zshrc |
| 12:43 | alex_baranosky | http://stackoverflow.com/questions/9435019/how-do-i-source-my-zshrc-within-emacs |
| 12:44 | duck1123 | I hate emacs on osx due to the path issues |
| 12:45 | uvtc | duck1123: I'm not crazy about the issue there with having that extra Command/Clover key... |
| 12:45 | duck1123 | I don't think I ever got my path quite right. I ended up just setting up a vm |
| 12:46 | duck1123 | I use a MBP, but I run my emacs over SSH forwarding from my linux server. I can't tell you how many times I've gone to copy, and closed the entire window |
| 13:01 | xumingmingv | I want to develop a producer-consumer queue, if use java, I will use ConcurrentLinkedQueue, how to do it in clojure? |
| 13:08 | xumingmingv | http://stackoverflow.com/questions/11703024/producer-consumer-queue-in-clojure |
| 13:22 | antares_ | xumingmingv: typically some queue implementation from j.u.c. is sufficient. Consumer can just loop and take/remove/poll items in a separate thread. |
| 13:23 | xumingmingv | is it possible to implement it in pure clojure way? |
| 13:24 | xumingmingv | ...because clojure is claimed to be very good at concurrency programming, dont know if i understand it correctly? antares_ |
| 13:25 | antares_ | xumingmingv: it is possible to implement a lot of things in just Clojure, but why would you reinvent j.u.c. queue implementations? |
| 13:25 | antares_ | there are not that many ways in which you can improve them |
| 13:26 | xumingmingv | antares_: my intension is not to beat j.u.c |
| 13:26 | antares_ | if you insist on having a Clojure version, use an atom that stores a collection. Appending items to it is as straightforward as (swap! an-atom conj item) |
| 13:27 | antares_ | consuming correctly is a bit trickier but also will use swap! and sequence/collection operations |
| 13:29 | xumingmingv | yeah, this is what in mind now(use atom, swap!), but if multiple threads producing/consuming the messages concurrently |
| 13:29 | xumingmingv | then I need to use ref and dosync |
| 13:29 | antares_ | xumingmingv: why? |
| 13:29 | antares_ | atom is atomic reference |
| 13:29 | antares_ | it is pretty hard to be safer than that |
| 13:30 | xumingmingv | oh, maybe I didnt really understand atom, let me learn it again |o| |
| 13:31 | antares_ | for just one identity (like a queue), using a ref over an atom makes no sense. It will work the same way but carry more overhead. |
| 13:32 | xumingmingv | so it is safe to have multiple threads adding/removing from the collection in a atom? |
| 13:32 | xumingmingv | concurrently |
| 13:34 | devn | "Changes to atoms are always free of race conditions." |
| 13:34 | xumingmingv | but the performance is bad, right? because the swap! use compare-and-set, so technically the producer and consumer cannt adding/removing items from the atom at the same time |
| 13:40 | duck1123 | xumingmingv: this is probably not what you're looking for, but have you looked at lamina? |
| 13:41 | xumingmingv | thanks duck1123 devn antares_ |
| 13:41 | devn | xumingmingv: the comment on your SO post is worth looking into -- clojure.lang.PersistentQueue |
| 13:44 | devn | xumingmingv: maybe you do want a ref... hm... |
| 13:44 | xumingmingv | devn, how to solve this concrete problem is not really my biggest concern |
| 13:44 | xumingmingv | duck1123, devn: I think what I'm really confused is that: clojure is claimed to be good at concurrency programming, but for this producer-consumer case we need to looking java for help |
| 13:45 | duck1123 | I think it's less that you *need* to look to clojure, but rather that java already has it covered |
| 13:45 | duck1123 | look to java |
| 13:46 | antares_ | xumingmingv: Clojure makes concurrency easier where Java itself does not. Clojure was designed to be a symbiotic/hosted language. Why reinvent concurrent queues if there is already several implementations in the JDK? |
| 13:48 | devn | xumingmingv: clojure.lang.PersistentQueue is a clojure thing. |
| 13:52 | xumingmingv | thanks all, maybe I just too focused on solve problems using pure clojure |
| 13:53 | devn | xumingmingv: clojure.lang.PersistentQueue is "pure" clojure. |
| 13:53 | devn | it also used to be implemented using ConcurrentLinkedQueue |
| 13:53 | xumingmingv | devn: haha I will take at look at it |
| 13:55 | devn | now i feel bad -- i am now thinking he probably shouldn't use persistentqueue :\ |
| 13:58 | craigbro | haha |
| 14:36 | ToxicFrog | devn: it kind of feels like you could implement reader/writer architectures in clojure without needing a shared queue at all, to me |
| 14:36 | ToxicFrog | And possibly should |
| 15:27 | michaelr525 | good evening! |
| 15:47 | cldwalker | hi all, anyone know of a parser for maven-metadata.xml? if not I was just going to do it with clojure.xml/parse |
| 15:50 | cldwalker | _ato: this is for showing clojar dependencies, thoughts? |
| 15:52 | Frozenlock | Amazing to see how the channel is slower on weekends |
| 15:52 | Frozenlock | in/on weekends? |
| 16:09 | cldwalker | nevermind, found org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader |
| 16:47 | KyleBrodie | hola clojurians |
| 16:47 | duck1123 | hello |
| 16:48 | KyleBrodie | hows it going? |
| 16:48 | duck1123 | pretty good, you? |
| 16:48 | KyleBrodie | alright. are you an experienced clojurian? |
| 17:18 | duck1123 | I've been using clojure for a couple years. There are certainly better than me. Did you have a question? |
| 17:30 | dsantiago | Does clojurescript support clojure's (.fieldname myrecord) access style on defrecords? |
| 17:45 | hiredman | dsantiago: (.- |
| 17:46 | dsantiago | Ah. |
| 19:40 | presto | Is there a way of introducing a local binding without having to use it in a new scope (IOW: introducing a binding in the current scope)? For instance: (let a 1) so I can use 'a' in the next statements instead of inside the 'let' form. |
| 19:41 | presto | Also: would this be a good idea? Why? |
| 19:44 | antares_ | ,(let [a 1 b a] b) |
| 19:44 | clojurebot | 1 |
| 19:44 | antares_ | presto: if I understand your question correctly, that is very common |
| 19:45 | antares_ | but you can only use locals inside a scope created with let, if-let, with-open and so on |
| 19:45 | presto | antares_, not quite. I mean something like (let a 1) a ; return 1 |
| 19:45 | presto | As you would do in Javascript, for instance. var a = 1; a; |
| 19:46 | brainproxy | presto: how about def |
| 19:46 | brainproxy | (def a 1) |
| 19:46 | presto | brainproxy, def introduces the binding in the whole thread, as far as I know, not only in the current scope. |
| 19:46 | brainproxy | oh sorry, didn't read your question carefully enough |
| 19:47 | antares_ | presto: no necessarily the whole thread but namespace, yes |
| 19:47 | presto | I mean, using (let [?] ?) is no big deal, but I guess that it would be easier to teach (and sometimes visually), if it would have some parallel with other dynamic languages, where doing a simple "a = b; b" would suffice. |
| 19:47 | presto | antares_, oh ok. |
| 19:47 | antares_ | presto: that's what let does |
| 19:47 | antares_ | and let-like forms |
| 19:48 | brainproxy | (let [a b] (...) (...) ) |
| 19:48 | presto | antares_, indeed, but you have to use the bindings *inside* the let form. That's my point. |
| 19:48 | antares_ | presto: yes and that is by design |
| 19:49 | antares_ | you can have the entire function body to be a let statement, there is nothing wrong with that |
| 19:50 | presto | antares_, sure, I do get that. |
| 19:50 | presto | My point is that it is still one level deeper that it would be if let would introduce the bindings in the *current* scope, instead of creating a new one. |
| 19:51 | presto | I'm not saying that it's wrong, by the way. :D |
| 19:51 | gfredericks | presto: that kind of makes it more imperative than expression-based |
| 19:51 | brainproxy | presto: can you gist an example where let and def don't give you quite what you want? |
| 19:51 | presto | Just that it would be simpler to teach someone as an introductory language if that was not the case. |
| 19:51 | presto | gfredericks, yes, I do agree with you there. |
| 19:52 | gfredericks | presto: have you had trouble teaching programming-beginners non-imperative languages? |
| 19:52 | antares_ | presto: in that case you would have a lot more unexpected side effects (well, shadowing) |
| 19:52 | presto | brainproxy, they both do. My point is not about functionality. Just about how it looks for a beginner. |
| 19:53 | antares_ | which is not unheard of in JavaScript, for example, where scoping is one of the most common sources of issues |
| 19:55 | presto | gfredericks, well, yes, and imperative ones as well. But I'm not a teacher anyway, I probably suck at explaining things. :D |
| 19:56 | brainproxy | presto: okay, i think i get it, you're suggesting that it may seem complicated to a beginner to have to introduce/nest a let statement in order to create a binding |
| 19:56 | antares_ | it would be a serious disservice to beginners |
| 19:56 | antares_ | it would be convenient for the first 3 days |
| 19:56 | antares_ | then they would start hitting the same issues as in JavaScript |
| 19:56 | casion` | so with a condp, you have an expression, then if the expression matches one of the values... the subsequent predicate is returned immediately, correct? |
| 19:56 | brainproxy | yeah, have to agree, coming from a few years of javascript |
| 19:57 | casion` | no concept of break; it just returns the predicate? |
| 19:57 | casion` | and goes to the next expresssion? |
| 19:58 | antares_ | explicit scoping is not "right" but it does discipline and protect you from many issues that have nothing to do with your problem's complexity |
| 19:58 | antares_ | casion`: yes, "first match wins" |
| 19:59 | presto | antares_, Javascript do have issues, but I think you're referring to some specific one that is related to binding values, right? |
| 19:59 | casion` | what's the difference with (cond _ _) then? |
| 19:59 | presto | antares_, like forgetting to use "var"? |
| 19:59 | antares_ | yes, that kind of issues, implicit scoping |
| 19:59 | brainproxy | yes, particularly inside of a function definition |
| 19:59 | brainproxy | if you're reusing a var name |
| 20:00 | brainproxy | but your intent is actually to shadow |
| 20:00 | presto | I see, well I'm doing only javascript nowadays (more than one year), I don't remember having binding issues but I'm using a javascript compiler, which do catch errors. So I guess I'm not the common case... |
| 20:01 | casion` | condp seems like a simple switch with implicit breaks, I get that (I assume I do)... what would the C equivalent of cond be then? |
| 20:01 | gfredericks | presto: I find clojure's let much easier to reason about than anything imperative |
| 20:02 | presto | gfredericks, yes, I also don't see any problem reasoning with let forms. |
| 20:02 | presto | I guess what I'm saying is... |
| 20:02 | presto | If there was a kind of let form that would introduce a binding in the *current* scope, I would probably use it sometimes. |
| 20:03 | gfredericks | and most clojure users would get angry at anyone who used it |
| 20:04 | presto | Yes, it's not Clojure-y. :D Not even Lispy I think. |
| 20:05 | presto | Anyway? I was just wondering if I was missing something. Thank you guys. |
| 20:05 | gfredericks | casion`: I don't think condp is like anything in C; nor cond; case is probably pretty similar to what you're describing |
| 20:05 | casion` | gfredericks: gah, why can't this shit all be like C :P |
| 20:06 | gfredericks | cuz then we wouldn't have much reason to use it |
| 20:06 | hyPiRion | casion`: condp would be like, hmm |
| 20:06 | casion` | someone should make C-lojure |
| 20:06 | casion` | gfredericks: yeah, well I'm learning this sspecifically because it's nothing like what I'm used to |
| 20:06 | casion` | still frustrating at times |
| 20:06 | hyPiRion | (cond expr1 stat1 expr2 stat2 expr3 stat3 ...) -> if (expr1) {stat1} else if (expr2) {stat2} else if .... |
| 20:07 | gfredericks | casion`: I've been using clojure for years and have never once used condp and didn't know what it did |
| 20:07 | hyPiRion | Oh wait, condp. |
| 20:07 | casion` | hyPiRion: I'm getting a bit lost in the differenc between cond and condp |
| 20:08 | hyPiRion | &(doc condp) |
| 20:08 | lazybot | ⇒ "Macro ([pred expr & clauses]); Takes a binary predicate, an expression, and a set of clauses. Each clause can take the form of either: test-expr result-expr test-expr :>> result-fn Note :>> is an ordinary keyword. For each clause, (pred test-expr expr) is evalu... https://www.refheap.com/paste/3861 |
| 20:08 | gfredericks | casion`: but I use cond all the time |
| 20:08 | antares_ | casion`: cond matches on equality. condp lets you decide what to use to match. |
| 20:09 | antares_ | casion`: also, everything in Clojure is an expression while in C it is usually the opposite. I think you want cond, not condp. |
| 20:09 | hyPiRion | antares_: cond isn't matching on equality, I think you're talking about case. |
| 20:09 | gfredericks | that :>> thing is a little ugly; I hadn't ever seen that before |
| 20:09 | antares_ | err |
| 20:10 | casion` | ok ok |
| 20:10 | casion` | I think maybe I get it? |
| 20:10 | casion` | condp is an expression, followed by value predicate pairs, if the value matches the expression the predicate is returned |
| 20:10 | antares_ | hyPiRion: more or less, I was talking about cond but did not explain it correctly |
| 20:11 | antares_ | case is used even more often than cond |
| 20:11 | casion` | cond is just expresssion predicate pairs |
| 20:11 | hyPiRion | casion`: It's probably best with examples, I'll give you the cdoc examples in a second. |
| 20:11 | casion` | hyPiRion: ok thank you |
| 20:12 | antares_ | casion`: so yes, you probably want case. cond is a nice way to avoid some if … elseif … elseif kind of code. |
| 20:13 | casion` | antares_: it's not so much of what I want, I'm just learning atm |
| 20:13 | hyPiRion | casion`: https://www.refheap.com/paste/3862 |
| 20:13 | casion` | going through code and referencing |
| 20:14 | casion` | what is :>> |
| 20:14 | casion` | I haven't come across that yet |
| 20:15 | antares_ | just a keyword |
| 20:15 | antares_ | it could be :joe |
| 20:15 | antares_ | or :rightright |
| 20:15 | antares_ | this example seems to be from http://clojuredocs.org/clojure_core/clojure.core/condp |
| 20:16 | casion` | ah |
| 20:16 | hyPiRion | casion`: Think of it like this: :>> means that you're using a function on the value given instead of a value to return. |
| 20:16 | casion` | the second example there was confusing me for a second |
| 20:18 | hyPiRion | so for instance, (condp even? n true (inc n) false (dec n)) would be the same as (condp even? n true :>> inc false :>> dec) |
| 20:19 | casion` | hmm |
| 20:19 | antares_ | I am afraid that's even more confusing :) |
| 20:19 | casion` | I understand, but I also don't |
| 20:19 | casion` | :>> is just a normal keyword? |
| 20:19 | hyPiRion | Yeah |
| 20:19 | casion` | I don't get how :keyword form works there? |
| 20:20 | casion` | or am I confused even more than I think |
| 20:20 | antares_ | casion`: don't worry about it, I think case and cond are what you really need to understand to work with Clojure, condp is rarely used |
| 20:20 | hyPiRion | I would recommend you to do the following: Ignore the :>> usage and use the "standard" way of using condp |
| 20:21 | casion` | will I be encoutnering that syntax elsewhere? |
| 20:21 | hyPiRion | Not as far as I know. |
| 20:21 | casion` | the :>> inc instead of say (inc n) |
| 20:22 | hyPiRion | I don't believe so, casion`. |
| 20:22 | gfredericks | casion`: the :>> only distinguishes the ternary case from the binary case; you should, though, get used to seeing functions referenced without being called |
| 20:22 | gfredericks | that is the nature of a functional language |
| 20:23 | casion` | gfredericks: I believe I understand that |
| 20:23 | casion` | but I don't get why :>> inc does anything? |
| 20:23 | gfredericks | :>> is specific to condp |
| 20:24 | gfredericks | the fact that it's used that way is very peculiar in clojure; I've never seen it anywhere else |
| 20:25 | gfredericks | anywhere else in clojure I mean |
| 20:25 | gfredericks | (not "in any other language") |
| 20:27 | casion` | I'm stuck on it saying "Note :>> is an ordinary keyword." |
| 20:27 | casion` | I understand what it is doing |
| 20:27 | gfredericks | it probably has the note there because that usage is so weird that nobody would expect it |
| 20:28 | gfredericks | casion`: do you know what a keyword is? |
| 20:28 | casion` | gfredericks: I thought I did, but I'm doubting that now |
| 20:28 | gfredericks | casion`: what do you think a keyword is? |
| 20:29 | casion` | a unique identifier for a value |
| 20:29 | hyPiRion | gfredericks: It's kind of interesting though, I don't understand how they figure out that it's the ternary case, and not the binary one. |
| 20:30 | gfredericks | hyPiRion: yeah since :>> is a function presumably it might be the binary case. I assume you just can't ever use :>> as a function; #(:>> %) if you really want to |
| 20:30 | gfredericks | casion`: what other languages are you familiar with? |
| 20:30 | Chousuke | casion`: keywords are not identifiers in clojure. they are simply things that evaluate to themselves |
| 20:31 | casion` | gfredericks: C/asm (in a few contexts) |
| 20:31 | Chousuke | you can use keywords as macro syntax for that reason |
| 20:31 | gfredericks | Chousuke: no, you could use anything in macro syntax |
| 20:31 | casion` | gfredericks: I've done most entirely embedded development |
| 20:31 | hyPiRion | So I don't understand which one is used here, for instance: https://www.refheap.com/paste/3863 |
| 20:31 | Chousuke | gfredericks: well, you could, but keywords are a good choice |
| 20:31 | casion` | clojure is my first functional language, or 'high level language' |
| 20:31 | Chousuke | gfredericks: since then you won't be hijacking anything |
| 20:32 | gfredericks | Chousuke: symbols are nicer |
| 20:32 | gfredericks | Chousuke: you hijack any usage of the keyword as a function, which we discussed a couple minutes ago |
| 20:33 | gfredericks | casion`: okay, well keywords are similar to strings, but they are used in contexts where the only thing you would care to do with them is compare them to other keywords (for equality); a lot of their uses is similar to enums in static languages |
| 20:33 | Chousuke | enums? hm :/ |
| 20:34 | Chousuke | they are good for anything that needs a constant. map keys usually. |
| 20:35 | casion` | hmmm |
| 20:35 | casion` | trying to process this |
| 20:35 | gfredericks | they are very good as map keys |
| 20:35 | casion` | keywords and guaranteed unique? |
| 20:36 | casion` | are* |
| 20:36 | gfredericks | not sure what that means |
| 20:36 | casion` | a map |
| 20:36 | gfredericks | :foo and :foo are the same |
| 20:36 | casion` | udh, sorry |
| 20:36 | casion` | yes |
| 20:36 | casion` | my brain is overloading apparently. |
| 20:36 | augustl | strings require string compare, symbols are memory address compares, so to speak |
| 20:36 | augustl | since :foo and :foo points to the same memory |
| 20:37 | gfredericks | yes keywords compare in O(1) while strings compare in O(n) |
| 20:37 | Chousuke | yeah you can't have two keywords that are both :foo and not the same object |
| 20:37 | gfredericks | ,(identical? :foo (keyword "foo")) |
| 20:37 | clojurebot | true |
| 20:37 | Chousuke | not without some hideous hackery anyway |
| 20:37 | hyPiRion | well, you do have :: |
| 20:37 | hyPiRion | ,::foo |
| 20:37 | clojurebot | :sandbox/foo |
| 20:37 | Chousuke | that's different |
| 20:38 | casion` | so it's like a const pointer then? |
| 20:38 | Chousuke | :foo/bar is still ::foo/bar |
| 20:38 | Chousuke | :foo/bar :P |
| 20:38 | Chousuke | damn typos |
| 20:38 | hyPiRion | ,::foo/bar |
| 20:38 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: ::foo/bar> |
| 20:38 | casion` | an identifier that always evaluates to the same address space? |
| 20:38 | hyPiRion | hah. |
| 20:38 | Chousuke | casion`: I'm not sure if it's an identifier. it's just an object |
| 20:38 | casion` | ok |
| 20:38 | gfredericks | casion`: that's true, but it's an implementation detail; really keywords are like strings |
| 20:39 | gfredericks | they are used in ways that you would not use strings in a low-level language because it wouldn't be efficient |
| 20:39 | Chousuke | casion`: and the semantics of keywords are such that iff a keyword has the same name as another, they are the same object |
| 20:39 | casion` | gfredericks: ok, that makes sense |
| 20:40 | casion` | you can compare keywords at runtime? |
| 20:40 | gfredericks | yep |
| 20:40 | hyPiRion | yes. |
| 20:40 | gfredericks | ,(= :foo :bar) |
| 20:40 | clojurebot | false |
| 20:40 | gfredericks | ,(= :baz :baz) |
| 20:40 | clojurebot | true |
| 20:40 | Chousuke | you can store keywords in data structures. they're just data. |
| 20:41 | gfredericks | ,(= [:foo] (list :foo)) |
| 20:41 | clojurebot | true |
| 20:41 | casion` | ,(= :right (keyword (str "ri" "ght"))) |
| 20:41 | clojurebot | true |
| 20:41 | casion` | mind bown |
| 20:42 | Chousuke | ,(identical? :right (keyword "right")) |
| 20:42 | clojurebot | true |
| 20:42 | Chousuke | that's the important thing |
| 20:42 | gfredericks | casion`: those things are all true of strings as well; just not the identical? part |
| 20:42 | Chousuke | they're the same object. |
| 20:42 | gfredericks | everything that keywords are used for in clojure strings could be used as well, just a little slower |
| 20:42 | Chousuke | they use java interned strings internally :P |
| 20:42 | casion` | that is amazing to me haha |
| 20:44 | augustl | are keywords GC-ed? In Ruby, the equivalent (symbols) aren't. |
| 20:44 | augustl | so if you keywordize strings from user input that's a nice way to run out of memory |
| 20:44 | casion` | so, back to condp, I assume the :>> keyword is just used by the macro? |
| 20:45 | augustl | symbolize* |
| 20:45 | gfredericks | casion`: yes it's a special case in the macro |
| 20:45 | casion` | is there a way to see how condp expands? |
| 20:45 | gfredericks | ,(source condp) |
| 20:45 | clojurebot | Source not found |
| 20:45 | gfredericks | casion`: yeah you can use macroexpand-1 |
| 20:45 | gfredericks | &(source condp) |
| 20:45 | lazybot | java.lang.RuntimeException: Unable to resolve symbol: source in this context |
| 20:54 | hyPiRion | Meh, condp is ambigous. |
| 20:57 | casion` | I can't find the source for it |
| 20:58 | gfredericks | &(clojure.repl/source condp) |
| 20:58 | lazybot | ⇒ Source not found nil |
| 20:58 | gfredericks | baaaah |
| 20:59 | hyPiRion | &(macroexpand-1 '(condp = foo baz bar spam egg)) |
| 20:59 | lazybot | ⇒ (clojure.core/let [pred__15215 = expr__15216 foo] (if (pred__15215 baz expr__15216) bar (if (pred__15215 spam expr__15216) egg (throw (java.lang.IllegalArgumentException. (clojure.core/str "No matching clause: " expr__15216)))))) |
| 20:59 | hyPiRion | &(macroexpand-1 '(condp = foo baz :>> bar spam :>> egg)) |
| 20:59 | lazybot | ⇒ (clojure.core/let [pred__15225 = expr__15226 foo] (clojure.core/if-let [p__4925__auto__ (pred__15225 baz expr__15226)] (bar p__4925__auto__) (clojure.core/if-let [p__4925__auto__ (pred__15225 spam expr__15226)] (egg p__4925__auto__) (throw (java.lang.IllegalArgu... https://www.refheap.com/paste/3865 |
| 21:00 | hyPiRion | That's basically how it works. |
| 21:00 | gfredericks | http://clojuredocs.org/clojure_core/clojure.core/condp#source |
| 21:02 | hyPiRion | hm, so it's just :>> that's affected. |
| 21:03 | gfredericks | of course |
| 21:03 | casion` | hum |
| 21:03 | hyPiRion | I was thrown off by the "Note :>> is an ordinary keyword. |
| 21:03 | casion` | I get it now |
| 21:03 | casion` | awesome |
| 21:03 | casion` | you guys are awesome |
| 21:04 | gfredericks | hyPiRion: hah; yeah the whole thing is a mess |
| 21:04 | gfredericks | (inc you-guys) |
| 21:04 | lazybot | ⇒ 1 |
| 21:05 | hyPiRion | I find defn- and dec' messy as well. I mean, the heck. |
| 21:05 | hyPiRion | &(doc dec') |
| 21:05 | lazybot | ⇒ "([x]); Returns a number one less than num. Supports arbitrary precision. See also: dec" |
| 21:05 | ToxicFrog | ,(doc dec) |
| 21:05 | clojurebot | "([x]); Returns a number one less than num. Does not auto-promote longs, will throw on overflow. See also: dec'" |
| 21:05 | ToxicFrog | Aah. |
| 21:05 | gfredericks | hyPiRion: eh; that's just performance stuff |
| 21:05 | gfredericks | dec' at least; not defn- |
| 21:06 | hyPiRion | gfredericks: it's the single quote in the name I'm a bit frightened at. |
| 21:06 | gfredericks | oh you don't like that being syntactically legal? |
| 21:06 | hyPiRion | Well, yeah. |
| 21:07 | mattmoss | It's just a name. |
| 21:07 | mattmoss | Makes me think of calculus, where f was a function and "f-prime" or f' was the first derivative. |
| 21:07 | ToxicFrog | hyPiRion: you don't like being able to write foo-prime as a name? |
| 21:07 | _ato | cldwalker: |
| 21:08 | gfredericks | I use it all the time |
| 21:08 | ToxicFrog | mattmoss: pretty sure that is exactly how it is being used here |
| 21:08 | mattmoss | Gotcha. |
| 21:08 | ToxicFrog | ' is a reasonable ascii approximation of the unicode prime symbol. |
| 21:08 | hyPiRion | Well. |
| 21:08 | gfredericks | ToxicFrog: wat; you're saying dec' is the first derivative of dec? |
| 21:08 | craigbro | in H.S. only tho |
| 21:08 | ToxicFrog | gfredericks: no; foo' has more applications that just derivatives |
| 21:08 | hyPiRion | &[(dec '1.0) (dec' 1.0)] |
| 21:08 | lazybot | ⇒ [0.0 0.0] |
| 21:09 | mattmoss | I've refrained from actually using myself, since I didn't see it mentioned in clojure book or other docs as being valid syntax... but maybe I didn't look hard enough. |
| 21:09 | ToxicFrog | generally A' is just "sometime derived from or closely related to A" |
| 21:09 | ToxicFrog | In calculus, by convention, this is a derivative. |
| 21:09 | mattmoss | What ToxicFrog said. |
| 21:09 | gfredericks | ToxicFrog: yes I read too much into your "that is exactly how it is being used here" |
| 21:09 | _ato | cldwalker: yes just a using a plain XML parser is what I'd do. It's simple enough calling a dedicated maven parser would be overkill. I'm sure there's a class in Aether (which Clojars depends on) which does it, but it'd probably be more work trouble to figure out how to use it than just doing it yourself. |
| 21:09 | ToxicFrog | gfredericks: yeah, sorry, that was ambiguous - I meant "it's being used as a prime symbol", not "it's being used as a derivative" |
| 21:10 | ToxicFrog | Hmm |
| 21:11 | ToxicFrog | Yeah, actually, according to the manual, dec' is not legal |
| 21:11 | gfredericks | the manual? |
| 21:11 | ToxicFrog | Well, the reader reference on the website, http://clojure.org/reader |
| 21:11 | ToxicFrog | "Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, and ? (other characters will be allowed eventually, but not all macro characters have been determined)." |
| 21:11 | mattmoss | ToxicFrog: Yeah that. |
| 21:12 | gfredericks | it's old then |
| 21:12 | mattmoss | Using ' as part of identifier seems to work, but I've refrained from doing so because I hadn't found any reference that supported it. |
| 21:12 | ToxicFrog | ,(defn f' [x] x) (f' 1) |
| 21:12 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 21:12 | ToxicFrog | &(defn f' [x] x) (f' 1) |
| 21:12 | lazybot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 21:12 | gfredericks | mattmoss: rich hickey supports it |
| 21:12 | ToxicFrog | eat me lazybot |
| 21:12 | hyPiRion | &(let [f' (fn [x] x)] (f' 1)) |
| 21:12 | lazybot | ⇒ 1 |
| 21:12 | ToxicFrog | Thank you. |
| 21:13 | mattmoss | gfredericks: That's good enough for me... just finding it in any doc/reference is lacking. |
| 21:13 | ToxicFrog | gfredericks: yeah, but if it's not documented... |
| 21:13 | gfredericks | ToxicFrog: it was documented verbally at the first clojure conj :) |
| 21:13 | gfredericks | he said "Now you can put primes on your symbols" |
| 21:13 | mattmoss | Ah. |
| 21:13 | ToxicFrog | gfredericks: word-of-mouth doesn't count as documentation :P |
| 21:13 | hyPiRion | &(let [!' (fn [x] x)] (!' 1)) |
| 21:13 | lazybot | ⇒ 1 |
| 21:14 | hyPiRion | &(let ['! (fn [x] x)] ('! 1)) |
| 21:14 | lazybot | java.lang.Exception: Unsupported binding form: (quote !) |
| 21:14 | hyPiRion | So the quote is a special case: Cannot occur at start of name. |
| 21:14 | gfredericks | ToxicFrog: my point was it's not an accident |
| 21:14 | hyPiRion | /s/name/symbol |
| 21:14 | ToxicFrog | gfredericks: yeah, I didn't expect it was, I'm just saying the docs need to be updated |
| 21:14 | gfredericks | hyPiRion: yes it has a different meaning at the start |
| 21:15 | gfredericks | clojure.org doesn't get a lot of compliments |
| 21:15 | hyPiRion | &(let [?'! (fn [x] x)] (?'! 1)) |
| 21:15 | lazybot | ⇒ 1 |
| 21:15 | hyPiRion | Well, that's creative at least. |
| 21:16 | gfredericks | ,'%foo |
| 21:16 | clojurebot | %foo |
| 21:16 | gfredericks | % is a fun one; can only be initial |
| 21:16 | hyPiRion | what. |
| 21:16 | hyPiRion | ,'%% |
| 21:16 | clojurebot | % |
| 21:17 | gfredericks | ,'[%%] |
| 21:17 | clojurebot | [% %] |
| 21:17 | gfredericks | %% just makes two of them |
| 21:17 | hyPiRion | Woah. |
| 21:17 | hyPiRion | ,'[%''%] |
| 21:17 | clojurebot | [%'' %] |
| 21:18 | gfredericks | the worst thing in the current reader that I know of is clojure.core// |
| 21:18 | hyPiRion | I don't like that one either, heh. |
| 21:18 | gfredericks | ,(read-string "clojure.core//") |
| 21:18 | clojurebot | clojure.core// |
| 21:18 | gfredericks | ,(read-string "something.else//") |
| 21:18 | clojurebot | #<RuntimeException java.lang.RuntimeException: Invalid token: something.else//> |
| 21:19 | ToxicFrog | what |
| 21:19 | hyPiRion | heh. It's the special case of the specials. |
| 21:19 | mattmoss | Obfucscated clojure? |
| 21:19 | hyPiRion | But actually... |
| 21:19 | hyPiRion | &(let [/ *] (/ 2 3)) |
| 21:19 | lazybot | ⇒ 6 |
| 21:20 | hyPiRion | And you can defn it too. |
| 21:53 | howard_ | Hello Clojurians! |
| 21:54 | howard_ | I have a question regarding using = to compare lists. Why does (def a 1) (= '(a) '(1)) return false? |
| 21:55 | howard_ | however, (= [1] [a]) is true |
| 21:55 | howard_ | :-( |
| 21:56 | gert | '(a) is a list with the symbol a |
| 21:56 | gert | that's not equal to a list with the number 1 |
| 21:56 | howard_ | ok thanks |
| 21:56 | howard_ | so does that mean a is not a symbol in [a]? |
| 21:57 | gert | the difference is in using the quote ' character |
| 21:57 | mattmoss | ,(= (list a) '(1)) |
| 21:57 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)> |
| 21:57 | mattmoss | silly me |
| 21:57 | gert | (def a 1) (= (list a) (list 1)) |
| 21:57 | howard_ | aha! |
| 21:57 | gert | that will work |
| 21:57 | howard_ | thank you Matt and Gert |
| 21:58 | gert | no worries |
| 21:58 | mattmoss | ,(let [a 1] '(a)) |
| 21:58 | clojurebot | (a) |
| 21:58 | howard_ | Now I will be more careful when using quote :D |
| 21:58 | mattmoss | ,(let [a 1] [a]) |
| 21:58 | clojurebot | [1] |
| 21:59 | gert | ,(let [a 1] (list a)) |
| 21:59 | clojurebot | (1) |
| 21:59 | gert | voila :) |
| 22:00 | gert | howard_: you could also say (def a 1) (= `(~a) `(1)) |
| 22:01 | gert | if you really don't like to use "list" |
| 22:01 | howard_ | i love everything Clojure |
| 22:01 | howard_ | hehe.. |
| 22:06 | gfredericks | ,(let [a 1] `(~a)) |
| 22:06 | clojurebot | (1) |
| 22:08 | howard_ | let me try and see if this works.. |
| 22:08 | howard_ | ,(slurp "/etc/hostname") |
| 22:08 | clojurebot | #<SecurityException java.lang.SecurityException: denied> |
| 22:08 | howard_ | nope :D |
| 22:09 | howard_ | ,(print "ha") |
| 22:09 | clojurebot | ha |
| 22:10 | howard_ | ,(loop [] (recur)) |
| 22:10 | howard_ | ,(print "hehe") |
| 22:10 | clojurebot | hehe |
| 22:10 | hyPiRion | timeout. |
| 22:10 | clojurebot | Execution Timed Out |
| 22:10 | howard_ | clever |
| 22:13 | hyPiRion | ,set! |
| 22:13 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: set! in this context, compiling:(NO_SOURCE_PATH:0)> |
| 22:15 | gfredericks | ,(doc set!) |
| 22:15 | clojurebot | Excuse me? |
| 22:18 | hyPiRion | Gurr. I want an immutable map to contain itself. Is there some trick to that? |
| 22:19 | howard_ | ,(do (declare b) (def b (atom {:b b}))) |
| 22:19 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 22:20 | howard_ | eh, it worked for me |
| 22:21 | hyPiRion | declare and def are scary. |
| 22:21 | howard_ | :D |
| 22:21 | gert | it won't happen howard_. a service evaluating clojure forms, on the public internet, is really not going to be *that* insecure |
| 22:22 | howard_ | also it is powered by Clojure |
| 22:22 | hyPiRion | However, it's not working properly. b doesn't contain itself. |
| 22:22 | howard_ | i just realized that.. |
| 22:22 | gert | at the time you're defining your atom, b is nil. So your atom holds {:b nil} |
| 22:23 | gfredericks | whatever you guys do will end up being essentially not an immutable map anymore |
| 22:23 | hyPiRion | gert: b is unbound, actually. |
| 22:23 | gert | ah yes, true |
| 22:23 | howard_ | yeah... it's always unbound |
| 22:23 | howard_ | let me try other ways |
| 22:23 | hyPiRion | gfredericks: That's sad, because there's nothing "illegal" pointing to itself. :( |
| 22:24 | hyPiRion | You're not mutable if you do that. |
| 22:24 | gfredericks | it's not a finite value though |
| 22:24 | hyPiRion | No, but neither is an infinite list. |
| 22:24 | hyPiRion | Both are immutable. |
| 22:27 | howard_ | ,(do (declare a) (def a {:self (atom a) :data 7}) (:data (ref (:self a))) |
| 22:27 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 22:27 | howard_ | ,(do (declare a) (def a {:self (atom a) :data 7}) (:data (ref (:self a)))) |
| 22:27 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 22:28 | howard_ | the bot doesn't take atoms? |
| 22:28 | hyPiRion | You can't def anything. |
| 22:29 | howard_ | well i just found a way... |
| 22:29 | howard_ | probably isn't exactly what you want |
| 22:29 | hyPiRion | ,(condp #(get %2 %1) {:>> {:>> :>>}} :>> :>> :>>) |
| 22:29 | clojurebot | :>> |
| 22:30 | howard_ | ,(let [m (:self (fn [] m))] ((:self m))) |
| 22:30 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: m in this context, compiling:(NO_SOURCE_PATH:0)> |
| 22:30 | howard_ | eh.. |
| 22:30 | hyPiRion | heh, you need to declare it, which is rather hard in a sandbox |
| 22:30 | howard_ | put m into def |
| 22:30 | howard_ | and it worked for me |
| 22:30 | howard_ | you have a self included map by using function |
| 22:32 | howard_ | (def m {:self (fn[] m) :data 7}) |
| 22:32 | howard_ | (:data ((:self m))) |
| 22:32 | howard_ | that works |
| 22:33 | howard_ | test color code |
| 22:34 | hyPiRion | Creative. I'll try and look for some core-hacky way of making it contain itself. |
| 22:34 | howard_ | :D |
| 22:34 | howard_ | good luck |
| 22:35 | hyPiRion | As of right now, I'm only able to get something like ##(let [a (transient {})] (assoc! a :a a) (persistent! a)) , which is almost there. |
| 22:35 | lazybot | ⇒ {:a #<TransientArrayMap clojure.lang.PersistentArrayMap$TransientArrayMap@15947ca>} |
| 22:35 | gfredericks | hyPiRion: what do you need this for? |
| 22:35 | hyPiRion | gfredericks: Intellectual stimulation. |
| 22:35 | howard_ | slow clap |
| 22:36 | hyPiRion | It's only an interesting problem, nothing more than that. :) |
| 22:40 | gfredericks | ,(let [m' (promise), m {:self m'}] (deliver m' m) m) |
| 22:40 | clojurebot | {:self #<core$promise$reify__3678@340d5852: {:self #<core$promise$reify__3678@340d5852: {:self #<core$promise$reify__3678@340d5852: {:self #<core$promise$reify__3678@340d5852: {:self #<core$promise$reify__3678@340d5852: #>}>}>}>}>} |
| 22:41 | muhoo | wat? |
| 22:41 | clojurebot | For Jswat: start clojure with -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888 |
| 22:42 | gfredericks | I think beyond that you'd have to look into hacking the private fields on the map classes |
| 22:45 | hyPiRion | gfredericks: heh. |
| 22:47 | hyPiRion | Oh well, I'll look at it tomorrow. |
| 22:48 | howard_ | what is the difference between a Cons and a list? |
| 22:49 | howard_ | i'm wondering why i cannot use peek in Cons |
| 22:49 | howard_ | .(peek '(1 2)) |
| 22:49 | howard_ | ,(peek (cons 1 '(2 3)) |
| 22:49 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 22:49 | howard_ | ,(peek (cons 1 '(2 3))) |
| 22:49 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IPersistentStack> |
| 22:49 | howard_ | :-( |
| 22:49 | howard_ | ,(first (cons 1 '(2 3))) |
| 22:49 | clojurebot | 1 |
| 22:49 | howard_ | oh, first works.. |
| 22:49 | hyPiRion | ,(doc peek) |
| 22:49 | clojurebot | "([coll]); For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil." |
| 22:50 | hyPiRion | So it's undefined for Conses. |
| 22:50 | howard_ | ,(doc first) |
| 22:50 | clojurebot | "([coll]); Returns the first item in the collection. Calls seq on its argument. If coll is nil, returns nil." |
| 22:50 | alandipert | howard_: cons returns a seq (not a concrete data structure), not a list |
| 22:50 | howard_ | i see.. |
| 22:51 | howard_ | thank you |
| 22:51 | howard_ | is there a way to pop more than one item from a stack (list)? |
| 22:51 | howard_ | ,(doc pop) |
| 22:51 | clojurebot | "([coll]); For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as next/butlast." |
| 22:52 | howard_ | ,(pop (pop (pop '(1 2 3 4)))) |
| 22:52 | clojurebot | (4) |
| 22:52 | howard_ | meh... that solves the problem but i wanna pop 100 from stack |
| 22:53 | gfredericks | (apply comp (repeat 100 pop)) |
| 22:53 | howard_ | so it makes a copy of the stack each time an element is popped? |
| 22:53 | hyPiRion | No. |
| 22:53 | howard_ | ok great! |
| 22:54 | alandipert | ,(drop 3 '(1 2 3 4)) ; if you can deal in seqs |
| 22:54 | howard_ | thanks guys! |
| 22:54 | clojurebot | (4) |
| 22:54 | hyPiRion | (reduce (fn [a _] (pop a)) [1 2 3 4 5 6] (repeat 3 nil)) |
| 22:55 | hyPiRion | ,(reduce (fn [a _] (pop a)) [1 2 3 4 5 6] (repeat 3 nil)) |
| 22:55 | clojurebot | [1 2 3] |
| 22:56 | alandipert | ,(nthrest '(1 2 3 4) 3) |
| 22:56 | clojurebot | (4) |
| 22:57 | alandipert | i think that lil guy stays a list |
| 22:59 | gfredericks | ,(-> '(1 2 3 4) (nthrest 3) type) |
| 22:59 | clojurebot | clojure.lang.PersistentList |
| 23:37 | muhoo | what's the most current hello-world for cljs? is it cljs-template? |
| 23:50 | nsxt | noob question - if i've a string, say, foo.bar, and i want 'bar', i can do "ListTables" |
| 23:50 | nsxt | user=> |
| 23:50 | nsxt | wrong paste... |
| 23:51 | nsxt | i can do (second (clojure.string/split "foo.bar" #"\.")) |
| 23:51 | nsxt | but that feels... unnatural? |
| 23:52 | nsxt | is there a more idiomatic way of getting "bar"? |
| 23:52 | howard_ | i did it in that way too... |
| 23:53 | nsxt | alright, i'll run with it for now. |
| 23:53 | howard_ | :) |
| 23:53 | howard_ | by the way.. |
| 23:53 | howard_ | are you trying to get file extension name? |
| 23:53 | howard_ | if so, use last rather than second |
| 23:53 | nsxt | no... it will always be string.string |
| 23:53 | howard_ | ok |
| 23:53 | nsxt | but yes, i agree last is better |
| 23:54 | nsxt | (if there were multiple elements) |
| 23:54 | howard_ | and if it is performance critical |
| 23:54 | howard_ | use peek rather than second |
| 23:54 | nsxt | thanks, howard_ |
| 23:54 | howard_ | ,(peek (clojure.string.split "foo.bar" #"\."))) |
| 23:54 | clojurebot | #<CompilerException java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.string.split, compiling:(NO_SOURCE_PATH:0)> |
| 23:54 | howard_ | oops |
| 23:54 | howard_ | ,(peek (clojure.string/split "foo.bar" #"\."))) |
| 23:54 | clojurebot | "bar" |
| 23:54 | howard_ | today i learned that peek is much faster than last :D |
| 23:55 | muhoo | also, noir-cljs or lein-cljsbuild? |
| 23:55 | nsxt | yeah, just checked clojuredocs and there's a benchmark, good to know |