{"id":20932756,"url":"https://github.com/leonoel/injure","last_synced_at":"2025-07-05T08:34:39.734Z","repository":{"id":62432978,"uuid":"170553484","full_name":"leonoel/injure","owner":"leonoel","description":"A dependency injector for Clojure and Clojurescript","archived":false,"fork":false,"pushed_at":"2020-03-28T08:49:37.000Z","size":11,"stargazers_count":23,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T07:22:59.799Z","etag":null,"topics":["clojure","clojurescript","dependency-injection"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leonoel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-13T17:57:03.000Z","updated_at":"2024-11-07T14:05:09.000Z","dependencies_parsed_at":"2022-11-01T20:47:19.218Z","dependency_job_id":null,"html_url":"https://github.com/leonoel/injure","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonoel%2Finjure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonoel%2Finjure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonoel%2Finjure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonoel%2Finjure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leonoel","download_url":"https://codeload.github.com/leonoel/injure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254020902,"owners_count":22000805,"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","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":["clojure","clojurescript","dependency-injection"],"created_at":"2024-11-18T21:53:16.444Z","updated_at":"2025-05-13T20:30:46.058Z","avatar_url":"https://github.com/leonoel.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# injure\n\nA dependency injector for Clojure and ClojureScript.\n\n[![clojars](https://img.shields.io/clojars/v/injure.svg)](https://clojars.org/injure)\n\n[![cljdoc](https://cljdoc.org/badge/injure/injure)](https://cljdoc.org/d/injure/injure/CURRENT)\n\n[![build](https://travis-ci.org/leonoel/injure.svg?branch=master)](https://travis-ci.org/leonoel/injure)\n\n[![license](https://img.shields.io/github/license/leonoel/injure.svg)](LICENSE)\n\n\n## Rationale\n\nDependency injection refers to the process of deferring bindings between components in a system. Exhibiting dependencies allows to reify the system topology as plain data, loosening coupling and increasing modularity.\n\n`injure` aims to capture the essence of this pattern, providing helpers to describe component systems as data and arbitrarily resolve them later. Lifecycle management and other OO-related details are outside of the scope of this library.\n\nDependency resolution happens at compile-time and produces plain local bindings, avoiding hashmap lookups. Therefore, the resulting system has zero run-time overhead and will perform as fast as a hardwired one.\n\n\n## Usage\n`injure` exposes a single namespace `injure.core` with 2 macros, `target` and `inject`.\n\n```clojure\n(require '[injure.core :as i])\n```\n\n`target` requires a dependency. It takes an arbitrary number of compile-time forms and emits a symbol bound to the resolution of the dependency matched by provided forms. It is illegal to call `target` outside of an `inject` context, but resolution can be deferred with quoting.\n\n```clojure\n(def system        ;; defines a system of 3 components identified by keywords :a, :b, :c\n  `{:a 6\n    :b (inc (i/target :a))\n    :c (* (i/target :a) (i/target :b))})\n```\n\n`inject` performs the dependency resolution of a fully defined system. The first argument must evaluate (compile-time) to a function providing forms associated to required targets (arguments to `target` will be passed as-is). Next arguments are forms to be evaluated within this context.\n\n```clojure\n(i/inject system (str (i/target :c)))     ;; emits (let [a 6, b (inc a), c (* a b)] (str c))\n```\n\n\n## Guides\n\nThe following patterns will be illustrated with an example taken from [plumatic/plumbing](https://github.com/plumatic/plumbing), a library providing a similar feature (with a different strategy, however).\n\nFirst, let's define `stats-graph`, a partial dependency graph defining a bunch of statistics operations that can be performed on an input sequence of numeric values.\n\n```clojure\n(def stats-graph\n  `{:n  (count (i/target :xs))\n    :m  (/ (reduce + (i/target :xs)) (i/target :n))\n    :m2 (/ (reduce + (map #(* % %) (i/target :xs))) (i/target :n))\n    :v  (- (i/target :m2) (* (i/target :m) (i/target :m)))})\n```\n\n\n### Step optimization\nWe can abstract away input to build a plain function performing the minimal subset of required computations :\n```clojure\n(defn mean [xs]                             ;; computes :n and :m\n  (i/inject (assoc stats-graph :xs 'xs)\n    (i/target :m)))\n\n(defn mean-and-variance [xs]                ;; computes :n :m :m2 and :v\n  (i/inject (assoc stats-graph :xs 'xs)\n    [(i/target :m) (i/target :v)]))\n\n(mean [1 2 3 6])                  ;; returns 3\n(mean-and-variance [1 2 3 6])     ;; returns [3 7/2]\n```\n\n\n### Unit testing\nWe can unit test each computation step by binding inputs to static values and validating results according to these inputs :\n\n```clojure\n(deftest unit\n  (i/inject (assoc stats-graph :xs [1 2 3 6])\n    (is (= (i/target :xs) [1 2 3 6]))\n    (is (= (i/target :n) 4))\n    (is (= (i/target :m) 3))\n    (is (= (i/target :m2) (/ 25 2)))\n    (is (= (i/target :v) (/ 7 2)))))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonoel%2Finjure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleonoel%2Finjure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonoel%2Finjure/lists"}