Skip to content

Commit 84696e0

Browse files
Merge pull request #323 from mattrjacobs/static-core
Static core
2 parents df4121b + d2a00ff commit 84696e0

File tree

56 files changed

+2453
-5085
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2453
-5085
lines changed

build.gradle

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
apply from: file('gradle/convention.gradle')
2+
apply from: file('gradle/maven.gradle')
3+
//apply from: file('gradle/check.gradle')
4+
apply from: file('gradle/license.gradle')
5+
apply from: file('gradle/release.gradle')
6+
17
ext.githubProjectName = rootProject.name
28

39
buildscript {
@@ -9,20 +15,55 @@ allprojects {
915
repositories { mavenCentral() }
1016
}
1117

12-
apply from: file('gradle/convention.gradle')
13-
apply from: file('gradle/maven.gradle')
14-
//apply from: file('gradle/check.gradle')
15-
apply from: file('gradle/license.gradle')
16-
apply from: file('gradle/release.gradle')
1718

1819
subprojects {
20+
apply plugin: 'java'
21+
apply plugin: 'eclipse'
22+
apply plugin: 'idea'
1923

2024
group = "com.netflix.${githubProjectName}"
2125

26+
// make 'examples' use the same classpath
27+
configurations {
28+
examplesCompile.extendsFrom compile
29+
examplesRuntime.extendsFrom runtime
30+
}
31+
2232
sourceSets.test.java.srcDir 'src/main/java'
2333

2434
tasks.withType(Javadoc).each {
2535
it.classpath = sourceSets.main.compileClasspath
2636
}
37+
38+
//include /src/examples folder
39+
sourceSets {
40+
examples
41+
}
42+
43+
//include 'examples' in build task
44+
tasks.build {
45+
dependsOn(examplesClasses)
46+
}
47+
48+
eclipse {
49+
classpath {
50+
// include 'provided' dependencies on the classpath
51+
plusConfigurations += configurations.provided
52+
53+
downloadSources = true
54+
downloadJavadoc = true
55+
}
56+
}
57+
58+
idea {
59+
module {
60+
// include 'provided' dependencies on the classpath
61+
scopes.PROVIDED.plus += configurations.provided
62+
}
63+
}
64+
}
65+
66+
project(':rxjava-core') {
67+
sourceSets.test.java.srcDir 'src/test/java'
2768
}
2869

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=0.10.2
1+
version=0.11.0-SNAPSHOT

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=http\://services.gradle.org/distributions/gradle-1.3-bin.zip
6+
distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip

language-adaptors/rxjava-clojure/README.md

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,57 @@
11
# Clojure Adaptor for RxJava
22

3+
This 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.
34

4-
This adaptor allows 'fn' functions to be used and RxJava will know how to invoke them.
5+
# Basic Usage
56

6-
This enables code such as:
7+
## Requiring the interop namespace
8+
The first thing to do is to require the namespace:
79

810
```clojure
9-
(->
10-
(Observable/toObservable ["one" "two" "three"])
11-
(.take 2)
12-
(.subscribe (fn [arg] (println arg))))
11+
(ns my.namespace
12+
(:require [rx.lang.clojure.interop :as rx])
13+
(:import [rx Observable]))
1314
```
1415

15-
This still dependes on Clojure using Java interop against the Java API.
16+
or, at the REPL:
1617

17-
A future goal is a Clojure wrapper to expose the functions in a more idiomatic way.
18+
```clojure
19+
(require '[rx.lang.clojure.interop :as rx])
20+
```
21+
22+
## Using rx/fn
23+
Once the namespace is required, you can use the `rx/fn` macro anywhere RxJava wants a `rx.util.functions.Func` object. The syntax is exactly the same as `clojure.core/fn`:
24+
25+
```clojure
26+
(-> my-observable
27+
(.map (rx/fn [v] (* 2 v))))
28+
```
29+
30+
If 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.util.functions.Func`:
31+
32+
```clojure
33+
(-> my-numbers
34+
(.reduce (rx/fn* +)))
35+
```
36+
37+
## Using rx/action
38+
The `rx/action` macro is identical to `rx/fn` except that the object returned implements `rx.util.functions.Action` interfaces. It's used in `subscribe` and other side-effect-y contexts:
39+
40+
```clojure
41+
(-> my-observable
42+
(.map (rx/fn* transform-data))
43+
(.finallyDo (rx/action [] (println "Finished transform")))
44+
(.subscribe (rx/action [v] (println "Got value" v))
45+
(rx/action [e] (println "Get error" e))
46+
(rx/action [] (println "Sequence complete"))))
47+
```
48+
49+
# Gotchas
50+
Here are a few things to keep in mind when using this interop:
1851

52+
* Keep in mind the (mostly empty) distinction between `Func` and `Action` and which is used in which contexts
53+
* 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.
54+
* 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`.
1955

2056
# Binaries
2157

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
apply plugin: 'java'
21
apply plugin: 'clojure'
3-
apply plugin: 'eclipse'
4-
apply plugin: 'idea'
52
apply plugin: 'osgi'
63

74
dependencies {
85
compile project(':rxjava-core')
9-
provided 'org.clojure:clojure:1.4.+'
10-
provided 'junit:junit-dep:4.10'
11-
provided 'org.mockito:mockito-core:1.8.5'
12-
6+
137
// clojure
14-
testCompile 'clj-http:clj-http:0.6.4' // https://clojars.org/clj-http
8+
compile 'org.clojure:clojure:1.4.+'
9+
//compile 'clj-http:clj-http:0.6.4' // https://clojars.org/clj-http
1510
}
1611

1712
/*
@@ -22,11 +17,10 @@ warnOnReflection = true
2217

2318
buildscript {
2419
repositories { maven { url "http://clojars.org/repo" } }
25-
dependencies { classpath "clojuresque:clojuresque:1.5.4" }
20+
dependencies { classpath "clojuresque:clojuresque:1.5.8" }
2621
}
2722

2823
repositories {
29-
mavenCentral()
3024
clojarsRepo()
3125
}
3226

@@ -37,45 +31,16 @@ eclipse {
3731
project {
3832
natures "ccw.nature"
3933
}
40-
classpath {
41-
plusConfigurations += configurations.provided
42-
downloadSources = true
43-
downloadJavadoc = true
44-
}
45-
}
46-
47-
idea {
48-
module {
49-
// include 'provided' dependencies on the classpath
50-
scopes.PROVIDED.plus += configurations.provided
51-
}
52-
}
53-
54-
55-
eclipse {
56-
classpath {
57-
// include 'provided' dependencies on the classpath
58-
plusConfigurations += configurations.provided
59-
60-
downloadSources = true
61-
downloadJavadoc = true
62-
}
6334
}
6435

65-
// include /src/examples folder
66-
sourceSets {
67-
examples
36+
tasks.clojureTest {
37+
classpath = classpath + configurations.provided
6838
}
6939

70-
// make 'examples' use the same classpath
71-
configurations {
72-
examplesCompile.extendsFrom compile
73-
examplesRuntime.extendsFrom runtime
40+
tasks.compileExamplesClojure {
41+
classpath = classpath + configurations.provided
7442
}
7543

76-
// include 'examples' in build task
77-
build.dependsOn examplesClasses
78-
7944
jar {
8045
manifest {
8146
name = 'rxjava-clojure'
@@ -84,4 +49,4 @@ jar {
8449
instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*'
8550
instruction 'Fragment-Host', 'com.netflix.rxjava.core'
8651
}
87-
}
52+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
(ns rx.lang.clojure.examples.http-examples
2+
(:require [rx.lang.clojure.interop :as rx]
3+
[clj-http.client :as http])
4+
(:import rx.Observable rx.subscriptions.Subscriptions))
5+
6+
; NOTE on naming conventions. I'm using camelCase names (against clojure convention)
7+
; in this file as I'm purposefully keeping functions and methods across
8+
; different language implementations in-sync for easy comparison.
9+
10+
(defn fetchWikipediaArticleAsynchronously [wikipediaArticleNames]
11+
"Fetch a list of Wikipedia articles asynchronously.
12+
13+
return Observable<String> of HTML"
14+
(Observable/create
15+
(rx/fn [observer]
16+
(let [f (future
17+
(doseq [articleName wikipediaArticleNames]
18+
(-> observer (.onNext (http/get (str "http://en.wikipedia.org/wiki/" articleName)))))
19+
; after sending response to onnext we complete the sequence
20+
(-> observer .onCompleted))]
21+
; a subscription that cancels the future if unsubscribed
22+
(Subscriptions/create (rx/action [] (future-cancel f)))))))
23+
24+
; To see output
25+
(comment
26+
(-> (fetchWikipediaArticleAsynchronously ["Tiger" "Elephant"])
27+
(.subscribe (rx/action [v] (println "--- Article ---\n" (subs (:body v) 0 125) "...")))))
28+
29+
30+
; --------------------------------------------------
31+
; Error Handling
32+
; --------------------------------------------------
33+
34+
(defn fetchWikipediaArticleAsynchronouslyWithErrorHandling [wikipediaArticleNames]
35+
"Fetch a list of Wikipedia articles asynchronously
36+
with proper error handling.
37+
38+
return Observable<String> of HTML"
39+
(Observable/create
40+
(rx/fn [observer]
41+
(let [f (future
42+
(try
43+
(doseq [articleName wikipediaArticleNames]
44+
(-> observer (.onNext (http/get (str "http://en.wikipedia.org/wiki/" articleName)))))
45+
;(catch Exception e (prn "exception")))
46+
(catch Exception e (-> observer (.onError e))))
47+
; after sending response to onNext we complete the sequence
48+
(-> observer .onCompleted))]
49+
; a subscription that cancels the future if unsubscribed
50+
(Subscriptions/create (rx/action [] (future-cancel f)))))))
51+
52+
; To see output
53+
(comment
54+
(-> (fetchWikipediaArticleAsynchronouslyWithErrorHandling ["Tiger" "NonExistentTitle" "Elephant"])
55+
(.subscribe (rx/action [v] (println "--- Article ---\n" (subs (:body v) 0 125) "..."))
56+
(rx/action [e] (println "--- Error ---\n" (.getMessage e))))))
57+
58+

0 commit comments

Comments
 (0)