Skip to content

Commit 924dba2

Browse files
authored
Merge pull request #99 from behrica/lazyRDefs
Lazy r defs
2 parents 625822f + ebfe240 commit 924dba2

File tree

8 files changed

+318
-67
lines changed

8 files changed

+318
-67
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ pom.xml.asc
1818
.clay*
1919
*qmd
2020
.clerk
21+
.calva

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
33

44
## unreleased
5-
5+
- added more operators `%/%`, `%%` ,`%in%`, `xor`
66
- use devcontainer setup following template
77

8-
98
## [1.0.0]
109
- `require-r` creates namespace as `r.namespace`, also `namespace` as an alias
1110
- dependencies update, TMD 7.029

deps.edn

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
:extra-deps {org.scicloj/clay {:mvn/version "2-beta16"}
1313
io.github.nextjournal/clerk {:mvn/version "0.7.418"}}}
1414
:test {:extra-paths ["test"]
15-
:extra-deps {io.github.cognitect-labs/test-runner
15+
:extra-deps {org.scicloj/clay {:mvn/version "2-beta8"}
16+
io.github.cognitect-labs/test-runner
1617
{:git/tag "v0.5.0" :git/sha "b3fd0d2"}}
1718
:main-opts ["-m" "cognitect.test-runner"]
19+
:jvm-opts ["-Djava.awt.headless=true" ]
1820
:exec-fn cognitect.test-runner.api/test}}}

project.clj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
55
:url "https://www.eclipse.org/legal/epl-2.0/"}
66
:plugins [[lein-tools-deps "0.4.5"]]
7-
:test-paths ["notebooks"]
7+
:test-paths ["test","notebooks"]
88
:middleware [lein-tools-deps.plugin/resolve-dependencies-with-deps-edn]
99
;; :repositories {"bedatadriven" {:url "https://nexus.bedatadriven.com/content/groups/public/"}}
1010
:lein-tools-deps/config {:config-files [:install :user :project]}
11+
:profiles {
12+
:test {:dependencies [[org.scicloj/clay "2-beta8"]]}}
13+
1114
:jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/jul-factory"])

src/clojisr/v1/applications/plotting.clj

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,53 +11,57 @@
1111
[java.awt.image BufferedImage]
1212
[javax.swing ImageIcon]))
1313

14-
(require-r '[grDevices])
1514

16-
(def files->fns (atom (let [devices (select-keys (ns-publics 'r.grDevices) '[pdf png svg jpeg tiff bmp])]
17-
(if-let [jpg (get devices 'jpeg)]
18-
(let [devices (assoc devices 'jpg jpg)]
19-
(if (-> '(%in% "svglite" (rownames (installed.packages))) ;; check if svglite is available
20-
(r)
21-
(r->clj)
22-
(first))
23-
(assoc devices 'svg (rsymbol "svglite" "svglite"))
24-
(do (log/warn [::plotting {:messaage "We highly recommend installing of `svglite` package."}])
25-
devices)))
26-
devices))))
15+
16+
17+
(def files->fns (delay
18+
(atom (let [_ (require-r '[grDevices])
19+
devices (select-keys (ns-publics 'r.grDevices) '[pdf png svg jpeg tiff bmp])]
20+
(if-let [jpg (get devices 'jpeg)]
21+
(let [devices (assoc devices 'jpg jpg)]
22+
(if (-> '(%in% "svglite" (rownames (installed.packages))) ;; check if svglite is available
23+
(r)
24+
(r->clj)
25+
(first))
26+
(assoc devices 'svg (rsymbol "svglite" "svglite"))
27+
(do (log/warn [::plotting {:messaage "We highly recommend installing of `svglite` package."}])
28+
devices)))
29+
devices)))))
2730

2831

2932
(defn use-svg!
3033
"Use from now on build-in svg device for plotting svg."
3134
[]
32-
(swap! files->fns assoc 'svg (get (ns-publics 'r.grDevices) 'svg)))
35+
(swap! @files->fns assoc 'svg (get (ns-publics 'r.grDevices) 'svg)))
3336

3437
(defn use-svglite!
3538
"Use from now on svglite device for plotting svg.
3639
Requires package `svglite` to be installed"
3740
[]
38-
(swap! files->fns assoc 'svg (rsymbol "svglite" "svglite")))
41+
(swap! @files->fns assoc 'svg (rsymbol "svglite" "svglite")))
42+
3943

4044

41-
(def ^:private r-print (r "print")) ;; avoid importing `base` here
4245

4346
(defn plot->file
4447
[^String filename plotting-function-or-object & device-params]
45-
(let [apath (.getAbsolutePath (File. filename))
48+
(let [r-print (delay (r "print"))
49+
apath (.getAbsolutePath (File. filename))
4650
extension (symbol (or (second (re-find #"\.(\w+)$" apath)) :no))
47-
device (@files->fns extension)]
48-
(if-not (contains? @files->fns extension)
51+
device (@@files->fns extension)]
52+
(if-not (contains? @@files->fns extension)
4953
(log/warn [::plot->file {:message (format "%s filetype is not supported!" (name extension))}])
5054
(try
5155
(make-parents filename)
5256
(apply device :filename apath device-params)
5357
(let [the-plot-robject (try
5458
(if (instance? RObject plotting-function-or-object)
55-
(r-print plotting-function-or-object)
59+
(@r-print plotting-function-or-object)
5660
(plotting-function-or-object))
5761
(catch Exception e
5862
(log/warn [::plot->file {:message "Evaluation plotting function failed."
5963
:exception (exception-cause e)}]))
60-
(finally (r.grDevices/dev-off)))]
64+
(finally (r "grDevices::dev.off()")))]
6165
(log/debug [[::plot->file {:message (format "File %s saved." apath)}]])
6266
the-plot-robject)
6367
(catch clojure.lang.ExceptionInfo e (throw e))

src/clojisr/v1/r.clj

Lines changed: 159 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
[clojisr.v1.impl.java-to-clj :as java2clj]
1010
[clojisr.v1.impl.clj-to-java :as clj2java]
1111
[clojure.string :as string]
12-
[clojisr.v1.util :refer [bracket-data maybe-wrap-backtick]]
12+
[clojisr.v1.util :refer [maybe-wrap-backtick]]
1313
[clojisr.v1.require :refer [require-r-package]]
1414
[clojisr.v1.engines :refer [engines]])
1515
(:import clojisr.v1.robject.RObject))
@@ -124,40 +124,25 @@
124124
(r (format fmt n (name package)))
125125
(intern *ns* ns (r ns)))))
126126

127-
(def r== (r "`==`"))
128-
(def r!= (r "`!=`"))
129-
(def r< (r "`<`"))
130-
(def r> (r "`>`"))
131-
(def r<= (r "`<=`"))
132-
(def r>= (r "`>=`"))
133-
(def r& (r "`&`"))
134-
(def r&& (r "`&&`"))
135-
(def r| (r "`||`"))
136-
(def r|| (r "`||`"))
137-
(def r! (r "`!`"))
138-
(def r$ (r "`$`"))
139-
140-
(def captured-str
141-
"For the R function [str](https://www.rdocumentation.org/packages/utils/versions/3.6.1/topics/str), we capture the standard output and return the corresponding string."
142-
(r "function(x) capture.output(str(x))"))
143-
144-
(def println-captured-str (comp println-r-lines captured-str))
145-
146-
(def str-md (comp r-lines->md captured-str))
147-
148-
(def r** (r "`^`"))
149-
(def rdiv (r "`/`"))
150-
(def r- (r "`-`"))
151-
(defn r* [& args] (reduce (r "`*`") args))
152-
(defn r+
153-
"The plus operator is a binary one, and we want to use it on an arbitraty number of arguments."
154-
[& args]
155-
(reduce (r "`+`") args))
156127

157-
;; Some special characters will get a name in letters.
158-
(def colon (r "`:`"))
128+
(defn- captured-str []
129+
"For the R function [str](https://www.rdocumentation.org/packages/utils/versions/3.6.1/topics/str), we capture the standard output and return the corresponding string."
130+
(r "function(x) capture.output(str(x))") )
131+
132+
(defn println-captured-str[x]
133+
(->
134+
(apply-function
135+
(captured-str)
136+
[x])
137+
println-r-lines))
138+
139+
(defn str-md [x]
140+
(->
141+
(apply-function
142+
(captured-str)
143+
[x])
144+
r-lines->md))
159145

160-
;;
161146

162147
(defmacro defr
163148
"Create Clojure and R bindings at the same time"
@@ -174,7 +159,7 @@
174159
([package string-or-symbol]
175160
(r (str (maybe-wrap-backtick package) "::" (maybe-wrap-backtick string-or-symbol)))))
176161

177-
;; brackets!
162+
178163

179164
;; FIXME! Waiting for session management.
180165
(defn- prepare-args-for-bra
@@ -185,16 +170,8 @@
185170
(prepare-args-for-bra pars)
186171
(conj (prepare-args-for-bra (butlast pars)) (last pars)))))
187172

188-
(defmacro ^:private make-bras
189-
[]
190-
`(do ~@(for [[bra-sym-name [bra-str all?]] bracket-data
191-
:let [bra-sym (symbol bra-sym-name)]]
192-
`(let [bra# (r ~bra-str)]
193-
(defn ~bra-sym [& pars#]
194-
(let [fixed# (prepare-args-for-bra pars# ~all?)]
195-
(apply bra# fixed#)))))))
196173

197-
(make-bras)
174+
198175

199176
;; register shutdown hook
200177
;; should be called once
@@ -222,3 +199,142 @@
222199
"Prints help for an R object or function"
223200
([r-object] (println (help r-object)))
224201
([function package] (println (help function package))))
202+
203+
204+
;; arithmetic operators
205+
(defn r-
206+
"R arithmetic operator `-`"
207+
[e1 e2] ((r "`-`") e1 e2))
208+
209+
(defn rdiv
210+
"R arithmetic operator `/`"
211+
[e1 e2] ((r "`/`") e1 e2))
212+
213+
(defn r*
214+
"R arithmetic operator `*`, but can be used on an arbitraty number of arguments."
215+
[& args]
216+
(reduce (r "`*`") args))
217+
218+
(defn r+
219+
"R arithmetic operator `+`, but can be used on an arbitraty number of arguments."
220+
[& args]
221+
(reduce (r "`+`") args))
222+
223+
(defn r**
224+
"R arithmetic operator `^`"
225+
[e1 e2]
226+
((r "`^`") e1 e2))
227+
228+
(defn r%div%
229+
"R arithmetic operator `%/%`"
230+
[e1 e2]
231+
((r "`%/%`") e1 e2))
232+
233+
(defn r%%
234+
"R arithmetic operator `%%`"
235+
[e1 e2]
236+
((r "`%%`") e1 e2))
237+
238+
;; relational operators
239+
(defn r==
240+
"R relational operator `==`"
241+
[e1 e2] ( (r "`==`") e1 e2))
242+
243+
(defn r!=
244+
"R relational operator `=!`"
245+
[e1 e2] ((r "`!=`") e1 e2))
246+
247+
(defn r<
248+
"R relational operator `<`"
249+
[e1 e2] ((r "`<`") e1 e2))
250+
251+
(defn r>
252+
"R relational operator `>`"
253+
[e1 e2] ((r "`>`") e1 e2))
254+
255+
(defn r<=
256+
"R relational operator `<=`"
257+
[e1 e2] ((r "`<=`") e1 e2))
258+
259+
(defn r>=
260+
"R relational operator `>=`"
261+
[e1 e2] ((r "`>=`") e1 e2))
262+
263+
;; logical operators
264+
(defn r&
265+
"R logical operator `&`"
266+
[e1 e2] ((r "`&`") e1 e2))
267+
268+
(defn r&&
269+
"R logical operator `&&`"
270+
[e1 e2] ((r "`&&`") e1 e2))
271+
272+
(defn r|
273+
"R logical operator `|`"
274+
[e1 e2] ((r "`|`") e1 e2))
275+
276+
(defn r||
277+
"R logical operator `||`"
278+
[e1 e2] ((r "`||`") e1 e2))
279+
280+
(defn r!
281+
"R logical operator `!`"
282+
[e] ((r "`!`") e))
283+
284+
(defn rxor
285+
"R logical operator `xor`"
286+
[e1 e2] ((r "`xor`") e1 e2))
287+
288+
289+
;; colon operators
290+
(defn colon
291+
"R colon operator `:`"
292+
[e1 e2] ((r "`:`") e1 e2))
293+
(defn rcolon
294+
"R colon operator `:`"
295+
[e1 e2] (colon e1 e2))
296+
297+
;; extract/replace operators
298+
(defn r$
299+
"R extract operator `$`"
300+
[e1 e2] ((r "`$`") e1 e2))
301+
302+
303+
(defn r%in%
304+
"R match operator `%in%`"
305+
[e1 e2] ((r "`%in%`") e1 e2))
306+
307+
308+
309+
(defn bra
310+
"R extract operator `[`"
311+
[& pars]
312+
(let
313+
[bra (clojisr.v1.r/r "`[`")
314+
fixed (prepare-args-for-bra pars true)]
315+
(clojure.core/apply bra fixed)))
316+
317+
(defn brabra
318+
"R extract operator `[[`"
319+
[& pars]
320+
(let
321+
[bra (clojisr.v1.r/r "`[[`")
322+
fixed (prepare-args-for-bra pars true)]
323+
(clojure.core/apply bra fixed)))
324+
325+
(defn bra<-
326+
"R replace operator `[<-`"
327+
[& pars]
328+
(let
329+
[bra (clojisr.v1.r/r "`[<-`")
330+
fixed (prepare-args-for-bra pars false)]
331+
(clojure.core/apply bra fixed)))
332+
333+
(defn brabra<-
334+
"R replace operator `[[<-`"
335+
[& pars]
336+
(let
337+
[bra (clojisr.v1.r/r "`[[<-`")
338+
fixed (prepare-args-for-bra pars false)]
339+
(clojure.core/apply bra fixed)))
340+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
(ns clojisr.v1.applications.plotting-test
2+
(:require [clojisr.v1.applications.plotting :as plot]
3+
[clojisr.v1.r :as r]
4+
[clojure.string :as str]
5+
[clojisr.v1.applications.plotting :refer [plot->svg plot->file plot->buffered-image]]
6+
[clojure.test :refer [is deftest]]))
7+
8+
(r/require-r '[graphics :refer [plot hist]])
9+
10+
(deftest plot-svg
11+
(let [svg
12+
(plot->svg
13+
(fn []
14+
(->> rand
15+
(repeatedly 30)
16+
(reductions +)
17+
(plot :xlab "t"
18+
:ylab "y"
19+
:type "l"))))]
20+
21+
(is ( true?
22+
(str/includes?
23+
svg
24+
"M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625")))))
25+

0 commit comments

Comments
 (0)