This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-09
Channels
- # aleph (4)
- # arachne (3)
- # beginners (41)
- # boot (300)
- # cider (17)
- # cljs-dev (37)
- # cljsjs (4)
- # cljsrn (5)
- # clojure (249)
- # clojure-boston (3)
- # clojure-czech (4)
- # clojure-dev (14)
- # clojure-greece (183)
- # clojure-nl (2)
- # clojure-russia (11)
- # clojure-spec (135)
- # clojure-uk (37)
- # clojurescript (56)
- # community-development (8)
- # cursive (22)
- # data-science (4)
- # datomic (150)
- # devcards (6)
- # emacs (5)
- # euroclojure (8)
- # funcool (18)
- # hoplon (29)
- # immutant (1)
- # jobs (1)
- # lambdaisland (3)
- # lein-figwheel (7)
- # leiningen (18)
- # mount (1)
- # om (81)
- # onyx (95)
- # planck (50)
- # proton (6)
- # re-frame (62)
- # reagent (2)
- # ring (1)
- # robots (1)
- # spacemacs (2)
- # specter (88)
- # test-check (32)
- # untangled (23)
- # yada (1)
@triggernz: clojure.test is built-in to Clojure. Thats what I’d recommend.
I second clojure.test
@triggernz: clojure.test, also org.clojure/test.check and clojure.spec
Looks like an error on 4clojure: this code
((fn [col x]
(vec (vals
(filter #(not= (mod (key %) x) 0) (zipmap (iterate inc 1) col)))))
[1 2 3 4 5 6 7 8] 3)
gives => [1 2 4 5 7 8]
but [8 7 5 4 2 1]
there. Cant pass test because of that. Would be ice to fix 🤓4clojure is running an old version of clojure, between it and the version of clojure you are running your code on, clojure changed how it hashes things, which changed the internal structure of collections based on hashing, which changed the order of their seqs (which was not guaranteed to be in any particular order)
...which was never guaranteed to be in any particular order? ^ @hiredman
-> does not compose functions, it rewrites syntax, the effect can be similar but it is different
usually -> is better (no runtime cost), use comp when you have no other choice, or when it makes more sense (ex xforms)
so if you were in a situation where you needed to take a function as an argument to another function, and you wanted to be able to "compose" different functions to form the argument, and had a choice between -> and comp, you would have to use comp?
you'd want the behavior to be composed, so a person can press both w and d at the same time to go up and right at the same time
if you want to let the user change the keybindings on the fly, you'd have to use comp?
I use to teach the -> functions with drawings full of arrows moving stuff around, it's easier to understand
well you need a function, then the way you get to that doesn't really matter, but comp is one of the most obvious choices
so to take what you said earlier, -> would be better for that too, unless you needed to be able to compose an uncertain number of transducers in an uncertain order at runtime
srry computer crashed, the error message is "don't know how to create ISeq from: clojure.core%partial%fn_4759"
no, but if the namespace is compiled as a class, then that function will be the main function of the class
Hey... I've been very pleased with clojure.spec, which looks absolutely fantastic, and a nice step up from plumatic.schema - and I am fully intending to play with it properly (I've only really had time to read the announcement, listen to Rich on the cognicast, and looked at a few examples)... Anyway, one thing I'd really like to do is understand how this fits with JSON schema... Now, clojure.spec is clearly far superior to JSON schema, but it's not used by the javascript community etc... So I was wondering if anyone has thought about how one might be able to build a JSON schema from a clojure.spec. As spec is way more expressive, I'm guessing that to do this you'd have to stick to a subset of spec (and I guess you could probably use clojure.spec to specify that subset)... The basic idea would be to write a super-spec in spec; and output JSON schemas to interoperate with other tooling/libraries in other languages etc... e.g. swagger clients etc.
but obviously from within clojure you'd be able reuse that subset of spec (which generated JSON schemas), and layer ontop the additional expressivity and specs you'd want clojure side.
Sorry - just seen there's a #C1B1BB2Q3 channel - reposting the above there.
Hi All, I have a question about macros…first some background: I have a need to interface with a nodejs library and love clojure so I figured I would give clojurescript a try (I know this is not #C03S1L9DN but my question is more about defmacro in general)
so, I started working with the nodejs library and quickly was annoyed with the callback hell and thought I would take the opportunity to learn a few things I’ve been meaning to pick up like core.async and defmacro
I was inspired by https://github.com/gilbertw1/cljs-asynchronize, but it didnt do quite what I wanted…I figured this was a good opportunity to learn
what I wanted was something as follows: say I had some form with a callback pattern, like (form-with-callback param1 param2 (fn [resp] (do-next-thing resp)))
say my macro is called “syncexec”, so that could become (syncexec (form-with-callback param1 param2 …)), which would evaluate to “resp” from the callback
I more or less got everything working but I ran into somewhat of a chicken-egg problem and I am starting to come to the conclusion that it cant be done, heh
@ghaskins: promise-monad will sort you out nicely
hold on.. i'll give you some reading @ghaskins
ghaskins: I wrote a simple macro to do something similar for jayq back in the days, expands as a sort of "let" form (akin to what "do" notation would look like in haskell): https://github.com/ibdknox/jayq/blob/master/src/jayq/macros.clj#L15-L36
then you could write
(let-deferred
[a (jq/ajax "")
:let [foo "bar"]
:when (= (concat a foo) "foobar")
b (jq/ajax "")]
(merge a b foo))
@ghaskins: http://funcool.github.io/cats/latest/#mlet can be used with a bunch of different promise-monad implementations...
and here's a cljs impl @ghaskins https://github.com/funcool/promesa/blob/1.2.0/src/promesa/monad.cljc
not sure where it's gone in v1.3 though
thank you @mpenet and @mccraigmccraig
I guess for my own learning, it would be interesting to discuss what I ran into if anyone is willing
the basic problem I was having was that I needed to take the passed-in form, replace the ‘…’ with something that closes on a core.async/chan, run the original-form in a go block, and then block on the channel waiting for a response before returning
the problem was I was constantly wrestling between the runtime/compile-time evaluation of the channel
If I deferred the eval deep enough in the form to satisfy the synthesis of the target form, I had trouble extracting the channel I needed to wait for….if I did it early enough to know what to wait for, evaluating the synthesized form became impossible because it seems you cant use references like ‘#object’ in an (eval)
its quite possible that I was simply asking for something that cant easily be expressed in clojure, but I have a gut feeling I just lack the sophistication to pull it off 😉
if i understood what you wanted to do, in clojure you could do this:
(defn syncexec
[f & args]
(let [ch (chan)]
(apply form-with-callback args
#(go (>! ch %)))
(<!! ch)))
and call it (syncexec form-with-callback param1 param2)
to return the result the callback would receiveyou can do nasty stuff and use refs to synchronize them as well i think (but idk how this works in clojurescript)
(defn syncexec
[f & args]
(let [s (atom {:res nil
:ready nil})]
(apply form-with-callback args
#(reset! s {:res %
:ready true}))
(loop [ready (<@U06QXASV8> :ready)]
(if ready
(<@U06QXASV8> :res)
(recur (<@U06QXASV8> :ready))))))
no macros needed as well@caio: ah, that is interesting…i hadnt thought of collapsing the syncexec and form-with-callback
I was running into problems because I could easily process the form to synthesize callbacks where the ‘…’ appeared, but then had trouble actually doing something with it
I'm trying to figure out what's idiomatic for lambdas. I discovered last night that you can't embed a sugary lambda within another sugary lambda #(#()), the interpreter doesn't allow it, so it's less powerful.
Only for very short functions. You can’t nest the shorthand syntax and it is arguably less readable.
noonian: I personally find them less readable if there are arguments so then you have to number your percents. I'm a beginner, so maybe I'll just become used to it. If I never use them in my code, would that be fine?
mhr: Yes it is perfectly okay to never use the shorthand version for anonymous functions 🙂
I'm wondering about the recommendation to not include lein in an application's production host. Does this still make sense if you're building your app in a docker image?
Imho yes. It's also a matter of having less potential for breakage (possibly broken dependencies, unavailable clojars etc)
Leiningen is a development tool. It injects lots of extra stuff: REPL libraries, JVM command-line arguments optimized for startup time over runtime performance.
why
user=> (realized? (iterate inc 0))
true
when iterate "Returns a lazy sequence" and realized? "Returns true if a value has been produced for a promise, delay, future or lazy sequence."
ok I just answered my own question
but what meant was (iterate inc 0) isn't realized
so is there a way to determine if an object is a lazy-sequence ?
blackblock: why do you need to?
is do
the same thing as a lambda
? it says its implemented as a special form, but as far as i can tell it has the same semantics as a normal function call
it's just for combining things together
to "do" sequentially
yeah but you can do that with a lambda, no need for a do special form. it seems redundant
you mean ((fn [] (one thing) (another thing)))?
it's probably special so the compiler can easily not compile it as function calls
let
is redundant in the same way
and probably for the same reason
I don't know of any other
bsima: the reason is probably optimization. do
is trivial, fn
is much more involved, and to optimize away the effort of a fn
that is just there to imitate a do
is significant.
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L5380
is it just because recur
is ambiguous or does it mess it up more than that?
@gfredericks: no reason, just wondered
a large part of the work that optimizing compilers do for scheme (which generally do implement stuff in terms of lambdas) is actually recovering the distinction, lambdas that are invoked immediately and don't escape can be compiled more effeciently
blackblock: a lot of times you should be able to get away with not needing to know
@hiredman: interestingly Compiler.java does the opposite by lifting some loop bodies into fns to help the JVM JIT
@gfredericks: ok but say i did need to know ?
is that why the compiler does that? I just assumed it was to make the compilers job easier
expression semantics for a goto and a bunch of labels is tricky, but if you hoist it out as a function you automatically get it by invoking the function
blackblock: chehcking the class is probably the easiest way; in this case, iterate
used to return a lazy seq, but now it returns an ad-hoc optimized type, so I'm not sure whether the current docstring should be considered accurate
@hiredman: I don't remember the specifics but I remember cgrand talking about it in some JIRA ticket and that was the reason he gave -- I didn't have much trouble in t.e.jvm emitting expr loops w/o wrapping them in once-only fns
it's not much to go on but I remember I did some digging and found a few conversations in the early days of the clojure ML that talked about it
@gfredericks: maybe just seq?
blackblock: no, returns true for lists
er yeh
hrmmm
I think the type hierarchy is complicated enough that there's probably not an objective answer, you have to say what you're trying to do first
user=> (realized? (take 7 (iterate inc 0)))
false
user=> (realized? (iterate inc 0))
true
well i'm interesting in detecting if something's infinite
oh I don't think that's generally possible
hmm vs (cons 1 '(2 3))
ok
(defn goldbach-counterexamples "Returns a lazy seq of positive even integers that can't be expressed as the sum of two primes." [])
⇑ not only would not know whether that's infinite, you wouldn't know how long it would take to realize the first element, if ever
i know (range) is
i know (iterate inc 0)
iss
because of their types
(defn infinite? "Returns :yes, :no, or :dunno" [coll max-runtime])
done.
now if only you could reliably kill jvm threads it'd be easy to write that
what about the types of those things do you think is telling you something about if it is infinite or not?
hiredman: I'd bet clojure.lang.Iterate
is always infinite
well if the object says it's infinite and you cons something on to it
you can infer the result is too
so maybe in certain limited cases it's possible
bronsa: it has a different type
good counterexample
@gfredericks: right, but that's an implementation detail :)
oh god
so you can't rely on checking types ?
of course not
not unless the function makes a promise about the returned type, and I don't think any do
implementations change ok
eh well learned something there thanks!
chapter 4 of http://repository.readscheme.org/ftp/papers/orbit-thesis.pdf is "Closure Analysis" which is about taking all the lambdas in a scheme program and figuring out if they actually need to be function objects, or just stack manipulation or whatever
wait so there's no way for a fn to signal that it will return an infinite sequence ?
(sorry to go on about this)
there is no way to tell the difference between a lazy seq that terminates and one that doesn't besides walking it
no i get that but
isn't there a way that the fn definition can mark itself as returning an infinite seq
no i guess not
wait maybe spec can do that ?
can spec say that about a fn ?
yeh ok metadata
hrmmm
eh ok i'll drop it thanks
some functions will return a infinite seq or a terminating seq based on their arguments
some functions will return seqs based on requesting external resources (http requests or database queries) and their termination or not may depend on what is returned from the external resource
yeh i'm not interested in side effects
or halting problem
only what fns say they are
their being infinite is just one example
could be any quality
it's a question of types really
anyway too vague
Why doesn’t my function take two arguments? I just don’t understand. I suspect I am doing something wrong.