tonsky / rum Goto Github PK
View Code? Open in Web Editor NEWSimple, decomplected, isomorphic HTML UI library for Clojure and ClojureScript
License: Eclipse Public License 1.0
Simple, decomplected, isomorphic HTML UI library for Clojure and ClojureScript
License: Eclipse Public License 1.0
I'm playing around with rum, using the idea of https://github.com/tonsky/datascript-chat - I'm omtting the async/chan part for this example. The application is rather heavily query-based, and I want to implement a :should-update mixin, which will update the components only if the queries are changed (sounds pretty obvious).
I have something like:
(def root (rum/mount (body) (.-body js/document)))
(defonce init (fn []
(ds/listen! conn (fn [tx-report]
(rum/request-render root)))))
(init)
Any updates in the database trigger a rum/request-render. Now, the 'should-update' mixin looks like:
(rum/defc comp < {:should-update (fn [o n] ... )} [args]
(let [q (ds/q ...)]
... ))
However, the 'old' state and the 'new' state are not the old and new state of the transaction (or the component as such), but rather some intermediate states of the component (so it seems to me). The old value is not the 'previous query result' or 'previous state which led to that query result'. What I'd like is to compare the previous result of the query with the new result of the query.
What's the most logic/best way to do this using rum?
In Om, mounting the component root with om/root
also allows for supplying shared state which can then be accessed by any component under the root component via om/get-shared
. This allows for global data and services to be set without resorting to global state since all state is still local to the mounted component tree. This allows, for example, multiple mounts of the same app on the same page with "global" data and services independent from each other.
Would it be possible to include something similar to rum? Or are there any suggested patterns to get the same result?
It has happened to me a few times now that I got stuck because I put the mixin in the wrong place.
(defc x
[a b]
< rum/static
[:div "bla"])
I think this is something that could be improved to give better feedback.
While throwing an exception isn't guaranteed to be correct the probability of false positives seems low (i.e. component bodies starting with a plain <
).
Would you be interested in a patch that throws for the above snippet? Do you have alternative suggestions that might be less absolute?
Maybe throwing an exception is a good first step and can be revisited once there is some user feedback.
Let's say I have the following state:
(def model
(atom
{:people/by-id {1 {:id 1 :name "Bob"} 2 {:id 2 :name "Jane"}}
:departments/by-id {0 {:name "Software" :people #{} :id 0}
1 {:name "Marketing" :people #{} :id 1}
2 {:name "HR" :people #{[:people/by-id 1] [:people/by-id 2]} :id 2}}}))
Using Reagent's track I could get a materialised view into the departments, meaning that they'd have the actual employee data and not just the idents, by first defining a function something like this:
(defn materialised-departments [atom]
(map
(fn [dept]
(assoc dept :people
(set (map
(fn [emp-q]
(get-in @atom emp-q))
(:people dept)))))
(vals (get-in @atom [:departments/by-id]))))
Then I would use the above function with r/track, to create a materialised view of the departments. My components will handle it just like a normal ratom, and react to its changes.
(let [departments (r/track model/materialised-departments atom)])
Rum (like Reagent) has cursor
, but I don't know if it can be used to accomplish something like this. Honestly, I'm not sure if this issue is a support request / question, or a valid feature request. I'd be happy to hear your thoughts on this!
It took me a while to figure out how to get React's Perf tools working within ClojureScript, and I think it'd be helpful for others to have a section in the Rum README.
I've enclosed a draft below.
I'm not sure the best way to configure Leiningen / cljsbuild / figwheel to keep the Perf tools only in development builds (or if they'll get advanced-optimizationed away) --- I bet it could be done with Leiningen's project.clj :profiles
key, but there may be a better way.
I'd love if someone could chime in on that.
## Profiling
To use [React.js Perf tools](https://facebook.github.io/react/docs/perf.html) from Rum, specify the `react-with-addons` dependency in your `project.clj`, making sure to exclude any transitive react dependencies:
```clj
[rum "0.9.0" :exclusions [cljsjs/react cljsjs/react-dom]]
[cljsjs/react-dom "15.1.0-0" :exclusions [cljsjs/react]]
[cljsjs/react-dom-server "15.1.0-0" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "15.1.0-0"]
```
Then from within your program run:
```clj
(js/React.addons.Perf.start)
;;run your app
(js/React.addons.Perf.stop)
(js/React.addons.Perf.printWasted)
```
and results will be printed to the developer console.
Based on my work of porting my app to Rum, I would like to extract some of the mix-ins I have created into stand alone examples people can refer to. I would like your input on how best to share this work with the community.
Some possibilities:
Do you have a preference?
In rum.clj
, there is
(defn- fn-body? [form]
(and (list? form)
(vector? (first form))))
Why do we need to check if form
is a list here? The reason I ask is that I'm writing a macro that generates a defcs
form. I can't do this because in clojure form is an ArraySeq. form
appears to only be a list when defcs
is expanded directly from cljs.
Following the 'how it all fits together' section in the docs, I'm trying to create and mount a simple React element without using defc
.
I've created a fresh project with the following code:
(def a
(rum/build-class
{:render
(fn [state]
[(sablono.core/html [:div "a"]) state])}
"a-component"))
(rum/mount (rum/element a {} nil) (.-body js/document))
Should this work? it gives me a Uncaught TypeError: Cannot read property 'call' of null
...
stacktrace:
rum.build_class.React.createClass.render @ rum.cljs?rel=1441294910065:96
ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext @ react.inc.js:6975
ReactCompositeComponentMixin._renderValidatedComponent @ react.inc.js:7002
ReactPerf.measure.wrapper @ react.inc.js:13427
ReactCompositeComponentMixin.mountComponent @ react.inc.js:6423
ReactPerf.measure.wrapper @ react.inc.js:13427
relevant code point:
:render
(fn []
(this-as this
(let [state (state this)
[dom next-state] (wrapped-render @state)] ; <<<<<
(vreset! state next-state)
dom)))
I realize that part of the docs is already incorrect because build-class
requires two arguments, and the label-mixin
has a nested map. I'd submit a pull request about those issues but I'd like to get an example working first.
Add the following function:
(defn unmount [node]
(js/ReactDOM.unmountComponentAtNode node))
See https://facebook.github.io/react/blog/2015/10/01/react-render-and-top-level-api.html.
Reproduced on IE11, Win8.
http://tonsky.me/rum/ - when fast typing in input field (like "Color"), some symbols will be missing. There's no such problem with pure react form. Replacing :value
with :defaultValue
fixes the problem, so it seems the problem is with controlled inputs only.
I have a (rum) hiccup-ish snippet in a template, that is rendered differently by the server side code than it is in the client side code, resulting in a React warning.
;; component in cljc
(rum/defc app []
[:input#topics {:type "text"}])
;; server in clj
(rum/render-html (components/app))
;; client in cljs
(rum/mount (components/app) node)
Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <input type="text" id="topi
(server) <input id="topics" type="te
Potential fix might be achieved by using something like https://github.com/amalloy/ordered on both clj and cljs sides, or sorted-map
.
Currently react has attributes whitelist, to be able to use custom attributes you can apply this workaround
(from http://stackoverflow.com/questions/31273093/how-to-add-custom-html-attributes-in-jsx):
Custom attributes are currently not supported. See this open issue for more info: facebook/react#140
As a workaround, you can do something like this in componentDidMount:
componentDidMount: function() {
this.refs.test.getDOMNode().setAttribute('custom-attribute', 'some value');
}
See https://jsfiddle.net/peterjmag/kysymow0/ for a working example. (Inspired by syranide's suggestion in this comment.)
How i can use this workaround with rum? i need to add webkitdirectory to file upload.
Thanks!
Please look https://github.com/Matt-Esch/virtual-dom.
I guess this has similar to rum philosophy regarding state management.
Today i've updated rum to 0.3.0 version and this warning appears:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of pic-likes. See https://fb.me/react-warning-keys for more information.
My pic-likes
component looks like:
(rum/defc pic-likes < rum/static
[{:keys [likes] :as image} user]
(let [likes-count (count likes)
liked (contains? likes (:id user))]
[:a {:class-name "pic-likes"
:href "#like"
:on-click #(do
(.preventDefault %)
(toggle-pic-like image user))}
(pic-likes-counter likes-count)
(icon {:class-name "pic-likes-icon"
:icon (if liked "favorite" "favorite-outline")})]))
If I wrap both pic-counter
and icon
components with with-key
function and give them different keys - problem disappears. But it's kind of strange, you can see I don't iterate over these blocks. They are just siblings.
I'm working on a mixin that inject styles into component and sub-component
this mixin takes a function that take the component state and return a style hash-map and possibly another hash-map of type sub-element-selector -> style-function and so on
for the moment I use dommy for the sub-element-selectors and get raw HTMLelements , i would like to be able to get the value of the rum element that is mounted on in order to feed the corresponding style-fn. I really hope that it is understandable
Is there a way to get a list of all sub rum components of a rum component?
In some cases rum\react is loosing non-default values in state between :did-mount
and :will-unmount
hooks in mixin. It doesn't happen if we manually transfer our state in :transfer-state
hook.
The following example describes the issue https://gist.github.com/narma/46a990def0e1c6f279a2
In this code errors appear if we use dynamic count of children or we change parent elements.
Errors don't happen if we use constant count of children and don't touch parent elements because :will-unmount
doesn't fire at all.
Is this expected and normal behaviour or is this a bug?
https://github.com/tonsky/rum/blob/gh-pages/src/rum/core.cljs#L180
Shouldn't it be the other way around, i.e.
(defn request-render
"Schedules react component to be rendered on next animation frame"
[component]
(when (seq @render-queue)
(schedule render))
(vswap! render-queue conj component))
Cheers!
I'm using Rum to build reusable components.
These components typically don't have local state --- they're "controlled components" that take a value
and on-change
callback as arguments:
(rum/defc *color-picker < rum/static
[color on-change]
[:input {:type "color" :value color :on-change #(on-change (.-value (.-target %)))}])
Their parents use this callback to propagate new values across the app:
(rum/defc *parent < rum/static
[parent-id color]
[:div
[:h1 {:style {:background-color color}} parent-id]
(*color-picker color #(update-color-elsewhere-in-app! parent-id %))])
Semantically everything works great, but I'm having trouble with performance.
Using rum/static
doesn't help because the on-change
callbacks are anonymous functions --- on each render of the parent's body, a new on-change
is created that is not equal to the previous on-change
callback.
Are there any recommended patterns for handling this situation?
The only solution I can think of is to pass the functions in as vars rather than closures.
E.g., the above example would become:
(rum/defc *color-picker < rum/static
[color on-change-args]
[:input {:type "color" :value color :on-change #(apply (first on-change-args) (rest on-change-args) (.-value (.-target %))}])
(rum/defc *parent < rum/static
[parent-id color]
[:div
[:h1 {:style {:background-color color}} parent-id]
(*color-picker color [update-color-elsewhere-in-app! parent-id]))])
but this doesn't strike me as a great solution.
I am not sure I should file this here. But the dependency in core.cljs on core.clj for macros seem to confuse CIDER refactor tool.
{:reason :mranderson046.toolsnamespace.v0v3v0-alpha1.clojure.tools.namespace.dependency/circular-dependency, :node rum.core, :dependency rum.core}
When using derived-atom
a watch is added to all source atoms but there's no way to remove these watches potentially causing stale watches when the derived atom is no longer needed.
I have a very rough implementation that extends the derived atom implementation by a IDisposable
protocol which provides a method that will remove all relevant watches on source atoms:
https://github.com/martinklepsch/derivatives/blob/disposable/src/org/martinklepsch/derived.cljc
Watching a derived atom is broken in this implementation because it's not an atom but that's easily fixable.
Now the question, would you be interested in extending Rum's derived atom to cover this aspect?
If people have a typo in their mixin keys things will silently fail. Would you be open to a PR that logs a warning or similar when an unknown key is passed as part of a mixin map?
In case multi-arity component's fns just call each other with additional arguments, each arity of such self-referencing component still creates its own React component. For instance, this is React's components hierarchy for the tree
example component (notice two tree
's, outer one created by (tree [:a [:b [:c :d [:e] :g]]])
, and inner one - by (tree [:a [:b [:c :d [:e] :g]]] 0)
):
Such behaviour is quite logical when each arity produces slightly different components (or completely different ones), but when they simply call next arity with additional default arguments (like tree
example) wrapping components seem redundant, and can cause some problems (for example, if custom did-mount
is used, it would be called for each wrapping component).
So, is there any chance that in future Rum
would support addition of mixins to the specific arities of multi-arity component and/or would remove redundant wrappers from produced component hierarchy of multi-arity component?
Right now Rum returns [:noscript]
on server when there is no DOM generated.
What it needs to return is a comment like <!--react-empty: %d-->
, where %d
is a data-reactid
(number from the same list of numbers, also taken by sequence).
I'm not exactly sure what's the best way to implement that...
Hi,
Rum works really well in re-natal w/ react-native. However, recent (unreleased) change "Do all re-renders on requestAnimationFrame in a single batch" breaks it. The same is available in react native though.
I did a workaround like this. It works. Maybe there could be a better way rum can support.
(set! js/window.ReactDOM (js/require "react-native"))
Thanks
Using any HTML form controls, e.g. [:input] causes React to emit the following warnings:
Warning: Something is calling a React component directly. Use a factory or JSX instead. See: http://fb.me/react-legacyfactory
Warning: transferPropsTo is deprecated. See http://fb.me/react-transferpropsto for more information.
I spent some time tracking this down to make sure it wasn't something I was doing wrong, and I found the problem in sablono. They create a new React component to wrap each form control, and they are using createClass instead of createElement. This has been fixed in master, although I could not get my app to build using the 3.0.0-snapshot version published to clojars.
I created this issue mainly as a heads up for anyone else who runs into it, so they know that it's expected behavior and nothing is wrong. Also, maybe this can serve as a reminder to update the sablono dependency when they release a new version.
By @dwwoelfel:
I noticed that attributes aren't escaped when Rum builds html with its server-side rendering.
For example,
[:div {:className "\"><script>alert('hi')</script>"}]
is perfectly safe on the cljs side, but will alert if it's rendered on the server.
Problem
In emacs, the mixin macro does not get indented properly. You have to either write your components like this:
(rum/defc text [] < rum/reactive (rum/local "" ::text) ...)
Or, like this:
(rum/defc text [] < rum/reactive
(rum/local "" ::text)
...)
This unfortunately is not pleasing to the eye at all, and can get confusing very quickly as you add more mixins to your component.
Proposed solution
The Emacs plugin, cider, allows you to specify how it should indent a function or macro. You can read about that here. Adding this to rum
would be incredibly helpful!
This might be be just something missing from documentation, but I'm having a small issue getting external components to work. I'm using that like this:
[(.-Route js/ReactRouter) {:name "home"} ]
where window.ReactRouter.Route is the component I want to use. It throws an error from this function.
(defn normalize-element
"Ensure an element vector is of the form [tag-name attrs content]."
[[tag & content]]
(when (not (or (keyword? tag) (symbol? tag) (string? tag)))
(throw (ex-info (str tag " is not a valid element name.") {:tag tag :content content})))
(let [[tag id class] (match-tag tag)
tag-attrs (compact-map {:id id :class class})
map-attrs (first content)]
(if (map? map-attrs)
[tag (merge-with-class tag-attrs map-attrs) (next content)]
[tag tag-attrs content])))
Any pointers on how to get non rum components to work?
rum seems very interesting! I'd love to have components that get data from DataScript and automatically re-render on change. Do you think that is easy to do with rum?
The latest version of sablono
now depends on [cljsjs/react]
which breaks rum
in avanced compilation mode whilst it still depends on [com.facebook/react]
(because there are two competing externs
files).
Would you be interested in a pull request that updates the codebase to depend on [sablono "0.3.1"]
and [cljsjs/react "0.12.2-5"]
and the new foreign libraries features of ClojureScript?
This has the addiontal benefit that you no longer need both index.html
and web/dev.html
since all optimization levels now work with the same template.
Hi,
Is there any non-trivial example using Rum?
thanks in advance.
For more examples, see examples/examples.cljs. Live version of examples is here
https://github.com/tonsky/rum/blob/gh-pages/examples/examples.cljs gives a 404. I think you want to
change it to :
https://github.com/tonsky/rum/blob/gh-pages/examples/rum/examples.cljs
I can compare old and new state in transfer-state
hook, but it's not called on forceUpdate
(and that's what's done in rum/request-render
called by rum/local
mixin among other possible cases).
Here's jsFiddle showing how componentWillReceiveProps
works: http://jsfiddle.net/kb3gN/10756/
rum.derived-atom/derived-atom
has a nice docstring, but it doesn't transfer over to rum.core/derived-atom
, which appears to be undocumented. A fix could be to move the docstring to the def
in rum.core
.
I have one single atom for state.
Some components may want to watch some parts of this atom.
But their parents pure components without data.
For example: page header contain user control. Header doesnt have any data from state, but user control have. In react I pass this state by context. And wrap user control in container that watch data in state and pass as props to user control. I can do it with rum, but I want to know is this best way?
Also my question not about only state atom, but about all things components may want deep in tree.
In my case is state and dispatcher (chan).
(rum/defc input1 < rum/reactive [ref & [attrs]]
[:input (merge {:type "text"
:value @ref
:on-change #(reset! ref (.. % -target -value))}
attrs)])
(rum/defc input2 < rum/reactive
([ref] (input ref nil)
([ref attrs]
[:input (merge {:type "text"
:value @ref
:on-change #(reset! ref (.. % -target -value))}
attrs)]))
I think the two defc
calls above don't work. input1
causes:
WARNING: Use of undeclared Var fcc.app/& at line 12 /Users/martin/.boot/tmp/Users/martin/projects/fun-club/ta/-p9hf6h/fcc/app.cljs
input2
causes
WARNING: Use of undeclared Var fcc.app/attrs at line 16 /Users/martin/.boot/tmp/Users/martin/projects/fun-club/30i/-p9hf6h/fcc/app.cljs
Hello,
In the Readme file, it says:
On higher level, Rum comes with already-built types of components which emulate behavior found in Om, Reagent and Quiescent"
It makes me think that Rum can already work exactly like Reagent, but I think that is not the case because one feature that Reagent can do that Rum cannot do out of the box is the following, as referenced from https://reagent-project.github.io/news/reagent-is-async.html:
... proper batching of renderings even when changes to atoms are done outside of event handlers (which is great for e.g core.async users).
So is there a plan to match at least that feature of Reagent?
Example piece of code below shows an input that can only accept numbers. Typing in alphabet keys will not render the alphabets at all in the input in Reagent, but does render for a split second with the Rum code below.
(def text (atom ""))
(def my-chan (chan))
(rum/defc num-input < rum/reactive []
[:input {:value (rum/react text) :on-change
(fn [e] (put! my-chan (string/replace (.-value (.-target e)) #"[a-zA-Z]*" "")))}])
(go
(while true
(reset! text (string/replace (<! my-chan) #"[a-zA-Z]*" ""))))
(rum/mount (num-input) js/document.body)
@ajchemist has already suggested a solution by using (rum/request-render component) but must be inside the event handler. However does that match the behaviour of Reagent?
Kind regards,
Robin
Could you have a look at this repo https://github.com/visibletrap/rum-issue? I got invalid checksum error with a simple template like
(rum/defc my-comp []
[:div [:div]])
I want to use my own React build. I added
:dependencies [[rum "0.2.6"]]
:exclusions [cljsjs/react]
to my project.clj
but it can't compile Rum now giving this error:
clojure.lang.ExceptionInfo: No such namespace: cljsjs.react at line 1 file:/Users/petrus/.m2/repository/rum/rum/0.2.6/rum-0.2.6.jar!/rum.cljs {:tag :cljs/analysis-error, :file "file:/Users/petrus/.m2/repository/rum/rum/0.2.6/rum-0.2.6.jar!/rum.cljs", :line 1, :column 1}
Is there another way for doing this?
(We were talking about this in chat, but probably here is a better place for discussion).
Posting as requested on Twitter: http://twitter.com/prathyvsh/status/750641432386367489
Using rum.core/render-static-markup solely for server side rendering leads to import of Clojurescript.
Excluding Clojurescript is a no go since Sablono is being pulled in on the core ns.
This can be remedied by using
[rum "0.10.3" :only [server-render]]
on import.
But a better solution could be out there.
defc
is different from almost all of the other def-something
forms seen in the Clojure world in that its first argument is not the name of the thing being defined. Would you consider changing the semantics of it to be (defc name mixin(s) args & body)
instead? I'm guessing your intention was to avoid having two vectors following each other, which might look confusing to a lot of people, but the way it works right now breaks syntax highlighting with most editors.
This is obviously a totally breaking change for a rather petty reason, but I figured that since the project is still so young this might not be such a big deal.
Code like this:
(rum/defc Label [{:keys [id text] :as item}]
(js/console.log (pr-str item) (pr-str text))
[:div {:key id} (str text " ") [:span.badge id]])
outputs this to console:
{:keys [2 "Two"], :as {:id 2, :text "Two"}} nil
I really like rum. Thanks, @tonsky! You have good taste.
Consider adding your reasons for making Rum to the README, to help others decide when and why to choose use Rum over Om, Reagent or Quiescent.
Hello,
Would it be useful for a fn like macro, as to defc stateless component?
I'm thinking it'd be useful for higher-order function/component use cases. Essentially, what :wrap-render mixins do right now.
Thanks!
In reagent you can return the render function instead of directly returning the component description.1
So you can do this, for example:
(defn timer-component []
(let [seconds-elapsed (reagent/atom 0)] ;; setup, and local state
(fn [] ;; inner, render function is returned
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:div "Seconds Elapsed: " @seconds-elapsed])))
I'm wondering what is the corresponding solution in rum.
Using
[rum "0.2.7" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "0.12.2-7"]
Rum causes a React keys warning when a component render body is within a let.
The minimal test case below:
(defn raw-sablono
[]
(sablono.core/html
[:div
[:span "A"]
[:span "B"]]))
(defn let-sablono
[]
(sablono.core/html
(let [x 1]
[:div
[:span "A"]
[:span "B"]])))
(rum/defc raw-rum
[]
[:div
[:span "A"]
[:span "B"]])
(rum/defc let-rum
[]
(let [x 1]
[:div
[:span "A"]
[:span "B"]]))
(rum/defc app
[]
[:div
(raw-sablono)
(let-sablono)
(raw-rum)
(let-rum)])
(.render js/React (app) (.getElementById js/document "container"))
Causes the following warnings in the JavaScript console:
Each child in an array should have a unique "key" prop. Check the render method of app. See http://fb.me/react-warning-keys for more information.
Each child in an array should have a unique "key" prop. Check the render method of let-rum. See http://fb.me/react-warning-keys for more information.
I'm confused by both warnings since none of this code is using sequences --- everything should compile into direct React calls without intermediate arrays.
I've tried debugging by expanding rum's output in a Clojure REPL:
(macroexpand
'(rum/defc app
[]
[:div
[:span]
[:span]]))
but it blows up:
1. Unhandled java.lang.IllegalArgumentException
Syntax error at ([] [:div [:span] [:span]])
rum.clj: 25 rum/parse-defc
rum.clj: 31 rum/-defc
rum.clj: 54 rum/defc
I could just be doing something wrong but Rum seems to be running afoul of the change in React 0.13 to immutable props. See here and here.
(defonce app-state (atom {:text "Hello World!"}))
(rum/defc app < rum/cursored rum/cursored-watch [app-state]
[:h1 (:text @app-state)])
(defn main []
(rum/mount
(app app-state)
(. js/document (getElementById "app"))))
Warning: Don't set .props.:rum/state of the React component <app />. Instead, specify the correct value when initially creating the element or use React.cloneElement to make a new element with updated props.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.