This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-28
Channels
- # aleph (50)
- # announcements (3)
- # aws (35)
- # beginners (74)
- # boot (25)
- # calva (39)
- # cider (18)
- # clara (2)
- # cljdoc (18)
- # cljs-dev (24)
- # cljsrn (11)
- # clojure (166)
- # clojure-europe (13)
- # clojure-italy (5)
- # clojure-nl (6)
- # clojure-spec (35)
- # clojure-uk (263)
- # clojurescript (22)
- # clojutre (1)
- # code-reviews (34)
- # cursive (58)
- # data-science (2)
- # datascript (4)
- # datomic (4)
- # duct (6)
- # emacs (7)
- # figwheel-main (9)
- # fulcro (2)
- # graphql (3)
- # hoplon (22)
- # hyperfiddle (2)
- # juxt (5)
- # kaocha (6)
- # leiningen (33)
- # luminus (15)
- # off-topic (1)
- # pedestal (5)
- # reagent (18)
- # reitit (12)
- # shadow-cljs (171)
- # vim (5)
Ok I'm very confused right now. I made the following function (to be able to turn functions that process one data point and with arbitrary number of arguments before able to process batches of data points)
(defn batcher [f & args]
(def batch (last args))
(def beg-args (take (- (count args) 1) args))
(def new-args (map #(reverse (conj (reverse beg-args) %)) batch))
(println (map #(count %) new-args))
(map #(apply f %) new-args))
And if I comment the println
it crashes on some calls telling me that f doesn't get the proper number of arguments, but if I leave the println, then it worksStep one would be to use let
instead of def
. let
is the way to create local (lexical) bindings.
and similarly, with the following function
(defn ngrams-to-bow
"turn text into bag of words based of dictionary"
[dict ngrams]
(def revdict (clojure.set/map-invert dict))
(def ngram-freqs
(-> (filter #(contains? revdict %) ngrams)
(frequencies)))
(def res (map (fn [word_id] (if-let [x (get ngram-freqs (get dict (str word_id)))] x 0)) (range (count dict))))
(println (take 10 res))
res
)
when I call it in the following context
(def nlabels (count labels))
(->> (ut/batcher text-to-ngrams min-ngram max-ngram texts)
(ut/batcher ngrams-to-bow dict)
(bow-to-tensor)
if I remove the println
, bow-to-tensor receives copies of the same bow, but if I keep it, bow-to-tensor gets different (and correct) vectors(defn batcher [f & args]
(let [batch (last args)
beg-args (drop-last args)
new-args (map #(reverse (conj (reverse beg-args) %)) batch)]
(do (println (type batch)
(count batch)
(type beg-args)
(count beg-args)
(map #(count %) new-args))
(map #(apply f %) new-args))))
You don't need do
here -- the body of a let
is implicitly wrapped in do
already.
@jaihindh.reddy thank you very much, I changed a few functions using let
and it works
I don't think apply would work because I need the last argument to remain a list and not be considered a continuation of a list of arguments (e.g. (apply + 1 2 '(3 4)) ; equivalent to (apply + '(1 2 3 4))
from the doc)
In my case, I have many functions with different arities, for example text-to-ngram
and it can only process one text at the time, so batcher takes the list of argument + a batch of texts and maps text-to-ngram with the appropriate arguments + individual texts
I'm unable to understand the intention behind you're function. I have a sneaking suspicion you don't need this function. Check out apply
@archibald.pontier_clo If you put beg-args
into a vector, you won't need those reverse
calls I suspect:
beg-args (into [] (butlast args)
new-args (map #(conj beg-args %) batch)
conj
on a vector will append the new item (whereas conj
on a list or sequence will prepend it).
(but I agree with @jaihindh.reddy that it's very hard to understand what you're trying to do from that code)
(defn batcher [f & args]
(let [batch (last args)
beg-args (drop-last args)
new-args (map #(reverse (conj (reverse beg-args) %)) batch)]
(map #(apply f %) new-args)))
user=> (batcher #(println "args: " %&) 1 2 [4 5 6])
(args: (1 2 4)
args: (1 2 5)
args: (1 2 6)
nil nil nil)
This is the same as
(defn batcher [f args-for-each-call args]
(map #(apply f (conj (vec args-for-each-call) %)) args))
(batcher #(println "args: " %&) [1 2] [4 5 6])
which is the same as
(defn batcher [f & args]
(map #(apply f (conj (vec (butlast args)) %)) (last args)))
if you want to stick to the original calling convention.thank you a lot for the help
The reason I want this function is because I have many functions with different arities, for example text-to-ngram
and it can only process one text at the time, so batcher takes the list of argument + a batch of texts and maps text-to-ngram with the appropriate arguments + individual texts
def
creates a global (top-level) definition each time so it's never what you want inside a function.
I think, perhaps, there was also some interaction with laziness which was why having the println
made the original work -- but once the function was simplified, and made less imperative, whatever problem was there before went away.
It can take a while to go from an imperative mindset to a functional mindset @archibald.pontier_clo -- may I ask what other languages you've used before Clojure?
OK, so you've probably had some exposure to functional programming style already in Scala and OCaml, although both of those support imperative and object-oriented styles too -- both of which are a lot less idiomatic in Clojure.
(defn foo [args] body)
is a shorthand for (def foo (fn [args] body))
and both define global (top-level) Var
s.
Var
s can be treated as (global) mutable "variables" but it's not idiomatic (and not recommended).
Clojure is a lot more "opinionated" than a lot of other languages 🙂
I did Scala for about 18 months before I came to Clojure, and I've done a bit of F# which I gather is similar to OCaml.
It will take some getting used to it, that being said I quite happy with the language so far. To discover it I decided to port one of our machine learning service to clojure this week and it has been relatively painless and the code is much clearer than our python version
@archibald.pontier_clo That's great to hear! Hopefully you'll find the community is really helpful and welcoming. We're certainly very passionate about Clojure 🙂
Is there a better way to do (remove nil? (map ...))
than this ? (I'm thinking about flatMap
in Scala)
Check out mapcat
flatMap doesn’t sound the same to me, or at least in JavaScript it will flatten nested arrays one level
scala> val strings = Seq("1", "2", "foo", "3", "bar")
strings: Seq[java.lang.String] = List(1, 2, foo, 3, bar)
scala> strings.map(toInt)
res0: Seq[Option[Int]] = List(Some(1), Some(2), None, Some(3), None)
scala> strings.flatMap(toInt)
res1: Seq[Int] = List(1, 2, 3)
yeah, that was what I was thinking
But there is (keep f coll)
, that keeps all values in coll
for which f
did not return nil
Right, my explanation was shotty, f
is also applied, but if f
returned nil
, the result is removed from the (new) collection
Far sharper minds than mine can explain better: https://clojuredocs.org/clojure.core/keep
I have my service that is working fine which loads a config file that is in resources
as well as a bunch of other files, would it be possible to have one jar containing everything, using lein?
i'm working on this excercise:
An Armstrong number is a number that is the sum of its own digits each raised to the power of the number of digits.
For example:
9 is an Armstrong number, because 9 = 9^1 = 9
10 is not an Armstrong number, because 10 != 1^2 + 0^2 = 1
153 is an Armstrong number, because: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
154 is not an Armstrong number, because: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190
Write some code to determine whether a number is an Armstrong number.
And here's what I've come up with:
(ns armstrong-numbers)
(defn exp [x n]
(reduce * (repeat n x)))
(defn armstrong? [num]
(let [numStr (String/valueOf num)
numLen (count numStr)
nums (seq numStr)
expn (fn [x] (exp (Character/getNumericValue x) numLen))]
(= (reduce + (map expn nums)) num)))
This my first clojure code that is not a single expression. Had to ddg (duckduckgo) a lot.looks good to me, @thirdy.derivera. numLen
can probably be just (-> num str count)
, also I believe there's a power
function in clojure.math
for handling exponentials
Hey, I’m on Mac OS and after a brew upgrade I can’t run “lein repl”. I get a permission denied back, saying to check my ...repl-port. Leiningen was updated to 2.9.1...
might help to ask in #leiningen and include the full error
Is it actually something that is used? If not, how do you write unit tests in Clojure without them turning into integration tests, or methods that don't require you to continually pass in your dependencies requirementsn?
you can write unit tests by using a (embedded/in memory) database populated with test data, no need to mock a DB that way. for other services you can mock something. personally I favor writing integration tests, need them anyway, less work than doing both and catches the errors I’m interested in.
also you can use with-redefs
to mock functions, or use mock components (using the before mentioned library)
I want to test a function, just that function and none of it's dependencies, or I want the ability to change what that function does for whatever reason
Following that line of thinking, I would have to pass in the functions dependencies instead of using the statically defined functions in the rest of the language, correct?
it seems there is a spec for require that now means you can only use a sequence of symbols