This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-18
Channels
- # alda (6)
- # architecture (1)
- # bangalore-clj (3)
- # beginners (39)
- # boot (292)
- # braveandtrue (1)
- # cider (7)
- # clara (2)
- # cljs-dev (20)
- # cljsjs (9)
- # cljsrn (42)
- # clojure (127)
- # clojure-chennai (1)
- # clojure-dev (96)
- # clojure-india (1)
- # clojure-russia (175)
- # clojure-spec (56)
- # clojure-uk (11)
- # clojureindia (1)
- # clojurescript (82)
- # core-async (7)
- # cursive (21)
- # data-science (1)
- # datomic (173)
- # funcool (4)
- # hoplon (8)
- # instaparse (1)
- # jobs (7)
- # jobs-discuss (1)
- # jobs-rus (30)
- # lambdaisland (1)
- # lein-figwheel (8)
- # off-topic (5)
- # om (51)
- # onyx (79)
- # other-languages (7)
- # planck (8)
- # re-frame (95)
- # reagent (6)
- # rum (8)
- # specter (4)
- # untangled (54)
- # yada (5)
@dpsutton: mapv
is map
but returns a vector instead of a seq, so side effects happen before it returns
@peter.d: This looks great. Two comments: 1) It’s important to think about edge cases. What does your function return when given zero arguments? Probably should either throw an error or return a function that does nothing and returns nil. But right now such a function would return a sequence of its arguments, which is probably not what you want:
((any-number-comp) 5 6 7)
;; => repl output: (5 6 7)
@peter.d
2) When you evaluate (comp f1 f2 f3 f4)
, only f4
can take multiple arguments while the rest can only take a single argument (because of course in Clojure functions can only return one value):
(def mult-then-inc (comp str inc *))
(mult-then-inc 2 3 5)
;; => repl output: “31"
So you could have an initial step which evaluates the first function (the last in the argument vector before the reversal), and then the loop could evaluate all the other ones, without needing that (if (coll? result) ...)
expression. This would also have the added effect of throwing an error if you pass no arguments to any-number-comp
, which would be, if not exactly what you want, slightly better than what it’s doing now (see #1 above).
Good work, overall!Question for anyone: I want to have a sorted sequence of items in a priority queue, that I conj
other items into frequently, and it needs to resort itself every time there is an insertion. What is the most efficient way to do this? Using a sorted-set, or using a vector and running sort
after every insertion?
Constraints: I will never have more than a few hundred items, and all of the items are guaranteed to be unique, so I don’t need set semantics for avoiding duplication.
I believe sorted-set would be better
sort
uses the java Arrays sorting library, so in addition to being an n*log(n)
operation, you’re also incurring some overhead with conversion
sorted-set
is just log(n)
to add
https://clojurians.slack.com/archives/beginners/p1471461591001261
https://clojurians.slack.com/archives/beginners/p1471476167001268
@dpsutton Depending on your use-case, doseq
may be more suitable
from: https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects
"doseq: good default choice, clearly indicates side effects
run!: new in Clojure 1.7, can take the place of (dorun (map ...))"
@surreal.analysis: n*log(n) is only worst-case, you get far better results when the input coll is almost sorted already
@richardh: I do encourage you to benchmark
but I would also go for sorted-set by default
Right, but even best case is n
, not log(n)
Assuming the sorting method is still timsort
But then again, when talking about algorithms the coefficients are normally ignored
And if you have only 300 or so items
The extra stuff is what matters, so I’d encourage benchmarking too
But I’d be surprised if sort
won
yeah maybe only for very small sets
in which case you may not care anyway
@surreal.analysis @val_waeselynck Thank you both for your help. I will do some benchmarks.
Not that it really matters with such small data sets, as you mention. But I’m curious.
It depends on the context
Good question, don’t know. I’m just assuming 300 is small for what I’m doing. There’s a lot of information being passed between network sockets too — I imagine that’s much more likely to be a bottleneck in my case.
In my opinion - Large data is whenever manipulating the data itself is the bottleneck preventing the software from being better
So if you’re working with highly performant code that needs to be heavily optimized, large data could be anything in the hundreds of elements
If you are working with SQL, large data is in the 10M+ range
@guy Yeah, I didn’t actually think the answer to my question mattered practically — I was just curious if there was an obvious, clear answer for all cases. Code clarity is more important than performance optimization, until it’s not.
@peter.d One more nitpicky style thing: the main argument list for your comp function is [& f]
. I would probably make it [& fs]
or something, to make clear that you’re binding a collection of functions, not a single function.
@guy: not official, but it describes a lot of code that's in the wild: https://github.com/bbatsov/clojure-style-guide