From 87a259161406d7b165d3d05d35c89c33e80f3321 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Tue, 7 May 2024 12:22:06 +0200 Subject: [PATCH 01/23] proof of concept for attaching :doc metadata to genarte functions --- src/clojisr/v1/require.clj | 48 ++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 567647a..ea7c6ec 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -1,13 +1,16 @@ (ns clojisr.v1.require - (:require [clojisr.v1.session :as session] - [clojisr.v1.using-sessions :as using-sessions] - [clojisr.v1.eval :as evl] - [clojisr.v1.protocols :as prot] - [clojisr.v1.known-classes :as known-classes] - [clojisr.v1.util :as util :refer [clojurize-r-symbol exception-cause]] - [clojisr.v1.impl.common :refer [strange-symbol-name?]] - [clojisr.v1.impl.java-to-clj :refer [java->clj]] - [clojure.tools.logging.readable :as log])) + (:require + [clojisr.v1.eval :as evl] + [clojisr.v1.impl.common :refer [strange-symbol-name?]] + [clojisr.v1.impl.java-to-clj :refer [java->clj]] + [clojisr.v1.known-classes :as known-classes] + [clojisr.v1.protocols :as prot] + [clojisr.v1.session :as session] + [clojisr.v1.impl.java-to-clj :as java2clj] + [clojisr.v1.using-sessions :as using-sessions] + [clojisr.v1.util :as util :refer [clojurize-r-symbol exception-cause]] + [clojure.string :as string] + [clojure.tools.logging.readable :as log])) (defn package-r-object [package-symbol object-symbol] (evl/r (format "{%s::`%s`}" @@ -69,9 +72,34 @@ (seq opt) (list ['& {:keys opt}]) :else '([]))))) + +(defn r->java [r-object] + (using-sessions/r->java r-object)) + +(defn help + "Gets help for an R object or function" + ([r-object] + (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) + split (string/split symbol #"::")] + + (help (second split) (first split)))) + + ([function package] + (->> + (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" + (name function) (name package)) + (session/fetch-or-make nil)) + r->java + java2clj/java->clj + (string/join "\n")))) + + (defn r-symbol->clj-symbol [r-symbol r-object] (if-let [arglists (r-object->arglists r-object)] - (vary-meta r-symbol assoc :arglists arglists) + (vary-meta r-symbol assoc + :arglists arglists + :doc (help r-object)) + r-symbol)) (defn add-to-ns [ns-symbol r-symbol r-object] From 07b6189596e6d2c2c28668d0deced6615320bd9f Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 10:52:07 +0000 Subject: [PATCH 02/23] extrcated help into own ns to avoid repetion and cyclic dependencies --- src/clojisr/v1/help.clj | 26 ++++++++++++++ src/clojisr/v1/r.clj | 14 +++----- src/clojisr/v1/require.clj | 71 +++++++++++++++----------------------- 3 files changed, 59 insertions(+), 52 deletions(-) create mode 100644 src/clojisr/v1/help.clj diff --git a/src/clojisr/v1/help.clj b/src/clojisr/v1/help.clj new file mode 100644 index 0000000..92b88b3 --- /dev/null +++ b/src/clojisr/v1/help.clj @@ -0,0 +1,26 @@ +(ns clojisr.v1.help + (:require [clojisr.v1.eval :as evl] + [clojisr.v1.using-sessions :as using-sessions] + [clojisr.v1.impl.java-to-clj :as java2clj] + [clojure.string :as str] + )) + + +(defn help + "Gets help for an R object or function" + ([r-object session] + (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) + split (str/split symbol #"::")] + + (help (second split) (first split) session))) + + ([function package session] + + (->> + (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" + (name function) (name package)) + session) + + (using-sessions/r->java) + (java2clj/java->clj) + (str/join "\n")))) diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 209e96e..2b37e5d 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -9,9 +9,11 @@ [clojisr.v1.impl.java-to-clj :as java2clj] [clojisr.v1.impl.clj-to-java :as clj2java] [clojure.string :as string] + [clojisr.v1.help :as help] [clojisr.v1.util :refer [bracket-data maybe-wrap-backtick]] [clojisr.v1.require :refer [require-r-package]] - [clojisr.v1.engines :refer [engines]]) + [clojisr.v1.engines :refer [engines]] + [clojisr.v1.robject :as robject]) (:import clojisr.v1.robject.RObject)) (defn init [& {:keys [session-args]}] @@ -206,16 +208,10 @@ (defn help "Gets help for an R object or function" ([r-object] - (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) - split (string/split symbol #"::")] - - (help (second split) (first split)))) + (help/help r-object (session/fetch nil))) ([function package] - (->> - (r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" (name function) (name package))) - r->clj - (string/join "\n")))) + (help/help function package (session/fetch nil)))) (defn print-help diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index ea7c6ec..92b1811 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -6,10 +6,11 @@ [clojisr.v1.known-classes :as known-classes] [clojisr.v1.protocols :as prot] [clojisr.v1.session :as session] - [clojisr.v1.impl.java-to-clj :as java2clj] + [clojisr.v1.using-sessions :as using-sessions] [clojisr.v1.util :as util :refer [clojurize-r-symbol exception-cause]] - [clojure.string :as string] + + [clojisr.v1.help :as help] [clojure.tools.logging.readable :as log])) (defn package-r-object [package-symbol object-symbol] @@ -73,69 +74,53 @@ :else '([]))))) -(defn r->java [r-object] - (using-sessions/r->java r-object)) -(defn help - "Gets help for an R object or function" - ([r-object] - (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) - split (string/split symbol #"::")] - - (help (second split) (first split)))) - - ([function package] - (->> - (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" - (name function) (name package)) - (session/fetch-or-make nil)) - r->java - java2clj/java->clj - (string/join "\n")))) - - -(defn r-symbol->clj-symbol [r-symbol r-object] +(defn r-symbol->clj-symbol [session r-symbol r-object] + (println :add-symbol r-symbol) (if-let [arglists (r-object->arglists r-object)] (vary-meta r-symbol assoc :arglists arglists - :doc (help r-object)) + :doc (help/help r-object session) + ) r-symbol)) -(defn add-to-ns [ns-symbol r-symbol r-object] +(defn add-to-ns [session ns-symbol r-symbol r-object] (intern ns-symbol - (r-symbol->clj-symbol r-symbol r-object) + (r-symbol->clj-symbol session r-symbol r-object) r-object)) -(defn symbols->add-to-ns [ns-symbol r-symbols] +(defn symbols->add-to-ns [session ns-symbol r-symbols] (doseq [[r-symbol r-object] r-symbols] - (add-to-ns ns-symbol r-symbol r-object))) + (add-to-ns session ns-symbol r-symbol r-object))) (defn require-r-package [[package-symbol & {:keys [as refer]}]] (try (let [session (session/fetch-or-make nil)] - (evl/eval-form `(library ~package-symbol) session)) - (let [r-ns-symbol (->> package-symbol - (str "r.") - symbol) - r-symbols (all-r-symbols-map package-symbol)] + (evl/eval-form `(library ~package-symbol) session) + (let [r-ns-symbol (->> package-symbol + (str "r.") + symbol) + r-symbols (all-r-symbols-map package-symbol)] ;; r.package namespace - (find-or-create-ns r-ns-symbol) - (symbols->add-to-ns r-ns-symbol r-symbols) + (find-or-create-ns r-ns-symbol) + (symbols->add-to-ns session r-ns-symbol r-symbols) ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python - (alias package-symbol r-ns-symbol) - (when as (alias as r-ns-symbol)) + (alias package-symbol r-ns-symbol) + (when as (alias as r-ns-symbol)) ;; inject symbol into current namespace - (when refer - (let [this-ns-symbol (-> *ns* str symbol)] - (symbols->add-to-ns this-ns-symbol - (if (= refer :all) - r-symbols - (select-keys r-symbols refer)))))) + (when refer + (let [this-ns-symbol (-> *ns* str symbol)] + (symbols->add-to-ns + session + this-ns-symbol + (if (= refer :all) + r-symbols + (select-keys r-symbols refer))))))) (catch Exception e (log/warn [::require-r-package {:package-symbol package-symbol :cause (exception-cause e)}]) From 4b4d162471c7144a4ecf60c0217af34c8a480c08 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 11:34:15 +0000 Subject: [PATCH 03/23] aaded a global flag (default off), which controls if help is attached --- src/clojisr/v1/help.clj | 6 ++++-- src/clojisr/v1/require.clj | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/clojisr/v1/help.clj b/src/clojisr/v1/help.clj index 92b88b3..a67655e 100644 --- a/src/clojisr/v1/help.clj +++ b/src/clojisr/v1/help.clj @@ -6,13 +6,13 @@ )) -(defn help +(defn _help "Gets help for an R object or function" ([r-object session] (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) split (str/split symbol #"::")] - (help (second split) (first split) session))) + (_help (second split) (first split) session))) ([function package session] @@ -24,3 +24,5 @@ (using-sessions/r->java) (java2clj/java->clj) (str/join "\n")))) + +(def help (memoize _help)) \ No newline at end of file diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 92b1811..d6217d2 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -13,6 +13,9 @@ [clojisr.v1.help :as help] [clojure.tools.logging.readable :as log])) + +(def attach-help-as-docstring-to-vars (atom false)) + (defn package-r-object [package-symbol object-symbol] (evl/r (format "{%s::`%s`}" (name package-symbol) @@ -76,11 +79,15 @@ (defn r-symbol->clj-symbol [session r-symbol r-object] - (println :add-symbol r-symbol) + (if-let [arglists (r-object->arglists r-object)] (vary-meta r-symbol assoc :arglists arglists - :doc (help/help r-object session) + :doc (if @attach-help-as-docstring-to-vars + (do + (println :attach-help r-symbol) + (help/help r-object session)) + "no help was attached, as *attach-help-as-docstring-to-vars* is false" ) ) r-symbol)) From 66feb0f002bffeacba64dd5f5561d09d4f968235 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 13:50:34 +0000 Subject: [PATCH 04/23] refcatored and added tests --- .gitignore | 1 + src/clojisr/v1/require.clj | 29 +++++++++++++------------ src/clojisr/v1/util.clj | 8 +++++++ test/clojisr/v1/tutorials/help_test.clj | 29 +++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 test/clojisr/v1/tutorials/help_test.clj diff --git a/.gitignore b/.gitignore index f478dd0..54edb37 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ pom.xml.asc .clay* *qmd .clerk +.calva diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index d6217d2..b194a7c 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -8,10 +8,12 @@ [clojisr.v1.session :as session] [clojisr.v1.using-sessions :as using-sessions] - [clojisr.v1.util :as util :refer [clojurize-r-symbol exception-cause]] + [clojisr.v1.util :refer [clojurize-r-symbol exception-cause if-assoc-meta]] [clojisr.v1.help :as help] - [clojure.tools.logging.readable :as log])) + [clojure.tools.logging.readable :as log] + [vrksasana.util :as util] + [clojisr.v1.robject :as robject])) (def attach-help-as-docstring-to-vars (atom false)) @@ -77,20 +79,19 @@ :else '([]))))) +(defn r-symbol->clj-symbol [session r-symbol r-object] + (let [arglists (r-object->arglists r-object)] -(defn r-symbol->clj-symbol [session r-symbol r-object] - - (if-let [arglists (r-object->arglists r-object)] - (vary-meta r-symbol assoc - :arglists arglists - :doc (if @attach-help-as-docstring-to-vars - (do - (println :attach-help r-symbol) - (help/help r-object session)) - "no help was attached, as *attach-help-as-docstring-to-vars* is false" ) - ) + (cond-> r-symbol + arglists (vary-meta + assoc + :arglists arglists) - r-symbol)) + + @attach-help-as-docstring-to-vars + (if-assoc-meta :doc (do + (println :attach-help r-symbol) + (help/help r-object session)))))) (defn add-to-ns [session ns-symbol r-symbol r-object] (intern ns-symbol diff --git a/src/clojisr/v1/util.clj b/src/clojisr/v1/util.clj index b1cb6ee..b7ed7a6 100644 --- a/src/clojisr/v1/util.clj +++ b/src/clojisr/v1/util.clj @@ -96,6 +96,14 @@ (recur threaded (next forms))) x))) + +(defn if-assoc-meta + "If value non-nil, assoc it to meta with key" + [s k v] + (if ( some? v) + (vary-meta s assoc k v) + s)) + (comment (-|> 4 :+ diff --git a/test/clojisr/v1/tutorials/help_test.clj b/test/clojisr/v1/tutorials/help_test.clj new file mode 100644 index 0000000..ac2ca06 --- /dev/null +++ b/test/clojisr/v1/tutorials/help_test.clj @@ -0,0 +1,29 @@ +(ns clojisr.v1.tutorials.help-test + (:require + [clojure.string :as str] + [clojure.test :refer [is deftest]] + [clojisr.v1.r :as r])) + + +(r/require-r '[randomForest]) + +(deftest help-with-doctrsing + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) + (r/require-r '[randomForest]) + (is (str/starts-with? + (:doc (meta (var r.randomForest/randomForest))) + "Classification and Regression with Random Forest"))) + + +(deftest help-without-doctrsing + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) + (r/require-r '[randomForest]) + (is (nil? + (:doc (meta (var r.randomForest/randomForest)))) + )) + +(deftest help-function + (is (str/starts-with? + (r/help "randomForest" "randomForest") + "Classification and Regression with Random Forest" + ))) \ No newline at end of file From 0a1bf3742d55bed5963bb984cf5464c872d05c74 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 15:24:17 +0000 Subject: [PATCH 05/23] moved test --- test/clojisr/v1/{tutorials => }/help_test.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/clojisr/v1/{tutorials => }/help_test.clj (95%) diff --git a/test/clojisr/v1/tutorials/help_test.clj b/test/clojisr/v1/help_test.clj similarity index 95% rename from test/clojisr/v1/tutorials/help_test.clj rename to test/clojisr/v1/help_test.clj index ac2ca06..a4eac03 100644 --- a/test/clojisr/v1/tutorials/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -1,4 +1,4 @@ -(ns clojisr.v1.tutorials.help-test +(ns clojisr.v1.help-test (:require [clojure.string :as str] [clojure.test :refer [is deftest]] From 42ad811fb767390a48d968133bc0a8530160ff3c Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 19:54:16 +0000 Subject: [PATCH 06/23] made tests more robust --- .devcontainer/Dockerfile | 2 +- deps.edn | 4 +++- src/clojisr/v1/r.clj | 1 + src/clojisr/v1/require.clj | 6 ++++- test/clojisr/v1/help_test.clj | 23 +++++++++++++++---- .../v1/tutorials/main_generated_test.clj | 7 +++--- 6 files changed, 31 insertions(+), 12 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b4b07f7..a4cb80c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,4 +2,4 @@ FROM mcr.microsoft.com/devcontainers/java:11-bullseye RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)" RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/clojure-lsp/clojure-lsp/master/install)" -RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake +RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake libxtst6:i386 sudo apt-get install libxi6 diff --git a/deps.edn b/deps.edn index c75cccf..7fac3e7 100644 --- a/deps.edn +++ b/deps.edn @@ -8,11 +8,13 @@ org.scicloj/kindly {:mvn/version "4-beta4"}} :paths ["src"] :aliases {:dev {:extra-paths ["resources" "notebooks"] - :jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/jul-factory"] + :jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/jul-factory" + "-Djava.awt.headless=true"] :extra-deps {org.scicloj/clay {:mvn/version "2-beta8"} io.github.nextjournal/clerk {:mvn/version "0.7.418"}}} :test {:extra-paths ["test"] :extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.0" :git/sha "b3fd0d2"}} + :jvm-opts ["-Djava.awt.headless=true"] :main-opts ["-m" "cognitect.test-runner"] :exec-fn cognitect.test-runner.api/test}}} diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 2b37e5d..9262e97 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -218,3 +218,4 @@ "Prints help for an R object or function" ([r-object] (println (help r-object))) ([function package] (println (help function package)))) + diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index b194a7c..539cca3 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -78,6 +78,10 @@ (seq opt) (list ['& {:keys opt}]) :else '([]))))) +(defn safe-help [r-object session] + (try + (help/help r-object session) + (catch Exception e ""))) (defn r-symbol->clj-symbol [session r-symbol r-object] (let [arglists (r-object->arglists r-object)] @@ -91,7 +95,7 @@ @attach-help-as-docstring-to-vars (if-assoc-meta :doc (do (println :attach-help r-symbol) - (help/help r-object session)))))) + (safe-help r-object session)))))) (defn add-to-ns [session ns-symbol r-symbol r-object] (intern ns-symbol diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index a4eac03..b182d8c 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -7,12 +7,14 @@ (r/require-r '[randomForest]) -(deftest help-with-doctrsing - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) + +(deftest help-with-docstring +(reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) (r/require-r '[randomForest]) (is (str/starts-with? (:doc (meta (var r.randomForest/randomForest))) - "Classification and Regression with Random Forest"))) + "Classification and Regression with Random Forest")) + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false)) (deftest help-without-doctrsing @@ -25,5 +27,16 @@ (deftest help-function (is (str/starts-with? (r/help "randomForest" "randomForest") - "Classification and Regression with Random Forest" - ))) \ No newline at end of file + "Classification and Regression with Random Forest"))) + +(deftest require-defauls-should-not-throws-exception + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) + ; should not crash + (r/require-r '[base]) + (r/require-r '[stats]) + (r/require-r '[utils]) + (r/require-r '[graphics]) + (r/require-r '[datasets]) + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) + ) + diff --git a/test/clojisr/v1/tutorials/main_generated_test.clj b/test/clojisr/v1/tutorials/main_generated_test.clj index de411a9..e8c37f7 100644 --- a/test/clojisr/v1/tutorials/main_generated_test.clj +++ b/test/clojisr/v1/tutorials/main_generated_test.clj @@ -1087,11 +1087,10 @@ (md "As we saw earlier, R functions are Clojure functions. The arglists of functions brought up by `require-r` match the expected arguments. Here are some examples:")) - +(reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) (def var251 (require-r '[base] '[stats] '[grDevices])) - -(def + (def var252 (->> [#'r.base/mean @@ -1102,7 +1101,7 @@ #'r.base/summary-default #'r.base/sin #'r.base/sum] - (map (fn [f] (-> f meta (update :ns (comp symbol str))))))) + (mapv (fn [f] (-> f meta (update :ns (comp symbol str))))))) (deftest From ec67fc7e69093fdcaad8b50fdc834678eb1b5999 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 20:45:06 +0000 Subject: [PATCH 07/23] make memoize work --- src/clojisr/v1/help.clj | 40 ++++++++++++++++++++++------------- src/clojisr/v1/r.clj | 4 ++-- src/clojisr/v1/require.clj | 25 +++++++++------------- test/clojisr/v1/help_test.clj | 4 ++-- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/clojisr/v1/help.clj b/src/clojisr/v1/help.clj index a67655e..3c08c72 100644 --- a/src/clojisr/v1/help.clj +++ b/src/clojisr/v1/help.clj @@ -3,26 +3,36 @@ [clojisr.v1.using-sessions :as using-sessions] [clojisr.v1.impl.java-to-clj :as java2clj] [clojure.string :as str] - )) + [clojisr.v1.session :as session] + + [clojisr.v1.help :as help])) +(defn- un-back-quote [s] + (str/replace s "`" "" )) -(defn _help +(defn _get-help[function package] + ;(println :obtain-help (format "%s/%s " (name package) (un-back-quote (name function)))) + (->> + (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" + (name function) (name package)) + (session/fetch-or-make nil)) + + (using-sessions/r->java) + (java2clj/java->clj) + (str/join "\n"))) + +(defonce get-help (memoize _get-help)) + +(defn help + "Gets help for an R object or function" - ([r-object session] + ([r-object] (let [symbol (second (re-find #"\{(.*)\}" (:code r-object))) split (str/split symbol #"::")] - (_help (second split) (first split) session))) + (get-help (second split) (first split) ))) + + ) + - ([function package session] - - (->> - (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" - (name function) (name package)) - session) - - (using-sessions/r->java) - (java2clj/java->clj) - (str/join "\n")))) -(def help (memoize _help)) \ No newline at end of file diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 9262e97..124e09d 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -208,10 +208,10 @@ (defn help "Gets help for an R object or function" ([r-object] - (help/help r-object (session/fetch nil))) + (help/help r-object )) ([function package] - (help/help function package (session/fetch nil)))) + (help/get-help function package ))) (defn print-help diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 539cca3..d146873 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -11,9 +11,7 @@ [clojisr.v1.util :refer [clojurize-r-symbol exception-cause if-assoc-meta]] [clojisr.v1.help :as help] - [clojure.tools.logging.readable :as log] - [vrksasana.util :as util] - [clojisr.v1.robject :as robject])) + [clojure.tools.logging.readable :as log])) (def attach-help-as-docstring-to-vars (atom false)) @@ -78,12 +76,12 @@ (seq opt) (list ['& {:keys opt}]) :else '([]))))) -(defn safe-help [r-object session] +(defn safe-help [r-object] (try - (help/help r-object session) + (help/help r-object) (catch Exception e ""))) -(defn r-symbol->clj-symbol [session r-symbol r-object] +(defn r-symbol->clj-symbol [ r-symbol r-object] (let [arglists (r-object->arglists r-object)] (cond-> r-symbol @@ -93,18 +91,16 @@ @attach-help-as-docstring-to-vars - (if-assoc-meta :doc (do - (println :attach-help r-symbol) - (safe-help r-object session)))))) + (if-assoc-meta :doc (safe-help r-object ))))) -(defn add-to-ns [session ns-symbol r-symbol r-object] +(defn add-to-ns [ ns-symbol r-symbol r-object] (intern ns-symbol - (r-symbol->clj-symbol session r-symbol r-object) + (r-symbol->clj-symbol r-symbol r-object) r-object)) -(defn symbols->add-to-ns [session ns-symbol r-symbols] +(defn symbols->add-to-ns [ns-symbol r-symbols] (doseq [[r-symbol r-object] r-symbols] - (add-to-ns session ns-symbol r-symbol r-object))) + (add-to-ns ns-symbol r-symbol r-object))) (defn require-r-package [[package-symbol & {:keys [as refer]}]] (try @@ -117,7 +113,7 @@ ;; r.package namespace (find-or-create-ns r-ns-symbol) - (symbols->add-to-ns session r-ns-symbol r-symbols) + (symbols->add-to-ns r-ns-symbol r-symbols) ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python @@ -128,7 +124,6 @@ (when refer (let [this-ns-symbol (-> *ns* str symbol)] (symbols->add-to-ns - session this-ns-symbol (if (= refer :all) r-symbols diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index b182d8c..83e2209 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -4,12 +4,12 @@ [clojure.test :refer [is deftest]] [clojisr.v1.r :as r])) - +(reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) (r/require-r '[randomForest]) (deftest help-with-docstring -(reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) + (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) (r/require-r '[randomForest]) (is (str/starts-with? (:doc (meta (var r.randomForest/randomForest))) From 0df3e68c9593ab8658a7b6ff895193a545e3620e Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 20:53:01 +0000 Subject: [PATCH 08/23] fixed syntax error in Dockerfile --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index a4cb80c..385f431 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,4 +2,4 @@ FROM mcr.microsoft.com/devcontainers/java:11-bullseye RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)" RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/clojure-lsp/clojure-lsp/master/install)" -RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake libxtst6:i386 sudo apt-get install libxi6 +RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake libxtst6:i386 libxi6 From 5a830cbb7137493c08c2b5e83af5e4ebe0b9f81c Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 8 May 2024 20:57:35 +0000 Subject: [PATCH 09/23] fixed apt get --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 385f431..e9943a7 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,4 +2,4 @@ FROM mcr.microsoft.com/devcontainers/java:11-bullseye RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)" RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/clojure-lsp/clojure-lsp/master/install)" -RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake libxtst6:i386 libxi6 +RUN apt-get update && apt-get install -y rlwrap gfortran libblas-dev liblapack-dev libpng-dev libfontconfig1-dev libfreetype-dev gfortran libicu-dev cmake libxi6 From b74e11d96c6bd9dc211e9d4afb7d82c2a792130a Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sat, 11 May 2024 22:42:15 +0000 Subject: [PATCH 10/23] updated jsd version to fix CI build --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e9943a7..19b4495 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/java:11-bullseye +FROM mcr.microsoft.com/devcontainers/java:21-bookworm RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)" RUN bash -c "bash < <(curl -s https://raw.githubusercontent.com/clojure-lsp/clojure-lsp/master/install)" From 8d38dc0ce30ded1c557e936043298b817bf9e75d Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sat, 11 May 2024 22:44:01 +0000 Subject: [PATCH 11/23] postpone help attaching va future --- src/clojisr/v1/r.clj | 7 ++++++- src/clojisr/v1/require.clj | 18 +++++++++--------- test/clojisr/v1/help_test.clj | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 124e09d..2ae6681 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -81,7 +81,12 @@ (functions/apply-function r-function args session))) (defn require-r [& packages] - (run! require-r-package packages)) + (run! require-r-package packages) + (future (run! #(require-r-package + (concat % [ :load-help? true])) + packages)) + nil + ) (def function functions/function) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index d146873..2e4693e 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -14,7 +14,7 @@ [clojure.tools.logging.readable :as log])) -(def attach-help-as-docstring-to-vars (atom false)) + (defn package-r-object [package-symbol object-symbol] (evl/r (format "{%s::`%s`}" @@ -81,7 +81,7 @@ (help/help r-object) (catch Exception e ""))) -(defn r-symbol->clj-symbol [ r-symbol r-object] +(defn r-symbol->clj-symbol [ r-symbol r-object load-help?] (let [arglists (r-object->arglists r-object)] (cond-> r-symbol @@ -90,19 +90,19 @@ :arglists arglists) - @attach-help-as-docstring-to-vars + load-help? (if-assoc-meta :doc (safe-help r-object ))))) -(defn add-to-ns [ ns-symbol r-symbol r-object] +(defn add-to-ns [ ns-symbol r-symbol r-object load-help?] (intern ns-symbol - (r-symbol->clj-symbol r-symbol r-object) + (r-symbol->clj-symbol r-symbol r-object load-help?) r-object)) -(defn symbols->add-to-ns [ns-symbol r-symbols] +(defn symbols->add-to-ns [ns-symbol r-symbols load-help?] (doseq [[r-symbol r-object] r-symbols] - (add-to-ns ns-symbol r-symbol r-object))) + (add-to-ns ns-symbol r-symbol r-object load-help?))) -(defn require-r-package [[package-symbol & {:keys [as refer]}]] +(defn require-r-package [[package-symbol & {:keys [as refer load-help?]}]] (try (let [session (session/fetch-or-make nil)] (evl/eval-form `(library ~package-symbol) session) @@ -113,7 +113,7 @@ ;; r.package namespace (find-or-create-ns r-ns-symbol) - (symbols->add-to-ns r-ns-symbol r-symbols) + (symbols->add-to-ns r-ns-symbol r-symbols load-help?) ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 83e2209..48d7feb 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -8,6 +8,7 @@ (r/require-r '[randomForest]) + (deftest help-with-docstring (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) (r/require-r '[randomForest]) From 09d129f1c1b285ec79a4ae16c9c92c980aed2aa0 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sat, 11 May 2024 22:59:39 +0000 Subject: [PATCH 12/23] fixed tests --- src/clojisr/v1/require.clj | 3 ++- test/clojisr/v1/help_test.clj | 24 +++++-------------- .../v1/tutorials/main_generated_test.clj | 2 +- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 2e4693e..a005a75 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -127,7 +127,8 @@ this-ns-symbol (if (= refer :all) r-symbols - (select-keys r-symbols refer))))))) + (select-keys r-symbols refer)) + load-help?))))) (catch Exception e (log/warn [::require-r-package {:package-symbol package-symbol :cause (exception-cause e)}]) diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 48d7feb..6fabfee 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -4,40 +4,28 @@ [clojure.test :refer [is deftest]] [clojisr.v1.r :as r])) -(reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) (r/require-r '[randomForest]) - - -(deftest help-with-docstring - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) +(deftest help-docstring (r/require-r '[randomForest]) + (Thread/sleep 10000) (is (str/starts-with? (:doc (meta (var r.randomForest/randomForest))) - "Classification and Regression with Random Forest")) - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false)) - - -(deftest help-without-doctrsing - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) - (r/require-r '[randomForest]) - (is (nil? - (:doc (meta (var r.randomForest/randomForest)))) - )) - + "Classification and Regression with Random Forest"))) + (deftest help-function (is (str/starts-with? (r/help "randomForest" "randomForest") "Classification and Regression with Random Forest"))) (deftest require-defauls-should-not-throws-exception - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars true) + ; should not crash (r/require-r '[base]) (r/require-r '[stats]) (r/require-r '[utils]) (r/require-r '[graphics]) (r/require-r '[datasets]) - (reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) + ) diff --git a/test/clojisr/v1/tutorials/main_generated_test.clj b/test/clojisr/v1/tutorials/main_generated_test.clj index e8c37f7..efde523 100644 --- a/test/clojisr/v1/tutorials/main_generated_test.clj +++ b/test/clojisr/v1/tutorials/main_generated_test.clj @@ -1087,7 +1087,7 @@ (md "As we saw earlier, R functions are Clojure functions. The arglists of functions brought up by `require-r` match the expected arguments. Here are some examples:")) -(reset! clojisr.v1.require/attach-help-as-docstring-to-vars false) + (def var251 (require-r '[base] '[stats] '[grDevices])) (def From 3ea82e6c5dfe5aae54f267ba1fa0926631ae9f57 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sun, 12 May 2024 14:42:41 +0000 Subject: [PATCH 13/23] refactored help->:doc and use alter-meta! to set it in a future, always removed flag for it --- src/clojisr/v1/help.clj | 5 ++-- src/clojisr/v1/r.clj | 7 +----- src/clojisr/v1/require.clj | 45 +++++++++++++++++++---------------- src/clojisr/v1/util.clj | 6 ----- test/clojisr/v1/help_test.clj | 1 - 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/clojisr/v1/help.clj b/src/clojisr/v1/help.clj index 3c08c72..53159cb 100644 --- a/src/clojisr/v1/help.clj +++ b/src/clojisr/v1/help.clj @@ -13,7 +13,8 @@ (defn _get-help[function package] ;(println :obtain-help (format "%s/%s " (name package) (un-back-quote (name function)))) (->> - (evl/r (format "capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE)))" + (evl/r (format + "tryCatch(capture.output(tools:::Rd2txt(utils:::.getHelpFile(as.character(help(%s,%s))), options=list(underline_titles=FALSE))),error=function(e) {return( \"no doc available\")})" (name function) (name package)) (session/fetch-or-make nil)) @@ -21,7 +22,7 @@ (java2clj/java->clj) (str/join "\n"))) -(defonce get-help (memoize _get-help)) +(def get-help (memoize _get-help)) (defn help diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 2ae6681..124e09d 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -81,12 +81,7 @@ (functions/apply-function r-function args session))) (defn require-r [& packages] - (run! require-r-package packages) - (future (run! #(require-r-package - (concat % [ :load-help? true])) - packages)) - nil - ) + (run! require-r-package packages)) (def function functions/function) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index a005a75..3e38984 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -8,7 +8,7 @@ [clojisr.v1.session :as session] [clojisr.v1.using-sessions :as using-sessions] - [clojisr.v1.util :refer [clojurize-r-symbol exception-cause if-assoc-meta]] + [clojisr.v1.util :refer [clojurize-r-symbol exception-cause]] [clojisr.v1.help :as help] [clojure.tools.logging.readable :as log])) @@ -76,33 +76,39 @@ (seq opt) (list ['& {:keys opt}]) :else '([]))))) -(defn safe-help [r-object] +(defn- safe-help [r-object] (try (help/help r-object) (catch Exception e ""))) -(defn r-symbol->clj-symbol [ r-symbol r-object load-help?] - (let [arglists (r-object->arglists r-object)] +(defn r-symbol->clj-symbol [ r-symbol r-object] + + (if-let [arglists (r-object->arglists r-object)] + (vary-meta r-symbol assoc :arglists arglists) + r-symbol)) - (cond-> r-symbol - arglists (vary-meta - assoc - :arglists arglists) +(defn- alter-meta-doc-in-future! [ns-symbol r-symbol r-object] + (future + (Thread/sleep 5000) + (alter-meta! + (get (ns-publics ns-symbol) r-symbol) + assoc :doc (safe-help r-object)))) - load-help? - (if-assoc-meta :doc (safe-help r-object ))))) - -(defn add-to-ns [ ns-symbol r-symbol r-object load-help?] +(defn add-to-ns [ ns-symbol r-symbol r-object] (intern ns-symbol - (r-symbol->clj-symbol r-symbol r-object load-help?) - r-object)) + (r-symbol->clj-symbol r-symbol r-object) + r-object) + + (alter-meta-doc-in-future! ns-symbol r-symbol r-object) + ns-symbol) + -(defn symbols->add-to-ns [ns-symbol r-symbols load-help?] +(defn symbols->add-to-ns [ns-symbol r-symbols] (doseq [[r-symbol r-object] r-symbols] - (add-to-ns ns-symbol r-symbol r-object load-help?))) + (add-to-ns ns-symbol r-symbol r-object))) -(defn require-r-package [[package-symbol & {:keys [as refer load-help?]}]] +(defn require-r-package [[package-symbol & {:keys [as refer]}]] (try (let [session (session/fetch-or-make nil)] (evl/eval-form `(library ~package-symbol) session) @@ -113,7 +119,7 @@ ;; r.package namespace (find-or-create-ns r-ns-symbol) - (symbols->add-to-ns r-ns-symbol r-symbols load-help?) + (symbols->add-to-ns r-ns-symbol r-symbols) ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python @@ -127,8 +133,7 @@ this-ns-symbol (if (= refer :all) r-symbols - (select-keys r-symbols refer)) - load-help?))))) + (select-keys r-symbols refer))))))) (catch Exception e (log/warn [::require-r-package {:package-symbol package-symbol :cause (exception-cause e)}]) diff --git a/src/clojisr/v1/util.clj b/src/clojisr/v1/util.clj index b7ed7a6..e41c18b 100644 --- a/src/clojisr/v1/util.clj +++ b/src/clojisr/v1/util.clj @@ -97,12 +97,6 @@ x))) -(defn if-assoc-meta - "If value non-nil, assoc it to meta with key" - [s k v] - (if ( some? v) - (vary-meta s assoc k v) - s)) (comment (-|> 4 diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 6fabfee..68d3a39 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -28,4 +28,3 @@ (r/require-r '[datasets]) ) - From 435da7658aba311d80165a04f1e32ee4c360bde8 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sun, 12 May 2024 21:03:03 +0000 Subject: [PATCH 14/23] commented one failing test , as :doc is now present on vars --- notebooks/clojisr/v1/tutorials/main.clj | 50 +++++++------- test/clojisr/v1/help_test.clj | 2 +- .../v1/tutorials/main_generated_test.clj | 69 ++++++++++--------- 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/notebooks/clojisr/v1/tutorials/main.clj b/notebooks/clojisr/v1/tutorials/main.clj index 5776484..7bc1232 100644 --- a/notebooks/clojisr/v1/tutorials/main.clj +++ b/notebooks/clojisr/v1/tutorials/main.clj @@ -749,28 +749,28 @@ Now, we see some arguments that do have default values.") meta (update :ns (comp symbol str)))))) - -(kindly/check - = - '({:arglists ([x & {:keys [...]}]), :name mean, :ns r.base} - {:arglists ([x & {:keys [trim na.rm ...]}]), - :name mean-default, - :ns r.base} - {:arglists - ([x & {:keys - [order seasonal xreg include.mean delta - transform.pars fixed init method n.cond - optim.control]}]), - :name arima0, - :ns r.stats} - {:arglists ([& {:keys [which]}]), - :name dev-off, - :ns r.grDevices} - {:arglists ([]), - :name Sys-info, - :ns r.base} - {:arglists ([object & {:keys [... digits quantile.type]}]), - :name summary-default, - :ns r.base} - {:arglists ([x]), :name sin, :ns r.base} - {:arglists ([& {:keys [... na.rm]}]), :name sum, :ns r.base})) +;; fails due to :doc present on vars +;; (kindly/check +;; = +;; '({:arglists ([x & {:keys [...]}]), :name mean, :ns r.base} +;; {:arglists ([x & {:keys [trim na.rm ...]}]), +;; :name mean-default, +;; :ns r.base} +;; {:arglists +;; ([x & {:keys +;; [order seasonal xreg include.mean delta +;; transform.pars fixed init method n.cond +;; optim.control]}]), +;; :name arima0, +;; :ns r.stats} +;; {:arglists ([& {:keys [which]}]), +;; :name dev-off, +;; :ns r.grDevices} +;; {:arglists ([]), +;; :name Sys-info, +;; :ns r.base} +;; {:arglists ([object & {:keys [... digits quantile.type]}]), +;; :name summary-default, +;; :ns r.base} +;; {:arglists ([x]), :name sin, :ns r.base} +;; {:arglists ([& {:keys [... na.rm]}]), :name sum, :ns r.base})) diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 68d3a39..ffb67e5 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -8,7 +8,7 @@ (deftest help-docstring (r/require-r '[randomForest]) - (Thread/sleep 10000) + (Thread/sleep 30000) (is (str/starts-with? (:doc (meta (var r.randomForest/randomForest))) "Classification and Regression with Random Forest"))) diff --git a/test/clojisr/v1/tutorials/main_generated_test.clj b/test/clojisr/v1/tutorials/main_generated_test.clj index efde523..2b4b996 100644 --- a/test/clojisr/v1/tutorials/main_generated_test.clj +++ b/test/clojisr/v1/tutorials/main_generated_test.clj @@ -1103,37 +1103,38 @@ #'r.base/sum] (mapv (fn [f] (-> f meta (update :ns (comp symbol str))))))) - -(deftest - test253 - (is - (= - var252 - '({:arglists ([x & {:keys [...]}]), :name mean, :ns r.base} - {:arglists ([x & {:keys [trim na.rm ...]}]), - :name mean-default, - :ns r.base} - {:arglists - ([x - & - {:keys - [order - seasonal - xreg - include.mean - delta - transform.pars - fixed - init - method - n.cond - optim.control]}]), - :name arima0, - :ns r.stats} - {:arglists ([& {:keys [which]}]), :name dev-off, :ns r.grDevices} - {:arglists ([]), :name Sys-info, :ns r.base} - {:arglists ([object & {:keys [... digits quantile.type]}]), - :name summary-default, - :ns r.base} - {:arglists ([x]), :name sin, :ns r.base} - {:arglists ([& {:keys [... na.rm]}]), :name sum, :ns r.base})))) +;; fails due to :doc present +;; (deftest +;; test253 +;; (is +;; (= +;; var252 + +;; '({:arglists ([x & {:keys [...]}]), :name mean, :ns r.base} +;; {:arglists ([x & {:keys [trim na.rm ...]}]), +;; :name mean-default, +;; :ns r.base} +;; {:arglists +;; ([x +;; & +;; {:keys +;; [order +;; seasonal +;; xreg +;; include.mean +;; delta +;; transform.pars +;; fixed +;; init +;; method +;; n.cond +;; optim.control]}]), +;; :name arima0, +;; :ns r.stats} +;; {:arglists ([& {:keys [which]}]), :name dev-off, :ns r.grDevices} +;; {:arglists ([]), :name Sys-info, :ns r.base} +;; {:arglists ([object & {:keys [... digits quantile.type]}]), +;; :name summary-default, +;; :ns r.base} +;; {:arglists ([x]), :name sin, :ns r.base} +;; {:arglists ([& {:keys [... na.rm]}]), :name sum, :ns r.base})))) From 54478975e88ca5a97a978f534e75572e8e91fbb1 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sun, 22 Sep 2024 21:34:40 +0000 Subject: [PATCH 15/23] use one thred per required librray --- src/clojisr/v1/require.clj | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 3e38984..d134b89 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -88,25 +88,25 @@ r-symbol)) -(defn- alter-meta-doc-in-future! [ns-symbol r-symbol r-object] - (future - (Thread/sleep 5000) - (alter-meta! - (get (ns-publics ns-symbol) r-symbol) - assoc :doc (safe-help r-object)))) +(defn- assoc-doc-to-meta! [ns-symbol r-symbol r-object] + (alter-meta! + (get (ns-publics ns-symbol) r-symbol) + assoc :doc (safe-help r-object))) -(defn add-to-ns [ ns-symbol r-symbol r-object] +(defn add-to-ns [ns-symbol r-symbol r-object] (intern ns-symbol (r-symbol->clj-symbol r-symbol r-object) r-object) - - (alter-meta-doc-in-future! ns-symbol r-symbol r-object) ns-symbol) (defn symbols->add-to-ns [ns-symbol r-symbols] (doseq [[r-symbol r-object] r-symbols] - (add-to-ns ns-symbol r-symbol r-object))) + (add-to-ns ns-symbol r-symbol r-object)) + (future + (Thread/sleep 5000) ;; this has the effect that the evaluatin of r-require "returns immidiately" during interactive work + (doseq [[r-symbol r-object] r-symbols] + (assoc-doc-to-meta! ns-symbol r-symbol r-object)))) (defn require-r-package [[package-symbol & {:keys [as refer]}]] (try From 510dc54cea98be1329c9272912254af7523fa3a4 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Sun, 22 Sep 2024 21:47:20 +0000 Subject: [PATCH 16/23] use build packages for test --- test/clojisr/v1/help_test.clj | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index ffb67e5..61d3207 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -4,22 +4,21 @@ [clojure.test :refer [is deftest]] [clojisr.v1.r :as r])) -(r/require-r '[randomForest]) (deftest help-docstring - (r/require-r '[randomForest]) - (Thread/sleep 30000) + (r/require-r '[stats]) + (Thread/sleep 10000) (is (str/starts-with? - (:doc (meta (var r.randomForest/randomForest))) - "Classification and Regression with Random Forest"))) + (:doc (meta (var r.stats/lm))) + "Fitting Linear"))) (deftest help-function (is (str/starts-with? - (r/help "randomForest" "randomForest") - "Classification and Regression with Random Forest"))) + (r/help "lm" "stats") + "Fitting Linear"))) (deftest require-defauls-should-not-throws-exception - + ; should not crash (r/require-r '[base]) (r/require-r '[stats]) From a4c03c0b2aa4f23df99fd7636776f9c19bbb8586 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Tue, 14 Jan 2025 20:23:27 +0000 Subject: [PATCH 17/23] replace future by using java Thread --- src/clojisr/v1/require.clj | 16 +++++++++------- test/clojisr/v1/help_test.clj | 14 +++++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index d134b89..43d4aa6 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -89,9 +89,10 @@ (defn- assoc-doc-to-meta! [ns-symbol r-symbol r-object] - (alter-meta! - (get (ns-publics ns-symbol) r-symbol) - assoc :doc (safe-help r-object))) + (.start (Thread. (fn [] + (alter-meta! + (get (ns-publics ns-symbol) r-symbol) + assoc :doc (safe-help r-object)))))) (defn add-to-ns [ns-symbol r-symbol r-object] (intern ns-symbol @@ -103,10 +104,11 @@ (defn symbols->add-to-ns [ns-symbol r-symbols] (doseq [[r-symbol r-object] r-symbols] (add-to-ns ns-symbol r-symbol r-object)) - (future - (Thread/sleep 5000) ;; this has the effect that the evaluatin of r-require "returns immidiately" during interactive work - (doseq [[r-symbol r-object] r-symbols] - (assoc-doc-to-meta! ns-symbol r-symbol r-object)))) + (run! + (fn [[r-symbol r-object]] + (assoc-doc-to-meta! ns-symbol r-symbol r-object)) + r-symbols)) + (defn require-r-package [[package-symbol & {:keys [as refer]}]] (try diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 61d3207..9862a4d 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -4,10 +4,13 @@ [clojure.test :refer [is deftest]] [clojisr.v1.r :as r])) +(r/require-r '[stats]) +(Thread/sleep 5000) + (deftest help-docstring (r/require-r '[stats]) - (Thread/sleep 10000) + (Thread/sleep 5000) (is (str/starts-with? (:doc (meta (var r.stats/lm))) "Fitting Linear"))) @@ -17,13 +20,14 @@ (r/help "lm" "stats") "Fitting Linear"))) -(deftest require-defauls-should-not-throws-exception +(deftest require-defauls-should-not-throws-exception ; should not crash (r/require-r '[base]) (r/require-r '[stats]) (r/require-r '[utils]) (r/require-r '[graphics]) - (r/require-r '[datasets]) - - ) + (r/require-r '[datasets])) + + + From b8f19201d012f11683b5f33ffbe0eee00f61207f Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Tue, 14 Jan 2025 20:32:06 +0000 Subject: [PATCH 18/23] merged with master --- README.md | 5 ++++- deps.edn | 12 ++++++------ project.clj | 2 +- src/clojisr/v1/impl/common.clj | 7 +++++++ src/clojisr/v1/require.clj | 6 ++++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 67f1259..45098e7 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,8 @@ Installing R with Rserve on MacOS can be problematic due to issues related to op ### Docker image + + Thanks to Carsten Behring we have a Docker template prepared https://github.com/behrica/clj-py-r-template @@ -94,7 +96,8 @@ The Dockerfile of the template adds as well python + libpython-clj for completen So it has in a single place all dependencies and they do work together and no further setup is required. -There is as well a `devcontainer` setup in this GitHub [template](https://github.com/behrica/clojure-datascience-devcontainer). It provides as well an out-of-the box working environment and template for projects using ClojisR (and [libpythion-clj](https://github.com/clj-python/libpython-clj) +### devcontainer +The scicloj community is maintaining a `devcontainer` [template](https://github.com/scicloj/devcontainer-templates/tree/main/src/scicloj) on which `clojisr` is known to work out of the box. ## Checking if it works diff --git a/deps.edn b/deps.edn index 7fac3e7..3162d47 100644 --- a/deps.edn +++ b/deps.edn @@ -1,16 +1,16 @@ -{:deps {org.clojure/clojure {:mvn/version "1.11.1"}, - org.clojure/tools.logging {:mvn/version "1.3.0"}, - scicloj/tablecloth {:mvn/version "7.029.1"} +{:deps {org.clojure/clojure {:mvn/version "1.11.1"} + org.clojure/tools.logging {:mvn/version "1.3.0"} + scicloj/tablecloth {:mvn/version "7.029.2"} org.scicloj/clojisr-rengine {:mvn/version "0.1.2"} - ;; org.rosuda.REngine/Rserve {:mvn/version "1.8.1"}, + ;; org.rosuda.REngine/Rserve {:mvn/version "1.8.1"} hiccup/hiccup {:mvn/version "2.0.0-RC3"} org.clojure/core.async {:mvn/version "1.6.681"} - org.scicloj/kindly {:mvn/version "4-beta4"}} + org.scicloj/kindly {:mvn/version "4-beta12"}} :paths ["src"] :aliases {:dev {:extra-paths ["resources" "notebooks"] :jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/jul-factory" "-Djava.awt.headless=true"] - :extra-deps {org.scicloj/clay {:mvn/version "2-beta8"} + :extra-deps {org.scicloj/clay {:mvn/version "2-beta16"} io.github.nextjournal/clerk {:mvn/version "0.7.418"}}} :test {:extra-paths ["test"] :extra-deps {io.github.cognitect-labs/test-runner diff --git a/project.clj b/project.clj index 3edc1ae..238248b 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject scicloj/clojisr "1.0.0" +(defproject scicloj/clojisr "1.1.0-SNAPSHOT" :description "Clojure <-> R interop" :url "https://github.com/scicloj/clojisr" :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" diff --git a/src/clojisr/v1/impl/common.clj b/src/clojisr/v1/impl/common.clj index 874003d..9951147 100644 --- a/src/clojisr/v1/impl/common.clj +++ b/src/clojisr/v1/impl/common.clj @@ -48,6 +48,13 @@ (->clj [obj] obj) (->native [obj] obj)) +(extend-type nil + prot/RProto + (inherits? [_ _] false) + prot/Clojable + (->clj [obj] obj) + (->native [obj] obj)) + (defn ->seq-with-missing [xs missing] (mapv (fn [d na] (when-not na d)) xs missing)) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 43d4aa6..0f8cf3d 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -125,8 +125,10 @@ ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python - (alias package-symbol r-ns-symbol) - (when as (alias as r-ns-symbol)) + ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/clojisr.201.2E1.2E0/near/441026754 + (if as + (alias as r-ns-symbol) + (alias package-symbol r-ns-symbol)) ;; inject symbol into current namespace (when refer From 2b090257ab31e3a846107666a499f5275f04b62d Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Tue, 14 Jan 2025 20:47:25 +0000 Subject: [PATCH 19/23] use daemon thread --- src/clojisr/v1/r.clj | 4 ++-- src/clojisr/v1/require.clj | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 124e09d..1027672 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -208,10 +208,10 @@ (defn help "Gets help for an R object or function" ([r-object] - (help/help r-object )) + (help/help r-object)) ([function package] - (help/get-help function package ))) + (help/get-help function package))) (defn print-help diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 0f8cf3d..24af31a 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -89,10 +89,12 @@ (defn- assoc-doc-to-meta! [ns-symbol r-symbol r-object] - (.start (Thread. (fn [] + (let [t (Thread. (fn [] (alter-meta! (get (ns-publics ns-symbol) r-symbol) - assoc :doc (safe-help r-object)))))) + assoc :doc (safe-help r-object))))] + (.setDaemon t true) + (.start t))) (defn add-to-ns [ns-symbol r-symbol r-object] (intern ns-symbol From 2708928237c67074f17ebf858dddac9f158ae4b2 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Tue, 14 Jan 2025 21:00:01 +0000 Subject: [PATCH 20/23] remove returned symbol --- src/clojisr/v1/require.clj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 24af31a..0f1dea8 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -99,8 +99,7 @@ (defn add-to-ns [ns-symbol r-symbol r-object] (intern ns-symbol (r-symbol->clj-symbol r-symbol r-object) - r-object) - ns-symbol) + r-object)) (defn symbols->add-to-ns [ns-symbol r-symbols] From ef1fcc9da86df5d3425e25d6112b0757b873dd63 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 15 Jan 2025 19:36:36 +0000 Subject: [PATCH 21/23] introduced flag to generate-doc-strings --- src/clojisr/v1/require.clj | 34 +++++++++++++++++----------------- test/clojisr/v1/help_test.clj | 17 +++++++++-------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/clojisr/v1/require.clj b/src/clojisr/v1/require.clj index 0f1dea8..9acbbeb 100644 --- a/src/clojisr/v1/require.clj +++ b/src/clojisr/v1/require.clj @@ -89,12 +89,9 @@ (defn- assoc-doc-to-meta! [ns-symbol r-symbol r-object] - (let [t (Thread. (fn [] - (alter-meta! - (get (ns-publics ns-symbol) r-symbol) - assoc :doc (safe-help r-object))))] - (.setDaemon t true) - (.start t))) + (alter-meta! + (get (ns-publics ns-symbol) r-symbol) + assoc :doc (safe-help r-object))) (defn add-to-ns [ns-symbol r-symbol r-object] (intern ns-symbol @@ -102,16 +99,18 @@ r-object)) -(defn symbols->add-to-ns [ns-symbol r-symbols] +(defn symbols->add-to-ns [ns-symbol r-symbols generate-doc-strings?] (doseq [[r-symbol r-object] r-symbols] (add-to-ns ns-symbol r-symbol r-object)) - (run! - (fn [[r-symbol r-object]] - (assoc-doc-to-meta! ns-symbol r-symbol r-object)) - r-symbols)) + + (when generate-doc-strings? + (run! + (fn [[r-symbol r-object]] + (assoc-doc-to-meta! ns-symbol r-symbol r-object)) + r-symbols))) -(defn require-r-package [[package-symbol & {:keys [as refer]}]] +(defn require-r-package [[package-symbol & {:keys [as refer generate-doc-strings?]}]] (try (let [session (session/fetch-or-make nil)] (evl/eval-form `(library ~package-symbol) session) @@ -122,14 +121,14 @@ ;; r.package namespace (find-or-create-ns r-ns-symbol) - (symbols->add-to-ns r-ns-symbol r-symbols) + (symbols->add-to-ns r-ns-symbol r-symbols generate-doc-strings?) ;; alias namespaces ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/require-r.20vs.20-require-python ;; https://clojurians.zulipchat.com/#narrow/stream/224816-clojisr-dev/topic/clojisr.201.2E1.2E0/near/441026754 - (if as - (alias as r-ns-symbol) - (alias package-symbol r-ns-symbol)) + (if as + (alias as r-ns-symbol) + (alias package-symbol r-ns-symbol)) ;; inject symbol into current namespace (when refer @@ -138,7 +137,8 @@ this-ns-symbol (if (= refer :all) r-symbols - (select-keys r-symbols refer))))))) + (select-keys r-symbols refer)) + generate-doc-strings?))))) (catch Exception e (log/warn [::require-r-package {:package-symbol package-symbol :cause (exception-cause e)}]) diff --git a/test/clojisr/v1/help_test.clj b/test/clojisr/v1/help_test.clj index 9862a4d..441ce41 100644 --- a/test/clojisr/v1/help_test.clj +++ b/test/clojisr/v1/help_test.clj @@ -4,17 +4,18 @@ [clojure.test :refer [is deftest]] [clojisr.v1.r :as r])) -(r/require-r '[stats]) -(Thread/sleep 5000) - (deftest help-docstring - (r/require-r '[stats]) - (Thread/sleep 5000) + (r/require-r '[stats :generate-doc-strings? true]) (is (str/starts-with? - (:doc (meta (var r.stats/lm))) + (-> + (ns-publics 'r.stats) + (get 'lm) + meta + :doc) + "Fitting Linear"))) - + (deftest help-function (is (str/starts-with? (r/help "lm" "stats") @@ -23,7 +24,7 @@ (deftest require-defauls-should-not-throws-exception ; should not crash - (r/require-r '[base]) + (r/require-r '[base :generate-doc-strings? true]) (r/require-r '[stats]) (r/require-r '[utils]) (r/require-r '[graphics]) From 6b8a3e98dee9a0e2819fd1f674fde753471dbc3f Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Wed, 15 Jan 2025 19:51:39 +0000 Subject: [PATCH 22/23] added doc-string to 'require-r' --- src/clojisr/v1/r.clj | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/clojisr/v1/r.clj b/src/clojisr/v1/r.clj index 487050f..4cb5335 100644 --- a/src/clojisr/v1/r.clj +++ b/src/clojisr/v1/r.clj @@ -80,7 +80,27 @@ (let [session (session/fetch-or-make session-args)] (functions/apply-function r-function args session))) -(defn require-r [& packages] +(defn require-r + " + Requires R packages and creates 2 clojure namespaces with functions for each R object per package. + The 2 namespaces get names of 'package-name' and 'r.package-name'. + + It supports as well :as and :refer as clojure.core/require does. + The function can as well attach the R help of R objects as doc string to the created clojure vars, + so IDEs can show it. + + As this is slow (several seconds for larger packages), it is not enabled by default. It can be enabled + using ':generate-doc-strings?' true in the package spec. + + Examples: + + (r/require-r '[base]) + (r/require-r '[stats] :as statistics) + (r/require-r '[base :as my-base :generate-doc-strings? true]) + + + " + [& packages] (run! require-r-package packages)) (def function functions/function) From 62e55133be16563efc02b89fc5046578c7826361 Mon Sep 17 00:00:00 2001 From: Carsten Behring Date: Thu, 16 Jan 2025 15:01:25 +0000 Subject: [PATCH 23/23] addedd a few tests for requirer --- .portal/vs-code.edn | 1 + deps.edn | 5 ++- test/clojisr/v1/r_test.clj | 81 ++++++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 .portal/vs-code.edn diff --git a/.portal/vs-code.edn b/.portal/vs-code.edn new file mode 100644 index 0000000..64ee46f --- /dev/null +++ b/.portal/vs-code.edn @@ -0,0 +1 @@ +{:host "localhost", :port 33653} \ No newline at end of file diff --git a/deps.edn b/deps.edn index 89e657f..2b09b91 100644 --- a/deps.edn +++ b/deps.edn @@ -11,7 +11,10 @@ :jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/jul-factory" "-Djava.awt.headless=true"] :extra-deps {org.scicloj/clay {:mvn/version "2-beta16"} - io.github.nextjournal/clerk {:mvn/version "0.7.418"}}} + io.github.nextjournal/clerk {:mvn/version "0.7.418"} + org.scicloj/kind-portal {:mvn/version "1-beta3"} + djblue/portal {:mvn/version "0.58.5"} + }} :test {:extra-paths ["test"] :extra-deps {org.scicloj/clay {:mvn/version "2-beta8"} io.github.cognitect-labs/test-runner diff --git a/test/clojisr/v1/r_test.clj b/test/clojisr/v1/r_test.clj index e734b53..068cd0f 100644 --- a/test/clojisr/v1/r_test.clj +++ b/test/clojisr/v1/r_test.clj @@ -1,14 +1,16 @@ (ns clojisr.v1.r-test - (:require [clojisr.v1.r :as r] - [tech.v3.dataset :as ds] - [clojisr.v1.require :as require-r] - [clojure.test :refer [is deftest] :as t])) + (:require + [clojisr.v1.r :as r] + [clojisr.v1.require :as require-r] + [clojure.string :as str] + [clojure.test :refer [deftest is] :as t] + [tech.v3.dataset :as ds])) (require-r/require-r '[datasets]) (require-r/require-r '[base]) (def v [1 2 3]) - + (deftest bras (is (= [1] @@ -17,15 +19,15 @@ (-> (r/brabra v 1) r/r->clj)))) -(deftest binaries +(deftest binaries (is (= [true false false false true true true true true true 0 2 1 1.0 1 1 1 0 false true] - - (mapv + + (mapv (fn [f] (first (r/r->clj (f 1 1)))) - - [r/r== - r/r!= + + [r/r== + r/r!= r/r< r/r> r/r<= @@ -43,20 +45,19 @@ r/r%div% r/r%% r/rxor - r/r%in% - ])))) + r/r%in%])))) -(deftest unary - +(deftest unary + (is (= 9.0 (-> (r/r** 3 2) r/r->clj first))) (is (not - (-> (r/r! true) r/r->clj first) - ))) + (-> (r/r! true) r/r->clj first)))) (deftest bra-colon + (is (= [21.0] (-> r.datasets/mtcars (r/r$ "mpg") @@ -69,14 +70,16 @@ (r/r->clj))))) (deftest str-md + (r/println-captured-str r.datasets/mtcars) - (is (= + (is (= "```\n'data.frame':\t32 obs. of 11 variables:\n $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...\n $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...\n $ disp: num 160 160 108 258 360 ...\n $ hp : num 110 110 93 110 175 105 245 62 95 123 ...\n $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...\n $ wt : num 2.62 2.88 2.32 3.21 3.44 ...\n $ qsec: num 16.5 17 18.6 19.4 17 ...\n $ vs : num 0 0 1 1 0 1 0 1 1 1 ...\n $ am : num 1 1 1 0 0 0 0 0 0 0 ...\n $ gear: num 4 4 4 3 3 3 3 4 4 4 ...\n $ carb: num 4 4 1 1 2 1 4 2 2 4 ...\n```" (r/str-md r.datasets/mtcars)))) -(deftest brabra<- +(deftest brabra<- + (is (= 8 (-> (r/brabra<- @@ -93,9 +96,45 @@ (range 5) 1 8) r/r->clj - first) - ))) + first)))) +(deftest r-require + (r/require-r '[graphics :refer [plot hist] :generate-doc-strings? true]) + + (is (= "#'user/plot" + (-> + (ns-interns *ns*) + (get 'plot) + str))) + (is (= "#'user/hist" + (-> + (ns-interns *ns*) + (get 'hist) + str))) + (r/require-r '[graphics]) + (is (some? + (find-ns 'r.graphics))) + (is (some? + (-> + (ns-aliases *ns*) + (get 'graphics)))) + + (r/require-r '[stats :refer [lm] :generate-doc-strings? true]) + (is (= "#'user/lm" + (-> + (ns-interns *ns*) + (get 'lm) + str))) + + (is + (str/starts-with? + + (-> + (ns-interns *ns*) + (get 'lm) + meta + :doc) + "Fitting Linear Model")))