Back

datafy (clj)

(source)

function

(datafy x)
Attempts to return x as data. datafy will return the value of clojure.core.protocols/datafy. If the value has been transformed and the result supports metadata, :clojure.datafy/obj will be set on the metadata to the original value of x, and :clojure.datafy/class to the name of the class of x, as a symbol.

Examples

clojure/clojurescript
(ns clojure.datafy-test
  (:require [cljs.test :as test
             :refer-macros [deftest is testing]]
            [clojure.datafy :as d]))

(deftest datafy-test
  (testing "Datafy works when datafied value is arbitrary JS objects"
    (let [datafied #js {}
          x (with-meta [1 2 3] {`clojure.core.protocols/datafy (fn [_] datafied)})]
      (is (= datafied (d/datafy x)))))
  (testing "Datafy adds ::obj metadata when return value != original value and supports metadata"
    (let [datafied [2 3 4]
          original [1 2 3]
          x (with-meta original {`clojure.core.protocols/datafy (fn [_] datafied)})]
      (is (= datafied (d/datafy x)))
      (is (= {:clojure.datafy/obj original} (meta (d/datafy x)))))))

(deftest datafy-js-errors-test
  (let [x (js/Error. "foo")]
    (is (= (Throwable->map x) (d/datafy x))))
  ;; Ensure we can datafy objects that extend js/Error
  (let [x (js/RangeError. "x must be between 1 and 5")]
    (is (= (Throwable->map x) (d/datafy x)))))

(deftest datafy-ex-info-test
  (let [x (ex-info "foo" {:a 1} (ex-info "bar" {:b 2}))]
    (is (= (Throwable->map x) (d/datafy x)))))
clojure/clojurescript
(ns test-runner
  (:require [cljs.test :refer-macros [run-tests]]
            [cljs.apply-test]
            [cljs.primitives-test]
            [cljs.destructuring-test]
            [cljs.new-new-test]
            [cljs.printing-test]
            [cljs.seqs-test]
            [cljs.collections-test]
            [cljs.hashing-test]
            [cljs.core-test :as core-test]
            [cljs.reader-test]
            [cljs.binding-test]
            [cljs.parse-test]
            [cljs.ns-test]
            [clojure.set-test]
            [clojure.string-test]
            [clojure.data-test]
            [clojure.datafy-test]
            [clojure.edn-test]
            [clojure.walk-test]
            [clojure.math-test]
            [cljs.macro-test]
            [cljs.letfn-test]
            [foo.ns-shadow-test]
            [cljs.top-level]
            [cljs.reducers-test]
            [cljs.keyword-test]
            [cljs.import-test]
            [cljs.ns-test.foo]
            [cljs.syntax-quote-test]
            [cljs.pprint]
            [cljs.pprint-test]
            [cljs.spec-test]
            [cljs.specials-test]
            [cljs.spec.test-test]
            [cljs.clojure-alias-test]
            [cljs.hash-map-test]
            [cljs.map-entry-test]
            [cljs.metadata-test]
            [cljs.npm-deps-test]
            [cljs.other-functions-test]
            [cljs.predicates-test]
            [cljs.tagged-literals-test]
            [cljs.test-test]
            [static.core-test]
            [cljs.recur-test]
            [cljs.array-access-test]
            [cljs.inference-test]
            [cljs.walk-test]
            [cljs.repl-test]
            [cljs.extend-to-native-test]))

(run-tests
  'cljs.apply-test
  'cljs.primitives-test
  'cljs.destructuring-test
  'cljs.new-new-test
  'cljs.printing-test
  'cljs.seqs-test
  'cljs.collections-test
  'cljs.hashing-test
  'cljs.core-test
  'cljs.reader-test
  'cljs.parse-test
  'clojure.set-test
  'clojure.string-test
  'clojure.data-test
  'clojure.datafy-test
  'clojure.edn-test
  'clojure.walk-test
  'clojure.math-test
  'cljs.letfn-test
  'cljs.reducers-test
  'cljs.binding-test
  'cljs.macro-test
  'cljs.top-level
  'cljs.keyword-test
  'cljs.ns-test
  'cljs.ns-test.foo
  'foo.ns-shadow-test
  'cljs.import-test
  'cljs.pprint
  'cljs.spec-test
  'cljs.specials-test
  'cljs.spec.test-test
  'cljs.clojure-alias-test
  'cljs.hash-map-test
  'cljs.map-entry-test
  'cljs.metadata-test
  'cljs.npm-deps-test
  'cljs.other-functions-test
  'cljs.pprint-test
  'cljs.predicates-test
  'cljs.syntax-quote-test
  'cljs.tagged-literals-test
  'cljs.test-test
  'static.core-test
  'cljs.recur-test
  'cljs.array-access-test
  'cljs.inference-test
  'cljs.walk-test
  'cljs.repl-test
  'cljs.extend-to-native-test)
babashka/babashka
(ns babashka.impl.protocols
  (:require [babashka.impl.protocols :as protocols]
            [clojure.core.protocols :as p]
            [clojure.datafy :as d]
            ;; ensure datafy is loaded, we're going to override its
            ;; clojure.lang.Namespace implementation for datafy
            [clojure.reflect]
            [sci.core :as sci :refer [copy-var]]
            [sci.impl.types :as types]
            [sci.impl.vars]))

;;;; datafy

(defmulti datafy types/type-impl)

(defmethod datafy :sci.impl.protocols/reified [x]
  (let [methods (types/getMethods x)]
    ((get methods 'datafy) x)))

(defmethod datafy :default [x]
  ;; note: Clojure itself will handle checking metadata for impls
  (d/datafy x))

(def protocols-namespace
  {;; Datafiable
   'Datafiable (sci/new-var 'clojure.core.protocols/Datafiable {:methods #{'datafy}
                                                                :protocol p/Datafiable
                                                                :ns protocols-ns}
                            {:ns protocols-ns})
   'datafy (copy-var datafy protocols-ns)
nextjournal/clerk
;; # 🖨 Better Printing ADR
^{:nextjournal.clerk/visibility {:code :hide}}
(ns ^:nextjournal.clerk/no-cache viewers.printing
  (:require [clojure.datafy :as datafy]
            [clojure.java.io :as io]
            [clojure.set :as set]
            [clojure.string :as str]
            [nextjournal.clerk :as clerk :refer [with-viewer]]
            [nextjournal.clerk.viewer :as v]))

;; Initially I thought we'd use `clojure.core/datafy` in case there's a non-trivial implementation for a given object.
;; But I rejected this because the default implementations for `class` and `namespace` would be confusing.
(type (atom {}))

(datafy/datafy (type (atom {})))

(datafy/datafy #'inc)

(datafy/datafy (find-ns 'nextjournal.clerk))
hyperfiddle/electric
(ns dustin.y2022.file-watcher
  (:require [clojure.java.io :as io]
            [clojure.java.data :as j]
            [clojure.datafy :refer [datafy]]
            [leo.file-watcher :refer [watch-dir
                                      read-edn-forms
                                      watch-file
                                      path]]
            [hyperfiddle.rcf :as rcf :refer [tests % tap]]
            [missionary.core :as m]))

  (def x @!x)
  (bean x)
  (datafy x)
  (j/from-java x)
  (str x)