2015-01-11
| 00:00 | rritoch | arrdem: The way I see it, there are potentially an infinite number of possible operators and no language could ever include them all. It may be beneficial to algorithmic thinkers to develop such a capability in an algorithmlic language. |
| 00:01 | rritoch | arrdem: I also believe, based on some proofs provided by a "friend" of mine, that it could provide a higher level of security, since without knowledge of the operators and their implementation, the language could have "perfect secracy". |
| 00:01 | rritoch | arrdem: see http://rosuav.com/1/?id=683 |
| 00:03 | rritoch | arrdem: I don't particularly agree with all his conclusions, but the fact that the same source code can represent multiple different programs is a potential benefit for providing security. |
| 00:06 | rritoch | arrdem: I do agree with one point though. As soon as you make operators that can be changed, source codes no longer contain any information, therefore meeting the condition of perfect secracy. |
| 00:07 | rritoch | arrdem: Though, I"m not sure if that conclusion was in the document I sent, or in personal emails. |
| 00:08 | andyf | rritoch: Reading your original message, are you saying that you are having difficulty parsing a language, because the formal grammar of that language is changing during run time? |
| 00:09 | rritoch | andyf: The grammar itself becomes ambigous is the problem, so either operators need to be replaced with functions prior to parsing or the parser itself needs to consult some algorithm to determine a resolution to those conflicts. |
| 00:10 | andyf | There are parsing algorithms for context-free grammars that can handle ambiguous grammars. I believe Instaparse implements one such algorithm. |
| 00:11 | andyf | But there can still be ambiguity of not knowing what an identifier means during parsing, so you don't even know what kind of token it should be in the parsing process. |
| 00:12 | andyf | If the latter case, then those parsing algorithms I mentioned won't help you. |
| 00:12 | rritoch | andyf: Thanks. I'll take a look at it. The simplest representation of the problem I found is the grammar rule "symbol spaces symbol spaces? semicolon" This could represent a variable declaration or a unary operation. |
| 00:13 | andyf | Lisp using a 'everything is prefix notation, with parentheses around each operator/function, plus its arguments' makes some things easier to parse, certainly. Postfix notation has the same benefit. |
| 00:13 | rritoch | andyf: During parsing the resolution can be provided, the problem is the resolution rules can't be defined by the grammar since they need to be determined algorithmically. |
| 00:14 | rritoch | andyf: Unfortunatly I want to allow multiple inheritance in the language, if that wasn't the case than I'd simply be doing a search/replace, shifting the parenthesis, and sending it to the clojure runtime to handle. |
| 00:14 | arrdem | andyf: working on Grimoire ATM, adding support for platforms (clj, cljs, cljclr etc) |
| 00:14 | andyf | not sure what you mean by a resolution rule there. Do you mean rules for deciding whether a particular 'lexical token' is, say, a number, variable, function, or something else? |
| 00:14 | arrdem | andyf: thoughts on how I should resolve a namespace qualified symbol to documentation in the case of implementations on multiple platforms? |
| 00:15 | andyf | arrdem: Nice. |
| 00:15 | arrdem | I'm thinking that I default to clj, and otherwise "first" wins |
| 00:15 | rritoch | andyf: The parser I'm using, and I believe any LALR parser will report a conflict if it can't resolve an ambiguity on it's own. |
| 00:16 | andyf | LALR parsers are one class of algorithms that handle a subset of context free grammars. There are other algorithms that can handle all context free grammars, even handling ambiguity in those grammars (meaning that the algorithms can produce correct parse trees even if there is more than one parse tree that produces the parsed string). |
| 00:16 | andyf | LALR can't do that, though. |
| 00:17 | arrdem | &(sort ["clj" "cljclr" "cljs"]) |
| 00:17 | lazybot | ⇒ ("clj" "cljclr" "cljs") |
| 00:18 | arrdem | okay well that "just worked" |
| 00:19 | arrdem | aaand now I have to fix my datafiles because I've successuflly upgraded (and broken) all my clients. |
| 00:19 | rritoch | andyf: Thanks, I'll look at instaparse. I wasn't aware that there was anything more advanced than LALR available |
| 00:20 | rritoch | andyf: I simply need to be able to resolve conflicts via a method call from the parser, with that capability the language becomes possible, but I believe it is still computationally expensive. |
| 00:20 | rritoch | andyf: At least during the compilation phase. |
| 00:20 | arrdem | .... shit |
| 00:21 | arrdem | accidental git reset –hard |
| 00:21 | arrdem | there goes my evening |
| 00:21 | arrdem | g'night gents |
| 00:21 | andyf | sorry, have company for a few mins -- will be back soon |
| 00:29 | rritoch | (inc andyf) |
| 00:29 | lazybot | ⇒ 23 |
| 00:30 | ryancole | (inc ryancole) |
| 00:30 | lazybot | You can't adjust your own karma. |
| 00:30 | ryancole | fml |
| 00:31 | rritoch | andyf: I haven't finished reviewing instaparse but from the description I think it is exactly what I need. Using a ambiguous grammer with say 255 recursion depth for operator precidence, and instaparse may solve the problems. |
| 00:34 | rritoch | andyf: Once I figure out exactly how the ambiguity resolution process is implemented. |
| 00:34 | ncthom91 | hey all. What's the customary approach to config files for clojure apps? For example, with javascript, config files are fairly typically a json file. |
| 00:35 | ncthom91 | a clj file? |
| 00:35 | ncthom91 | like project.clj for leinengen? |
| 00:36 | arrdem | ncthom91: do you have a specific platform/app in mind or are you just asking generally |
| 00:36 | ncthom91 | arrdem generally, though I guess I'm thinking about just running a web app that can be configured with a set of rules |
| 00:37 | ncthom91 | basically a web app that can be pinged with post-receive hooks from a git repository, and the rules govern what to do with those events |
| 00:37 | arrdem | ncthom91: TL;DR there is no standard. Everyone I know of rolls their own. |
| 00:37 | ncthom91 | arrdem ah, interesting |
| 00:38 | ncthom91 | arrdem how might I do it with a clj file? I notice leinengen specifies a `defproject` function? |
| 00:40 | arrdem | ncthom91: there is no technique which I will commend with a straight face for loading a configuration from a .clj file. It's not unheard of to eval an arbitrary "config.clj" off of the classpath, or to read some "config.edn" off of the classpath but both have their downsides. |
| 00:41 | ncthom91 | arrdem heh, ok. What approach would you take for my situation? Mind you, I'm *very* new to clojure |
| 00:41 | arrdem | ncthom91: you just want to configure responses to webhooks? |
| 00:41 | ncthom91 | yea basically |
| 00:42 | arrdem | is there some reason you can't write as a dispatch table in your program propper? |
| 00:42 | rritoch | ncthom91: I would suggest putting it on your classpath, in your resources folder, end-users could adjust their classpath to override the provided configuration file. Something like (read-string (slurp (clojure.java.io/reader (.openStream (clojure.java.io/resource "config.clj")))) |
| 00:44 | rritoch | ncthom91: It certainly isn't a best practice, but it is an easy "hack" |
| 00:44 | ncthom91 | rritoch would I then have to eval/parse the clj file? |
| 00:44 | ncthom91 | arrdem yea I guess I just wanted to make a generic server that someone could spin up on their own with a different rule set |
| 00:45 | Lanzafame | Ok feeling like I am missing the obvious solution here. Installing leiningen. It successfully installed to my ~/bin/ folder but the `lein [command]` is only executing from that folder. I have added it to my PATH (.profile), and then run `source .profile`. I just can't get it to execute from any other location? Please point out the stupid mistake I am making... (OS: Ubuntu 12.04 Vagrant VM) |
| 00:45 | arrdem | ncthom91: then having an EDN file that specifies finite configurations would be my suggestion rather than having a full "configuration program" which is what rritoch's proposal allows. |
| 00:45 | arrdem | Lanzafame: what's `echo $PATH` come out too for you? |
| 00:46 | rritoch | ncthom91: No, you only need to eval if your configuration file is a clojure form, if it is just data, like { :key "val" ...} than read-string will return a map. |
| 00:47 | arrdem | having read-eval'd the string, which allows arbitrary code execution |
| 00:47 | Lanzafame | "/home/vagrant/.rvm/gems/ruby-2.1.3/bin:/home/vagrant/.rvm/gems/ruby-2.1.3@global/bin:/home/vagrant/.rvm/rubies/ruby-2.1.3/bin:/home/vagrant/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/vagrant_ruby/bin:/home/vagrant/.rvm/bin:/home/vagrant/.rvm/bin:/home/vagrant/bin/leiningen" |
| 00:47 | arrdem | use tools.reader if you want a "safe" reader |
| 00:48 | arrdem | Lanzafame: you don't have to add the file ~/bin/leiningen to your path |
| 00:48 | arrdem | Lanzafame: otherwise that looks fine... |
| 00:48 | ncthom91 | rritoch interesting thanks |
| 00:48 | ncthom91 | arrdem do you knwo of any examples of writing/reading edn files? |
| 00:49 | Lanzafame | arrdem I didn't... Should I remove it? |
| 00:49 | arrdem | ncthom91: for various (bad) reasons we don't have a "print-edn" operation, however pr-str is equivalent most™ of the time |
| 00:50 | arrdem | ncthom91: you can use clojure.edn/read-string, but pr-str is the only way to "write" edn |
| 00:50 | arrdem | $grim clojure.edn/read-string |
| 00:50 | lazybot | http://grimoire.arrdem.com/1.6.0/clojure.edn/read-string |
| 00:50 | rritoch | ncthom91: Just remember to close the stream when your done with it. The exact code I provided is a memory leak. |
| 00:52 | rritoch | ncthom91: I use similar code in my project.clj files to load my repository lists from a configuration file in my home directory. |
| 00:53 | rritoch | ncthom91: So in my case the memory leak isn't a problem since the code is only executed during compilation |
| 00:54 | ncthom91 | rritoch cool, ok |
| 01:17 | rritoch | andyf: It looks like I need to continue looking for a better parser. Instaparse is certainly better than what I'm using. I especially like the look-ahead features, but it trades processing time for memory usage (via the parses function) which with a highly ambiguous recursive structure it would only take a small source code to exhaust all memory resources. |
| 01:17 | Lanzafame | arrdem Solution: Uninstall from ~/bin/ and install in /usr/local/bin/... Contrary to the leiningen install docs, but that is life aye :) |
| 01:18 | arrdem | Lanzafame: heh best of luck to you |
| 01:19 | rritoch | andyf: What I really need is a LALR that utlizes callbacks to resolve any conflict instead of aborting the parse. |
| 01:19 | Lanzafame | arrdem thanks |
| 01:31 | rritoch | I get the feeling I have just entered a bottomless pit. This all started with the need for a dynamic language, which brought me to lisp. The need for more features and preference for algorithmic syntax brought me to compiler design, not even the existing parsers provide the features I need. I suspect I should quit the project now before I end up having to design a new processor on an ASIC. |
| 01:55 | dagda1_ | If I am returnign a lazy-seq here https://gist.github.com/dagda1/d99bf42f31e99ae3b07c is it possible to loop..recur lazily over the list or how do I avoid eager evaluation |
| 01:56 | dagda1_ | will calling (rest se) on the lazy seq mean the whole thing is evaluated? |
| 02:08 | tomjack | (seq (rest s)) is, I believe, (next s) |
| 02:09 | tomjack | and it won't realize the whole thing |
| 05:31 | hellofunk | hypothetically what happens if you use pmap to process something in parallel, and then each item in the collection is a collection that is then also processed with pmap, would each thread be spinning off more threads, like a tree? |
| 05:42 | kenrestivo | has anyone else besides me tried to get core.async and swing to work together, and run into what appear to be eventqueue deadlocks? |
| 05:43 | kenrestivo | j.u.c.locks.LockSupport.park() is used by awt, it seems. |
| 05:45 | kenrestivo | and all this breaks only on a single-cpu machine. on a multi-core machine, everyting works perfectly. |
| 06:23 | hellofunk | amalloy: rather enjoying reading through the flatland utilities. cool stuff |
| 07:05 | jonathanj | i don't understand gen-class |
| 07:06 | jonathanj | (ns foo.Bar (:gen-class :extends java.io.InputStream :main false)) |
| 07:06 | jonathanj | how do i use this foo.Bar thing i've supposedly defined? |
| 07:09 | cljsn00b | when I turn this into a def, the javascript generated by cljs crashes in node: (defn published [] (pub output #(get % "channel"))) any idea what could be causing this? |
| 07:51 | AeroNotix | define crashes |
| 07:52 | cljsn00b | (L.b ? L.b(aj) : L.call(null, aj)).call(null, Rh); ^ TypeError: Cannot read property 'call' of null |
| 07:52 | cljsn00b | something indecipherable |
| 08:03 | Biofobico | is (print "test") an expression? |
| 08:04 | AimHere | Yes. It evaluates to 'nil' though |
| 08:04 | AimHere | The side-effect may occasionally be useful |
| 08:05 | Biofobico | (+ 2 2) also an expression right? |
| 08:05 | clojurebot | 4 |
| 08:05 | AimHere | Yes. |
| 08:05 | AeroNotix | Biofobico: it might be easier to ask what isn't an expression |
| 08:06 | Biofobico | so why (do (print "test ") (+ 1 1)) evaluates the print? |
| 08:06 | AeroNotix | Biofobico: what do you think is happening? |
| 08:06 | AimHere | ,(do (print "test") (+ 1 1)) |
| 08:06 | mi6x3m | Biofobico: because print is in the function position |
| 08:06 | clojurebot | test2 |
| 08:06 | AeroNotix | what does do, do? |
| 08:06 | mi6x3m | AeroNotix: do evaluates all of the provided forms |
| 08:06 | mi6x3m | one by one |
| 08:07 | Biofobico | from docs : Evaluates the expressions in order and returns the value of the last. |
| 08:07 | AeroNotix | mi6x3m: I know, duh |
| 08:07 | AeroNotix | mi6x3m: I wanted to guide Biofobico through it instead of just giving them the answer. |
| 08:07 | mi6x3m | AeroNotix: oh :D |
| 08:07 | AimHere | ,(do (+ 100 100) (+ 2 2)) |
| 08:07 | clojurebot | 4 |
| 08:08 | dagda1_ | when I call rest on a lazy seq is the whole thing evaluated or what actually happens? |
| 08:08 | AimHere | ,(rest (range)) |
| 08:08 | clojurebot | (1 2 3 4 5 ...) |
| 08:09 | AeroNotix | ,(class (rest (range))) |
| 08:09 | clojurebot | clojure.lang.ChunkedCons |
| 08:09 | dagda1_ | I also see (seq (rest s)) used a lot |
| 08:09 | AeroNotix | (rest '(1)) |
| 08:09 | AeroNotix | ,(rest '(1)) |
| 08:09 | clojurebot | () |
| 08:09 | AeroNotix | ,(seq (rest '(1))) |
| 08:09 | clojurebot | nil |
| 08:10 | AeroNotix | ,(if (rest '(1)) :t :f) |
| 08:10 | clojurebot | :t |
| 08:10 | AeroNotix | ,(if (seq (rest '(1))) :t :f) |
| 08:10 | clojurebot | :f |
| 08:10 | AeroNotix | dagda1_: ^ |
| 08:11 | dagda1_ | what about (recur (rest s)) on a lazy seq? |
| 08:11 | AeroNotix | dagda1_: what about it? |
| 08:11 | AeroNotix | Does it evaluate the lazy seq you mean? |
| 08:12 | dagda1_ | AeroNotix: yes |
| 08:12 | AeroNotix | No, it doesn't. |
| 08:12 | dagda1_ | AeroNotix: that is interesting, |
| 08:16 | Biofobico | so (do (* 2 2) (* 3 3)) returns 9 but (do (print "test ") (+ 2 2)) returns test 4. If do evaluates the expressions in order and returns the value of the last, shouldn't return only 4? |
| 08:16 | Biofobico | sorry if it is a stupid question, but clojure is my first programming language so bear with me please |
| 08:17 | AeroNotix | Biofobico: it does not return test 4 |
| 08:17 | AeroNotix | it prints test and returns 4 |
| 08:18 | AeroNotix | it may look in the repl as if it "returns" test4 but it does not |
| 08:18 | AeroNotix | ,(do (print "test") (+ 2 2)) |
| 08:18 | clojurebot | test4 |
| 08:18 | AeroNotix | ,(+ (do (print "test") (+ 2 2)) 1) |
| 08:18 | clojurebot | test5 |
| 08:18 | AeroNotix | see? |
| 08:19 | AeroNotix | if it "returned" test4 then the + operation would've failed. |
| 08:19 | AeroNotix | ,(def v (do (print "test") (+ 2 2))) |
| 08:19 | clojurebot | test#'sandbox/v |
| 08:19 | AeroNotix | ,v |
| 08:19 | clojurebot | 4 |
| 08:19 | AeroNotix | Biofobico: see^? |
| 08:20 | AeroNotix | the print function has a *side-effect* (very important to understand, go look it up) of sending characters to the screen. |
| 08:21 | Biofobico | thank you |
| 08:21 | Biofobico | understand it now. the repl induced me into error |
| 08:21 | AeroNotix | nw |
| 08:22 | Biofobico | does that *side-effect* is in the docs? |
| 08:22 | Lanzafame | How would I go about sending weather api data from server-side (Clojure) to client-side (ClojureScript)? I use a handler to get the client's ip and process that through geolocation then a weather api to get json formatted data. I want to now send that through? Any help would be appreciated |
| 08:25 | AeroNotix | Lanzafame: send it as the response from the request the client initiated? |
| 08:25 | AeroNotix | Otherwise, if you need a persistent connection and you want to do async communication or something, look into WebSockets. |
| 08:26 | hellofunk | Lanzafame: simple ajax would be straightforward. i use the cljs-ajax library for this type of stuff: https://github.com/JulianBirch/cljs-ajax |
| 08:27 | hellofunk | Lanzafame: websockets are a possiblity but require more overhead to setup and probably aren't needed for your task. |
| 08:28 | Lanzafame | Thanks for the pointers. |
| 08:29 | ticking | I always found websockets to be simpler to set up than ajax :P |
| 08:29 | hellofunk | ticking: are you using http-kit? |
| 08:55 | ticking | hellofunk: yeah |
| 08:57 | ticking_ | hellofunk: there are plenty of helper libs (sente, chord), but doing it by hand takes about 30-200 loc depending on how much bels and whistles you want (calback style or core async) |
| 09:05 | lodin | ,(deftype Foo.bar []) (Foo.bar.) |
| 09:05 | clojurebot | sandbox.Foo.bar |
| 09:06 | lodin | Which version is clojurebot running? |
| 09:06 | lodin | ,(clojure-version) |
| 09:06 | clojurebot | "1.7.0-master-SNAPSHOT" |
| 09:07 | Bronsa | ,(Foo.bar.) |
| 09:07 | clojurebot | #<CompilerException java.lang.ClassNotFoundException: Foo.bar, compiling:(NO_SOURCE_PATH:0:0)> |
| 09:07 | Bronsa | lodin: "Foo.bar" is not a valid class name |
| 09:07 | lodin | Bronsa: You can deftype it. |
| 09:08 | lodin | And you can resolve it. |
| 09:08 | Bronsa | lodin: still not a valid class name |
| 09:08 | lodin | if you use ns-resolve. |
| 09:08 | lodin | Bronsa: Good. :-) |
| 09:14 | hellofunk | ticking: my understanding is that currently http-kit does not support secure websockets (wss:) and thus ajax is the only option if you want to encrypt the transfers. |
| 09:14 | ticking | hellofunk: yes true |
| 09:14 | hellofunk | ticking: which may not matter to most people |
| 09:14 | ticking | hellofunk: yeah its annoying as heck |
| 09:14 | hellofunk | ticking: and websockets without http-kit are pretty much a no-op if i understand correctly, unless you go down a rabbit whole of significant custom engineering on jetty |
| 09:15 | hellofunk | *hole |
| 09:16 | ticking | hellofunk: even with this? https://github.com/sunng87/ring-jetty9-adapter |
| 09:16 | hellofunk | ticking: oh i haven't tried that, but remember reading about it. there are so few people actually using it, so made me nervous to dependon it |
| 09:17 | ticking | seems reasonably maintained though |
| 09:17 | hellofunk | ticking: i wonder if secure sockets are available with that |
| 09:18 | ticking | hellofunk: I'm not sure how capable aleph is with wss but it's a very nice lib |
| 09:18 | ticking | https://github.com/ztellman/aleph |
| 09:18 | ticking | hellofunk: yeah, might work out of the box but I'm not sure |
| 09:19 | hellofunk | ticking: do you have other reasons for preferring/using http-kit besides websockets? |
| 09:21 | cljsn00b | is there a way to make function calls partial by default? |
| 09:22 | cljsn00b | or is that a terrible idea? |
| 09:22 | hellofunk | cljsn00b: what do you mean "partial by default" ? |
| 09:23 | cljsn00b | ((partial + 1) 1) |
| 09:23 | opqdonut | like (#(+ %1 %2 %3) 7) would return a function taking two arguments |
| 09:23 | opqdonut | I think it'd be a pain in the ass when coupled with lack of typing |
| 09:23 | ticking | hellofunk: there has been some interesting discussions on this lately, ztellman (the guy behind lamina and aleph and a pretty smart guy) argued against it (when using websocket) because it lacks the ability to produce backpressure on connections https://groups.google.com/forum/#!msg/clojure/TVMQJwaij1U/ikNVo-58WggJ |
| 09:23 | arrdem | opqdonut: no we don't have currying. what you just typed would apply a function of three arguments with one argument. |
| 09:24 | opqdonut | arrdem: I know, see cljsn00b's question |
| 09:24 | arrdem | Ah. |
| 09:24 | opqdonut | also, due to how clojure is implemented on the jvm, it would cause lots of unnecessary closures that would need new optimizations to disappear |
| 09:25 | razum2um | opqdonut: but still, what's the "pain in the ass" if such will exist? |
| 09:25 | ticking | cljsn00b: you can build a macro that produces curryable functions, but that creates speciall functiosn that always call partial with not enough args and be pretty confusing, so yeah it's possible in a proof of concept scenatio |
| 09:25 | opqdonut | razum2um: weird errors because you made a typo / forgot one argument 3 levels up the stack |
| 09:25 | cljsn00b | ticking: alright |
| 09:25 | arrdem | yeah odds are you'll just increase source to sink distances :c |
| 09:26 | hellofunk | ticking: i've always found sockets a bit unstable, i wonder if it's just me. lot of people love them. even the figwheel stuff which is cool when it works often hangs for me with socket errors. at least ajax is an old and dependable technique |
| 09:26 | ticking | hellofunk: yeah, if it works for you use it :D |
| 09:27 | hellofunk | ticking: that thread you linked to is all greek to me. i don't know what backpressure is nor do i have a deep understanding of http and server architecture |
| 09:28 | ticking | hellofunk: the idea is, when a consumer can't keep up with the producer of messages, there should be some way to cause the producer to slow down |
| 09:29 | hellofunk | ticking: i see. so if jetty provides a max of 50 simultaneousl requests (because there are about 50 threads in teh pool, one thread per request) and the server has more than 50 requests... hm, i wonder what happens in that case. the requests are tossed out by default unless you have a channel in place somewhere? |
| 09:30 | hellofunk | opqdonut: what FP languages would provide that default currying behavoir? |
| 09:30 | hellofunk | does Haskell maybe do that? |
| 09:30 | opqdonut | hellofunk: haskell & ML languages |
| 09:30 | ticking | hellofunk: haskell |
| 09:30 | hellofunk | interesting i didn't know that |
| 09:31 | opqdonut | once you get used to it, higher-order programming feels rather weird without it |
| 09:31 | hellofunk | opqdonut: so the explicit requirement in clojure to use partial slows you down? |
| 09:31 | ticking | hellofunk: The backpressure thing doesn't work for new connections, but for existing ones if you have a constant stream of data say from a websocket |
| 09:31 | opqdonut | hellofunk: or rather makes the code more verbose |
| 09:31 | nuwanda_ | opqdonut: well, it's way less confusing in a strongly typed language |
| 09:32 | opqdonut | yeah, that's what I said earlier |
| 09:32 | opqdonut | I don't think it would be a good fit for clojure |
| 09:32 | hellofunk | opqdonut: so in Haskell, funcation calls with fewer than required arity actually result in a returned function, otherwise, a returned value from the function |
| 09:32 | opqdonut | hellofunk: yeah |
| 09:32 | opqdonut | hellofunk: also haskell is lazy so the evaluation just works differently in general |
| 09:33 | opqdonut | (graph reduction instead of function calls) |
| 09:33 | hellofunk | opqdonut: that is actually pretty cool. in a sense, a transducer seems to sort of do that, though i realize that's a different application |
| 09:38 | hellofunk | ticking: interesting quote from that thread: "This means that any attempt to use http-kit in conjunction with core.async will be subtly but fundamentally broken" |
| 09:38 | ticking | hrhr yeah |
| 09:39 | hellofunk | "Arguably, even without core.async in the equation it's broken. This is not a good state of affairs." |
| 09:39 | hellofunk | well, tell us how you really feel |
| 09:41 | mavbozo | well, if i'm a author of library that wraps REST api and using http-kit as client, should i use another http client library? |
| 09:48 | hellofunk | mavbozo: unless impossible i'd consider letting your library work with any server the user chooses, jetty or http-kit, etc |
| 09:49 | mavbozo | hellofunk: i'm considering another simpler case, where my library is a wrapper for a http rest api, for example, twitter-rest-api |
| 09:50 | mavbozo | obviously, my library use a http-client library |
| 09:50 | mavbozo | there is a blocking http client--clj-http or non-blocking http-client, like http-kit |
| 09:51 | mavbozo | another quote from that thread "using core.async should be an application-level decision, not one made for you by your libraries" |
| 09:51 | mavbozo | makes me question, should the nature of http-client (blocking/non-blocking) made by me--the author of library, or consumer of my library |
| 09:53 | ticking | I think a lot of people would disagree with that quote though :) |
| 09:54 | hellofunk | mavbozo: i certainly agree |
| 09:54 | tvanhens | Are there any other authentication libraries out there other than friend and buddy? |
| 09:55 | mavbozo | ticking: but it is an interesting challenge for wanna-be library author, such as myself |
| 09:56 | ticking | yeah |
| 09:57 | mavbozo | provide wrapper for a http rest api, but not depend on any http client library and let the consumer of my library choose their own http client to be used by my library |
| 09:58 | lodin | If the library uses core.async and you don't want that in your application code, then you can make blocking wrappers, no? |
| 10:00 | mi6x3m | mavbozo: I am a wanna-be author also, just finishing my first clojure lib :) |
| 10:00 | lodin | Maybe not in the general case. |
| 10:00 | lodin | But for things like http? |
| 10:02 | mavbozo | lodin: maybe the library can provide 2 public function for blocking and non-blocking |
| 10:03 | mavbozo | example, if you want to block use get-block, else get-nonblock |
| 10:03 | lodin | mavbozo: In cases where applicable I'd prefer passing the async output to a function that blocks. |
| 10:04 | lodin | Like I once wrote a chan->seq function that returned when the channel closed. |
| 10:04 | lodin | Or actually, I think it was lazy. |
| 10:04 | hellofunk | ticking: look, Einstein disagreed with Bohr, even though he was wrong to do so. so there. |
| 10:05 | lodin | mavbozo: But the point is that the rest of the code didn't need to care about channels or go blocks. |
| 10:17 | lodin | Is foo_bar illegal as a namespace? |
| 10:18 | dysfun | ,(ns foo_bar) |
| 10:18 | clojurebot | nil |
| 10:18 | dysfun | nope |
| 10:18 | dysfun | not that i'd advise it |
| 10:18 | lodin | I know it works, but that question was about being legal. :-) |
| 10:18 | dysfun | well if it works, it's legal |
| 10:19 | dysfun | but be aware you may enrage your coworkers |
| 10:19 | lodin | dysfun: Scroll up to my conversation with Bronsa about (deftype foo.bar []). |
| 10:19 | dysfun | heh |
| 10:19 | dysfun | again, perfectly legal, and perfectly likely to make your coworkers violent |
| 10:26 | hellofunk | what are clojure's analogs to haskell's fold left and fold right? i assume reduce is foldr? |
| 10:27 | arrdem | yes, reduce is foldr, we have no foldl built in |
| 10:27 | jackhill | dysfun: I'm new to clojure, why would that make people upset? (I assume because it's confusing or difficult to work with, but I'm interested in what way it could be confusing, etc.) |
| 10:27 | arrdem | jackhill: because _ is not part of the "conventional" naming scheme. |
| 10:28 | lodin | jackhill: And in the namespace part of class names "-" is replaced with "_". |
| 10:28 | arrdem | https://github.com/bbatsov/clojure-style-guide#naming |
| 10:29 | jackhill | arrdem, lodin: ah, thank you! |
| 10:30 | lodin | ,(do (in-ns 'foo-bar) (clojure.core/deftype T [])) |
| 10:30 | clojurebot | foo_bar.T |
| 10:34 | lodin | ,(do (ns foo_bar) (deftype T []) (defn T? [x] (= x T)) (foo_bar/T? foo_bar.T)) |
| 10:34 | clojurebot | true |
| 10:34 | lodin | ,(do (ns foo_bar) (deftype T []) (defn T? [x] (= x T)) (ns foo-bar) (deftype T []) (foo_bar/T? foo_bar.T)) |
| 10:34 | clojurebot | false |
| 10:34 | lodin | jackhill: That's confusion. :-) |
| 10:38 | si14_ | oh wow. is it by design? |
| 10:38 | si14_ | https://www.irccloud.com/pastebin/SAfQGrJ6 |
| 10:40 | si14 | seems buggy to me tbh |
| 10:42 | hellofunk | si14: https://clojure.github.io/clojure/clojure.data-api.html#clojure.data/diff |
| 10:43 | si14 | hellofunk: yeah, I've seen that. I don't see how #{} gets converted to nil |
| 10:43 | arrdem | si14: "sets are never subdiffed" |
| 10:44 | si14 | arrdem: there is no "nil" in the second map |
| 10:44 | si14 | "subdiff" is a diff on elements |
| 10:44 | arrdem | &(= #{} nil) |
| 10:44 | lazybot | ⇒ false |
| 10:44 | mavbozo | ,(clojure.data/diff #{1 2 3} #{1 2}) |
| 10:44 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.data> |
| 10:45 | si14 | ,(do (require '[clojure.data]) (clojure.data/diff #{1 2 3} #{1 2})) |
| 10:45 | clojurebot | [#{3} nil #{1 2}] |
| 10:46 | si14 | and "no subdiffing" rule is about this |
| 10:46 | si14 | ,(do (require '[clojure.data]) (clojure.data/diff #{#{1} #{2}} #{#{1 42} #{2}})) |
| 10:46 | clojurebot | [#{#{1}} #{#{1 42}} #{#{2}}] |
| 10:47 | si14 | it didn't subdiff #{1 2}, as stated in docs |
| 10:49 | lodin | sil4: What output would you expect from your pasted example? |
| 10:51 | si14 | (sorry, misplaced /me) |
| 10:53 | lodin | And what do you think about (diff #{1 2 3} #{1 2})? |
| 10:54 | si14 | lodin: there is no items in b that are not in a, so it's fine |
| 10:55 | si14 | lodin: whereas {:foo nil} is actually a *new value* of foo |
| 10:55 | lodin | sil: I think that :foo nil means that "there are no values in (:foo y) that are not in (:foo y)". |
| 10:55 | si14 | ,(do (require '[clojure.data]) (clojure.data/diff {:foo #{[:a :b]}} {:foo #{}})) |
| 10:55 | clojurebot | ({:foo #{[:a :b]}} {:foo nil} nil) |
| 10:55 | si14 | ,(do (require '[clojure.data]) (clojure.data/diff {:foo #{[:a :b]}} {:foo nil})) |
| 10:55 | clojurebot | ({:foo #{[:a :b]}} {:foo nil} nil) |
| 10:56 | si14 | but |
| 10:56 | si14 | &(= #{} nil) |
| 10:56 | lodin | si14: What should (diff #{1 2 3} #{}) return? |
| 10:57 | si14 | lodin: as I said, it returns a thing that is logically sound (there is nothing in b that is not in a) |
| 10:59 | lodin | si14: So there should be a :foo in both elements, because (:foo x) is not equal to (:foo y), right? (Assume (diff x y).) |
| 10:59 | lodin | si14: And there is nothing in (:foo y) that is not in (:foo x), so (:foo y) should be nil, right? |
| 11:00 | si14 | lodin: nope. #{nil} is more correct |
| 11:00 | lodin | (:foo y) for the output, that is. |
| 11:00 | lodin | si14: But there's no nil in (:foo y). |
| 11:00 | si14 | lodin: there is nothing *in the set* that is different |
| 11:01 | si14 | nope, disregard this, I'm wrong |
| 11:02 | lodin | si14: #{nil} would imply that (:foo y) has a nil, and (:foo x) doesn't. |
| 11:03 | si14 | "there is nothing in (:foo y)" can be conveyed by #{} |
| 11:03 | lodin | si14: But that doesn't match how (diff #{1 2} #{}) works. |
| 11:03 | si14 | there is no possible misinterpretation in this case |
| 11:04 | lodin | si14: There is. |
| 11:04 | si14 | lodin: "top-level" difference doesn't match what's done in the "subtree", too, so it's a bad analogy |
| 11:04 | lodin | si14: Try diffing {:foo 3} and {:foo #{}}. |
| 11:05 | si14 | uhm. what's more common — changing value to nil or changing value to empty set? |
| 11:05 | lodin | si14: How do you interpret the output of (diff {:foo 3} {:foo #{}})? |
| 11:08 | si14 | lodin: I see your point. What do you think is more common — {:foo #{1 2 3}} → {:foo nil} (you can't differentiate the two with current behavior) or {:foo 3} → {:foo #{}} (the problem you are pointing at)? |
| 11:08 | si14 | with current model it's a tradeoff, both behaviors are broken, but one breaks more common case |
| 11:12 | lodin | si14: Yeah I know. nils are a problem. Is that what you meant by "changing to nil"? |
| 11:13 | lodin | That is, some value happen to change to nil, and then you don't get a clue from diff? |
| 11:14 | si14 | lodin: yes. "value changes to nil" is way more common than "value suddenly changes type to a set" |
| 11:23 | lodin | si14: What if (diff #{1 2} #{}) returns [#{1 2} nil #{}]? (It would be the same for other containers as well.) |
| 11:24 | hellofunk | if anyone has some thoughts: https://github.com/clojure-emacs/clj-refactor.el/issues/110 |
| 11:26 | mmitchell | anyone here using the Prismatic Schema lib? I'm trying to find the best way to create a "default" instance of a schema |
| 11:26 | arrdem | hellofunk: I'll paste mine if you paste yours |
| 11:28 | si14 | lodin: it will return it then |
| 11:28 | lodin | si14: ? |
| 11:29 | si14 | mmitchell: can you give an example of what you mean? |
| 11:31 | mmitchell | si14: sorry, actually now I realize I'm approaching this wrong. The data will already exist, all I need to do is validate |
| 11:32 | si14 | mmitchell: ah, ok. Good luck with Schema, personally I like it a lot |
| 11:33 | lodin | si14: Wouldn't returning (empty v) disambiguate both cases above? |
| 11:34 | mmitchell | si14: Thanks! And good to know. I use it on a web api project, but it's been a few months since I've touched the code, so now trying to update to the latest schema version, and see what I can do to improve things. All of the code uses the schema records, but I'd like to see if I can get away with just defs |
| 11:34 | si14 | lodin: I believe it would be better |
| 11:34 | si14 | mmitchell: you may also like https://github.com/metosin/ring-swagger to get Swagger (http://swagger.io) integration |
| 11:43 | mmitchell | si14: cool, thanks! |
| 11:45 | mavbozo | sil4: i didn't know about swagger but it looks great |
| 11:45 | mavbozo | (inc sil4) |
| 11:45 | lazybot | ⇒ 1 |
| 11:46 | mmitchell | (inc sil4) |
| 11:46 | lazybot | ⇒ 2 |
| 11:48 | seangrove | dnolen_: May be faster to talk about https://github.com/swannodette/mori/issues/129 here - What about mut.conj_f1, mut.conj_f2 to avoid the extra lookup? It's likely negligible, but I'm not sure there's a downside to it. |
| 11:49 | dnolen_ | seangrove: this not how JS engines work, there isn't going to be an extra lookup |
| 11:50 | seangrove | dnolen_: Ok, wasn't aware of that. Irrelevant then |
| 11:51 | dnolen_ | seangrove: semantically there is a lookup but every major engine optimizes this away |
| 11:51 | seangrove | dnolen_: I had a suspicion, but wasn't sure |
| 11:53 | mavbozo | what are good books to understand more about backpressure? |
| 11:55 | hellofunk | mavbozo: check out #chiropractor |
| 11:55 | arrdem | (dec hellofunk) ;; that was just bad |
| 11:55 | lazybot | ⇒ 0 |
| 11:55 | hellofunk | aw come on |
| 11:56 | hellofunk | (dec arrdem) ;; for no sense of humor |
| 11:56 | lazybot | ⇒ 40 |
| 11:56 | justin_smith | (dec hellofunk) |
| 11:56 | lazybot | ⇒ -1 |
| 11:56 | hellofunk | geez this is a touch crowd |
| 11:56 | arrdem | justin_smith: it's early, not enough coffee and tests are failing for no obvious reason. bite me. |
| 11:56 | hellofunk | *tough. |
| 11:56 | hellofunk | but, i'll be here all night. tips welcome |
| 11:57 | justin_smith | arrdem: err... you need coffee - yed you do |
| 11:57 | mavbozo | (inc hellofunk) |
| 11:57 | lazybot | ⇒ 0 |
| 11:57 | mavbozo | for sense of humor |
| 11:57 | hellofunk | (inc mavbozo) ;; right on |
| 11:57 | lazybot | ⇒ 2 |
| 11:58 | si14 | mavbozo: it's "one", not "L" :) |
| 11:58 | mavbozo | (inc si14) |
| 11:58 | lazybot | ⇒ 1 |
| 12:00 | arrdem | (inc hellofunk) |
| 12:00 | lazybot | ⇒ 1 |
| 12:01 | justin_smith | hellofunk: decs for bad puns are s longstanding tradition, nothing personal |
| 12:03 | hellofunk | justin_smith: well it should be the opposite. :) |
| 12:16 | Kristien | Is there something like a lazy var? With delay I need @ and with memoize I need a call. |
| 12:17 | mmitchell | Anyone know if it's possible to add descriptions to prismatic.schema keys? I thought I saw someone talk about that once |
| 12:18 | dnolen_ | Kristien: there is not |
| 12:18 | Kristien | And Var is final so I guess it's impossible to achieve. :L |
| 12:20 | Kristien | I'll use delay then. Thanks! |
| 12:45 | instilled | hi! how can i chain a vector of fns, e.g. [fn1 fn2 fn2 …] -> (fn1 (fn2 (fn3 …))) |
| 12:47 | justin_smith | instilled: comp |
| 12:47 | justin_smith | ,((apply comp (inc inc inc inc)) 0) |
| 12:47 | instilled | justin_smith: cheers! i couldn't remember what it was called. |
| 12:48 | clojurebot | #<CompilerException clojure.lang.ArityException: Wrong number of args (3) passed to: core/inc--inliner--4221, compiling:(NO_SOURCE_PATH:0:0)> |
| 12:48 | justin_smith | instilled: with a vector you want apply |
| 12:48 | justin_smith | ,((apply comp [inc inc inc inc]) 0) |
| 12:48 | clojurebot | 4 |
| 12:48 | instilled | awesome! thanks a lot/ |
| 13:27 | Kristien | What's the reason case requires constant clauses? |
| 13:27 | seangrove | dnolen_: For iterating over arities in a macro and putting out properties on a defn'd form that'll survive munging, is this the final form you're expecting the cljs side to look like? - e.g. (do (defn my-fn [] (cljs.core/my-fn)) (set! (.-fn1 my-fn) (fn [x] (cljs.core/my-fn x)))) |
| 13:30 | seangrove | Kristien: Maybe you want cond or condp if you don't want constant clauses? |
| 13:30 | Kristien | Yeah. But still. |
| 13:32 | hellofunk | isn't case more or less analogout to "switch" ? |
| 13:32 | hellofunk | *analogous |
| 13:33 | Kristien | Yeah, but I don't see why it shouldn't work on everything that = works on. |
| 13:34 | hellofunk | Kristien: it's a macro, and: "The test-constants are not evaluated. They must be compile-time |
| 13:34 | hellofunk | literals" |
| 13:35 | hellofunk | another key point: "Unlike cond and condp, case does a constant-time dispatch" |
| 13:35 | seangrove | hellofunk: Makes sense, yeah |
| 13:38 | andyf | Kristien: compile-time constants enables case to generate very efficient 'jump tables', effectively, that do not depend on anything at run time other than the value in the first expression of the case. |
| 13:39 | Kristien | With a hypothetical case that uses = you can still do that if you can at compile detect that all cases are constants, which you can. |
| 13:39 | andyf | having variable values to compare to would not permit such an optimization, and in fact different invocations of case could have conflicting branches, e.g. what if two branches of the case had equal values? What would you want to happen then? |
| 13:40 | hiredman | Kristien: is you want to use = use cond or condp |
| 13:40 | hiredman | if |
| 13:41 | hiredman | case is just not for that |
| 13:42 | Gaza | (defn print-hello [nome] (print "Digo olá a " nome) (str "Olá " nome)) . What's the point of print if only the (str "Olá " nome) appears? |
| 13:42 | andyf | I can imagine creating a new construct that is 'between' case and cond/condp that optimizes to what case does if all test values are compile time constants, and behaves like condp with = if they are not. That isn't in Clojure, though. |
| 13:48 | nuwanda_ | Gaza: the (str "Olá" nome) is the return value of the function, the print...prints :) |
| 13:55 | seangrove | dnolen_: Actually, looks like just a normal (do (defn stdFn []...) (goog/exportSymbol "mori.stdFn.fn1" (fn [x] (stdFn x)))) would work well |
| 13:55 | rberdeen | is there a way to skip :prep-tasks for a leiningen task? |
| 13:55 | rberdeen | or some other way to ensure "cljx" always runs before "compile"? |
| 14:20 | Gazaf | (ns test) - what ns stands for here? |
| 14:22 | ticking | namespace |
| 14:22 | ticking | creates a namespace called test |
| 14:22 | Gazaf | thank you |
| 14:22 | ticking | everything below that in a file will be in that namespace |
| 14:24 | Gazaf | is it like a container? like <div id="container">stuff here</div> |
| 14:25 | nuwanda_ | what's your background in other programmming languages? Other analogies are simpler |
| 14:26 | Gazaf | have no background. Only html and css |
| 14:28 | gfredericks | a namespace is a collection of functions |
| 14:28 | gfredericks | a logical grouping |
| 14:30 | Gazaf | so any clojure program must have a namespace in the beginning? |
| 14:30 | gfredericks | more or less, yeah |
| 14:31 | ticking | Gazaf: a clojure program consists of many namespaces |
| 14:31 | ticking | you have one file per namespace usually |
| 14:31 | ticking | and thus a clojure program will consist of many files |
| 14:32 | nuwanda_ | ticking: s/will/may/ |
| 14:32 | nuwanda_ | otherwise it may be a little confusing on the guy :) |
| 14:32 | ticking | yeah |
| 14:35 | Gazaf | say contact.html, blog.html, gallery.html. |
| 14:35 | Gazaf | each one needs to have a namespace |
| 14:36 | Gazaf | is that it? |
| 14:36 | Gazaf | I trying to learn clojure for web dev so I tend to think that way |
| 14:38 | nuwanda_ | Gazaf: generally speaking, yes, each clojure file will declare a namespace |
| 14:47 | Gazaf | thank you. I guess things will became clearly as I dive in the language |
| 15:02 | justin_smith | Gazaf: namesoaces make explici which definitions you are using. This makes code simoler to read, and prevents certain kinds of errors. |
| 15:19 | ssideris | hello, could anyone confirm whether with-redefs has any effect with core.async? I thought it would, but from my experimentation is seems that it doesn't |
| 15:21 | justin_smith | ssideris: depends what you are redef'ing - many things in core.async are special macro markers and not vars you can redef |
| 15:22 | justin_smith | go is a marvelous and frightening beast |
| 15:24 | ssideris | justin_smith: I'm redefing functions that were originally def'ed with defn |
| 15:24 | ssideris | snippets: |
| 15:24 | ssideris | (defn aa [] (log/info 10)) |
| 15:25 | ssideris | (with-redefs [aa (fn [] (log/info 33))] (aa)) |
| 15:25 | ssideris | (with-redefs [aa (fn [] (log/info 33))] (thread (aa))) |
| 15:25 | ssideris | but I see the same behaviour with future: |
| 15:25 | ssideris | (with-redefs [aa (fn [] (log/info 33))] (future (aa))) |
| 15:25 | ssideris | which makes me think it's not core.async |
| 15:26 | chouser | the effect of with-redefs is global, and goes away as soon as flow control leaves the with-redef's block |
| 15:27 | ssideris | chouser: that's what I thought, but in the last snippet I should be getting 33, right? |
| 15:27 | ssideris | I get 10! |
| 15:27 | chouser | you've set up a race condition |
| 15:28 | ssideris | oh the future gets to it first? |
| 15:29 | chouser | apparently your redef is ending before the future fires. You can add a delay to tip the race the other direction. |
| 15:29 | chouser | (with-redefs [aa (fn [] 33)] (let [f (future (aa))] (Thread/sleep 100) f)) |
| 15:30 | ssideris | oh of course, the redef will exit right away |
| 15:31 | chouser | well, the future will also happen "right away", so they're racing. |
| 15:31 | chouser | Various unpredictable things like OS or JVM scheduling, garbage collection, etc. could tip the race either direction, potentially. |
| 15:35 | justin_smith | (inc chouser) |
| 15:35 | lazybot | ⇒ 17 |
| 15:35 | ssideris | sorry, but I'm not sure we your code works (and it does!): there is a delay after we've created the future, so it still starts immediately, right? |
| 15:35 | ssideris | *why |
| 15:36 | chouser | yes, the future happens "immediately" in both your code and mine. |
| 15:37 | ssideris | so how do we avoid the race condition in yours? |
| 15:37 | chouser | Mine delays the end of the redef block for a tenth of a second, which will usually be enough for the future to complete. Then when the redef block finishes, the value of aa goes back to normal. |
| 15:38 | chouser | I am NOT recommending this as a fix or as working code. In fact, just the opposite: this shows how fragile it would be to depend on *either* outcome. |
| 15:39 | chouser | The race condition is there in both expressions, the sleep just handicaps the race in favor of the future. |
| 15:39 | ssideris | ok thanks, I get it now. So the lesson is: make sure the code you're running in with-redefs, blocks for the whole duration for which you need the redefined things |
| 15:40 | chouser | Depending on what you're trying to do, you may consider dynamic vars and 'binding' instead. I believe core.async go blocks capture dynamic value bindings so they may be more predictable. |
| 15:40 | chouser | oh yes, locks are a good way to exchange race conditions for deadlocks. :-) |
| 15:40 | ssideris | I'm using real threads with (thread) |
| 15:41 | ssideris | so I'm not sure if it would work |
| 15:41 | chouser | me either. I haven't played with the combination of dynamic vars, core.async, and real threads. Sounds a bit terrifying, actually. |
| 15:42 | ssideris | I just want to stub out some functions to do a "dry-run" of my code |
| 15:42 | ssideris | do nothing instead of calling an API etc |
| 15:43 | justin_smith | would having the with-redef deref a promise filled in the other thread (at its end of course) be too much of s hack? |
| 15:44 | ssideris | hm, like a signal to block it until everything is done, right? |
| 15:45 | ssideris | it's possible, but it makes my (dry-run) macro way less generic |
| 15:47 | ssideris | but thanks in any case, I understand it now |
| 15:47 | ssideris | (inc chouser) |
| 15:47 | lazybot | ⇒ 18 |
| 15:47 | justin_smith | ssideris: the deref eould ensure thst the with-redef block won't exit until someone delivers to the promise |
| 15:47 | ssideris | (inc justin_smith) |
| 15:47 | lazybot | ⇒ 168 |
| 15:48 | kenrestivo | i can attest that combining core.async with real threads, and with a library that does its own thread management, is... challenging. |
| 15:49 | kenrestivo | actually terrifying is a much better choice of word |
| 15:49 | ssideris | justin_smith: I get it, but it means the prod code would have to handle a promise that wouldn't be there otherwise |
| 15:52 | kenrestivo | actually i've been wrestling with almost a month with a heisenbug deadlock that appears on a single-core ARM but does not appear on a multi-core intel |
| 15:53 | ssideris | I'm only using this as a dev tool to exercise my code, so the solution with sleep is probably ok |
| 15:54 | kenrestivo | when i see code where someone put in a sleep() to deal with a race, i usually run away screaming. |
| 15:55 | kenrestivo | when i've had to do it, it's usually with a comment that says "XXXX HACK FIX THIS" |
| 15:57 | justin_smith | ssideris: a wrapper that takes a function and a promise as args, runs the function, then felivers to the promise |
| 15:58 | justin_smith | *delivers |
| 15:59 | ssideris | justin_smith: just a second, if the function is asynchronous, it will unblock to early, the promise will be delivered too early, and the redef block will exit too early |
| 15:59 | ssideris | which is exactly the same as the original problem |
| 15:59 | SagiCZ1 | how do i imitate while in clojure? some loop that repeats until certain condition is met? |
| 15:59 | SagiCZ1 | maybe while? |
| 15:59 | Bronsa | &(doc while) |
| 15:59 | lazybot | ⇒ "Macro ([test & body]); Repeatedly executes body while test expression is true. Presumes some side-effect will cause test to become false/nil. Returns nil" |
| 16:00 | Bronsa | SagiCZ1: or loop/recur (or even reduce) if you don't need side-effecting |
| 16:00 | SagiCZ1 | thanks bronsa.. is calling a function of some remote api a side effect? probably yes huh |
| 16:08 | justin_smith | ssideris: oh, yeah, you're right |
| 16:17 | hellofunk | justin_smith: what does it mean to store and replay a ring request, i.e. via groundhog? |
| 16:18 | justin_smith | hellofunk: provide the ssme headers and body, to diagnose a bug or be sure it is fixed |
| 16:19 | justin_smith | hellofunk: thanks to the api, unless you have state outside the session driving things, the request should be perfectly replayable |
| 16:20 | justin_smith | *the ring api, that is |
| 16:20 | hellofunk | justin_smith: interesting |
| 16:22 | justin_smith | hellofunk: it was developed as a way to turn backend bug reports into unit tests |
| 16:39 | Bahman | http://www.bahmanm.com/blogs/responsibly-upgraded-your-lisp-machine |
| 16:39 | Bahman | Just to have a bit of fun. |
| 16:39 | Bahman | :-) |
| 17:17 | dnolen_ | seangrove: sounds promising |
| 17:20 | dnolen_ | cfleming: w/ a Maven project how do I setup a REPL? Is it the same as w/ a Cursive Leiningen project? |
| 17:50 | espinho | can anyone point me a good beginner web development tutorial please? |
| 17:51 | espinho | found this book https://pragprog.com/book/dswdcloj/web-development-with-clojure but im unsure if it is a good investment |
| 17:52 | cfleming | dnolen_: Almost, but you should use the "Use normal process" option rather than "Run with Leiningen" |
| 18:05 | dnolen_ | cfleming: ok thanks |
| 18:12 | hellofunk | espinho: check out cemerick's youtube channel for web dev tutorial for beginners |
| 18:13 | hellofunk | $mail espinho espinho: check out cemerick's youtube channel for web dev tutorial for beginners |
| 18:13 | lazybot | Message saved. |
| 18:28 | whodidthis | what's an easy way to execute a postgresql .sql file |
| 18:31 | AeroNotix | whodidthis: try yesql |
| 18:32 | whodidthis | i mean the entire file |
| 18:34 | AeroNotix | whodidthis: you'd just (slurp "/path/to/file") then and pass it to a psql execute call |
| 18:41 | whodidthis | sweet, execute |
| 18:51 | dnolen_ | pondering Google Closure Module support https://gist.github.com/swannodette/0eaf17815d49b7b77a95 |
| 18:51 | dnolen_ | feedback concerns welcome |
| 18:56 | rhg135 | that's cool but having to write code to load your code seems a bit... pointless |
| 18:59 | dnolen_ | rhg135: I don't see what needs to be written here other than ... script tags same as today. |
| 19:00 | dnolen_ | rhg135: if you don't have a large ClojureScript application this isn't for you :) |
| 19:00 | rhg135 | ah, then wouldn't the browser actually do MORE work? multi[le http requests |
| 19:01 | dnolen_ | rhg135: for many applications 2, core & whatever is needed for a sub page. |
| 19:01 | dnolen_ | rhg135: I don't think you've seen a large ClojureScript application |
| 19:01 | dnolen_ | we're talking 140,000+ lines of generated JS |
| 19:01 | dnolen_ | second request isn't going to matter than much |
| 19:01 | dnolen_ | breaking up the build will |
| 19:02 | rhg135 | ah now it makes sense, what clicked for me are multipage apps |
| 19:02 | dnolen_ | rhg135: yep |
| 19:03 | squeedee | David your dedication and sharing rocks man |
| 19:03 | rhg135 | i've only worked on spas so i wouldn't know much |
| 19:05 | squeedee | I wish labs NY would poach you and bring your attitude and skills to getting us out of plain-old-js. |
| 19:13 | ticking | is there a list of reusable om components somewhere? or are there only the three listed on oms website? |
| 19:16 | cfleming | squeedee: Was I imagining a tweet from you asking about Cursive keybindings? I can't find it now. |
| 19:16 | squeedee | I deleted it |
| 19:17 | squeedee | I didnt realise most of its already set up |
| 19:17 | squeedee | fyi we met at conj. I was the Aussie at the unconf about #ifdef |
| 19:18 | cfleming | squeedee: Ok - there's some doc here: https://cursiveclojure.com/userguide/keybindings.html and some explanation that hasn't made it into the doc yet at: https://github.com/cursiveclojure/cursive/issues/552#issuecomment-60475268 |
| 19:18 | squeedee | cfleming: I did throw in a few bindings that made some sense. A little sad that I cant use alt-( |
| 19:18 | cfleming | Yeah, I remember :-) |
| 19:18 | cfleming | squeedee: Yeah, are you using JDK 7+? I think that changed there. |
| 19:18 | squeedee | and alt-shift( and alt{ etc... lots of them dont bind at all (on a mac) |
| 19:18 | squeedee | i don't know to be honest |
| 19:19 | cfleming | It's a JVM problem |
| 19:19 | dnolen_ | gist updated with approach for dealing with avoiding enumeration of all transitive deps thanks to the-kenny, https://gist.github.com/swannodette/0eaf17815d49b7b77a95 |
| 19:19 | squeedee | Yeah looks like i am |
| 19:19 | squeedee | cfleming: wow, thats annoying |
| 19:20 | cfleming | squeedee: IIRC it was to bring Java in line with some Mac UI guidelines, I'd have to dig the link up |
| 19:20 | squeedee | Im sitting in an airport on standby for a flight to SF. 2 weeks in SF, and im going to spend all my spare time getting better at clojure. |
| 19:20 | cfleming | squeedee: But yeah, Java on the Mac is becoming more of a PITA |
| 19:20 | squeedee | cfleming: no big deal. I bound to ctrl instead |
| 19:21 | squeedee | Maybe its how I'll make an argument to buy myself a surface pro 3 :P |
| 19:21 | squeedee | "coz my keybindings dont work" |
| 19:21 | squeedee | my wife will understand |
| 19:21 | squeedee | i need a paredit trainer |
| 19:22 | squeedee | I've had a mac for 4 years now, and I still cant move to the start or end of a line without several false starts first. |
| 19:22 | ticking | ssideris: yeah but a surface has no unix aka most tools will suck |
| 19:23 | ticking | incredible hardware though :( |
| 19:24 | the-kenny | dnolen_: Do I get that right? With 'modules' we could advance-compile some namespaces to file A, some to file B, and some to lib.js and then load lib.js once in a webworker (A) and once in the 'page' (B) without having to export all functions in lib.js explicitly? |
| 19:26 | the-kenny | (and use functions from lib.js in both A and B as if they were included in both) |
| 19:26 | squeedee | ticking I love the digitiser on the surface, it's like having a Cintiq built right in. |
| 19:27 | dnolen_ | the-kenny: in truth everything is actually compiled together as far as I understand. it's one build that can be broken apart. so yes no exporting here. |
| 19:27 | ticking | squeedee: yeah it's really great, but windows development is horrible most of the time unless doing .net |
| 19:27 | squeedee | I havent tried in a while. I got a mac in the end because I was so annoyed with ruby dev in windows |
| 19:28 | ticking | squeedee: I'm not sure how well linux is supported on that thing :( |
| 19:28 | squeedee | I love .net but thats pretty limiting. |
| 19:28 | ticking | yeah |
| 19:28 | squeedee | cygwin was the order of the day back then |
| 19:28 | squeedee | probably still is |
| 19:28 | squeedee | i figure i just need one of each :D |
| 19:29 | squeedee | it's not like I'd throw my macbook away :D |
| 19:29 | the-kenny | dnolen_: so basically it's advance compilation, same shortened identifiers etc., but split into three files. Sounds quite good |
| 19:29 | dnolen_ | the-kenny: yes that's exactly right, same as before you just get to define the split. |
| 19:30 | dnolen_ | the-kenny: should really simplify a lot of patterns w/o futzing w/ multiple builds |
| 19:30 | the-kenny | Yup, I needed exactly that a year ago :) |
| 19:30 | the-kenny | Not so much in our current project, but it might come to it |
| 19:30 | ticking | squeedee: if clojurescript had an eval *cough* one could probably push all development into the browser and thus onto any device |
| 19:30 | dnolen_ | the-kenny: one thing that's hard to cover here is foreign JS libs (non-Closure stuff) |
| 19:30 | squeedee | cfleming: this is what i ended up with: https://docs.google.com/document/d/1yyqDNGLJpzWZyF9SDZmPn_4NskrCrEMJ-Txah3SBOUY/edit?usp=sharing |
| 19:30 | squeedee | scuse the link-of-doom |
| 19:31 | squeedee | i hear both boot and lein work fairly well on windows. cfleming which platform do you do most of your dev on? |
| 19:32 | the-kenny | dnolen_: why is that? Do you want to define different externs for each output? |
| 19:32 | ticking | squeedee: mikera does all development on windows, in a pretty strange maven only environment I think |
| 19:32 | squeedee | maven is yuck :P |
| 19:33 | dnolen_ | the-kenny: in the example you might have "codemirror" as dep for the editor ns |
| 19:33 | ticking | squeedee: yeah but core.matrix is pretty nice |
| 19:33 | dnolen_ | the-kenny: in a single build it's easy to preamble codemirror ourselves, but for modules it's not as simple |
| 19:34 | squeedee | ticking: took me a while to understand the context. :D |
| 19:34 | ticking | hrhr |
| 19:34 | squeedee | i wish this airport had a desk and a 27" second monitor |
| 19:34 | the-kenny | dnolen_: I understand. Tricky :/ Luckily I don't have to rely on external stuff yet. |
| 19:35 | the-kenny | dnolen_: Btw. thank you very much for tackling the tooling stuff for ClojureScript. The last releases were really great |
| 19:35 | squeedee | some people are just really ace eh |
| 19:36 | squeedee | Although, he doesnt have kids. Thats my excuse for being no damn use. |
| 19:37 | dnolen_ | the-kenny: no problem, lot more to do before I'm happy :) |
| 19:37 | the-kenny | haha |
| 19:37 | the-kenny | that's the right way of thinking |
| 19:42 | dnolen_ | the-kenny: actually foreign deps might not be such a problem after all due to CLJS-965 |
| 19:42 | dnolen_ | https://gist.github.com/swannodette/0eaf17815d49b7b77a95 |
| 19:42 | dnolen_ | something to stew on, night all |
| 19:44 | the-kenny | good night, I'm gonna head to bed too. |
| 19:49 | squeedee | I just met a woman at the airport named dijkstra. A lot better looking than the mathematician, and not in slightest bit interested in talking to a nerd about proofs and path finding. |
| 19:52 | AimHere | So much for that strategy for picking up women then |
| 19:56 | cfleming | squeedee: Thanks, I'll take a look. |
| 19:56 | cfleming | squeedee: I do all my dev on a mac. |
| 19:57 | squeedee | Oh I dont know why i got the impression you used windows |
| 19:58 | cfleming | squeedee: No, I switched years ago, after a brief dabble with Linux |
| 20:00 | squeedee | Linux desktop is just infuriating :D |
| 20:06 | cfleming | squeedee: Yeah, although I liked the window management better than any other OS I've tried |
| 20:06 | squeedee | i always liked windows for that (win 7 especially) |
| 20:07 | squeedee | I know a lot of its subjective |
| 20:07 | squeedee | But windows just felt consistant and relatively straight forward. |
| 20:07 | squeedee | Mac only becomes tolerable once you have shift-it or similar installed |
| 20:50 | justin_smith | right now my ui is literally bluetooth keyboard (full sized but very thin) logged into a linux server via a reverse port forward to a vps |
| 20:51 | justin_smith | I could have this UI with any usable OS (currently using a nokia cell phone that came with ssh installed(!)) |
| 20:52 | justin_smith | haha, keyboard is logged in, sic, I guess it just shows which part is most important here usability wise |
| 20:55 | seangrove | Man, struggling with this cljs.analyzer stuff |
| 20:55 | seangrove | Don't seem to be able to get the arity metadata about symbols like I'd expect |
| 20:56 | seangrove | Or rather, :arglists doesn't seem to be present |
| 20:56 | justin_smith | seangrove: isn't js really weird about argument count? |
| 20:56 | justin_smith | dunno if that's actually related or not... |
| 20:56 | seangrove | justin_smith: This should be before it's in js-land |
| 20:56 | seangrove | Still at macro-expansion time |
| 20:57 | justin_smith | ah, never mind then |
| 20:57 | justin_smith | so it's the jvm doing this analysis |
| 20:57 | seangrove | ,(resolve count) |
| 20:57 | seangrove | ,(resolve 'count) |
| 20:57 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.core$count cannot be cast to clojure.lang.Symbol> |
| 20:57 | clojurebot | #'clojure.core/count |
| 20:57 | seangrove | ,(meta (resolve 'concat)) |
| 20:57 | clojurebot | {:ns #<Namespace clojure.core>, :name concat, :added "1.0", :file "clojure/core.clj", :static true, ...} |
| 20:57 | seangrove | ,(:arglists (meta (resolve 'concat))) |
| 20:57 | clojurebot | ([] [x] [x y] [x y & zs]) |
| 20:58 | toxmeister | hi! can i bother you with a macro question? i'm trying to rewrite some array lookups with this macro here: (defmacro foo [buf & body] `(let [b# ~buf] ~@(postwalk-replace {'x '(aget `b# 0)} body))) |
| 20:58 | seangrove | so, I'd expect the cljs.analyzer equivalent to be (:arglists (meta (cljs.analyzer/resolve-var 'concat))) |
| 20:59 | toxmeister | the macro is almost doing it's thing: e.g. (foo buf (+ x x)) results in: (clojure.core/let [b__8468__auto__ buf] (+ (aget (quote b__8467__auto__) 0) (aget (quote b__8467__auto__) 0))) |
| 21:00 | toxmeister | however, how do i get rid of the quoting in the rewritten (aget) ??? i've tried so many things already... |
| 21:00 | seangrove | Ah, ok, looks like it's not in :arglists, it's in a few other places - :method-params looks promising |
| 21:00 | justin_smith | you want b# without the ` |
| 21:01 | justin_smith | you have a bunch of redundant ` in that macro actually |
| 21:01 | justin_smith | you should only need the outermost |
| 21:02 | justin_smith | err - wait, maybe you also want it in that postwalk arg, but not directly on b# that's for sure |
| 21:04 | toxmeister | justin_smith: thx, i know it's not right infront of the b#, but if i remove it i get a compile error... my general confusion is still how to deal with quoting inside a ~@ form.. does my head in every time and so not easy to find systematic docs for this |
| 21:05 | justin_smith | toxmeister: if you need the ` on the postwalk arg, then you need ~b# to get the binding unquoted |
| 21:06 | justin_smith | because ##(do `b#) is not the value you want |
| 21:06 | lazybot | ⇒ b__12184__auto__ |
| 21:06 | justin_smith | you want the thing that resolved to in the let form |
| 21:08 | toxmeister | justin_smith: hmmm... if i put the backquote for the whole aget form like this: (defmacro foo [buf & body] `(let [b# ~buf] ~@(postwalk-replace {'x `(aget b# 0)} body))) ... |
| 21:08 | justin_smith | and of course ##(quote `b#) is not much better |
| 21:08 | lazybot | ⇒ (quote b__12194__auto__) |
| 21:09 | justin_smith | you need to have a ~ before b# if you want to reference that let value |
| 21:10 | toxmeister | justin_smith: if i put a ~ before the b# in the above version it won't even compile |
| 21:28 | gfredericks | toxmeister: you can't use the b# syntax if you're using it across different backtick instances |
| 21:28 | gfredericks | because: |
| 21:28 | gfredericks | ,[`[b# b#] `b# `b#] |
| 21:28 | clojurebot | [[b__25__auto__ b__25__auto__] b__26__auto__ b__27__auto__] |
| 21:29 | gfredericks | ^ they end up being different symbols |
| 21:31 | toxmeister | gfredericks: thanks! i just worked around it via an extra outer let like this: (defmacro foo [buf & body] (let [b (gensym)] `(let [~b ~buf] ~@(postwalk-replace {'x (list 'aget b 0)} body)))) - works at last! :) |
| 21:31 | gfredericks | toxmeister: aw man I just did that too https://www.refheap.com/95992 |
| 21:31 | justin_smith | I find it weird that you would need nested backtics at all... |
| 21:32 | justin_smith | but I don't use macros much, so I could be missing something here |
| 21:32 | gfredericks | well it's inherently code-walking |
| 21:32 | gfredericks | it's not nested backticks in the strictest sense |
| 21:32 | gfredericks | which I've never used in my life because it's scary and I don't understand it |
| 21:33 | toxmeister | gfredericks: hehe - like minds! :) here's to hoping i'll remember that in the future |
| 21:33 | justin_smith | &````````a |
| 21:33 | hellofunk | gfredericks: it is the scary code that is by far the most exciting and inspirational to all of us |
| 21:34 | justin_smith | $ping lazybot |
| 21:34 | gfredericks | ~nested backticks are a code obfuscation technique that can only be used by ztellman |
| 21:34 | clojurebot | Titim gan éirí ort. |
| 21:34 | gfredericks | wait did that work |
| 21:34 | gfredericks | ~nested backticks |
| 21:34 | clojurebot | Huh? |
| 21:34 | gfredericks | ~nested backticks |are| a code obfuscation technique that can only be used by ztellman |
| 21:34 | clojurebot | Alles klar |
| 21:34 | justin_smith | ,```a |
| 21:34 | clojurebot | (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote sandbox/a)))) |
| 21:34 | justin_smith | ,````````````a |
| 21:34 | toxmeister | true words (both @hellofunk & @gfredericks) |
| 21:35 | clojurebot | #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space> |
| 21:35 | justin_smith | oh man, is `````````````````````` a bot dos? |
| 21:35 | hellofunk | now this is some art that is transpiring in here right now! |
| 21:35 | gfredericks | always has been |
| 21:35 | justin_smith | ,``````a |
| 21:35 | clojurebot | (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/seq)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/concat)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/list)) (clojure.core/list (clojure.core/seq #))))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clo... |
| 21:35 | justin_smith | fascinating |
| 21:35 | gfredericks | I've been backticking the bots since aught twelve |
| 21:35 | gfredericks | justin_smith: it's exponential |
| 21:36 | hellofunk | what the heck is going on. this is some quantum entanglement shit going on in here right now |
| 21:36 | gfredericks | bot backticking is like cow tipping |
| 21:36 | justin_smith | gfredericks: when you say that, I picture you in a cowboy hat, with a 3 inch diameter cigar hanging from your mouth "I remember it well, was the big bot roundup of '12..." |
| 21:37 | hellofunk | gfredericks: no it's not: no one has ever actually cow tipped. |
| 21:37 | gfredericks | it's only once a millennium that you get to refer to "aught twelve" |
| 21:38 | hellofunk | believe me i have searched far and wide. it is impossible to actually meet someone who has gone cow tipping. it is a great urban legend. |
| 21:38 | jackjames | greetings. transforming a map's keys: is one of these (or something else entirely) preferable? https://www.refheap.com/95994 |
| 21:39 | gfredericks | jackjames: that second one isn't complete is it? |
| 21:39 | gfredericks | you want an (apply hash-map ...) around it or something? |
| 21:39 | justin_smith | hellofunk: "urban" |
| 21:40 | gfredericks | in any case the first one is what we normally use in absence of a library; I use plumbing.core/map-key |
| 21:40 | gfredericks | map-keys* |
| 21:40 | jackjames | gfredericks: wow, yeah, definitely |
| 21:42 | jackjames | gfredericks: somehow misread the parens for brackets at the repl so i thought it was magically giving me what i wanted. thanks much |
| 21:48 | hellofunk | without starting a lecture series, i'm curious about thoughts on the proper use of eval in clojure code... when where and why? |
| 21:53 | gfredericks | I don't think I've ever used it for production business code; but there are lots of other reasons to write code |
| 21:54 | hellofunk | gfredericks: seeking examples. |
| 21:55 | gfredericks | if you are generating code for some reason, testing that it evaluates to what you think requires eval |
| 21:56 | hellofunk | sure, but i'm interested in the "generating code for some reason" part.... examples of those reasons |
| 21:56 | gfredericks | e.g., maybe you're the strange sort of person who does this in their free time: https://gist.github.com/gfredericks/96e284ce2d52b91d481e |
| 21:57 | hellofunk | gfredericks: rec-lazy-seq looks interesting |
| 21:57 | andyf | hellofunk: I haven't written a lot of Clojure projects, but the only one I can recall that uses eval is Eastwood, a Clojure lint tool, because it needs it (or would not check nearly as much as it does without it). |
| 21:59 | hellofunk | man can someone explain to me like i'm 5 years old what linting is |
| 22:00 | andyf | linting: Look for constructs in programs that might be mistakes, ones that a compiler usually doesn't catch, because the kinds of things caught aren't always mistakes. |
| 22:01 | hellofunk | andyf: i see. i should look at Eastwood to see exactly how one uses that meaningfully, i'm curious |
| 22:20 | justin_smith | hellofunk: linting is good at catching the kind of bugs thst make you facepalm |
| 22:21 | hellofunk | now.. i wonder if it would be too much to ask for an example of the type of bug linting catches? |
| 22:25 | mfikes | hellofunk: Regarding eval, there was a ML thread that appeared to make use of eval to gain a performance benefit in an interesting case: https://groups.google.com/forum/#!searchin/clojure/eval/clojure/mWrZhnFlhxs/RQz88fGeXTUJ |
| 22:31 | hellofunk | mfikes: for performance benefits, related is this macro observation that i've always been a bit curious about: https://gist.github.com/hellofunk/7d424d173125b5dc9640 |
| 22:35 | hellofunk | that is quite an interesting read |
| 22:38 | justin_smith | hellofunk: regarding linting bugs: file name / ns mismatch, wrong arg count, doc string in the wrong place, likely keyword typos |