{"id":28402385,"url":"https://github.com/reactivex/rxclojure","last_synced_at":"2025-10-05T12:14:51.635Z","repository":{"id":57736116,"uuid":"23095931","full_name":"ReactiveX/RxClojure","owner":"ReactiveX","description":"RxJava bindings for Clojure","archived":false,"fork":false,"pushed_at":"2020-02-22T07:03:09.000Z","size":9513,"stargazers_count":362,"open_issues_count":6,"forks_count":20,"subscribers_count":20,"default_branch":"0.x","last_synced_at":"2025-09-09T20:53:45.353Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ReactiveX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-19T03:45:43.000Z","updated_at":"2025-08-26T14:02:50.000Z","dependencies_parsed_at":"2022-08-23T22:40:27.146Z","dependency_job_id":null,"html_url":"https://github.com/ReactiveX/RxClojure","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ReactiveX/RxClojure","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxClojure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxClojure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxClojure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxClojure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ReactiveX","download_url":"https://codeload.github.com/ReactiveX/RxClojure/tar.gz/refs/heads/0.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveX%2FRxClojure/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278452729,"owners_count":25989219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-01T15:37:47.653Z","updated_at":"2025-10-05T12:14:51.600Z","avatar_url":"https://github.com/ReactiveX.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"Clojure bindings for RxJava.\n\n# Binaries\n\nBinaries and dependency information for Maven, Ivy, Gradle and others can be found at [http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22rxjava-clojure%22).\n\nExample for Leiningen:\n\n```clojure\n[io.reactivex/rxclojure \"x.y.z\"]\n```\n\nand for Gradle:\n\n```groovy\ncompile 'io.reactivex:rxclojure:x.y.z'\n```\n\nand for Maven:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.reactivex\u003c/groupId\u003e\n    \u003cartifactId\u003erxclojure\u003c/artifactId\u003e\n    \u003cversion\u003ex.y.z\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nand for Ivy:\n\n```xml\n\u003cdependency org=\"io.reactivex\" name=\"rxclojure\" rev=\"x.y.z\" /\u003e\n```\n\n# Clojure Bindings\nThis library provides convenient, idiomatic Clojure bindings for RxJava.\n\nThe bindings try to present an API that will be comfortable and familiar to a Clojure programmer that's familiar with the sequence operations in `clojure.core`. It \"fixes\" several issues with using RxJava with raw Java interop, for example:\n\n* Argument lists are in the \"right\" order. So in RxJava, the function applied in `Observable.map` is the second argument, while here it's the first argument with one or more Observables as trailing arguments\n* Operators take normal Clojure functions as arguments, bypassing need for the interop described below\n* Predicates accomodate Clojure's notion of truth\n* Operators are generally names as they would be in `clojure.core` rather than the Rx names\n\nThere is no object wrapping going on. That is, all functions return normal `rx.Observable` objects, so you can always drop back to Java interop for anything that's missing in this wrapper.\n\n## Basic Usage\nMost functionality resides in the `rx.lang.clojure.core` namespace and for the most part looks like normal Clojure sequence manipulation:\n\n```clojure\n(require '[rx.lang.clojure.core :as rx])\n\n(-\u003e\u003e my-observable\n     (rx/map (comp clojure.string/lower-case :first-name))\n     (rx/map clojure.string/lower-case)\n     (rx/filter #{\"bob\"})\n     (rx/distinct)\n     (rx/into []))\n;=\u003e An Observable that emits a single vector of names\n```\n\nBlocking operators, which are useful for testing, but should otherwise be avoided, reside in `rx.lang.clojure.blocking`. For example:\n\n```clojure\n(require '[rx.lang.clojure.blocking :as rxb])\n\n(rxb/doseq [{:keys [first-name]} users-observable]\n  (println \"Hey,\" first-name))\n;=\u003e nil\n```\n\n## Open Issues\n\n* The missing stuff mentioned below\n* `group-by` val-fn variant isn't implemented in RxJava\n* There are some functions for defining customer Observables and Operators (`subscriber`, `operator*`, `observable*`). I don't think these are really enough for serious operator implementation, but I'm hesitant to guess at an abstraction at this point. These will probably change dramatically.\n\n## What's Missing\nThis library is an ongoing work in progress driven primarily by the needs of one team at Netflix. As such some things are currently missing:\n\n* Highly-specific operators that we felt cluttered the API and were easily composed from existing operators, especially since we're in not-Java land. For example, `Observable.sumLong()`.\n* Most everything involving schedulers\n* Most everything involving time\n* `Observable.window` and `Observable.buffer`. Who knows which parts of these beasts to wrap?\n\nOf course, contributions that cover these cases are welcome.\n\n# Low-level Interop\nThis adaptor provides functions and macros to ease Clojure/RxJava interop. In particular, there are functions and macros for turning Clojure functions and code into RxJava `Func*` and `Action*` interfaces without the tedium of manually reifying the interfaces.\n\n## Basic Usage\n\n### Requiring the interop namespace\nThe first thing to do is to require the namespace:\n\n```clojure\n(ns my.namespace\n  (:require [rx.lang.clojure.interop :as rx])\n  (:import [rx Observable]))\n```\n\nor, at the REPL:\n\n```clojure\n(require '[rx.lang.clojure.interop :as rx])\n```\n\n### Using rx/fn\nOnce the namespace is required, you can use the `rx/fn` macro anywhere RxJava wants a `rx.functions.Func` object. The syntax is exactly the same as `clojure.core/fn`:\n\n```clojure\n(-\u003e my-observable\n    (.map (rx/fn [v] (* 2 v))))\n```\n\nIf you already have a plain old Clojure function you'd like to use, you can pass it to the `rx/fn*` function to get a new object that implements `rx.functions.Func`:\n\n```clojure\n(-\u003e my-numbers\n    (.reduce (rx/fn* +)))\n```\n\n### Using rx/action\nThe `rx/action` macro is identical to `rx/fn` except that the object returned implements `rx.functions.Action` interfaces. It's used in `subscribe` and other side-effect-y contexts:\n\n```clojure\n(-\u003e my-observable\n    (.map (rx/fn* transform-data))\n    (.finallyDo (rx/action [] (println \"Finished transform\")))\n    (.subscribe (rx/action [v] (println \"Got value\" v))\n                (rx/action [e] (println \"Get error\" e))\n                (rx/action [] (println \"Sequence complete\"))))\n```\n\n### Using Observable/create\nAs of 0.17, `rx.Observable/create` takes an implementation of `rx.Observable$OnSubscribe` which is basically an alias for `rx.functions.Action1` that takes an `rx.Subscriber` as its argument. Thus, you can just use `rx/action` when creating new observables:\n\n```clojure\n; A simple observable that emits 0..9 taking unsubscribe into account\n(Observable/create (rx/action [^rx.Subscriber s]\n                     (loop [i 0]\n                       (when (and (\u003c i 10) (.isUnsubscribed s))\n                         (.onNext s i)\n                         (recur (inc i))))\n                     (.onCompleted s)))\n```\n\n## Gotchas\nHere are a few things to keep in mind when using this interop:\n\n* Keep in mind the (mostly empty) distinction between `Func` and `Action` and which is used in which contexts\n* If there are multiple Java methods overloaded by `Func` arity, you'll need to use a type hint to let the compiler know which one to choose.\n* Methods that take a predicate (like filter) expect the predicate to return a boolean value. A function that returns a non-boolean value will result in a `ClassCastException`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivex%2Frxclojure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactivex%2Frxclojure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivex%2Frxclojure/lists"}