#clojure log - Jan 30 2016

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

0:01 Malnormalulo: going to have to go source diving some day to wrap my head round that

0:02 justin_smith: essentially whenever the reader finds # it takes the next form, and that form decides what to do with following data (and how much to consume)

0:02 eg #_ is a reader macro that says "take the next form and don't do anything beyond reading it"

1:04 macrolicious: in Emacs, when I C-x C-e (defn myfunction [foo] (str foo)), I get => #'testapp.core/myfunction in the minibuffer, but when I try to run (myfunction "bar") in the cider repl, I get an 'Unable to resolve symbol' error… what's going on?

1:05 To clarify, myfunction was in another buffer than the cider repl.

1:06 I'm not sure where/how to test individual functions after 'running' them with C-x C-e.

1:28 I guess it's more of an #emacs question, now that I think about it.

4:47 kenrestivo: namespace it was defined in was testapp.core. namespace you're running your repl buffer in is probably user

4:48 if you change the namespace of your repl, it'll work.

4:48 (ns testapp.core) might do ya

7:53 spuz: how do I load my clojure file into the repl such that I can call functions without giving the namespace?

8:04 kungi: spuz: you can use (:require [your.ns :refer [function-1 function-2]]) in your ns form

8:05 spuz: kungi, is there a way to do it without knowing the function names in advance?

8:17 loophole: spuz (:require [your.ns :refer :all])

8:17 spuz: loophole, thanks!

8:20 loophole, that doesn't seem to work

8:20 does it need some specific version of clojure?

8:20 loophole: spuz: one moment i will try it myself

8:23 spuz: (use 'your.ns)

8:23 spuz: I have to check the exact rquire syntax myself nut use should work anyways

8:24 spuz: s/nut/but/

8:24 spuz: but the style guide says: "Prefer :require over :use; the latter form should be considered deprecated for new code"

8:24 https://github.com/bbatsov/clojure-style-guide

8:24 loophole: spuz but you are talking about the repl?

8:24 spuz: yes

8:25 luma: in the repl, it's (require '[your.ns :refer :all])

8:25 inside the ns form, it's (:require [your.ns :refer :all])

8:25 spuz: thanks luma

8:25 loophole: luma: haha... the ':'

8:26 spuz: yes that was it

8:26 loophole: never cut and paste

8:26 *note to self*

8:26 spuz: how do I unrequire something?

8:27 loophole: spuz: i have no idea

8:27 luma: (remove-ns '

8:27 (remove-ns 'your.ns)

8:28 loophole: spuz: why not (require '[your.ns :as y])

8:28 spuz: ?

8:28 loophole: spuz then you don't have to ubnload at all

8:29 spuz (y/the-command)

8:29 spuz: seems strange

8:29 loophole: spuz: instead of (your.ns/the-command)

8:29 spuz: is there somewhere where I can find all namespace functions enumerated?

8:29 luma: but why would you need to "unrequire" something?

8:30 loophole: spuz importing all function into your namespace is not a good thing outside the repl

8:31 spuz: luma, so that i can unpolute the current namespace

8:31 loophole: spuz that is what the the :as syntax is for

8:32 spuz: to keep aliases short so that it is convinient enough to use them instead of the full blown namespace

8:32 spuz: maybe I don't understand what refer does but I don't see how :as helps

8:33 loophole: spuz say you want to use clojure.string/join

8:33 spuz without refer you have to write (clojure.string/join ...)

8:34 spuz: with refer :as you give the clojure.string part an alias say 's'

8:34 spuz: now you can write (s/join ....)

8:35 spuz: you can now have a function in your own code that is named join and it won't interfere with s/join

8:36 spuz: when you use :refer :all

8:36 your own join method will collide with the clojure.string/join method

8:40 ,(require '[clojure.string :as s])

8:41 clojurebot: nil

8:41 loophole: (s/join "X" [1 2 3])

8:41 ,(s/join "X" [1 2 3])

8:41 clojurebot: "1X2X3"

8:42 loophole: ,(defn join [xs] [:haha_no_join [xs]])

8:42 clojurebot: #'sandbox/join

8:42 loophole: ,(require '[clojure.string :refer :all])

8:42 clojurebot: #error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkPropertyAccess nil -1]\n [java.lang.System getProperty ...

8:43 spuz: try just refering join

8:45 ,(require '[clojure.string :refer [join]])

8:45 clojurebot: nil

8:45 spuz: ,(join "foo")

8:45 clojurebot: "foo"

8:45 spuz: ,(join "foo" "foo")

8:45 clojurebot: "ffooofooo"

8:45 spuz: so that's the clojure.string join ^

8:45 now how do i get my custom join back?

8:45 loophole: spuz that's ok too. I think it depends a bit on style. the prfix makes it clear that you use some external function when you read the code.

8:46 spuz: ,(defn join [xs] [:haha_no_join [xs]])

8:46 clojurebot: #error {\n :cause "join already refers to: #'clojure.string/join in namespace: sandbox"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalStateException: join already refers to: #'clojure.string/join in namespace: sandbox, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.IllegalStateException\...

8:46 loophole: spuz I always use the :as version

8:46 spuz in my code

8:47 spuz: so how do i get the previous definition of join back here?

8:47 loophole: spuz afaik the environemt repl will be restarted after a while

8:48 spuz: loophole, right... does that mean I have to restart everytime I want to change my own code?

8:48 it seems to defeat the point of the repl

8:49 luma: you can reload your file

8:49 ridcully_: just eval your defn again

8:53 spuz: if I use (require) to reload the file into the repl, it doesn't seem to actually bring in the changes

8:57 use of the repl in general just seems incredibly complex: https://github.com/clojure/tools.namespace#reloading-code-motivation

8:58 and as far as I understand the main motivation for using it slow compilation times?

9:01 mgaare: Slow repl startup

10:04 bcoburn: I'm trying to make a 'two-way' map where I can lookup key given val or val given key, is there a better way than doing (assoc {} key val val key) every time I want to add an entry?

10:15 dadinn: hi everyone

10:15 anyone here is familiar with clojure zippers?

10:17 I have found a behaviour which I cannot explain and it seems like a bug

10:18 here is an example testcase presenting the behavior: http://pastebin.com/wQzH826Q

10:20 kwladyka: dadinn you don't have seqzip

10:20 dadinn: sorry I missed it from the example lol

10:20 (def seqdat (list (list 1 2 3) (list 4 (list 5 6) 7) (list 8 9)))

10:20 (def seqzip (zip/seq-zip seqdat))

10:21 it's essentially the same structure as the veczip, but from seqs

10:23 kwladyka: updated the link: http://pastebin.com/iWHUSnDC

10:23 this one should have seqzip too

10:25 Malnormalulo: bcoburn: Per https://stackoverflow.com/questions/1183232/a-bi-directional-map-in-clojure, looks like it's either use a Java lib or roll your own bimap. Guava has one, reportedly

10:25 dadinn: oh noo, with sinax error too :P

10:25 kwladyka: dadinn for first look of eye it is not the same. your vector is nested one time more

10:26 ,(list (list 1 2 3) (list 4 (list 5 6) 7) (list 8 9))

10:26 clojurebot: ((1 2 3) (4 (5 6) 7) (8 9))

10:26 kwladyka: vs [[[1 2 3] [4 [5 6] 7] [8 9]]]

10:27 dadinn use '(1 2 3) instead of (list 1 2 3) - will be easier to read

10:27 dadinn: kwladyka: I didn't notice that ... oops

10:28 bcoburn: I think just having more keys is easier than both of those. I really should have searched first :(

10:28 dadinn: that vectorzipper was an example on clojuredocs so I just copied it to see if it really works like in the example

10:28 bcoburn: I guess all I'd need is a little function to call assoc

10:29 dadinn: and was a bit worried I don't get it why the down was behaving wierd..

10:29 Malnormalulo: bcoburn, Yeah, should be easy enough to abstract away. And assuming the map doesn't get too ginormous, the performance penalty of a naive approach won't be too bad

10:30 dadinn: thanks for helping

10:59 vise890: hey all. emacs question. has anyone managed to get cljr-find-usages and cljr-rename-symbol when working with clojure 1.5

11:10 dysfun: i get this strange error compiling a cljc file as cljs: Exception in thread "main" java.lang.AbstractMethodError: Method cljsbuild/compiler/SourcePaths._find_sources(Ljava/lang/Object;)Ljava/lang/Object; is abstract

11:10 code is here https://github.com/jjl/automat/blob/cljc/src/automat/fsm.cljc#L25

11:11 no line number or anything :)

11:47 justin_smith: dysfun: clojure 1.5 supports cljc?

11:48 dysfun: cljc is a 1.7 feature

11:48 oh, never mind, reading comprehension fail

12:33 dysfun: justin_smith: don't suppose you found the bug? :)

12:34 justin_smith: haha, no, that is the kind of error that is so weird that I would just run lein clean and try again

12:34 dysfun: yeah, but lein clean doesn't fix it :/

12:34 it's probably a bug in potemkin.types/deftype+ :)

12:36 justin_smith: but that shouldn't even be a possibility when you are compiling cljs...

12:37 dysfun: you'd think, but notice it talks about java.lang.Object

12:37 justin_smith: it's a compilation error, cljs is compiled by clojure

12:38 dysfun: yeah, and i'm moderately ignorant of clojurescript's internals

14:04 sdegutis: What's a reasonably simple way to do different things to a value based on whether it's a string, keyword, sequence, or map, without needing extensibility for new types?

14:05 dysfun: (cond (string? p) ... (vector? p) ... :else ...)

14:05 justin_smith: or even condp class p

14:06 never mind, not that

14:06 dysfun: plus you're asking for cljs portability issues doing that

14:07 sdegutis: justin_smith: I was about to do condp type v but it seemed weird.

14:07 dysfun: I hate cljs so that's ok

14:07 dysfun: hate is a strong word

14:08 sdegutis: Correct.

14:08 dysfun: why do you hate cljs?

14:08 sdegutis: Perhaps hate is wrong.

14:08 Loathe?

14:11 jk hate works

14:11 Clojure is great and Datomic is genius.

14:12 dysfun: i think most of us don't use datomic actually

14:12 we aren't their target customers

14:42 sdegutis: dysfun: who is?

14:42 dysfun: datomic is basically just a reall nice compromise between nosql and sql, I can't imagine who it's not right for

14:44 Anyway this task is too hard for my cognition to process.

14:48 justin_smith: sdegutis: it's not right for people who have large datasets or large throughput

14:48 I wish I could use it - we had to scale back our product because mongo wasn't delivering documents fast enough, and that was the fastest thing we found

14:58 sdegutis: justin_smith: mongo sucks when you have high-write and high-read, because every write slows down reads by locking /the entire db/

14:59 justin_smith: datomic is cool in how all reads/queries are basically free, because they happen in-process, and require no locking at all

15:00 justin_smith: with mongo and sql you have to have a super fast db server and your web server can be slow because it doesnt do much of the work on processing queries, but with datomic its reverse, the db server can be slow but the web server can be way faster

15:00 etc

15:00 justin_smith: sdegutis: multiple processes using the db, using it to send data, thus requiring frequent updates, datomic does not manage that nicely

15:00 sdegutis: justin_smith: meh

15:01 justin_smith: sdegutis: where datomic shines is if you can hold onto the same client side cache of things for a while - I'm not saying it doesn't work, but it doesn't work for our specific case

15:01 sdegutis: also we are using wired tiger, which does not lock the entire db for writes

15:01 sdegutis: justin_smith: you can put memcache between the web clients and the db server

15:03 justin_smith: sdegutis: will this work for thousands of writes a second?

15:08 sdegutis: naturally yes

15:58 creese: Has anyone created a back end for om.next that isn't datomic?

16:30 thesaskwatch: Hi, anyone here using cljs with node? I'm not sure I understand the dev workflow. Do you use cljs compiler watching and rebuilding and nodemon to autorestart the server or just cljs node repl somehow?

16:35 BRODUS: how can I `load-file` in a from a parent directory? Using ".." is not working

16:41 ridcully_: load-file from a plain repl with "../file.clj" works for me

16:41 is the error any useful?

16:48 BRODUS: ridcully_: no

16:48 ridcully_: just "No Such File or Directory"

16:49 ridcully_: I should mention that I'm not working in a project, its a just a .clj file in a directory that needs to read a clojure file in a directory above it

16:53 could it be because i started CIDER from another project?

16:55 trasto: Hi , I am new in clojure and have one question , how I can put one value for default in this form (let [[ v k] list]) ,is possible?

16:55 BRODUS: yep, that was the problem

16:56 trasto: I do not know how to do it

17:00 Mokuso: Hi. Would you recommend to someone to start learning Clojure, if he doesn't have much experience with Java and the Java environment? I have some experience with python and C# though.

17:01 (I don't mind the lisp/like looks of Clojure, what annoys me so far is that I don't really get the error messages, since they're Java related)

17:02 thx

17:11 dysfun: Mokuso: you get used to java. clojure was my first serious jvm programming experience

17:18 Mokuso: thanks dysfun. Just saw your answer, but I've got a dc as well

17:24 dysfun: er, dc?

17:28 Mokuso: disconnect

17:33 dysfun: well in any case, i think clojure is an entirely reasonable first language

17:33 and you get used to the parentheses

17:38 Mokuso: Yeah, I don't mind. It's cool that the repl has autocompletion for the parentheses as CL

17:39 anyways, we'll see how it goes

18:05 justin_smith: trasto: what does "one value for default" mean?

18:30 Mokuso: the state of the error messages is because clojure per se doesn't really have error messages or error handling for the most part. If you make a mistake that hits the vm then you get a trace showing the state of the vm and who the callers were and some implementation details revealed by the problem - which is distinct from a true error report of course.

18:31 Mokuso: it's as if python didn't do error handling and you just got operating system level access errors

18:31 Mokuso: aha, interesting

18:31 yeah, it sounds cool

18:31 but you'll have to know how your VM works, to decipher the errors msgs

18:31 justin_smith: Mokuso: cool, haha - the error handling (or lack of any explicit sort of error handling) is probably the worst thing about clojure

18:31 Mokuso: exactly

18:32 Mokuso: I don't mind, investing time in the JVM seems promising.

18:32 Esp. since I don't have in mind writing code for low level applications

18:32 justin_smith: Mokuso: on the plus side, it's not hard to find out what was happening at a low level, on the minus side, it's not hard to find out what was going on at a low level :)

18:33 Mokuso: uhm, what's the difference between happening and going on ?

18:33 justin_smith: Mokuso: editing error on my part, I meant them to both be the same

18:33 Mokuso: Ah ok :>

18:34 justin_smith: Mokuso: but more seriously, the art of dealing with the traces is mostly digging through and looking for your own code, then use other things in the trace as needed as context clues to see where it went wrong

18:35 the usual culprits are numeric operations, string methods, or calling methods on null - clojure code actually tends to be very resiliant it's just that these things blow up when they hit the vm implementation level

18:35 generally clojure itself is very optimistic and instead of checking that args are valid just pass them to the next layer of abstraction hoping for the best

18:36 ,(get 1 :a "default") ; obvious nonsense, works for implementation reasons

18:36 clojurebot: "default"

18:38 Mokuso: I'll probably start with a relevant book that explains how clojure is connected with JVM and all that stuff

18:38 justin_smith: the clojure.org docs are pretty good too

18:39 Mokuso: my "big picture" version is that clojure is a java library that generates jvm bytecode

18:39 Mokuso: heh

18:39 or a lisplike wrapper around Java classes perhaps

18:40 justin_smith: it's literally the truth though. It's a java lib (also runnable as a standalone program), you feed it text, it outputs bytecode, and it also contains the components needed to launch that bytecode as a program

18:40 Mokuso: kind of, yeah, but the outer layer is java - clojure itself is java code at the core, bootstrapped to clojure code for all but the most central stuff

18:41 Mokuso: aha..

18:41 justin_smith: so you have a java program, that defines a small lisp, then a bunch of lisp code it knows how to load, and all together that forms a usable bytecode compiler plus the stub needed to load and run that bytecode it generates

18:41 Malnormalulo: We call it a functional language, but really they're just IFn objects...

18:41 justin_smith: clojure programs are not standalone - they need the clojure runtime (since clojure is so meta / allows runtime definitions)

18:41 Mokuso: exactly!

18:42 so that's the bare basics, the code of clojure, and a good book or three, and you'll know all of it as well as any of us here

18:46 Mokuso: justin_smith, thanks a lots !!

18:46 justin_smith: np, glad I could help

18:46 Mokuso: oh, another cool thing that I can mention here is that clojure only has one mode of operation

18:46 Mokuso: what clojure does in the repl is exactly what it does when it reads your file and visa-versa

18:47 Mokuso: how else could it be ?

18:47 justin_smith: most languages allow using symbols before they are defined if they are defined in the same file

18:47 clojure doesn't, because it loads a file exactly the same way it reads your input at the repl, and if something isn't defined that's an error

18:48 Mokuso: if you look closely most languages have all sorts of special cases about how things run when the program is executing versus when things are being compiled and defined, but in clojure there is no split between those things

18:49 Malnormalulo: So it sounds like its compilation isn't super complex. It's more like ahead-of-time interpretation.

18:49 justin_smith: well, everything is always compiled

18:52 LucidTortoise: I am sure I will get some positive answers to this question: has anyone seen this talk?: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

18:53 I don't want to discuss the talk per se, but I do have one question?: What are the languages that embody his philosophy?

18:53 I suppose we have Clojure, Haskell, and other functional oriented languages. But what else fits the mold?

18:54 justin_smith: perhaps erlang?

18:54 * lokien puts ocaml there

18:54 LucidTortoise: Well, he does make a statement that "the world does not run by message passing", or something like that.

18:54 justin_smith: lokien: yeah, I grouped that with "other functional languages" - all mls would fit there ocaml included

18:55 LucidTortoise: oh yeah, fair enough, it's been a while since I saw that

18:55 LucidTortoise: So, is Erlang Smalltalk done right/functionally?

18:55 justin_smith: LucidTortoise: well you already mentioned the functional languages :)

18:55 lokien: justin_smith: but I'm sad when it's put together with "others"

18:55 justin_smith: it's not functional, I was trying to think of non-functional languages that come close to doing it right

18:56 LucidTortoise: I don't want to say I lost my enthusiasm for Smalltalk... but I think what I like most about Smalltalk is the contained, image based environment. Hm, maybe I should take a closer look at Self or Newspeak

18:57 lokien justin_smith That is my concern exactly, a paradigm does not sufficiently qualify a language.

18:57 So, any suggestions?

18:58 lokien: LucidTortoise: for how long have you been programming? I'm not trying to insult you or anything, I'm curious

18:59 LucidTortoise: Haha. Not long enough to even remotely be insulted by the question,.

19:00 lokien: so, for how long? :D

19:01 LucidTortoise: About 2 years, which honestly adds up to 2 months. I have been to inconsistent. I am one of those poser programmers who like talking and learning more about the language itself, then actually building something.

19:02 I have in the past month changed my mindset to actually be productive. I didn't realize how much of a book 4Clojure would be until I started using it today.

19:02 lokien: hey, I was like you for my first 10 months or so

19:02 and still am, but less

19:02 Malnormalulo: Yo same

19:02 LucidTortoise: Yeah, but got so boring being so... impotent.

19:02 lokien: LucidTortoise: we could do stuff together if you wanted

19:02 Malnormalulo: Spent my first year of programming doing pretty much nothing. I learned pretty much nothing.

19:03 lokien: I learned a lot, but did almost nothing :D

19:03 Malnormalulo: It didn't help that I found myself doing web development, which is exactly what I didn't want to be doing

19:03 LucidTortoise: lokien that would be fun. If you got a project going on, I would love to be another brain or just eyes. Or, if I think of something clever, you will be one of the first people I ask for help.

19:04 Malnormalulo Web Dev is such a trap. I think it is important, but unless you literally want to be making websites, there are so many other ways to use your programming skills.

19:06 Malnormalulo: Well see I applied for a job asking for SQL and Java knowledge. Offered, accepted, started work. They put me on an ASP.NET site.

19:06 It literally was a trap.

19:06 LucidTortoise: I say this because I actually tried Web Dev. A family friend wanted a website. I took this as an opportunity to learn a new technology, but didnt realize how much their is to learn.

19:06 justin_smith: there's companies out there that look for haskell experience then make you do java :P

19:06 LucidTortoise: The guy ended up getting what he need by signing up to Weebly

19:06 Malnormalulo: justin_smith, oh god why

19:07 justin_smith: Malnormalulo: they want java written by the kind of people that know haskell

19:07 Malnormalulo: also, they must think frustrated / resentful programmers write good code or something?

19:07 lol

19:07 Malnormalulo: I mean I guess they'll know better than to use instance variables like local variables

19:07 (Some of my coworkers do this.)

19:17 justin_smith: Malnormalulo: I mean that's just fine because you never use an object in more than one thread ever, I mean everyone knows that

19:18 of course if you use an object in more than one thread that would be totally insane but who uses objects in threads anyway

19:18 Malnormalulo: Ha well see, we don't. Want to know how we do multithreading? We start up a new JVM.

19:18 justin_smith: see, everything's fine then

19:18 lol

19:18 Malnormalulo: But we do reuse objects to avoid the overhead of instatiating new ones, so we have the same problem anyway

19:19 justin_smith: Malnormalulo: that's a great advantage with clojure actually, immutability makes thread stuff so much simpler

19:19 Malnormalulo: Yawp. One of many reason I really want to introduce it to our codebase.

19:30 trasto: justin_smith: one value default , sorry my english is bad

19:32 justin_smith: trasto: so something like (let [[v k] (or (not-empty list) [1])] ...) so that v would default to 1 but k would be nil if the input is less than 2 elements long?

19:36 trasto: yes but I need the second argument take the default value

19:36 justin_smith: oh, I misunderstood

19:40 trasto: with maps is possible with :or but is possible with vectors?

19:40 justin_smith: trasto: I don't know of a way - there might be but I don't think so

19:43 trasto: so the best form is transform this vector in one map... I think

19:58 justin_smith: (defn vec-default [v defaults] (concat v (drop (count v) defaults)))

19:58 ,(defn vec-default [v defaults] (concat v (drop (count v) defaults)))

19:58 clojurebot: #'sandbox/vec-default

19:58 justin_smith: ,(let [[a b c d] (vec-default [1 2] [:a :b :c :d])] {:a a :b b :c c :d d}) ; trasto

19:58 clojurebot: {:a 1, :b 2, :c :c, :d :d}

20:03 trasto: thanks justin_smith , to me it makes me complicated clojure

20:04 Mokuso: bah, dictionaries are annoying in any language :/

20:07 trasto: in clojure more than others XD

20:45 pulse207: /msg NickServ VERIFY REGISTER pulse207 nbrtbrukopxq

20:45 tolstoy: Heh. Oops!

20:47 justin_smith: hey that guy's password is a second teir superman villian

20:48 pulse207: dang guess I shouldn't use another superman villain, huh?

20:48 tolstoy: Ah, like Mister Mxyzptlk?

20:48 Mokuso: sounds like an alien friend of Rick's from Rick n Morty show to me

20:48 justin_smith: yeah, the one who fills in when Mxyzptlk is busy

20:49 haha

20:49 Mokuso: hehe, I think Mxyzptlk is a cool name

20:49 I'd name my dog that :P

20:51 tolstoy: My dog came pre-named. Jet. Not that he doesn't have a dozen names, depending on the time of day and my mood.

20:54 tier2villian: lets try this again

20:54 Mokuso: heh

20:58 tier2villian: so does anyone talk here?

20:58 justin_smith: yup, all things clojure are talked about here

20:58 tier2villian: well that's good. I figured I'd lurk, but there wasn't anything going on

20:59 justin_smith: ,((get get get get) (get get get get) (get get get get) 42)

20:59 clojurebot: 42

20:59 Malnormalulo: wat

20:59 justin_smith: Malnormalulo: it'll work in your own repl too

20:59 tolstoy: Well, it's Saturday night, and Clojurists are much in demand on the party circuit.

20:59 tier2villian: Ah, I should have known

21:00 justin_smith: tolstoy: funny enough, the above snippet is my favorite clojure party trick

21:00 Malnormalulo: I'm still trying to figure out why it works

21:00 justin_smith: just let me know if you need a hint

21:02 Malnormalulo: I'd expect it to try to cast `get` to a map and then fail

21:02 justin_smith: Malnormalulo: remember what I was saying about clojure and failures?

21:02 clojure is optimistic, it rarely validates inputs, if things are absurd it just keeps going unless it hits the bytecode (where things really do fail hard)

21:03 Malnormalulo: I guess I'd need to go dig into the implementation code to make sense of how it gets that far without a casting error

21:03 justin_smith: turns out get doesn't need a hash-map (there are other valid types to get from), and getting is not something that fails hard

21:04 Malnormalulo: if you took out the 42 it would return nil, if you turned the second (get get get get) into #{(get get get get)} it would return #'clojure.core/get

21:06 tolstoy: (get map key default-value) ... make sense. ((_ _ _ get) (_ _ _ get) (_ _ _ get) 42) -> (get get get 42) -> 42. Huh.

21:07 justin_smith: tolstoy: yup

21:07 tier2villian: I was wondering if it was just a trick to pass the default value back out

21:07 justin_smith: ,(+(*)(*))

21:07 clojurebot: 2

21:08 tolstoy: ,(get map reduce 42)

21:08 clojurebot: 42

21:08 Mokuso: (* 2 3 5 7 11 13 17 19)

21:08 clojurebot: *suffusion of yellow*

21:08 Mokuso: :(

21:08 (* 2 3 5 7)

21:08 clojurebot: *suffusion of yellow*

21:08 justin_smith: tier2villian: the base form is (get nil nil 42), then we add to this the fact that any instance of get can be replaced by (get get get get) and either of those nils can be replaced by just about anything...

21:09 Mokuso: (* 2 3)

21:09 clojurebot: *suffusion of yellow*

21:09 tier2villian: justin_smith: got it. that's cool

21:10 tolstoy: Looks like an excellent code-review troll.

21:10 justin_smith: ,(+(+(*)(*))(/(*)))

21:10 clojurebot: 3

21:11 justin_smith: ,(+(/(+(*)(*)))(/(*)))

21:11 clojurebot: 3/2

21:11 tier2villian: well I'm intrigued

21:12 justin_smith: that's just some second rate swearjure - the real deal is amazing but I am no master of swearjure

21:12 http://hypirion.com/musings/swearjure

21:13 tier2villian: That's one up on me. I don't actually know clojure, just looking for a new language to learn

21:13 justin_smith: oh shit this stuff makes clojure look terrible I'm so sorry

21:14 it's actually a very sane and readably language and these are bad code jokes we would never do in real code

21:14 tier2villian: Oh, I know. I never judge a language too quickly

21:15 Mokuso: does this bot get only the swearjure ?:P

21:15 tier2villian: (* 2 3 5 7 11 13 17 19)

21:15 clojurebot: *suffusion of yellow*

21:16 tier2villian: ,(* 2 3 5 7 11 13 17 19)

21:16 clojurebot: 9699690

21:16 tier2villian: weird

21:16 Mokuso: aha, maybe the comma

21:16 ,(* 2 3)

21:16 clojurebot: 6

21:16 tier2villian: I was watching you and wondering haha

21:16 justin_smith: Mokuso: absolutely not, the point of swearjure is that it is normal clojure - or at least understood by the normal clojure compiler

21:16 Mokuso: yeh :>

21:17 ,(defn ackermann [m n] (cond (zero? m) (inc n) (zero? n) (ackermann (dec m) 1) :else (ackermann (dec m) (ackermann m (dec n)))))

21:17 clojurebot: #'sandbox/ackermann

21:17 Mokuso: ,(ackermann 2 3)

21:17 clojurebot: 9

21:17 Mokuso: ,(ackermann 3 3)

21:17 clojurebot: 61

21:17 Mokuso: ,(ackermann 4 1)

21:17 tier2villian: I was very worried you were gonna pass it one of the big ones

21:17 clojurebot: eval service is offline

21:17 hyPiRion: 4 1 is one of the big ones :p

21:17 Mokuso: not really

21:18 4 3 is one of the big ones

21:18 tier2villian: speak of the devil

21:18 Mokuso: and 4 2

21:18 but it should be able to calc 4 1

21:18 justin_smith: it was big enough for clojurebot to ditch

21:18 Mokuso: it can, but not in the tiny time slice you are allowed

21:18 Mokuso: yeh, it's ok

21:18 aha :)

21:18 justin_smith: this is to protect the poor bot from trolls, of course

21:19 Mokuso: you know guys, I found some lisp code at the rosetta stone project for this monster function, and even if it's optimized it crashes at (ack 4 3)

21:19 I was wondering what kind of optimization one would need to use to calculate such a big integer

21:19 hyPiRion: Oh and yeah, you don't have to know Swearjure-related things to learn Clojure. I don't think I've ever seen anything I've learned from Swearjure in production quality Clojure code

21:19 justin_smith: heh, I'd hope not!

21:19 Mokuso: heh :)

21:20 justin_smith: hyPiRion: maybe very basic things, like knowing you can do (apply * l) and if l is empty it returns 1

21:20 Mokuso: I'm trying to translate the code from CL to clojure anyways, but it crashed for the time being. Would you like to have a look? I can provide the lisp code as well for comparison (that works fine).

21:21 justin_smith: Mokuso: feel free to share a link

21:21 hyPiRion: justin_smith: oh yeah, right. (*) and (+) is handy to learn just to know what happens when you do reduce on an empty list

21:21 justin_smith: right

21:21 ,(/ 2) ; related but not sweary

21:21 clojurebot: 1/2

21:22 justin_smith: ,(iterate / 2)

21:22 clojurebot: (2 1/2 2N 1/2 2N ...)

21:25 hyPiRion: Knowing about %& inside #(...) is also worthy. Rarely useful, but that one time you need it it's good to know

21:25 Mokuso: justin_smith, http://pastebin.com/9B3teGEw

21:25 hyPiRion: ,(#(reduce + %&) 1 2 3 4 5 6)

21:25 clojurebot: 21

21:25 justin_smith: Mokuso: so what's the error you get - stack overflow?

21:27 Mokuso: http://pastebin.com/EtLUf0YV

21:27 justin_smith: Mokuso: oh, you have the case syntax all scrambled

21:27 Mokuso: oh ?

21:28 justin_smith: Mokuso: every match clause in case needs the outer parens removed

21:28 cl -> (case x (m a) (m a)) clj -> (case x m a m a)

21:28 we use one less level of parens

21:28 Mokuso: ah !!

21:29 a bit confusing, but I'll give it a try

21:29 thanks :)

21:30 justin_smith: Mokuso: one more thing - remove the :else

21:30 Mokuso: maybe I'll use a cond instead

21:30 hyPiRion: Mokuso: https://www.refheap.com/114278 I think

21:30 justin_smith: just having an odd number of args suffices

21:30 with cond you also need to remove the parens around the matches

21:31 and replace each one with an equality test

21:31 *with case

21:31 Mokuso: this looks how it should be hyPiRion :)

21:33 yeah, it worked in the repl, but not through the core.clj, so I'll dig a bit more on that

21:33 justin_smith: so I use Math/pow instead of numeric-tower and (ackermann 4 2) simply returns Infinity

21:33 hah

21:33 wait, what worked in the repl?

21:33 Mokuso: the link hyPiRion gave :>

21:33 it's the correct 'translation' with the changes you mentioned

21:34 justin_smith: indeed (plus removing the redundant () on each case, which was not needed but is idiomatic)

21:34 Mokuso: ack 4 2 works fine, 4 3...I don't think I'll get a result :>

21:37 justin_smith: Mokuso: it took me for ever to stop writing (let [[a 0] [b 1]] (+ a b)) and variants, as someone who has coded scheme and common lisp in the past

21:39 Mokuso: It makes sense justin_smith. If you don't mind asking, what made you switch to clojure from those two?

21:39 *some habits are hard to break

21:40 justin_smith: Mokuso: I switched because I got hired to do clojure. I was hired because I had lispy experience, they were doing clojure and not one of the others because they needed to deploy to the jvm or at least have all the libs jvm would provide.

21:40 Kamuela: What’s a good explanation of the let form? I think it’s one that I’m not picking up so easily

21:41 justin_smith: Kamuela: it allows setting values to symbols that don't effect other cide

21:41 tier2villian: I could be wrong, but it's just a way to scope variables, right?

21:41 justin_smith: *other code

21:41 right

21:41 Mokuso: justin_smith, nice. Would you say that your background help you to learn clojure faster or had you wished you didn't know lisp/scheme before so you wouldn't have to unlearn all the extra stuff those languages had?

21:41 justin_smith: when you use def, you are changing something at namespace level, which could effect any of your other code

21:42 tier2villian: Okay, it's been a little while since I messed with scheme and that's my only lisp experience

21:42 justin_smith: Mokuso: definitely helped, most stuff was just simple translation - but I jumped ahead by far when I stopped treating clojure as "a weird lisp" and just dug into learning clojure as clojure

21:42 Mokuso: I'm asking, 'cos I'm considering some clojure related jobs for the future, and I'm wondering if I should go straight there or pass through scheme first.

21:42 justin_smith: tier2villian: so, in scheme you can use def to create locals

21:43 in clojure that's not a thing

21:43 Mokuso: Aha..thanks :)

21:43 tier2villian: justin_smith: oh so in clojure anything "def"'d is global?

21:43 justin_smith: Mokuso: if clojure gets to weird and confusing, plt-scheme or whatever they call it now is great, and is meant to be a language used to teach programming, so it has great tooling and documentation.

21:44 tier2villian: well, namespace level, so practically global, yeah

21:44 tier2villian: Mokuso: the racket community is also pretty welcoming, which is a plus

21:44 Mokuso: that's very interesting, Java is still calculating (ack 4 3). In scheme and CL it just crashed after a short time.

21:44 tier2villian: justin_smith: got it, thanks

21:45 justin_smith: Mokuso: numeric tower does promotion to unbounded bignums iirc

21:45 your cl may or may not do that

21:46 ,(inc' Long/MAX_VALUE)

21:46 clojurebot: 9223372036854775808N

21:46 justin_smith: ,(inc Long/MAX_VALUE)

21:46 clojurebot: #error {\n :cause "integer overflow"\n :via\n [{:type java.lang.ArithmeticException\n :message "integer overflow"\n :at [clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]}]\n :trace\n [[clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]\n [clojure.lang.Numbers inc "Numbers.java" 1839]\n [sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval49 invoke "NO_SOURCE_FIL...

21:50 Mokuso: ok, I've got an overflow after all, or close to that :>

21:50 ArithmeticException BigInteger would overflow supported range java.math.BigInteger.reportOverflow (BigInteger.java:1153)

21:50 justin_smith: that's a kind of overflow I have never seen

21:51 ,(iterate *' Long/MAX_VALUE)

21:51 clojurebot: (9223372036854775807 9223372036854775807 9223372036854775807 9223372036854775807 9223372036854775807 ...)

21:51 justin_smith: oh wait, with one arg it's just identity

21:51 ,(iterate #(*' % %) Long/MAX_VALUE)

21:51 clojurebot: (9223372036854775807 85070591730234615847396907784232501249N 7237005577332262210834635695349653859421902880380109739573089701262786560001N 52374249726338269874783614880766155793371912454611337886264179577532000370919343764787541041733925104025910035567032750922845842742640075519159173120001N 27430620343968443368695140184646988379527410343527824317354069354225552356596046115747958004859021025898780...

21:54 tier2villian: So question. I'm going to a 24 hour hackathon next weekend. Would it be unreasonable to try and pick up clojure and hope to have something to show for it?

21:55 justin_smith: that's one way to learn - you might want to make sure you have the basics for packaging and dependency management in check so you don't waste hackathon time on stupid stuff :)

21:56 tier2villian: alright. it really depends on my team I guess. If i end up flying solo, I'll probably give it a shot

21:56 justin_smith: not that clojure is bad at those things (far from it), but our tooling is weird at first to most people

21:56 tier2villian: weird in what way?

21:57 justin_smith: tier2villian: no global installs, instead you configure each individual project for hte lib versions it expects

21:57 which solves a lot of problems, but requires a bit more tedium up front when first starting

21:57 Mokuso: tier2villian, I've tried a hackathon like six months ago, but I went there without some concrete plan.

21:57 I'd advise you to have some idea before you go there

21:57 rhg135: Too awesome, controlling dependencies is something I miss when doing js

21:57 Mokuso: time flies fast :)

21:57 tier2villian: oh okay gotcha

21:58 Yeah, my first was last weekend actually

21:58 Mokuso: great experience though, no matter how you do in the end

21:58 tier2villian: got to try out mobile dev for the first time

21:58 Mokuso: you'll meet some people as well, so it's nice

21:58 tier2villian: Yeah, that was the best part

22:04 Mokuso: anyways, I'll better go get some sleep :)

22:05 thanks for the ack hack xD

22:25 princeso_: ,(clojure.walk/postwalk #(do (prn %) %) [1 {:2 3}])

22:25 clojurebot: #error {\n :cause "clojure.walk"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.walk"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java.net.U...

22:26 justin_smith: ,(require 'clojure.walk)

22:26 clojurebot: nil

22:26 princeso_: ,(clojure.walk/postwalk #(do (prn %) %) [1 {:2 3}])

22:26 clojurebot: 1\n:2\n3\n[:2 3]\n{:2 3}\n[1 {:2 3}]\n[1 {:2 3}]

22:26 justin_smith: fyi :2 is an abomination

22:26 princeso_: what does that mean?

22:27 justin_smith: princeso_: it's an exaggerated why of saying "Not only do I not see any point to using :2 as a keyword, seeing it used makes me twitch with annoyance". Kind of joking.

22:27 why not just use the number 2?

22:28 princeso_: well the point was, there is a vector in the result [:2 3].

22:29 justin_smith: ,(clojure.walk/postwalk #(doto % prn) [1 {2 3}])

22:29 clojurebot: 1\n2\n3\n[2 3]\n{2 3}\n[1 {2 3}]\n[1 {2 3}]

22:29 justin_smith: princeso_: yes, hash-maps are made of entries, which are each two element vectors

22:29 ,(seq {2 3})

22:29 clojurebot: ([2 3])

22:29 justin_smith: ,(seq {2 3 4 5})

22:29 clojurebot: ([2 3] [4 5])

22:29 justin_smith: ,(into {} [[2 3] [4 5]])

22:29 clojurebot: {2 3, 4 5}

22:31 princeso_: justin_smith: mmm ok. didnt know that. Im working on vectors, so there is going to be a hack

22:32 justin_smith: ,(map-entry? [1 2])

22:32 clojurebot: false

22:32 justin_smith: ,(map-entry (first {1 2}))

22:32 clojurebot: #error {\n :cause "Unable to resolve symbol: map-entry in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: map-entry in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: map-e...

22:32 justin_smith: ,(map-entry? (first {1 2}))

22:32 clojurebot: true

22:32 justin_smith: (= (first {1 2}) [1 2])

22:32 ,(= (first {1 2}) [1 2])

22:32 clojurebot: true

22:33 justin_smith: princeso_: the map-entry? function might help you

22:33 princeso_: godd: thanks justin_smith. you always rock!

22:36 justin_smith: haha that "makes me twitch with annoyance" was epic. any way i kind of like how it looks :D

22:38 justin_smith: princeso_: I deal with learners a lot, so it makes me wonder if the person using it thinks : is a syntax that means "lookup key in a hash map"

22:38 kind of like in js

22:42 Malnormalulo: yeah, the keyword syntax isn't the most intuitive thing in the world

22:43 justin_smith: ,(keyword " :: ::: ::: / / / ::: /")

22:43 clojurebot: : :: ::: ::: / / / ::: /

22:43 justin_smith: gotta love that clojure

22:43 to be clear, that returns a single keyword

22:43 ,(namespace (keyword " :: ::: ::: / / / ::: /"))

22:43 clojurebot: " :: ::: ::: "

22:43 justin_smith: ,(name (keyword " :: ::: ::: / / / ::: /"))

22:43 clojurebot: " / / ::: /"

23:12 princeso_: justin_smith: what could be possibly wrong whit postwalk, it says false to map-entry? [2 3]. And prewalk says yes.

23:13 justin_smith: princeso_: aha! post-walk is reconstructing the input, before your code gets to it

23:13 in retrospect I should have predicted that would be an issue

23:15 bbl

Logging service provided by n01se.net