This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-13
Channels
- # 100-days-of-code (5)
- # adventofcode (1)
- # announcements (8)
- # beginners (148)
- # boot (17)
- # calva (26)
- # cider (17)
- # cljdoc (2)
- # cljs-dev (55)
- # cljsjs (2)
- # clojure (198)
- # clojure-dev (11)
- # clojure-finland (1)
- # clojure-italy (23)
- # clojure-nl (6)
- # clojure-spec (44)
- # clojure-uk (148)
- # clojurescript (27)
- # clojutre (20)
- # core-logic (21)
- # cursive (12)
- # datascript (10)
- # datomic (33)
- # emacs (11)
- # figwheel-main (49)
- # fulcro (19)
- # graphql (2)
- # off-topic (48)
- # onyx (2)
- # other-languages (53)
- # pedestal (3)
- # reagent (75)
- # reitit (17)
- # rum (1)
- # slack-help (2)
- # specter (2)
- # sql (3)
- # tools-deps (24)
- # unrepl (4)
- # yada (1)
Does Sente (https://github.com/ptaoussanis/sente/) require you to have UI/SERVER in the same leiningen project? Only saw that composition in example projects. Is it possible to route it to my own specified port, host? aka not the same port as the ui
It's currently trying to go to:
Think I solved it by myself. Will probably make a PR to Sente/Examples showing how to set it up with a seperate UI and API project. from the docs for
make-channel-socket-client!
`
Common options:
:type ; e/o #{:auto :ws :ajax}. You'll usually want the default (:auto).
:protocol ; Server protocol, e/o #{:http :https}.
:host ; Server host (defaults to current page's host).
:params ; Map of any params to incl. in chsk Ring requests (handy
; for application-level auth, etc.).
:packer ; :edn (default), or an IPacker implementation.
:ajax-opts ; Base opts map provided to `taoensso.encore/ajax-lite`.
:wrap-recv-evs? ; Should events from server be wrapped in [:chsk/recv _]?
:ws-kalive-ms ; Ping to keep a WebSocket conn alive if no activity
; w/in given msecs. Should be different to server's :ws-kalive-ms."
Worked well.
A question related to def
. Could you explain in simple words why calling defining twice the same variable is not prevented by Clojure?
@borkdude Yes. But it confuses beginners when we say that Clojure on one hand encourages immutability and on the other hand allows you to redefine what is already defined
it has to do with the REPL workflow. this is the first thing a beginner should learn.
Do you have good material about: 1. the importance of REPL workflow 2. The details of REPL workflow
OK Thanks
@viebel using def
isnt exactly an assignment like other languages. its like a binding that gives a name to a memory location.
(def value 5)
(def value (+ value 1))
this case doesnt really mutate value
. a completely new memory location with the value of 6
is allocated and is now called value
again. so yes clojure is still immutable even with multiple def
s on the same name.that’s also a way to look at it, but fundamentally vars are mutable, e.g. you can call alter-var-root on them
correct. but i guess that is not advisable?
@rahul080327 @borkdude What is the fundamental difference between def
and alter-var-root
beside the fact that the latter is atomic and apply to its current value?
@viebel I think as lispyclouds pointed out, when you re-def something with the same name, the old var isn’t re-used
But what is the difference between not reusing the old var and creating a new var with the exact same name?
In both cases, the value is not modified
I think that both def
and alter-var-root
don’t modify the content
I don’t know the exact implementation of def, it could be that it reuses the old object
seems to be the case, no?
(def a 1)
(def b #'a)
(identical? (var a) @(var b))
(def a 2)
(identical? (var a) @(var b))
> Creates and interns a global var with the name of symbol in the current namespace (ns) or locates such a var if it already exists.
but to come back to mutation: the value that is referred to by the var isn’t mutated, like the value in an atom is not mutated, but replaced. but you could say the var itself is mutated
@borkdude did you mean (identical? @(var a) @@(var b))
?
yes, i'd like to think of it as changing the value
associated by the name. def
for me is an explicit naming of a value where as using atoms or alter-var-root
gives us a feel of in place mutation regardless of their actual implementations
but to make it simple: Clojure has a couple of mutable cell references: vars, atoms, refs and agents. vars are designed to be mutable.
Both the vars are identical and the values.
The same happen if we do (alter-var-root #'a inc)
@borkdude agreed 🙂
I have a vector of numbers, like [2,3,5]
Need to create a sorted sequence of (distinct, nice to have) it's multiplies (dunno how to express it better)
But the result I want is → [2,3,4,5,6,8,9,10,12,14,15, ...]
Would like an infinite sequence
but I want the multples, like
multiplying iterate
with this sequence, take the distinct and sort them
@denisgrebennicov is this a puzzle?
Do you mean, you want to take [2 3 5]
and get all possible multiplications of those numbers?
@borkdude for me for sure 😄 actually solving this problem: https://www.hackerrank.com/challenges/minimum-time-required/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=search And was thinking of doing something like this, since this would make solving the problem easier
> Do you mean, you want to take [2 3 5]
and get all possible multiplications of those numbers?
exactly. in sorted order, distinct only
I’m not sure what the formal problem is. Each number in this range is the product of either, 2, 3 or 5?
… machines that take [2, 3, 2] days to produce an item
. I.e., they produce [1/2 1/3 1/2]
items per day. So they produce 1 1/3
items per day. Number of items modulo that, right?
number of items modulo speed what about this e.g. [5 and 10], target is 2, won't your answer be 7.5/8 days or smth since at 8 the first machine will do 0.6 and machine 2 will do 0.8 amount of work
(def speed 2)
(def prod (let [xf (comp (map inc)
(map #(mod % speed))
(map-indexed vector)
(filter #(-> % second zero?))
(map first))]
(sequence xf (range))))
(take 10 prod)
=> (1 3 5 7 9 11 13 15 17 19)
I guess range and filter doesn't sound so good, since machines can be up to 10^9 to go through all of them for every i in range
But seqs are lazy, so drop
+ take
should let you iterate through an arbitrarily long sequence without blowing a giant hole in your memory.
A guess I can use a priority_queue or smth. Popping the day and multiplier of that day. Then looking at day-machines-map subtracting items to do by the day-machines-map[day] length and then insert the day with new multiplier priority-queue should work on day * multiplier or smth dunno
This is not really a clojure problem, sorry for spamming. Normally I try to solve problem in Python, then do a Clojure version
@denisgrebennicov I notice there is also a #puzzles channel. And if you would like, there will probably more activity around puzzles in #adventofcode around December.
Drop map first
and filter
and you get a sequence of vectors where the first item is the day, and the next is number of items produced that day.
(def speed 2)
(def prod (let [xf (comp (map inc)
(map #(mod % speed))
(map-indexed vector))]
(sequence xf (range))))
(take 10 prod)
=> ([0 1] [1 0] [2 1] [3 0] [4 1] [5 0] [6 1] [7 0] [8 1] [9 0])
Make three of these for speeds 2, 2, and 3, and you could easily loop over all three, adding the number produced that day until the desired number of items are reached. I think.For lazy sequences, you’re never holding the entire thing in memory at any one time. They are only computed when they are realized.
(range)
is infinite. But by doing (take 10)
I’m only considering 10 of those.
The problem is about speed being constant in this case and not dynamically set as an array/vector/seq
A philosophical question: Is it expected that (= [1 2] '(1 2))
?
You mean code inside Clojure itself or inside apps written in Clojure?
would be a good one to add to the faq: https://clojure.org/guides/faq
Is there a better way to achieve (assoc response :headers (merge (:headers response) {:a 1 :b 2}) )
?
@mfikes Indeed it makes sense to consider that (= (map inc [1 2 3]) '[2 3 4])
although (map inc [1 2 3])
is a lazy sequence
@viebel there is identical?
when you need the pointer/object reference comparison. But =
operator does make sense, since content inside is the same
@denisgrebennicov identical?
is very dangerous/tricky. For instance (identical? [1] [1])
is false
it works as equality for a small number of lists though 😛
(let [a '()
b '()]
(identical? a b))
What do you mean @mfikes by the abstract nature of =
?
For collections, there are “equality partitions” - sequentials, sets, and maps.
All sequential collections compare = (vectors, lists, sequences)
This is essential when working with a mix of collections and sequences
Interesting / related: https://github.com/clojure/clojure/blob/master/src/clj/clojure/data.clj#L67-L100
After years of reflection on it, I think that equality working over all sequential collections was a brilliant and non-obvious design choice
I have an article on the main ideas, and a few subtleties, of Clojure's = and hash implementations, here: https://github.com/jafingerhut/thalia/blob/master/doc/other-topics/equality.md
@U064X3EF3 can you share some examples of the advantages of this non-obvious design choice?
When I teach Clojure to beginners, and show them that (= [1 2] '(1 2))
is true, they find it very surprising. And indeed, when you put it out of any application context, it is surprising.
But when you think about in the context of an application, it starts to make sense: you don’t want to find yourself in a situation when [1 2 3]
is not equal to (map inc [0 1 2])
just because map
returns a lazy sequence.
Do you see it the same way?
How does it apply to numbers?
even ==
present some surprises:
(not (== (+ 0.1 0.2) 0.3))
(== (+ 0.2 0.3) 0.5)
Related to that
(+ 0.1 0.2 0.3)
needs to associate from the left 🙂
It would be incorrect for Clojure or ClojureScript to effectively do
(+ 0.1 (+ 0.2 0.3))
how do i express dependent relationships between components of a tuple spec? say I need a tuple of two strings such that the first one has the same characters as the second one
(s/tuple (s/coll-of ::public-key) (s/coll-of ::private-key) ???such that each private key corresponds to a public key??? )
@denisgrebennicov This is fun to tinker with! Thanks for the puzzle. It certainly takes time to calculate the production day for a billion items on my poor laptop, but it doesn’t use much memory at all.
@U250T6MFA the mbrainz example is a good starting place https://github.com/Datomic/mbrainz-sample
@U250T6MFA table/column or class/method is a good starting point, you'll figure the paterns soon enough, and Datomic gives you enough flexibility to recover from your mistakes
@U250T6MFA +1 for table/column. You will be able to figure this out as you go. Just get started.
In addition to table/column, I like to think about the schema as an attribute catalogue that I can use to create entities. So don´t worry about having ALL possible attributes upfront. Just add the minimal attributes your domain needs and follow the best practices https://docs.datomic.com/cloud/best.html#datomic-schema
@henrik you are welcome hahahah 😄 Obviously time is also very crucial here. (For this kind of hackerrank challenges) But a solution is better than no solution 😉
@denisgrebennicov Yeah, the final reduction can be easily done in parallel I think. I wonder if something like Neanderthal could take care of it.
@henrik actually the solution to their problem was really "cheap". I didn't expect somethign like this They just do binary search, since they know the input constraints Then for every mid point they compute, they sum all the products that can be done for every machine and check for the goal/items to produce if it is more or less than the given val 😞
Sample solution:
def minTime(machines, goal):
machines.sort()
low_rate = machines[0]
lower_bound = (goal // (len(machines) / low_rate))
high_rate = machines[-1]
upper_bound = (goal // (len(machines) / high_rate)) + 1
while lower_bound < upper_bound:
num_days = (lower_bound + upper_bound) // 2
total = getNumItems(machines, goal, num_days)
if total >= goal:
upper_bound = num_days
else:
lower_bound = num_days + 1
return int(lower_bound)
def getNumItems(machines, goal, num_days):
total = 0
for machine in machines:
total += (num_days // machine)
return total
reduction in parallel, that reminds me of https://clojure.org/reference/reducers
Hi. I am trying to "flatten" an xml tree while adding a depth count to some nodes. I've considered prewalk or xml-sec but it seems they won't help as they use one element at a time. My plan now is to use something like loop [z zipper result []]
over an xml-zip to copy nodes out and use (count zip/path)
where needed. Is there a more idiomatic approach?
Hello so a coworker has expressed interest in learning programming. I would love to introduce them to Clojure but I’m concerned it might not have a lot of educational content aimed at absolute beginners like Python currently has. Is there any resources that come to mind that would introduce absolute beginners to Clojure?
ClojureBridge curriculum maybe?
Kyle Kingsbury wrote a fine introduction that doesn’t assume any background knowledge a few years back: https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome
(defn- generate-lein-project-file! [& {:keys [keep-project] :or {keep-project true}}]
(require ')
(let [pfile ((resolve ') "project.clj")
; Only works when pom options are set using task-options!
{:keys [project version]} (:task-options (meta #'boot.task.built-in/pom))
prop #(when-let [x (get-env %2)] [%1 x])
head (list* 'defproject (or project 'boot-project) (or version "0.0.0-SNAPSHOT")
(concat
(prop :url :url)
(prop :license :license)
(prop :description :description)
[:dependencies (conj (get-env :dependencies)
['boot/core "2.6.0" :scope "compile"])
:repositories (get-env :repositories)
:source-paths (vec (concat (get-env :source-paths)
(get-env :resource-paths)))]))
proj (pp-str head)]
(if-not keep-project (.deleteOnExit pfile))
(spit pfile proj)))
(deftask lein-generate
"Generate a leiningen `project.clj` file.
This task generates a leiningen `project.clj` file based on the boot
environment configuration, including project name and version (generated
if not present), dependencies, and source paths. Additional keys may be added
to the generated `project.clj` file by specifying a `:lein` key in the boot
environment whose value is a map of keys-value pairs to add to `project.clj`."
[]
(with-pass-thru fs (generate-lein-project-file! :keep-project true)))
I added this snippet from the For Cursive Users
section of the boot docsIt seems successful for generating a clojure repl. But I can’t figure out how to get it create a clojurescript repl
that really depends on the kind of repl you want. Usually it's going to be a piggybacked REPL, where a clojure repl is started, and some function starts a cljs repl on top of that connected to a browser via websocket (this is how figwheel does things for example - the java side code recompiles, and sends to the browser, and the cljs repl operates via a websocket on top of that process)
@simon.orlovsky this might help https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl
Guys Sente is insanely nice.
Anyone tried to run it at a big scale? Thousands of clients
what I ended up needing was a "bounce channel" that propagated async results so that the client could still get them if they reconnected and load balanced to a different server
I didn't have thousands of clients, but a heavy enough app with enough clients to require multiple servers with load balancing
the tl;dr of the design is that for any delayed result, you need a way to get that result to the server that that client is currently talking to (or accept that that flow of data breaks if they find a new server)
Thank you for the insight @U051SS2EU 👍
the github appears to have been taken down
the author got fed up with clojure at some point (wrote a big blog post about it) and may still feel that way?