This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-02
Channels
- # aleph (5)
- # beginners (112)
- # boot (137)
- # cider (10)
- # cljs-dev (36)
- # cljsrn (2)
- # clojure (118)
- # clojure-argentina (1)
- # clojure-berlin (1)
- # clojure-brasil (3)
- # clojure-dev (4)
- # clojure-italy (2)
- # clojure-nl (13)
- # clojure-russia (23)
- # clojure-spec (5)
- # clojure-uk (53)
- # clojurescript (344)
- # clojutre (1)
- # core-async (65)
- # cursive (9)
- # datascript (7)
- # datomic (28)
- # devops (1)
- # emacs (16)
- # events (1)
- # jobs (5)
- # keechma (18)
- # lumo (56)
- # off-topic (7)
- # om (3)
- # onyx (14)
- # protorepl (21)
- # re-frame (3)
- # reagent (20)
- # ring (12)
- # ring-swagger (9)
- # specter (17)
- # unrepl (14)
- # vim (14)
- # yada (22)
one possibility:
(defn my-take [n coll]
(if-not (zero? n)
(when (not (empty? coll))
(cons (first coll) (my-take (dec n) (rest coll))))))
Here's a nother'n:
(defn my-take [n coll]
(when (and (not (zero? n)) (not (empty? coll)))
(cons (first coll) (my-take (dec n) (rest coll)))))
@john that will behave differently for floats, you might want to use zero?
small typo on that
So (not (empty? x))
is better than (identity? x)
to check if a sequence is not empty?
identity? is true for empty sequences
you might notice the doc string for empty?
says to use seq
instead of (not (empty ...))
because seq on an empty thing is nil
I have a case where one of my let
bindings needs to perform a trace-like side effect on an atom.
The side effect does not seem to happen until I use the binding in the expression part of my let form, which turns out unfavorable for my use case.
my problem was I assumed doall
is transitive, but it turns out if I doall
a sequence, but that sequence internally generates another sequence that isn't wrapped with doall
, that last sequence's side effects are kept lazy. I am not sure yet of this, as I should probably more deeply learn how laziness and side-effects affect one another.
I think one of my sequences was inadvertently kept lazy, hence side-effects on an atom only came about "late".
annoyingly this does not reproduce in a simplified version of my code, so I'll keep digging.
What is the equivalent of compile time type safety for Clojure? (reasoning: I'm coming from Elm and I really enjoyed the 'if it compiles it works' process.)
I've been using spec (instrument, exercise-fn) which is nice but is there anything else I should be aware of? In other-words what did Clojure developers do before spec to build robust software?
90% is just the REPL. Though I'm sure Elm has something similar. Schema was (and still probably is) popular. Core.typed attempted to provide a real, actual optional typing system for Clojure/ClojureScript. It's a little verbose though, compared to Elm.
But any optional type system on CLJ/CLJS is likely to be more verbose than something like Elm.
how do you apply (set! print-length 1) to only a single form?
I am using that to limit clojure.test's is
from printing huge collections when a test for collection equality fails....
not sure I dig how these two sentences in the docs (https://clojure.org/reference/vars#set) compose: >When the first operand is a symbol, it must resolve to a global var. The value of the var’s current thread binding is set to the value of expr.
set!
will change *print-length*
for everything within a given thread. Vars are "thread local."
john: only vars declared dynamic are thread local
~foo~
becomes foo
whereas binding
only overrides the meaning of it's bindings within the scope of its form.
Yeah, I try not to fiddle those things in normal code though.. sticking to functional code whenever possible
Aye, same here. And binding
is more in keeping with that practice than set!
. Though I rarely if ever find the need to rebind things either.
I'm not familiar with a "lazy binding" idiom. Maybe it's a thing? Where are you seeing it?
@vitruvia If you are referring to what's discussed above, it may be a concept where binding an expression to a name does not execute that expression. Instead it's executed when that expression's result is needed somewhere. Following the test given above, (let [a (println "x")])
does print x
in Clojure even though a
is unused in the body, because Clojure's let-bindings are not lazy. But for a lazy binding nothing would be printed. An example of that would be let
in RSpec (Ruby world), let(:a) { puts "x" }
would not print anything, unless a
was used somewhere in-context. For when it does have to be evaluated immediately, RSpec has let!
.
@d-side thanks. I would think the other way makes more sense (a lazy binding would execute the function when called) because that looks more lazy to me than the case where it doesn't execute the function automatically, lol.
It makes sense in a way that "expression? na-ah, will only do when asked about what it returns"
I'm lazy too, that's why I tell computers how to do stuff for me. If I get too lazy even for that, maybe it's not worth doing anyway.
i'm using boot for the first time. there are a few tasks defined like dev
, which modifies the resources available. How can i "execute" this task from the repl after i've jacked in with cider? when i run the task all i get back is a function:
dpsutton: (boot dev)
hmmm
boot.user> (boot dev)
java.lang.ClassCastException: boot.core$run_tasks$fn__915 cannot be cast to java.lang.CharSequence
(deftask dev []
(uber-env)
;; (require '[scratchpad :as sp :refer [dbspec queries]])
(repl))
I'm not sure but i'll look into it later. I appreciate your time. You're always so helpful Sean
My bad, it’s (boot (dev))
I don’t run tasks very often in the REPL, sorry.
ah yeah, i see why that's so weird. i think i'm running a repl inside of a repl haha
You’ll grow to love Boot 🙂 We use it for our entire dev/test/deploy pipeline at World Singles. We even build Docker images with it.
yeah I need to learn it. I like tasks more than a giant map that I need to figure out how to make it work in lein
(deftask dev []
(uber-env)
;; (require '[scratchpad :as sp :refer [dbspec queries]])
(repl))
recently at collage we talked about xpath, xquery, xslt those seem ugly to me are those go to tools when working with xml or?
lepistane: they are hideous indeed, but if you do a lot of xml work, indispensible, and well worth the trouble. xslt is purely functional. clojure has nothing even close to it for munging xml docs, alas.
we have clojure.xml and clojure.data.xml - I haven’t used them extensively but they make things a little friendlier to use from clojure
I have also had good luck with using clj-tagsoup to brute force some data I needed out of a document
Interesting side note: EDN is a sensible replacement for XML. And with specter-edn (https://github.com/maitria/specter-edn) you can get similar path selector stuff done.
Hello! I'm pretty new to functional programming, can you help me understand how would you implement dinamic programming without arrays? 🙂
for anything non trivial I would probably use an array actually, this is a viable approach in any clojure environment
but for most algorithms we replace mutation of data with recursion, passing a new value for the binding as an arg
that is, for any non-trivial problem I solve with dynamic programming, to be clear
but honestly it doesn’t come up much (and when it does I’m actually using some library that abstracts it, probably written in java)
@victora this talk from the most recent clojure/west has examples of using algorithms that are more natural with mutation, and the process of solving the kind of hard problems where these things come into play https://www.youtube.com/watch?v=TA9DBG8x-ys&list=PLZdCLR02grLp4W4ySd1sHPOsK83gvqBQp&index=13
Thanks for the help! Do we have arrays in vanilla clojure? As far as I got into the book I'm reading, we only had vectors and they are immutable. And I'm sure it will not come up in most situations, but I want to learn clojure as best as I can.
@victora clojure is a java library with a built in compiler
we have access to everything that comes with the jvm
but it’s good to take the time to understand why we leave arrays to special cases, and prefer immutable data, and I’d assume your book would be trying to explain that
for a random example, if something goes wrong in my app, I can almost always capture the data in place and store it, and come back to it in a repl and work with it directly
without worrying that it got mutated or invalidated later because of other code - I can be reasonably sure that when I use the data later, it behaves exactly like it did in the scope of my function
in fact, thanks to a library called transit, I can usually stash the precise data on disk, commit to git, and then use it later in a unit test
@noisesmith thank you for the thorough answer
I'm trying to write a macro that, in its simplified form, takes an expression and returns a hash-map with the expression as the key and its evaluation as the value, but I'm having trouble unquoting the expression's arguments... For example, given
(let [t "hello world"]
(my-macro (str t)))
I want the return value to be {(clojure.core/str "hello world") "hello world"}
but instead it's {(str t) "hello world"}
. This is my implementation so far.
(defmacro my-macro
[expr]
`(hash-map '~expr ~expr))
don’t you want ~‘expr ?
oh, that won’t help
` only namespace qualifies literals inside its form, it doesn’t namespace qualify symbols provided from outside
and similarly, you can choose to see the form passed in (str t)
or the full value, but not some intermediate partial evaluation
Hm, alright, thanks. Could I iterate over elements in the form, resolve each one, and reconstruct the form?
you can’t resolve locals
macros are for transformations that you can do based on the form as it exists in the source file
you could emit code that looks things up at runtime, but that doesn’t work so nicely with locals, and doing that is fighting against the grain of clojure
Sounds good. The initial goal was to memoize certain functions for the duration of an http request. This was obviously a simplified form of the macro. I decided to use this approach as I could have the whole map GC'd after I'm done with the request, and keys were straightforward. Anyway, I'll probably use an approach that just uses memoize and no macros