Giter Club home page Giter Club logo

delayed-map's Introduction

delayed-map

A small Clojure library that implements a two-stage map.

Installation

Include the following dependency in your project.clj file:

:dependencies [[delayed-map "0.1.0-SNAPSHOT"]]

Usage

A delayed map is defined by a "seed" map and a loader function that returns another map, the rest of the key-value pairs. This function receives the seed as its sole argument.

(use 'delayed-map.core)

(def lm
  (delayed-map {:foo 1 :bar 2}
            (fn [seed] {:baz (inc (:bar seed))})))

The loader function will not be called until necessary.

Realization

Realization is triggered transparently by one of the following:

  • A read on a key that is not part of the seed.
  • Any operation that uses the seqable or collection abstractions (count, seq and so on).
  • Certain map ops like merge or dissoc (see notes below).
user=> lm
{:foo 1, :bar 2, ...}
user=> (:foo lm)
1
user=> (realized? lm)
false
user=> lm
{:foo 1, :bar 2, ...}
user=> (seq lm)
([:bar 2] [:foo 1] [:baz 3])
user=> lm
{:bar 2, :foo 1, :baz 3}
user=> (realized? lm)
true

Operations that won't realize a delayed map include:

  • assoc, as it always returns another delayed map with a modified seed for not yet realized delayed maps (it returns a regular map for realized ones).
  • select-keys, if all the selected keys are present in the seed.

Does it act like an immutable map?

Yes. To maintain Clojure's immutability guarantee on maps, the seed is merged into the result of the loader function, not the other way around.

user=> (seq (delayed-map {:foo "old"} (fn [_] {:foo "new" :bar "hi"})))
([:foo "old"] [:bar "hi"])

Any practical uses for this?

I came up with the idea while coding a new, soon to be released client library for the Parse platform.

The Parse API returns so-called pointers when a value in a field is another database object. A pointer is nothing more than a map with the model class name and the object ID; if you need the full object, you have to load it based on this information.

This process can be made transparent using delayed maps for pointers, delaying the actual request until it becomes necessary.

(defn- load-pointer [{:keys [class-name object-id]}]
  (retrieve class-name object-id))

(defn- ptr->obj [ptr]
  (delayed-map
    (select-keys ptr [:class-name :object-id])
    load-pointer))

The decision to prevent print-method from realizing the map comes also from this use. Circular references in the database would make a REPL keep on loading objects forever otherwise (that is, until the heap is blown by the output buffer).

Notes

The dissoc operation realizes the map even if the key to be removed is in the seed. The reason for this is that we cannot allow something like the following to happen:

user=> (def lm (delayed-map {:foo 1 :bar 2} (fn [_] {:bar 3})))
#'user/lm
user=> (:bar (dissoc lm :bar))
3

License

Copyright © 2014 Roland Venesz / Wopata SARL

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

delayed-map's People

Stargazers

Tim Spann avatar

Watchers

James Cloos avatar Sidi Mohamed ELAATIFI avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.