#clojure log - Jul 28 2012

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

0:02 teurastaja: if i dont know java, should i learn it before learning clojure? i know scheme

0:04 emezeske: teurastaja: Knowing some java basics will probably make your life easier

0: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?

0:06 teurastaja: what features does someone who uses clojure and doesnt know java misses

0:06 ?

0:07 arohner: teurastaja: don't bother "learning" java. Just write what you want to write, and learn java lazily

0:08 emezeske: teurastaja: Well, for one thing, the error messages you will get from the clojure compiler are just java stack traces

0:08 teurastaja: can one write a metacircular interpreter in clojure alone?

0:08 arohner: yes

0:09 teurastaja: does it have continuations?

0:09 can it do systems programming?

0:10 arohner: no

0:10 teurastaja: no for which?

0:10 arohner: both, on the JVM

0:11 you can use JNA or JNI to load and call C libraries, but it wouldn't be useful for embedded systems, or interrupt handling

0:11 teurastaja: so what are clojures strengths

0:11 ?

0:11 arohner: It's a practical lisp

0:12 a lot of people use it for web stuff, and map reduce kinds of things

0:13 and it's good anywhere you'd use java, python or ruby

0:14 teurastaja: clojure vs common lisp vs scheme...?

0: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

0:16 probably bigger community at this point

0:19 you get to use JVM web servers and JVM DB drivers, so you can 'steal' from existing java libs when needed

0:20 teurastaja: java is not really an argument for me but its goode to know

0:21 what networking protocols does it support?

0:22 Raynes: *

0:23 emezeske: teurastaja: You want an exhaustive list?

0: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

0:27 teurastaja: just want to be sold clojure so i know if its good for me

0:28 arohner: what are you looking to do with it?

0:34 teurastaja: things i cant do easily with scheme

0:34 i dont know exactly

0:58 Raynes: If you can't easily do something in Scheme, it's usually related to there not being a library for it.

2: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 why there is no corresponding function to remove something from the nested structure?

10:18 user=> (swap! x assoc-in [:handlers :lst 0] "hello")

10:18 {:handlers {:lst ["hello"]}}

10:18 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 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 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 (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 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 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 i+=i+10

11:21 i+=10

11:21 uvtc: Oh, right, you want to keep a running total.

11:21 bordatoue: yes,

11:21 i want to chang the binding within a loop

11:22 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 (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 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 (C-style for)

11:24 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 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 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 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 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 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 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 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 s/would/wouldn't/

11:37 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 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 and most of those are in code I have for walking tree-zipper data structures

11:38 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 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 they will not point to the same object

11:40 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 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 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 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 CAS?

11:54 clojurebot: paredit screencast is http://p.hagelb.org/paredit-screencast.html

11:54 uvtc: Hm.

11:54 craigbro: SCREE

11:54 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 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 i know of rossetta code, anything elsse?

12:01 uvtc: A cookbook, perhaps?

12:01 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 s/clojures/clojure's/

12:06 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 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 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 (: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 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 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 I think I've found the issue: Emacs isn't configured to get my PATH from my .zshrc

12:43 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 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 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 ...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 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 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 then I need to use ref and dosync

13:29 antares_: xumingmingv: why?

13:29 atom is atomic reference

13:29 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 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 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 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 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 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 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 _ato: this is for showing clojar dependencies, thoughts?

15:52 Frozenlock: Amazing to see how the channel is slower on weekends

15:52 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 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 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 As you would do in Javascript, for instance. var a = 1; a;

19:46 brainproxy: presto: how about def

19:46 (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 antares_, oh ok.

19:47 antares_: presto: that's what let does

19:47 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 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 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 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 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 it would be convenient for the first 3 days

19:56 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 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 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 if you're reusing a var name

20:00 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 I guess what I'm saying is...

20:02 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 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 gfredericks: yeah, well I'm learning this sspecifically because it's nothing like what I'm used to

20:06 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 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 I think maybe I get it?

20:10 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 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 what is :>>

20:14 I haven't come across that yet

20:15 antares_: just a keyword

20:15 it could be :joe

20:15 or :rightright

20:15 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 :>> is just a normal keyword?

20:19 hyPiRion: Yeah

20:19 casion`: I don't get how :keyword form works there?

20:20 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 that is the nature of a functional language

20:23 casion`: gfredericks: I believe I understand that

20:23 but I don't get why :>> inc does anything?

20:23 gfredericks: :>> is specific to condp

20:24 the fact that it's used that way is very peculiar in clojure; I've never seen it anywhere else

20:25 anywhere else in clojure I mean

20:25 (not "in any other language")

20:27 casion`: I'm stuck on it saying "Note :>> is an ordinary keyword."

20:27 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 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 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 Chousuke: you hijack any usage of the keyword as a function, which we discussed a couple minutes ago

20:33 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 they are good for anything that needs a constant. map keys usually.

20:35 casion`: hmmm

20:35 trying to process this

20:35 gfredericks: they are very good as map keys

20:35 casion`: keywords and guaranteed unique?

20:36 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 yes

20:36 my brain is overloading apparently.

20:36 augustl: strings require string compare, symbols are memory address compares, so to speak

20:36 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 ,::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 :foo/bar :P

20:38 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 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 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 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 &(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 awesome

21:03 you guys are awesome

21:04 gfredericks: hyPiRion: hah; yeah the whole thing is a mess

21:04 (inc you-guys)

21:04 lazybot: ⇒ 1

21:05 hyPiRion: I find defn- and dec' messy as well. I mean, the heck.

21:05 &(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 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 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 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 Hmm

21:11 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 "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 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 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 ,'%%

21:16 clojurebot: %

21:17 gfredericks: ,'[%%]

21:17 clojurebot: [% %]

21:17 gfredericks: %% just makes two of them

21:17 hyPiRion: Woah.

21:17 ,'[%''%]

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 &(let [/ *] (/ 2 3))

21:19 lazybot: ⇒ 6

21:20 hyPiRion: And you can defn it too.

21:53 howard_: Hello Clojurians!

21:54 I have a question regarding using = to compare lists. Why does (def a 1) (= '(a) '(1)) return false?

21:55 however, (= [1] [a]) is true

21:55 :-(

21:56 gert: '(a) is a list with the symbol a

21:56 that's not equal to a list with the number 1

21:56 howard_: ok thanks

21:56 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 howard_: you could also say (def a 1) (= `(~a) `(1))

22:01 if you really don't like to use "list"

22:01 howard_: i love everything Clojure

22:01 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 ,(slurp "/etc/hostname")

22:08 clojurebot: #<SecurityException java.lang.SecurityException: denied>

22:08 howard_: nope :D

22:09 ,(print "ha")

22:09 clojurebot: ha

22:10 howard_: ,(loop [] (recur))

22:10 ,(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 let me try other ways

22:23 hyPiRion: gfredericks: That's sad, because there's nothing "illegal" pointing to itself. :(

22:24 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 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 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 and it worked for me

22:30 you have a self included map by using function

22:32 (def m {:self (fn[] m) :data 7})

22:32 (:data ((:self m)))

22:32 that works

22:33 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 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 Oh well, I'll look at it tomorrow.

22:48 howard_: what is the difference between a Cons and a list?

22:49 i'm wondering why i cannot use peek in Cons

22:49 .(peek '(1 2))

22:49 ,(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 ,(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 thank you

22:51 is there a way to pop more than one item from a stack (list)?

22:51 ,(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 ,(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 user=>

23:50 wrong paste...

23:51 i can do (second (clojure.string/split "foo.bar" #"\."))

23:51 but that feels... unnatural?

23:52 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 by the way..

23:53 are you trying to get file extension name?

23:53 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 (if there were multiple elements)

23:54 howard_: and if it is performance critical

23:54 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 ,(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

Logging service provided by n01se.net