2016-02-03
| 01:36 | marcfontaine | using cursive, I am getting the following error when compiling, there are no errors when sending the form directly to the repl. |
| 01:36 | marcfontaine | CompilerException java.lang.IllegalArgumentException: Value out of range for char: -61, compiling:(extract_from_quotes.clj:80:18) |
| 01:36 | marcfontaine | (def invoice-ids (apply str (interpose "," (map #(:invoiceId %) (flatten (map vals clearquotes))))) |
| 01:36 | marcfontaine | ) |
| 01:36 | marcfontaine | => #'csv.extract-from-quotes/invoice-ids |
| 01:38 | TEttinger | try checking the result of just (map :invoiceId (flatten (map vals clearquotes))) |
| 01:38 | TEttinger | wait |
| 01:39 | TEttinger | ,(flatten [{:invoiceId 1 :a 2} {:invoiceId 3 :a 4}]) |
| 01:39 | clojurebot | ({:invoiceId 1, :a 2} {:invoiceId 3, :a 4}) |
| 01:39 | TEttinger | ah, wasn't sure if flatten would do something to maps |
| 01:40 | marcfontaine | (map :invoiceId (flatten (map vals clearquotes))) =>("1000882" "1000883" "1000924" “1000926" …. ) |
| 01:40 | TEttinger | that “1000926" is odd |
| 01:41 | TEttinger | one quote is a smart quote, not sure if that's just IRC |
| 01:41 | TEttinger | ,(interpose "," ["1000882" "1000883" ]) |
| 01:41 | clojurebot | ("1000882" "," "1000883") |
| 01:42 | marcfontaine | yeah that’s just me typing |
| 01:42 | TEttinger | is clearquotes from a file? |
| 01:43 | TEttinger | ,(apply str (interpose "," ["1000882" "1000883" -61])) |
| 01:43 | clojurebot | "1000882,1000883,-61" |
| 01:44 | TEttinger | is this online, marcfontaine ? |
| 01:44 | TEttinger | the source I mean |
| 01:46 | amalloy | clojure.string/join |
| 01:46 | amalloy | also, clojure.core/mapcat |
| 01:47 | TEttinger | amalloy: thoughts on the out of range for char: -61 error? |
| 01:49 | amalloy | i think -61 is not a very good character |
| 01:50 | marcfontaine | ok great pointer, the clearquotes are coming from the deserialization of php data. |
| 01:50 | TEttinger | indeed. any idea what could cause that? |
| 01:50 | TEttinger | oooh |
| 01:50 | TEttinger | encoding maybe? |
| 02:40 | marcfontaine | ok problem was converting result (a bytearray of valid data size nb) to string using (subs (map char result) 0 nb) instead of (subs (String. result “UTF-8”) 0 nb) so the discrepancy between compilation and repl was due to how the byte-array is initialized in the compiler vs repl. |
| 02:47 | marcfontaine | or better yet (String. result 0 nb "UTF-8") |
| 05:06 | anti-freeze | Hi everyone. I'm having issues with core.async and transforming values. I have a list of files, I want to read them and then convert them to js/Blob objects before passing them to the out channel. I've tried this, but to no avail https://www.refheap.com/114412 |
| 05:07 | anti-freeze | io/read-file returns a channel |
| 08:00 | jeaye | I see this when I try to minify http://dpaste.com/3X3PTKJ#wrap |
| 08:00 | jeaye | Any ideas what'd cause this? |
| 08:04 | CaptainLex | jeaye: I guess the first thing that springs to mind is the real file path you're trying might not exist or it may be malformed |
| 08:04 | CaptainLex | jeaye: It seems like the kind of error that could be caused by a null file |
| 08:04 | CaptainLex | jeaye: What does it output if you use a file you /know/ doesn't exist? |
| 08:06 | jeaye | So, I tried specifying full paths for in and out. It gives me an error saying out must be relative. If I make in absolute and out relative, the same initial error shows. |
| 08:06 | jeaye | CaptainLex: If I specify files that don't exist, the same error comes up. |
| 08:06 | CaptainLex | jeaye: That might be a permissions issue then. Do you own the file you're trying to use, and does boot run as your user? |
| 08:07 | CaptainLex | jeaye: I would expect bo things to be true, but one can never be too careful |
| 08:07 | jeaye | Everything is owned by my user and being run by the same user. |
| 08:12 | CaptainLex | jeaye: Sorry, lost connection. Did I miss anything? |
| 08:13 | jeaye | CaptainLex: Someone in #bootclj has it figured out, I think. |
| 08:13 | jeaye | I'll follow up. |
| 08:13 | CaptainLex | jeaye: Thanks! |
| 08:26 | jeaye | CaptainLex: It wasn't part of the fileset `boot show -f` so minify couldn't find the file. I thought I could run it on arbitrary files, but I can't. |
| 08:26 | jeaye | CaptainLex: If I reference something in the src directories, the error doesn't show up. |
| 08:27 | CaptainLex | jeaye: Aha! Yep, I would have never been able to come up with that one. I'm glad it worked out for you! |
| 08:27 | jeaye | CaptainLex: Thank you! |
| 08:54 | Kamuela | Elixir must be a lisp in the same way that javascript is a lisp |
| 08:55 | Kamuela | because it feels like a basic language with basic syntax to me |
| 08:55 | Kamuela | is “has first-class functions” all it takes? |
| 09:05 | tdammers | IMO neither JS nor Elixir are lisps |
| 09:06 | mpenet | indeed |
| 09:06 | wmealing | elixir is nowhere near a lisp |
| 09:06 | tdammers | defining feature for being a lisp would be s-expressions, and how they are used for both code and data, essentially making code first-class for free |
| 09:06 | mpenet | it's more about the homoiconicity |
| 09:06 | wmealing | there is lisp flavored erlang, dont get me wrong |
| 09:10 | tdammers | there is some heavy lisp influence in both JS and elixir though |
| 09:11 | mpenet | there are just first class functions the rest is pretty common |
| 09:11 | tdammers | first class functions are also pretty common |
| 09:11 | kvtb | question, in ClojureScript, (max nil nil) returns nil, but in Clojure, (max nil nil) gives NullPointerException. How can I ensure (max nil nil) in Clojure returns nil like in ClojureScript? |
| 09:12 | tdammers | lots of details that resemble scheme though - scope, closures, defining functions as lambdas bound to variables, etc. |
| 09:12 | tdammers | (in JS, that is) |
| 09:12 | CaptainLex | kvtb: You could try catching that exception and returning nil, right? |
| 09:14 | kvtb | thanks CaptainLex did not not think of that :) |
| 09:15 | CaptainLex | kvtb: No problem! |
| 09:15 | wmealing1 | i often wonder if we're going to be stuck in js land forever in the browser. |
| 09:16 | wmealing1 | its a little weird. |
| 09:16 | CaptainLex | wmealing1: JS as a target or JS as a high-level language? |
| 09:16 | wmealing1 | js as the target |
| 09:16 | MJB47 | does asm.js count? |
| 09:17 | wmealing1 | it still feels like js |
| 09:17 | CaptainLex | Yeah, I worry about that too. If it works "well enough" then there will be no push to move to something nicer and more efficient |
| 09:17 | CaptainLex | On the other hand, using only JS until every browser agrees on a different standard would be bad for everyone |
| 09:18 | wmealing1 | so, thats it then, we're stuck |
| 09:18 | wmealing1 | i for one welcome our new js overlords. |
| 09:19 | wmealing1 | the browser is going to be around for a long, long time |
| 09:19 | wmealing1 | changing / adding another language is like playing chicken with the user |
| 09:19 | wmealing1 | while i know other things can transpile to javascript |
| 09:20 | mpenet | given that transpiled code often ends up more performant than hand writen code I don't think js is a huge problem anymore |
| 09:20 | tdammers | to be honest, none of the existing compile-to-JS solutions really convince me |
| 09:20 | wmealing1 | it seems that js tends to encourage some neurotic programming. |
| 09:21 | mpenet | at least we have options now |
| 09:21 | wmealing1 | that is true |
| 09:21 | CaptainLex | Yeah, the asynchronicity instead of real multi-threading leads to some really clunky workarounds for really common paradigms |
| 09:21 | CaptainLex | If we can't figure out a patch over that, every JS-targeting language will suffer from it |
| 09:22 | mpenet | this cuold evolve, we didn't have xhr until "recently" |
| 09:22 | mpenet | could* |
| 09:23 | tdammers | frankly, I believe there isn't a compelling reason why JS couldn't be extended to a multi-threaded runtime |
| 09:23 | tdammers | shared-mutable-state multithreading would be problematic due to the assumptions you can currently make, but with decent concurrency semantics, I believe this could be solved |
| 09:24 | tdammers | but you'd have to sandbox the whole threading runtime to avoid rogue JS eating up all the available OS threads |
| 09:24 | tdammers | and given how difficult sandboxing JS already is, ... |
| 09:25 | wmealing1 | on the side note, i really wanted to like elixir, but clojure won me over elixir due to clojurescript |
| 09:25 | wmealing1 | having the same language on both client and server, and one thats not insane.. is nice |
| 09:26 | CaptainLex | wmealing1: Yeah, what sold me on the pairing was shoreleave. Seamlessly sharing data between client and server! A dream come true! |
| 09:26 | tdammers | except that clojure and clojurescript are different enough for it to matter |
| 09:27 | wmealing1 | tdammers: brain context switching from clojure -> clojurescript is easier than elixir -> javascript |
| 09:27 | wmealing1 | i can't fit that in my head |
| 09:27 | tdammers | maybe I'm different that way |
| 09:28 | wmealing1 | (i also need to know C and c++) |
| 09:28 | wmealing1 | and erlang |
| 09:28 | tdammers | ah, hm |
| 09:28 | tdammers | I'm fairly comfortable with C myself, which helps a lot |
| 09:28 | wmealing1 | so ive dropped elixir and erlang.. |
| 09:28 | tdammers | my go-to combo, tentatively, is haskell + js |
| 09:28 | wmealing1 | i thought about learning haskell, it seemed.. to be a language people talk about |
| 09:28 | wmealing1 | but dont get things done in |
| 09:29 | wmealing1 | but again, thats my casual observation |
| 09:29 | tdammers | idk, haskell works fine for me |
| 09:29 | CaptainLex | tdammers: Have you looked into Haskell-y JS languages like Elm or PureScript? |
| 09:29 | tdammers | yeah |
| 09:29 | tdammers | purescript is still on my list |
| 09:29 | tdammers | elm looked promising at first, but I ended up dropping it |
| 09:29 | wmealing1 | tdammers: i'd love for it to "work" for me too.. it looks sane as far as a language goes |
| 09:30 | tdammers | for two reasons; one, it is too simple, and two, it's unstable and the toolchain is a bit brittle |
| 09:30 | wmealing1 | brittle like, unstable ? |
| 09:30 | tdammers | yeah |
| 09:30 | CaptainLex | Unstable like the API keeps changing? |
| 09:30 | tdammers | yes |
| 09:30 | tdammers | the API and the language itself change |
| 09:31 | tdammers | and the toolchain is supposed to deal with it automagically |
| 09:31 | CaptainLex | Ahhhh, yes. So good to play around with, but not to write code you need maintain in |
| 09:31 | CaptainLex | Not yet, anyway |
| 09:31 | tdammers | which is great, but when the toolchain fails to resolve those issues, you have nowhere to start looking |
| 09:31 | tdammers | there was this one thing that cost me several hours to figure out, where they had added a validator for the required package field that pointed at a github repo for the package |
| 09:32 | tdammers | and the default value that the package generator inserted was invalid |
| 09:32 | wmealing1 | ouch |
| 09:32 | tdammers | which is doubly frustrating because I wasn't ever going to publish this package, and it has never been nor will it ever be on github |
| 09:33 | wmealing1 | tdammers: i read that many people complain about debugging in haskell |
| 09:33 | wmealing1 | tdammers: do you use one, or do any ? |
| 09:33 | tdammers | use what, a debugger? |
| 09:33 | wmealing1 | yes |
| 09:33 | tdammers | I don't |
| 09:33 | wmealing1 | ive been tossing up haskell/ocaml on another project |
| 09:34 | tdammers | I don't generally have to do a lot of debugging, most of it is a matter of fixing compiler errors |
| 09:34 | tdammers | the rest I can almost always resolve using automated tests |
| 09:34 | tdammers | haskell shines at automated testing |
| 09:34 | wmealing1 | ok |
| 09:34 | wmealing1 | is there a midje like tool ? |
| 09:35 | sdegutis | Good morning all. |
| 09:35 | sdegutis | Hi there. |
| 09:35 | wmealing1 | if clojure talk happens in here, i'll mute. |
| 09:35 | sdegutis | Haha don't worry about it, we love talking about Haskell in here. |
| 09:35 | tdammers | wmealing1: or head over to #haskell ;) |
| 09:35 | wmealing1 | tdammers: heh |
| 09:36 | sdegutis | Question: What are the valid namespace characters? |
| 09:36 | wmealing1 | tdammers: i was in there for a bit, i felt so many wooshes… listening |
| 09:36 | sdegutis | Is it just alphanumeric plus hyphens? |
| 09:36 | sdegutis | Or can you also use something like % ? |
| 09:36 | tdammers | anyway, there's quickcheck for property tests, hunit for unit and integration tests, and tasty to provide a seamless unified API over them and a bunch of other testing libraries |
| 09:36 | wmealing1 | i'll take a look ! |
| 09:36 | tdammers | so the approach is different from midje, but definitely powerful |
| 09:37 | CaptainLex | sdegutis: I think you can use any identifier-valid character for namespaces, but be careful your OS can find those special characters on the filesystem |
| 09:37 | CaptainLex | sdegutis: But I don't know for sure |
| 09:37 | tdammers | and, again, a lot of the stuff you'd normally do in unit and property tests can be offloaded to the type checker |
| 09:37 | sdegutis | Good morning justin_smith. |
| 09:37 | sdegutis | But this only matters on the machine that is compiling the uberjar for deployment, right? |
| 09:38 | CaptainLex | sdegutis: That sounds about right to me, yeah. But I am not a jvm or systems or Clojure-compilation expert of any kind! |
| 09:38 | wmealing1 | hmm the jvm itself would need to unpack the filepaths |
| 09:38 | wmealing1 | so that could also get wierd |
| 09:39 | tdammers | "which characters are valid in namespaces" is one of those questions where the answer is "if you need to ask, you're doing it wrong" :D |
| 09:39 | tdammers | (like "what is the limit for how many columns I can have in a database table") |
| 09:39 | CaptainLex | Hehehe |
| 09:41 | wmealing1 | tdammers: my favourite is 'how many subdirectories deep does the operating system support' |
| 09:41 | wmealing1 | what.. is someone doing to require that !? |
| 09:42 | tdammers | well, things like sysfs and such might hit the limit at some point |
| 09:42 | wmealing1 | oh this person was -definitely- messing around on ext4 |
| 09:44 | MJB47 | at work we had a node project that couldnt run on windows because the node modules sub directories were too deep |
| 09:44 | MJB47 | was annoying |
| 09:44 | CaptainLex | That's a complex situation, morally |
| 09:44 | CaptainLex | On the one hand, what the hell Microsoft, as usual |
| 09:44 | wmealing1 | running node, or running windows ? |
| 09:44 | CaptainLex | On the other, how many directories deep was it?? |
| 09:45 | MJB47 | idk what the number was |
| 09:45 | MJB47 | but it worked fine on every other OS |
| 09:45 | MJB47 | wasnt a terribly big project |
| 09:46 | TMA | on Windows(R) the PATH_MAX is the problem |
| 09:46 | CaptainLex | PATH_MAX sounds like a problem |
| 09:46 | wmealing1 | you can work around it with relative referencing |
| 09:47 | Glenjamin | unc paths also work around afaik |
| 09:47 | MJB47 | idr how we fixed it |
| 09:47 | wmealing1 | but its annoying |
| 09:47 | wmealing1 | ah |
| 09:47 | MJB47 | everyone used unix systems |
| 09:47 | Glenjamin | npm v3 also made some changes to avoid path lengths |
| 09:47 | MJB47 | except 1 guy |
| 09:48 | wmealing1 | that guy.. |
| 09:48 | MJB47 | ikr |
| 09:54 | sdegutis | Hi. |
| 09:55 | CaptainLex | sdegutis: Hello again! |
| 10:59 | Shayanjm | ping justin_smith |
| 11:47 | sdegutis | Hi. |
| 11:48 | sdegutis | How are you? |
| 12:41 | justin_smith | Shayanjm: hello |
| 12:42 | Shayanjm | ello justin_smith - managed to get the author on skype to help me debug this thing |
| 12:43 | justin_smith | Shayanjm: OK. It's a kafka replacement not a kafka library, right? |
| 12:43 | Shayanjm | justin_smith: It's a kafka library but it uses redis instead of ZK on the consumer side because of scalability/reliability concerns at scale |
| 12:44 | Shayanjm | the producer side publishes messages directly to kafka via the brokers |
| 12:44 | justin_smith | oh I had no idea that was an option... |
| 12:44 | justin_smith | the redis part that is |
| 12:44 | justin_smith | publishing via brokers is totally standard |
| 12:44 | justin_smith | Shayanjm: choosing redis over zookeeper for reliability sounds really sketchy to me |
| 12:45 | Shayanjm | justin_smith: Yeah, I wanted to try it out because it sounded interesting |
| 12:45 | Shayanjm | if you read the readme on the project he has some points about why he made that decision |
| 12:48 | justin_smith | Shayanjm: btw in terms of reliability, out of CAP (where you can pick at most two) redis picks the empty set - it provides none of the three |
| 12:49 | justin_smith | Shayanjm: the amount of data you can lose is bounded by the replication lag |
| 12:50 | justin_smith | Shayanjm: I don't doubt that redis is easier to use and easier to scale, but reliability-wise it isn't even near zookeeper's league |
| 12:52 | amalloy | i bet it's faster though |
| 12:52 | justin_smith | amalloy: I don't doubt it at all - though this is why kafka uses zookeeper for coordination not for messages |
| 12:52 | justin_smith | once you have redis replacing zookeeper, why use kafka even? |
| 12:53 | amalloy | who needs reliability when you're blazing fast |
| 12:53 | justin_smith | amalloy: it makes me cry tears of blood because it's true |
| 12:58 | Shayanjm | justin_smith: got it working, but it's a bit slow |
| 12:58 | Shayanjm | going to see if increasing JVM RAM allocation will help |
| 12:59 | dysfun | anyone want to give me some feedback on this pre-release library please? :) https://github.com/irresponsible/emotional |
| 13:00 | justin_smith | Shayanjm: what is "slow"? I don't know what your domain is, but based on my vanilla kafka usage, if kafka was my speed bottleneck I would have an amazingly performant system. |
| 13:00 | CaptainLex | dysfun: That's a good URL. |
| 13:00 | dysfun | yeah, it is :) |
| 13:00 | justin_smith | haha |
| 13:00 | Shayanjm | justin_smith: it's the way the consumer is built I think |
| 13:00 | dysfun | hadn't really occurred to me haha |
| 13:00 | Shayanjm | at least on his system |
| 13:00 | Shayanjm | it hangs for at least a minute before returning |
| 13:01 | CaptainLex | dysfun: Although assuming your nick is short for dysfunctional, you should figure out how to work that in too |
| 13:01 | Shayanjm | he provides a vagrant build that can be used for testing, so I might test on that to see if its faster |
| 13:01 | dysfun | CaptainLex: it is, but i'm content to leave that out for this one project. there will be others :) |
| 13:01 | justin_smith | Shayanjm: oh wow - so in my usage the consumer doesn't return - I leave a consumer polling for messages (in a go loop or thread) and give it a function to call for each message it gets |
| 13:01 | dysfun | part of me is curious about what is the limit for people being prepared to use your library's name in front of their managers |
| 13:02 | justin_smith | I mean eventually the consumer returns when I forcibly shut it down but that's different |
| 13:02 | dysfun | i mean if you call your library something downright offensive, you're liable to get entire swathes of users refuse to use it |
| 13:02 | Shayanjm | justin_smith: Yeah for right now (testing purposes) I wanted to manually see if I could get the messages and do stuff with them |
| 13:02 | Shayanjm | so I wanted the consumer to sit there, read the messages, and stick them somewhere |
| 13:03 | amalloy | kafka is for throughput, not latency, isn't it? |
| 13:03 | justin_smith | dysfun: (:require [emotional.core :as rational]) |
| 13:03 | dysfun | justin_smith: this is my 'irresponsible clojure organisation', there is no rational |
| 13:03 | justin_smith | amalloy: throughput plus flexible routing with a log doubling as message queue, yes |
| 13:04 | justin_smith | plus reliability |
| 13:04 | justin_smith | Shayanjm: yeah, he has a good point, if latency is more important than throughput kafka might not be your bag, unless you want the other features badly enough that you can cope |
| 13:10 | justin_smith | Shayanjm: you mention that this kafka re-implementation has a rationale in the readme, but I'm not finding it. Is this the right README? https://github.com/gerritjvv/kafka-fast/#kafka-clj |
| 13:10 | Shayanjm | https://github.com/gerritjvv/kafka-fast/#consumer |
| 13:11 | Shayanjm | the readme(s) are a bit weirdly set up |
| 13:12 | justin_smith | Shayanjm: OK, so he choses fast+simple at the expense of reliable |
| 13:13 | Shayanjm | basically, with the assumption that by clustering redis you can approach the reliability of ZK at scale |
| 13:13 | justin_smith | Shayanjm: that bullshit |
| 13:13 | justin_smith | sorry, *that's bullshit |
| 13:13 | Shayanjm | justin_smith: Yeah I don't know enough about ZK to speak intelligently about the approach |
| 13:13 | Shayanjm | but I thought it was interesting that you could use redis + kafka together without them fighting |
| 13:14 | Shayanjm | so i'm poking at it to see how it works |
| 13:14 | Shayanjm | it's basically using redis to store the offsets of each tracked topic |
| 13:14 | justin_smith | Shayanjm: by reliability I mean "knowing your message gets from one end to the other", redis can't offer that... but OK |
| 13:14 | Shayanjm | justin_smith: Yeah I think he means "if one redis instance falls over, you can still guarantee some level of data integrity" |
| 13:14 | justin_smith | so the failure isn't "redis not running" but "silent data loss" |
| 13:15 | dysfun | yay! |
| 13:15 | justin_smith | I mean if continuously available while dropping some messages fits your use case, go for it |
| 13:15 | Shayanjm | yeah that ^^^ I asked him about silent losses earlier and he said "he hasn't seen any with a production deploy of a single redis instance" |
| 13:15 | amalloy | justin_smith: if you use any of the consumers built into kafka you can't actually know that either |
| 13:15 | mgaare | it depends on the semantics your app requires for message processing. |
| 13:16 | mgaare | with Kafka, in the case of zk/redis failure you wouldn't get dropped messages, you'd have messages consumed more than once |
| 13:16 | amalloy | because the consumers ACK the message as soon as they receive it, before your client code can confirm it's acted on the message |
| 13:17 | justin_smith | mgaare: oh, interesting. |
| 13:18 | mgaare | justin_smith: zk (and presumably redis in this alternate implementation) are only storing a given consumer's position in the topic, not any message data. |
| 13:18 | justin_smith | mgaare: of course, yeah - I should have connected those dots |
| 13:18 | justin_smith | I do know about the partitions on disk vs. the coordination on zk |
| 13:19 | mgaare | I don't think you can be reasonably blamed for a mistake here. services written in java and distributed systems both seem to have documentation that obfuscates the basic idea of what's going on - kafka even more so because it's both |
| 13:20 | justin_smith | amalloy: yeah, we end up using zookeeper directly because of this - we get a message via kafka, if the message describes a job to start zookeeper is used to mark the fact that it was started and in case of a system failure another box can pick up the orphaned job |
| 13:20 | Shayanjm | mgaare justin_smith: mgaare is right. redis just holds the offsets on each topic for the consumers |
| 13:20 | Shayanjm | I'd assume that's exactly what zk does |
| 13:20 | amalloy | right. you're just having to rebuild reliability on top of kafka, justin_smith |
| 13:21 | justin_smith | amalloy: right, fair enough. |
| 13:21 | amalloy | which like, yuck, isn't that supposed to be the point |
| 13:21 | amalloy | justin_smith: the workaround i used was to instead disable automatic ACKs, and write consumer offsets to zk myself |
| 13:22 | justin_smith | amalloy: to me distsys is like security - we have a huge number of known was to totally fuck it up, a few heuristics for what works better, and a lot of trying and hoping... |
| 13:22 | justin_smith | amalloy: interesting, I'll have to look into that some time |
| 13:22 | dysfun | justin_smith: pretty much |
| 13:22 | amalloy | i wish hadoop could be described so positively |
| 13:23 | dysfun | yes but it's difficult to even build hadoop, what do you expect? :p |
| 13:24 | justin_smith | oh, reminds me of this tweet from sorenmacbeth yesterday https://twitter.com/sorenmacbeth/status/694679147784765440 |
| 13:24 | mgaare | amalloy: what lib are you using to talk to zk? |
| 13:25 | amalloy | i don't remember. zookeeper-clj or something |
| 13:26 | justin_smith | Shayanjm: so it sounds like this redis for offsets thing might have legs - but I don't see where it would help with data throughput |
| 13:26 | amalloy | justin_smith: not related except that it's an image on twitter: https://twitter.com/HenryHoffman/status/694184106440200192 |
| 13:26 | Shayanjm | I'm still piecing it together myself justin_smith |
| 13:26 | justin_smith | amalloy: yeah, I retweeted that one |
| 13:28 | Shayanjm | I still can't figure out why the fuck it's hanging with 6 background polling threads |
| 13:28 | mgaare | justin_smith Shayanjm: I'd be inclined to look at it from a developer and ops friendliness angle rather than throughput/distributed theory. I think redis is a lot easier to work with than zookeeper for both dev and ops. |
| 13:29 | Shayanjm | mgaare: It could be, but for the most part this library has/is trying to abstract a lot of that away |
| 13:29 | justin_smith | /dev/null has a pretty awesome api |
| 13:29 | justin_smith | really easy to use! |
| 13:29 | justin_smith | :P |
| 13:29 | dysfun | maybe that's why mysql writes too much data there :p |
| 13:31 | amalloy | i think a lot of people doing distributed stuff have zookeeper already |
| 13:31 | justin_smith | amalloy: and if they don't, they'll probably need it soon |
| 13:32 | dysfun | only if they're in the habit of shipping in big use-all-the-things tools |
| 13:45 | justin_smith | dysfun: SELECT 0='banana' http://grimoire.ca/mysql/choose-something-else |
| 13:55 | justin_smith | dysfun: looking at irresponsible/emotional - I never know whether to expect someproject.core to contain "the core" as in the definitions that everything in the project uses vs. the top level functionality a client is looking for |
| 13:55 | dysfun | yup |
| 13:55 | justin_smith | my solution to this is to never have a .core ns |
| 13:55 | dysfun | a blunt instrument, but sure |
| 13:57 | justin_smith | what's the rationale for having one? the fact that lein created one? the fact that clojure has one? |
| 14:01 | amalloy | that many other projects have one |
| 14:01 | dysfun | justin_smith: mostly that single segment namespaces are disapproved of and you need *somewhere* to act as the main point of interaction |
| 14:02 | justin_smith | dysfun: my github group is noisesmith, if I make a new project foo, the top level ns that clients use will be noisesmith.foo |
| 14:02 | dysfun | yeah i thought of that, then though that irresponsible is a long word and i'm lazy |
| 14:02 | justin_smith | if I followed java conventions more closely it would be org.noisesmith.foo |
| 14:02 | justin_smith | haha |
| 14:03 | dysfun | i wish i was joking. i think :) |
| 14:03 | justin_smith | dysfun: in fact this is what lein does for you if you run "lein new irresponsible/emotional" |
| 14:03 | dysfun | well i don't apply the group to all of my things |
| 14:04 | dysfun | things that i don't expect anyone to make use of |
| 14:04 | dysfun | sometimes these get promoted to projects i feel are worth sharing |
| 14:04 | dysfun | this project started off as "wildebeest" heh |
| 14:05 | justin_smith | there's also src/foo/foo.clj if you don't want org in the package name, but I like the java style package names more and more too |
| 14:05 | dysfun | i like minimal |
| 14:05 | justin_smith | but .core isn't minimal, it's just arbitrary |
| 14:06 | dysfun | mostly because i am a bear of little brain and i like to be able to understand my code afterwards |
| 14:06 | dysfun | yes, it's entirely arbitrary. and commonly used |
| 14:06 | justin_smith | dysfun: but we already established .core doesn't provide information - project by project it might be the core definitions other namespaces use, or the top level ns that clients access |
| 14:06 | justin_smith | it doesn't add info, it adds ambiguity |
| 14:07 | dysfun | maybe i can rename it emotional.to-the-core for you |
| 14:07 | justin_smith | haha, sorry, I know everyone uses .core and not just you, so I don't mean to pick on you in particular |
| 14:07 | justin_smith | just giving my case against this convention |
| 14:08 | dysfun | i think i was hoping for something a bit more gripping than conventions |
| 14:08 | amalloy | justin_smith: do you actually own noisesmith.org? pretty sweet website there |
| 14:08 | justin_smith | amalloy: WIP :P |
| 14:08 | justin_smith | amalloy: I had plans, then I got a job |
| 14:09 | hfaafb | did you make it with omnext |
| 14:09 | justin_smith | hfaafb: lol |
| 14:09 | dysfun | that's so web 0.1 |
| 14:09 | ystael | that's my school of web design |
| 14:10 | justin_smith | dysfun: I can't lie, life as a professional clojure dev is pretty awesome. |
| 14:11 | justin_smith | I have other things I could rant about, but they would be so off topic on this forum... |
| 14:11 | dysfun | concur |
| 14:11 | dysfun | although i'm startuping, so i don't get vast quantities of money deposited in my bank account every month |
| 14:15 | spuz | justin_smith, whereabouts are you based? |
| 14:15 | spuz | (just wondering what companies are doing clojure out there) |
| 14:15 | justin_smith | spuz: PDX, if you are a clojure dev who can do frontend looking for work send me a DM |
| 14:16 | spuz | where is PDX? |
| 14:16 | dysfun | you should use my frontend library |
| 14:16 | justin_smith | spuz: out here Walmart, Staples, Puppet are all using clojure, plus many a scrappy startup like mine |
| 14:17 | spuz | 'here' being? |
| 14:17 | justin_smith | spuz: sorry, PDX is the airport code for Portland, Oregon |
| 14:17 | spuz | ah right |
| 14:17 | dysfun | we'll be hiring a clojure developer this year in amsterdam |
| 14:17 | spuz | i'm based in london but it's interesting who else is doing clojure |
| 14:17 | dysfun | i was in london until last month heh |
| 14:18 | dysfun | there are a few clojure-using companies in london, but it's not a common tech yet |
| 14:19 | spuz | nope |
| 14:20 | spuz | am currently brushing up on clojure to apply for a position |
| 14:20 | dysfun | the only way to change that is to use it and build software in it |
| 14:21 | dysfun | i find it a bit miserable how many scala positions there are relative to clojure ones. i wish they were more comparable in popularity |
| 14:25 | dysfun | justin_smith: i've just created a new core.cljc, thought i'd let you know :p |
| 14:25 | justin_smith | haha |
| 14:27 | dysfun | core.clj/core.cljs/core.cljc # core.clj.core.cljs.core |
| 14:28 | justin_smith | lol |
| 14:28 | dysfun | ^{:doc "Because calling a module 'core' annoys justinsmith"} |
| 14:31 | ajb | How would you get a value that is in a 2 level nested map while using another top level value from that map as a key for it? |
| 14:31 | justin_smith | ajb: with get-in |
| 14:31 | ajb | e.g. {:word "foo" {:terms {:foo "testing :bar "more testing"}}} |
| 14:32 | hfaafb | he only has the value |
| 14:32 | ajb | while using :word as the key to access the string "testing |
| 14:32 | hfaafb | oh v0v |
| 14:32 | ajb | v0v? |
| 14:33 | hfaafb | shrug emote |
| 14:34 | justin_smith | ajb: that's not a valid hash-map, what would the actual map look like? |
| 14:34 | ajb | same thing but with the string testing a full string, typo'd and forgot to include the closing quote |
| 14:34 | ajb | so {:word "foo" {:terms {:foo "testing" :bar "more testing"}}} |
| 14:34 | justin_smith | what? |
| 14:34 | clojurebot | what is short for ,(doc ...) |
| 14:35 | amalloy | that doesn't fix the issue ajb |
| 14:35 | justin_smith | that's still not a valid hash map |
| 14:35 | amalloy | {:x 1 2} is not good |
| 14:35 | ajb | OH, sorry, wasn't reading it correctly |
| 14:35 | ajb | so {:word "foo" :terms {:foo "testing" :bar "more testing"}} |
| 14:36 | justin_smith | ,((fn [m] (get-in m [:terms (keyword (:word m))])) {:word "foo" :terms {:foo "testing" :bar "more testing"}}) |
| 14:36 | clojurebot | "testing" |
| 14:36 | justin_smith | I mean I don't know if that helps or not |
| 14:37 | amalloy | also, strongly recommend against using keywords for keys if it means you'll be converting string<=>keyword to look things up. it sounds like your terms are really just strings |
| 14:37 | justin_smith | I would either use a string as the key in the nested map, or use a keyword as val under :word to avoid the silly keyword conversion though |
| 14:37 | justin_smith | exactly |
| 14:37 | justin_smith | keywords are not a magic type for hash map keys |
| 14:38 | ajb | so, just use the string? |
| 14:38 | justin_smith | ,((fn [m] (get-in m [:terms (:word m)])) {:word "foo" :terms {"foo" "testing" :bar "more testing"}}) ; yeah, like this |
| 14:38 | clojurebot | "testing" |
| 14:45 | justin_smith | dysfun: also on my annoyances list, using keywords as keys in maps when you already had data that made sense (especially horrific keywords like :1 ...) |
| 14:46 | dysfun | yeah, there's no accounting for taste |
| 14:46 | dysfun | yes, keywords are cool, but we got over them years ago, not *everything* must be one |
| 14:47 | dysfun | i do like them |
| 14:48 | justin_smith | ,(def annoying-things {:1 (keyword "core cargo culting")}) |
| 14:48 | clojurebot | #'sandbox/annoying-things |
| 14:48 | justin_smith | ,annoying-things |
| 14:48 | clojurebot | {:1 :core cargo culting} |
| 14:48 | amalloy | ,(keyword 1) |
| 14:48 | clojurebot | nil |
| 14:49 | tolstoy | I think that works in ClojureScript (or did at one time). Which caught me "keywording" UUIDs. |
| 14:49 | dysfun | ,'((((unnecessarily :nested)))) |
| 14:49 | clojurebot | ((((unnecessarily :nested)))) |
| 14:49 | justin_smith | tolstoy: in my repl it returns nils |
| 14:50 | justin_smith | tolstoy: for both longs and uuids |
| 14:50 | justin_smith | (in my cljs repl that is) |
| 14:50 | tolstoy | Ah. |
| 14:50 | tolstoy | Maybe it's fixed, now? |
| 14:51 | justin_smith | I mean it doesn't fail, it just happily returns nil |
| 14:51 | clojurebot | Excuse me? |
| 14:51 | tolstoy | Seems like one of the Clojure's allowed it. |
| 14:51 | justin_smith | which would still be a bug |
| 14:51 | justin_smith | depending on how you go on to use the value at least |
| 14:51 | dysfun | ,(-> 1 str keyword) |
| 14:51 | clojurebot | :1 |
| 14:51 | tolstoy | Anyway, apropos of inapproprite keywording, I was keywording UUIDs which mostly worked, until one of them starting with a number. |
| 14:52 | justin_smith | haha, must be an old cljs behavior then |
| 14:52 | tolstoy | Could be. It was a long time ago. |
| 14:52 | dysfun | that's a 10/16 chance. not good odds |
| 14:54 | tolstoy | Hm. Keyword (uuid) in regular clojure works just fine. |
| 14:54 | tolstoy | :17faa74a-c108-4139-aa5e-1e09d8f004b2 |
| 14:54 | justin_smith | tolstoy: happily returns nil, I mean that won't be correct code |
| 14:55 | justin_smith | wait, what clojure version does that? |
| 14:55 | tolstoy | 1.8 |
| 14:55 | justin_smith | ,(keyword (java.util.UUID/randomUUID)) |
| 14:55 | clojurebot | nil |
| 14:55 | justin_smith | tolstoy: citation needed |
| 14:55 | justin_smith | was it actually a keyword? |
| 14:55 | tolstoy | ,(keyword "2") |
| 14:55 | clojurebot | :2 |
| 14:55 | justin_smith | tolstoy: I mean was it actually a uuid? |
| 14:55 | tolstoy | (keyword "17faa74a-c108-4139-aa5e-1e09d8f004b2") |
| 14:55 | tolstoy | ,(keyword "17faa74a-c108-4139-aa5e-1e09d8f004b2") |
| 14:56 | clojurebot | :17faa74a-c108-4139-aa5e-1e09d8f004b2 |
| 14:56 | dysfun | yes, that's a string |
| 14:56 | Bronsa | ,:2/consistency |
| 14:56 | clojurebot | :2/consistency |
| 14:56 | justin_smith | that's not a UUID, that's a string |
| 14:56 | tolstoy | Right. |
| 14:56 | Bronsa | ,:2/3 |
| 14:56 | clojurebot | #<RuntimeException java.lang.RuntimeException: Invalid token: :2/3> |
| 14:56 | dysfun | strings will keywordify quite easily |
| 14:56 | tolstoy | So, keywords can begin with a number? |
| 14:56 | RedNifre | Clojure newbie here. If keywords can be arbitrary strings, why would I use them instead of strings? |
| 14:56 | Bronsa | tolstoy: no pls |
| 14:56 | dysfun | the problem isn't keywords, it's that the keyword function doesn't convert numbers to keywords |
| 14:56 | Bronsa | it's just an accident |
| 14:57 | Bronsa | dysfun: why should it? |
| 14:57 | tolstoy | Bronsa: Right. But it "works" in Clojure, not in ClojureScript? |
| 14:57 | dysfun | Bronsa: i didn't say it should :) |
| 14:57 | Bronsa | tolstoy: a lot of things "work" in clojure, doesn't mean you should use them |
| 14:57 | justin_smith | RedNifre: keywords should be used when the data "stands for itself" and isn't meaningful as a string. |
| 14:57 | justin_smith | RedNifre: if it exists only as a key in a map or a special arg to a function, and you won't need string operations |
| 14:58 | tolstoy | Bronsa: I'm not at all advocating that we should. In fact, I was supporting the idea that not everything should be a keyword by mentioning how I got screwed. |
| 14:58 | justin_smith | RedNifre: also, the keyword function accepts all kinds of crap that isn't valid in keywords, and will generate invalid keywords, it does no validation for correctness |
| 14:59 | Bronsa | tolstoy: sorry, I chimed into the conversation after it had started and I missed that :) |
| 14:59 | justin_smith | ,::1 :P |
| 14:59 | clojurebot | :sandbox/1 |
| 14:59 | Bronsa | :( |
| 14:59 | justin_smith | yeah, it's sad that that works |
| 14:59 | tolstoy | Bronsa: I don't have a CLJS repl handy, but it might actually balk at (keyword "2akjdas"). |
| 15:00 | justin_smith | tolstoy: my cljs repl thinks that is just hunky dory |
| 15:00 | Bronsa | it doesn't |
| 15:01 | justin_smith | ~keyword is gigo |
| 15:01 | clojurebot | You don't have to tell me twice. |
| 15:01 | tolstoy | Okay. Maybe it used to? Anyway, I swear I was bitten using keywords build from the string representation of a UUID. |
| 15:02 | justin_smith | ,(keyword (pr-str #uuid "a02a5e9a-34bf-4175-b0fa-76b5a6597a87")) omgbarf |
| 15:02 | clojurebot | :#uuid "a02a5e9a-34bf-4175-b0fa-76b5a6597a87" |
| 15:02 | RedNifre | justin_smith I'm not sure I understand. I interpreted keywords as values of a global enum, so I'm surprised that you can create them dynamically with the keyword function. When would you turn strings into keywords or create keywords programmatically? |
| 15:03 | justin_smith | RedNifre: people like to do this when consuming json. I actually think this is a terrible idea since many valid json keys are not good keywords, but it's popular to do |
| 15:04 | tolstoy | I bet it's popular because it just looks better in the code. (:id (str->json blob)) |
| 15:04 | justin_smith | RedNifre: my take is that when doing this people are letting aesthetics or an odd sense of convention eclipse common sense |
| 15:05 | dysfun | i actually quite like it, because if the structure has been validated, you can easily query it (keywords as functions) |
| 15:05 | dysfun | but in this case you're free to only choose keywords that make sense |
| 15:06 | RedNifre | I guess it's a good idea if you are sure that the JSON keys can be valid clojure keywords, huh? |
| 15:06 | dysfun | as always, check your input |
| 15:06 | justin_smith | RedNifre: there's room for intellegent developers to disagree there. |
| 15:07 | justin_smith | it's also a bunch of work done for a small benefit, creating a whole mess of keywords which takes more time than parsing the json does, just so you can use one or two of them in pretty code. |
| 15:08 | RedNifre | I'm a clojure beginner so I don't see the problem with turning JSON objects into clojure dictionaries where the keys are keywords, please enlighten me :) |
| 15:08 | dysfun | rage against the machine, justin_smith |
| 15:08 | justin_smith | RedNifre: because there are valid json keys that are not valid clojure keywords, and generating all the keywords takes more time then parsing the json does |
| 15:09 | justin_smith | but like I said, there's room for intelligent developers to disagree here, so whatever |
| 15:09 | tolstoy | RedNifre: For me, anyway, the only problem with keywording json docs is when doing so is more than just a flag on your converter. |
| 15:09 | dysfun | damnit, i was just making popcorn |
| 15:10 | RedNifre | Nah, I agree that it's bad if there are JSON keys that aren't valid keywords. That's why I qualified it "when you are sure" |
| 15:10 | tolstoy | RedNifre: Like undoing CamelCase to camel-case, etc, etc. |
| 15:10 | dysfun | tolstoy: camel-snake-kebab |
| 15:12 | RedNifre | Why does clojure use the dash style instead of camel case? |
| 15:12 | dysfun | because it's easier on the eyes |
| 15:12 | justin_smith | RedNifre: historical reasons, and we think it's more readable |
| 15:13 | tolstoy | IMHO, because it's easier to read, but also because it can. No "infix" notation. |
| 15:13 | tolstoy | foo-bar doesn't mean foo minus bar. |
| 15:13 | dysfun | the range of characters allowed in symbols helps make clojure very readable |
| 15:13 | justin_smith | RedNifre: LISP was originally meant to be a parsed internal representation that programmers would not use directly, so it doesn't really support much syntax |
| 15:14 | justin_smith | and we borrow heavily from that tradition |
| 15:14 | RedNifre | Personally I find it harder to read because the dash looks more like a space than a camel case capital letter does but maybe I just need a font with thicker dashes. |
| 15:14 | justin_smith | RedNifre: or it could be you are used to languages where - is not word-constituent? |
| 15:14 | tolstoy | My issue with CamelCase is its easy to FatFInger. |
| 15:15 | justin_smith | I find it kind of headache-inducing to read |
| 15:15 | justin_smith | it's telling that we don't write that HeadacheInducing |
| 15:15 | dysfun | justin_smith: i use camelcase for protocols and records. feel sick yet? :p |
| 15:16 | justin_smith | dysfun: that's where camelcase is expected |
| 15:16 | justin_smith | dysfun: since you are naming java classes |
| 15:16 | justin_smith | anything else would be annoying actually |
| 15:16 | dysfun | damnit, you're supposed to disapprove |
| 15:16 | RedNifre | (a-b c d-e-f g h) vs (aB c dEF gH) it's easier for me to see that the second list contains 4 things but you're right, it could be a habit. |
| 15:17 | justin_smith | the first one contains 5 things |
| 15:17 | dysfun | except they're rarely two characters long |
| 15:17 | sdegutis | justin_smith: what do you think of this idea? |
| 15:17 | dysfun | real-world example i'm writing just now. PassLocked vs pass-locked |
| 15:18 | sdegutis | (ns myapp.routes.order.orderid%) (defn invoice [request] ...) ;; becomes "/order/:orderid/invoice" |
| 15:19 | sdegutis | Or how about (ns myapp.routes.order) (defn orderid%invoice [request] ...) |
| 15:19 | justin_smith | sdegutis: I don't like it at all! |
| 15:20 | sdegutis | Why not? |
| 15:20 | justin_smith | magic |
| 15:20 | sdegutis | It wouldn't be dynamically found out. It would be, you'd have 'myapp.routes.order in your list of routes, which finds the namespace object and gets the info from that. |
| 15:20 | dysfun | yeah but it's specialcase for things that followed the expected rest routing |
| 15:20 | justin_smith | sdegutis: that's still magic |
| 15:21 | dysfun | and you always get edge cases in real world systems |
| 15:21 | sdegutis | It just feels too repetitive though, to always type (ANY "/order/:orderid/invoice" [request] ...) when I'm already in the myapp.routes.order namespace. |
| 15:21 | justin_smith | would creating the route automatically require? |
| 15:21 | dysfun | i mean if it were a macro i'd be okay with it |
| 15:21 | justin_smith | both yes and no lead to problems |
| 15:21 | sdegutis | justin_smith: nothing is automatically required |
| 15:21 | sdegutis | but yeah I think I see your point |
| 15:22 | dysfun | sdegutis: there is a macro for that in compojure as well, context |
| 15:22 | nkhodyunya | sdegutis: which library is that? |
| 15:22 | dysfun | so it's down to once |
| 15:22 | sdegutis | dysfun: it's more that I don't want the repetition between the namespace and the route path. |
| 15:23 | dysfun | but in my experience it's handy to be able to throw a few isolated handlers into one namespace for organisation |
| 15:23 | dysfun | irrespective of url |
| 15:24 | dysfun | there's a point at which something turns from a library to a framework. i like the former, i grudgingly use the latter |
| 15:24 | justin_smith | sdegutis: in my experience silly things like client aesthetic choices mean that routes change, and I don't want that to have any effect on my code, ideally all info about routes is totally separated from the code itself and I use bidirectional routings to figure out where my endpoints go |
| 15:24 | dysfun | i think it's the point where you invert control |
| 15:25 | sdegutis | justin_smith: good point |
| 15:25 | dysfun | justin_smith: because obviously /node/3456 is a great url! |
| 15:26 | justin_smith | dysfun: ? |
| 15:27 | sdegutis | justin_smith: thanks for helping me see that more clearly, I dunno what's wrong with my judgment today :/ |
| 15:27 | dysfun | aesthetic choices in urls are potentially valid usability concerns |
| 15:28 | justin_smith | dysfun: right, I have a huge respect for that, which is why I want URL structure to be totally decoupled from my code's logic, so that we can swap endpoint names arbitrarily without breaking code |
| 15:29 | justin_smith | names, structure, the whole deal |
| 15:29 | dysfun | 'silly things' was what i was objecting to |
| 15:30 | justin_smith | dysfun: oh, the decoupling is implemented because it could increase usability, but in practice the changes are silly and rarely actually do increase usability, that's just the cynical side coming out |
| 15:31 | dysfun | oh i know, i used to work in marketing and you know what marketing people are like ;) |
| 15:31 | justin_smith | but it is true, I was likely overly dismissive there |
| 15:31 | justin_smith | haha |
| 15:31 | justin_smith | dysfun: my product is a tool for marketers, so :P |
| 15:31 | dysfun | fun fun fun :) |
| 15:31 | dysfun | any of them want to help a struggling startup for free? |
| 15:35 | Shayanjm | justin_smith: I figured it out and this kafka-clj thing is pretty sweet |
| 15:35 | justin_smith | Shayanjm: interesting. |
| 15:35 | Shayanjm | it has some assumptions baked in about how you use kafka (i.e: message frequency) for optimization purposes |
| 15:35 | Shayanjm | but nothing you can't fiddle with |
| 15:36 | Shayanjm | that's why I was experiencing hanging earlier - a few settings regarding message chunking on the consumer end |
| 15:36 | justin_smith | regular kafka has a config for how long you buffere messages to combine then on a topic |
| 15:36 | justin_smith | that's a pretty larg default buffer |
| 15:37 | justin_smith | is it configured by size or time? |
| 15:37 | Shayanjm | Size with a timeout I believe |
| 15:37 | Shayanjm | so if it doesn't hit size x by time y it still fires off |
| 15:38 | Shayanjm | it's # of messages on 'size'. It basically accumulates messages and delivers them in chunks as 'work-units' |
| 15:39 | Shayanjm | The default out of the box is 100k messages to be consumed per 'work unit' |
| 15:39 | justin_smith | woah |
| 15:39 | Shayanjm | yeah, I think the author was assuming you don't batch inside the messages |
| 15:40 | Shayanjm | so each "message" is a basic record |
| 15:41 | Shayanjm | but you can change that in the consumer config, I just set it to 1 for testing purposes. Fired off two messages and could iterate over a lazy-seq to find them |
| 16:08 | zipper | Hey a good resource for learning clojure coming from haskell? |
| 16:08 | justin_smith | zipper: Joy of Clojure is good, as is Clojure Applied |
| 16:08 | justin_smith | zipper: once you grok the non-syntax it should come pretty easily |
| 16:08 | zipper | justin_smith: Thanks |
| 16:09 | zipper | non syntax? |
| 16:09 | zipper | You mean like python? |
| 16:09 | justin_smith | zipper: python has a lack of delimiters and a lot of syntax, clojure has a lack of syntax and a lot of delimiters |
| 16:10 | devth__ | not really a clj question, but noticed lein projects follow the convention: why are docs markdown files UPPER_CASE.md ? some gnu convention? |
| 16:10 | justin_smith | zipper: point being that (f arg another-arg) is the structure of just about everything in clojure, with a small set of exceptions that don't take long to learn. |
| 16:11 | justin_smith | sure, we have syntax, but we get as close to not having one as you can get |
| 16:11 | sdegutis | Hi. |
| 16:11 | sdegutis | Is anything shaking? |
| 16:13 | zipper | justin_smith: Okay that's interesting. So delimiters == brackets |
| 16:13 | justin_smith | () {} [] right |
| 16:13 | zipper | justin_smith: It's a lisp :D |
| 16:14 | justin_smith | zipper: right this whole delimiters instead of syntax thing is something we borrow from lisp |
| 16:14 | justin_smith | the origing LISP was meant to be a direct representation of program structure, and not a syntax humans would use, but as we all know usage evolved otherwise |
| 16:15 | justin_smith | so the tradeoff is that due to using delimiters explicitly it is very easy to use and manipulate data literals representing source code, the whole macro thing |
| 16:18 | zipper | I guess after learning clojure reading SICP will be easy :) |
| 16:19 | justin_smith | zipper: in fact people have translated parts of SICP to clojure- but SICP is not especially functional and doesn't expose the interesting parts of clojure |
| 16:20 | seubert | justin_smith: what are the interesting parts |
| 16:20 | seubert | that you're referring to, I mean |
| 16:20 | seubert | that's a broad question :P |
| 16:20 | justin_smith | seubert: using immutable values across multiple threads |
| 16:21 | justin_smith | being able to use persistent data structures where "modification" doesn't alter the original, nor does it require doing a full copy of the original |
| 16:23 | justin_smith | seubert: and pragmatically, if clojure is used well, large code bases where you don't have to deal with "spooky action at a distance" - things that would effect the result of a given function are explicitly visible where the function is defined and used and you don't have to go hunting for magic |
| 16:23 | seubert | I see |
| 16:23 | sdegutis | 3spooky5me |
| 16:34 | justin_smith | sdegutis: you have been spooked by a spoopy clojure, :DOOT |
| 16:34 | sdegutis | :D |
| 16:36 | sarcher | Is clojure well suited for writing code that reads from / writes to sockets? |
| 16:37 | justin_smith | sarcher: we've got some good libs for it |
| 16:37 | sarcher | I've dabbled in clojure from time to time, but it hasn't "stuck" yet. |
| 16:38 | justin_smith | eg. ztellman's gloss for packing data into streams of bytes, and manifold for pushing those streams around |
| 16:38 | sarcher | I haven't had the aha moment. |
| 16:38 | justin_smith | OK |
| 16:38 | justin_smith | sarcher: what have you wanted to do with raw sockets in clojure? |
| 16:38 | sarcher | I work for a company that has a socket-based API for real time data. |
| 16:39 | sarcher | I'd like to write a consumer that receives that data, maintains state based on it, and ultimately displays it on a web page. |
| 16:39 | rhg135 | even plain interop isn't too bad if not doing nio |
| 16:39 | sarcher | I have a working version written in node, but i'd like to implement with clojure to learn more about the language. |
| 16:40 | sarcher | Technically written in javascript on node. |
| 16:40 | justin_smith | so two node instances communicating over sockets? |
| 16:41 | sarcher | Something like that, yes |
| 16:56 | sdegutis | ,(let [[a b :as c] nil] [a b c]) |
| 16:56 | clojurebot | [nil nil nil] |
| 16:58 | noncom|2 | i am creating a 1-page app with clj+cljs and i have the "#/page" style nav in the app. ok, now i want to send notifications to users which have links to access a specific "#/page/1234-some-id-1233" how do i do this? |
| 17:00 | noncom|2 | if i just give them regular link, like "http://address/page/id" then the rest of the in-app nav goes crazy with "http://address/page/id/#/the-rest-of-the-nav-system-is-now-here" instead of "http://address/#/the-correct-nav-behavior" |
| 17:08 | justin_smith | noncom|2: link to http://address#/page/id |
| 17:11 | noncom|2 | yes, probably you are right.. i have to rewrite page allowance mechanism to allow this |
| 17:14 | noncom|2 | justin_smith: hmmm for some reason the reagent.session does not recognize the page.. it says the page is nil, though i have "/invitation/:id" in the routes now |
| 17:15 | justin_smith | noncom|2: are you sure the router is set up to route on the fragment? |
| 17:15 | noncom|2 | it does ok for in-app nav, but simply going to a in-app link from nowhere lands me on page nil which in my app redirects to login |
| 17:17 | noncom|2 | justin_smith: hmmm, well, i have it specified in the routes just the same way as the rest of the routes... |
| 17:18 | noncom|2 | justin_smith: oh, it works |
| 17:18 | noncom|2 | cache problems again! |
| 17:18 | noncom|2 | damn, there seems to be simply NO WAY to ensure that page cache is cleared... |
| 17:19 | noncom|2 | i press the ctrl+f5 for the 5th time and miracously on the 5th time it decicdes to finally clear the cache and rebuild and reload all |
| 17:25 | justin_smith | with figwheel it will push your new code as you save it |
| 17:49 | sdegutis | Hi. |
| 18:16 | sdegutis | justin_smith: what do you think of (for) taking an optional final argument which is executed when the seq is empty and there's nothing to enumerate? |
| 18:16 | sdegutis | (for [user users] (user/email user) ["n/a"]) |
| 18:16 | sdegutis | I don't like this idea but I want to hear what you think. |
| 18:16 | sdegutis | Because who knows, maybe I should like it? |
| 18:27 | arrdem | silly idea. |
| 18:28 | arrdem | for is a lazy/pure sequence comprehension expression. |
| 18:28 | arrdem | "on the first element" "on the nth element" "on the last element" are pretty imperative concepts/states |
| 18:28 | arrdem | no doubt you could do it with CL's for macro, but that macro has very very different goals. |
| 18:35 | CaptainLex | arrdem: I am on the edge of my seat! |
| 18:38 | arrdem | CaptainLex: uh... why? |
| 18:38 | CaptainLex | arrdem: I am waiting for the silly idea! Unless you unveiled before I logged on and you were just explaining it retroactively |
| 18:38 | justin_smith | arrdem: because that's next to "the last element" which he was on before, I think |
| 18:39 | CaptainLex | Ahhhhh okay |
| 18:39 | CaptainLex | I just walked in at the wrong time |
| 19:02 | zoite | hi, i'm trying to use korma to select items in a table but with the were get populated from a loop but it doesn't seem to be making the query right and was checking if anyone could point me in the right direction? http://pastebin.com/tzMnwh9N |
| 19:03 | justin_smith | zoite: map with one arg is probably not what you want here |
| 19:04 | zoite | Ok, sorry I'm new to clojure, what should I be using instead? |
| 19:04 | justin_smith | zoite: noticfe in the dry run that where you should have a parameter vector for the parameterized query you instead have a function, returned by map when it only has one arg |
| 19:04 | justin_smith | zoite: you should provide a second arg to map, the collection it should map across to create your query |
| 19:05 | justin_smith | ,(map inc) |
| 19:05 | clojurebot | #object[clojure.core$map$fn__4781 0x19d34ba0 "clojure.core$map$fn__4781@19d34ba0"] |
| 19:05 | justin_smith | ,(map inc [1 2 2]) |
| 19:05 | clojurebot | (2 3 3) |
| 19:05 | justin_smith | that's the difference |
| 19:05 | zoite | oh ok |
| 19:05 | zoite | I just need to loop over the key/value. originally I tried a for loop but then I learned that doesn't return anything |
| 19:06 | justin_smith | if we were like racket we would have a "beginner mode" where map always needs at least two args :0 |
| 19:06 | amalloy | probably exactly two tbh |
| 19:06 | justin_smith | zoite: for isn't a loop, and it does return something, in fact it is designed for returning lists |
| 19:06 | justin_smith | amalloy: yeah, makes sense |
| 19:06 | zoite | oh |
| 19:07 | justin_smith | zoite: doseq on the other hand, is for side effects and returns nil (but still isn't really a loop) |
| 19:07 | zoite | oops yeah I meant doseq not for |
| 19:07 | justin_smith | right - changing the doseq to for might have been simpler (probably would have given you easier to read code) |
| 19:08 | justin_smith | but map works too if you provide the args needed |
| 19:08 | amalloy | speaking of map int, last night i introduced some clojure guys at work who are doing js at the moment to the beauty of ["1", "23", "10"].map(parseInt) |
| 19:08 | amalloy | if you're not excited enough to run that in your chrome console, the result is [1, NaN, 2] |
| 19:08 | justin_smith | haha, wow |
| 19:09 | justin_smith | what the hell is that even doing? |
| 19:09 | amalloy | make up some more example inputs and try to figure out the pattern |
| 19:11 | amalloy | hint: an exciting slight change to the input: ["1", "23", "10", "112233445566"].map(parseInt) // [1, NaN, 2, 44] |
| 19:11 | hfaafb | :D |
| 19:12 | justin_smith | I'm still not seeing it, sorry... |
| 19:14 | amalloy | well, it's a puzzle! i can't give out spoilers |
| 19:17 | hyPiRion | amalloy: oh, that is just plain evil |
| 19:17 | amalloy | hyPiRion: my posing the puzzle is evil, or you found the answer and it's evil? |
| 19:18 | hyPiRion | amalloy: the answer |
| 19:18 | amalloy | srsly |
| 19:24 | zoite | justin_smith: I tried changing it to use 'for' but it's giving back clojure.lang.LazySeq, not sure how to get past that http://pastebin.com/vjhE86j0 sorry |
| 19:25 | hiredman | zoite: you are creating a collection of things, and the dsl just doesn't know how to handle a collecction of things like that, so it doesn't matter how you create the collection |
| 19:25 | sdegutis | arrdem: good point |
| 19:25 | justin_smith | zoite: you changed a couple of things there I think - wasn't there an "and" before? also ((first x) [like (second x)]) is not likely to return anything useful |
| 19:25 | zoite | hiredman: oh, so it's not going to work? |
| 19:25 | zoite | justin_smith: ya, I added in the and and it just gave back: "SELECT `test`.* FROM `test` WHERE ((NULL, NULL))" |
| 19:26 | sdegutis | Datomic is so cool. |
| 19:26 | hiredman | if you look at your previous usage of the dsl, when you pass literal things to the dsl (and {...} {...}) you are not passing a collection of maps |
| 19:27 | zoite | well i'm trying to turn the loop into how I ran it manually, just not sure how to do it |
| 19:27 | hiredman | you need whatever the dsls version of 'apply' is |
| 19:29 | zoite | i'm looking through the documentation but I don't think it has one |
| 19:37 | rhg135 | does lein trampoline not start nrepl? |
| 19:45 | justin_smith | rhg135: I don't think it does, no, with nrepl you need the two jvms, client and server |
| 19:46 | justin_smith | err... wait no it's saying nrepl in the boot splash |
| 19:47 | rhg135 | yeah... that's what confuses me |
| 19:47 | justin_smith | but also it seems not to have opened a port |
| 19:47 | justin_smith | so that part of the splash is lying? |
| 19:47 | rhg135 | exactly |
| 19:48 | justin_smith | rhg135: lein trampoline repl :headless opens a port and then provides no repl, as expected |
| 19:48 | justin_smith | (I mean you would get a repl on that port, but not in that terminal) |
| 19:49 | rhg135 | oh cool then, thx |
| 19:49 | rhg135 | this should be documented somewhere |
| 19:50 | justin_smith | rhg135: yes, it should |
| 19:54 | rhg135 | meh, I prefer to launch a client even if it takes much longer |
| 19:59 | rhg135 | justin_smith: the part that's strange is what is it doing normally? afaik you can't use nrepl without a server. |
| 19:59 | rhg135 | the splash is a lie |
| 20:00 | justin_smith | yeah, I think the splash is a lie |
| 20:00 | justin_smith | rhg135: it would be cool if trampoline repl made it start the server and client, both in the same vm |
| 20:01 | justin_smith | which more closely matches the expected features of both the trampoline prefix and the repl command |
| 20:13 | turbofail | i made a thing in clojurescript |
| 20:13 | turbofail | http://funkenblatt.github.io/coriolis/ |
| 22:28 | marcfontaine | is there a more functional way to write the loop ? https://gist.github.com/marcandrefontaine/103e4d2200e19eb6d5a8 |
| 22:42 | justin_smith | marcfontaine: the only thing I would fix is the dangling parens |
| 22:45 | marcfontaine | justin_smith: oups, thanks. |