This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-03-27
Channels
- # aleph (5)
- # announcements (18)
- # beginners (200)
- # cider (25)
- # cljdoc (4)
- # cljsrn (3)
- # clojure (90)
- # clojure-europe (3)
- # clojure-finland (5)
- # clojure-france (1)
- # clojure-houston (1)
- # clojure-italy (8)
- # clojure-nl (15)
- # clojure-spec (24)
- # clojure-uk (20)
- # clojurescript (199)
- # core-async (2)
- # cursive (45)
- # data-science (14)
- # datomic (33)
- # duct (13)
- # fulcro (4)
- # graphql (3)
- # kaocha (9)
- # leiningen (24)
- # nrepl (16)
- # off-topic (105)
- # pathom (15)
- # pedestal (28)
- # re-frame (1)
- # reagent (14)
- # shadow-cljs (28)
- # spacemacs (8)
- # tools-deps (8)
- # vim (4)
Rich's opinion on the GPL question: https://groups.google.com/d/msg/clojure/bpnKr88rvt8/AOtLHW4Lhh4J
GPL is "viral" and a lot of companies categorically won't touch libraries licensed under GPL.
What does it mean for a license to be “reciprocal”?
(e.g, when RH says MIT and BSD are not reciprocal)
In particular, MIT and BSD are discussed in that context at the bottom of that article.
Thanks! 🙏
(I didn't know -- it took me a few minutes on Bing to find something that actually explained it!)
All open source / free software / copy left licenses are just bandaids over the farcicality of the copyright / patent trade law in general
So, my dear fellow Clojurians, render for me in your mind, if you would, an imaginary data structure we shall call a #smv
The first column is the key index colum of the vector. The second is the key column for the map relations. If a key relation is missing (#smv/nil) then the index for the row (its first element) defaults to the key
If we were to define one of these #smv
like so:
(def smv
#smv
[[0 :a "bob"]
[1 :b "ann"]])
Calling conj
on an #smv
act's like a vector
:
(conj smv "ted")
Would produce:
#smv
[[0 :a "bob"]
[1 :b "ann"]
[2 :smv/nil "ted"]]
Calling assoc
would act like a hash-map
:
(assoc smv :granny "sue")
#smv
[[0 :a "bob"]
[1 :b "ann"]
[2 :smv/nil "ted"]
[3 :granny "sue"]]
When executing sequential operations, only the last element of each #smv
element is returned:
(vals smv)
#smv
("bob" "anm" "ann" "ted" "sue")
(seq smv)
#smv
("bob" "anm" "ann" "ted" "sue")
When executing map-like operations, it would act like a map:
(keys smv)
#smv
(:a :b 2 :granny)
Now, I haven't actually gone an implemented such a structure, but would something like that seem worth experimenting with?
It's like a unified structure that can be acted upon by all functions that act on sets, maps and vectors
Under the hood, it would hold an extra hashmap, which contains a map of keys to index nodes on the vector, to preserve fast lookup
But, in general, I'm thinking that the vals of a key value pair, should only impact the equality value of the thing
Just like how the key associated with the third item of a vector happens to be 2, but the value is not impacted by the twoness in its vector
I guess the bigger philosophical question would be, could it be possible to combine the sequential, associative and relational properties into one data structure, such that all mutation functions can operate over that one structure
well, :smv/nil
is suppose to be for internal use, so you can still use nil
as a key in your map, if you want
But calling (assoc (conj (conj #smv [] "a") "b") :blah "c")
would I think produce:
#smv
[[0 :nilish-thing "a"]
[1 :nilish-thing "b"]
[2 :blah "c"]]
well, you'd have some internal thing that allowed you to represent when the key should be represented as its index or as the key it's been provided
in the above example, #smv/nil nil
would literally mean "no key is here, use the number to the left as the key"
An important point of difference when trying to understand where sequence and mapping might conflict... when sequencing a map, it gives you key-value pairs. This gives you only the values, like a sequence would.
seems like values which were inserted using sequence-like conj
would then be inaccessible from the mapping-like operations
either first
or #(nth % 0)
or (get % 0)
... but I would be in error if I assumed "a" should have a named label. Which would rightly trouble your expectations of map-like things.
if I wanted a mapping data structure with a well defined ordering I'd use an (ordered-map)
and fmap
from fluokitten does a good job of abstracting maps as containers of their values (instead of kv pairs)
Complect too many things into one... Maybe. That's what I want to know though. Or would having a singular, uni-structure actually simplify things further?
Some very “interesting” side effects stem from that. I like Clojure precisely because it mostly avoids the problem, and its collection functions operate on structures in a sane way.
There is a problem with contains? on Clojure sets?
Thanks @U060FKQPN :D
Oh, understood then. Yeah, I've done what I know how to, and am authorized to do, for clojure.set over the years. I'm done with it.
This being most of that: https://github.com/jafingerhut/funjible
some day I will know why rename-keys
is in clojure.set. this is not that day, nor will be tomorrow
My best guess: clojure.set started as things like union, intersection, difference, then grew into operations on relations like join, project. Rich found it a good idea to create rename-keys in order to implement join.
It looks like a relational algebra implementation, because it is 🙂
Entirely for in-memory data structures, and not optimized to the N-th degree with indexes, etc. the way a production SQL database often is.
Thank you @hiredman, @seancorfield and everybody else for the responses on GPL and clojure! Much appreciated and yet another testament to the helpfulness of the community.
A mini rant on accretion not deletion. I've been failing to reify
an interface, getting the error message Can't define method not in interfaces: extract
. Added the this
parameter. Still no luck.
Turns out the documentation I was looking at was wrong. And, the interface had a breaking change in the next version! They added a previousTimestamp
parameter, and dropped the old method.
https://kafka.apache.org/0101/javadoc/org/apache/kafka/streams/processor/TimestampExtractor.html and https://kafka.apache.org/10/javadoc/org/apache/kafka/streams/processor/TimestampExtractor.html
</end>
Another interesting datastructure: a map where the keys are sets and assoc
ing simply adds a key to a keyset for an existing val. A get
would return the val for the keyset-val pair whose keyset contained the passed in key to get
. All keysets in a keyset map would have to be distinct though, to ensuring only one val per key.
Or, alternatively, a keyset map where keysets didn't have to have all distinct elements - just each keyset be unique. Then you could query the keyset map for all vals that include some passed in keyset.
But this idea of treating an associative data structure like a sequential one when provided to a function that normally operates on sequential things, like filter
, perhaps the keys associated with the value (if there is one) could be attached to the value as meta data, so the sequencing function still access to the key? Or would it be better to pass values that happen to have keys associated with them as KeyValuePairs when a sequential function runs into them?
otherwise, doing sequential operations on #smv like things would seem lossy, since the seq coming out the other end wouldn't preserve the keys
Or one could just go with Index-Key-Value tri's [i k v]
and seq operations just receive something like an IndexedMapEntry
that had those three components
But I'm still partial to exploring this idea where keys don't impact the value semantics for the values in an associative data structure
Been playing with bacon in cljs and using this as a reference to make some dynamic animations:
(ns app.animation
(:refer-clojure :exclude [range])
(:require [bacon :as bacon :refer [End]]))
(def time-started (atom 0))
(defn ease
[x]
(* x x))
(defn transition
"Takes a duration in ms and an easing function.
Returns a bacon stream that emits a percentage so that it reaches 1 at the
end of the duration."
[duration ease-fn]
(-> (.interval bacon (/ duration 100) 0)
(.scan 0 inc)
(.takeWhile #(<= % 100))
(.map #(/ % 100))
(.map ease-fn)))
(defn fade-in
[opacity]
(set! (-> js/document (.-body) (.-style) (.-opacity))
opacity))
(defn go!
[]
(-> (.once bacon 0)
(.flatMap #(transition 1000 ease))
(.doAction fade-in)
(.onEnd identity)))