Giter Club home page Giter Club logo

converso's Introduction

convert

A Clojure library allowing to specify conversions between types and then find some conversions that aren't directly specified.

Usage

This library is an experiment using core.logic to specify conversions between types.

For instance you can specify:

(ns ...
  (use converso.core))

(add-conversion :mm :cm #(/ % 10) #(* % 10))

and then do something like:

((search-conversion :mm :cm) 10)
;=> 1

((search-conversion :cm :mm) 10)
;=> 100

The goodies

Using core.logic to do only simples conversions like above is a waste, multi-methods are fine to do this. Converso brings more to the table.

Since we are working with conversions we can use their mathematical properties to find conversions that are not specified. This is were core.logic is used.

This library use two mathematical properties:

  • inverse functions
  • transitivity

Inverse functions

Suppose we want to specify a piece of the metric system. We will use the units:

  • millimeters :mm
  • centimeters :cm
  • decimeters :dm

We could specify the conversions like that:

(add-conversion :mm :cm #(/ % 10) #(* % 10))
(add-conversion :cm :dm #(/ % 10) #(* % 10))

You can then look up for the conversions:

  • :mm -> :cm
(search-conversion :mm :cm)
  • :cm -> :mm
(search-conversion :cm :mm)
  • :cm -> :dm
(search-conversion :cm :dm)
  • :dm -> :cm
(search-conversion :dm :cm)

It gets interesting because Converso lets you do that:

(defn *10    [n] (* n 10))
(defn div-10 [n] (/ n 10))

(add-conversion :mm :cm div-10 *10)
(add-conversion :cm :dm div-10)

(search-conversion :dm :cm)
;=> *10

Here we didn't specify the conversion from :dm to :cm. However Converso is capable of finding it because

(add-conversion :mm :cm div-10 *10)

specifies implicitely that div-10 and *10 are inverse functions. The conversion :dm -> :cm isn't specified but its inverse :cm -> :dm is, it is the div-10 function. Since we know that the inverse of div-10 is *10 we can say that

:dm -> :cm
<=> inverse(inverse(:dm -> :cm))
<=> inverse(div-10)
<=> *10

Transitivity

Converso is also capable to use transitivity to find conversions. If we take the previous example:

(defn *10    [n] (* n 10))
(defn div-10 [n] (/ n 10))

(add-conversion :mm :cm div-10 *10)
(add-conversion :cm :dm div-10)

The conversion :mm :dm isn't specified but converso can do this:

(search-conversion :mm :cm) ;=> div-10
(search-conversion :cm :dm) ;=> div-10

;thus
(search-conversion :mm :dm) ;=> (comp div-10 div-10)

:mm :dm isn't specified but Converso can still find a way to do it.

Transitivity + inverse functions

Converso can use a combination of the two strategies to find conversions. Once again with the example:

(defn *10    [n] (* n 10))
(defn div-10 [n] (/ n 10))

(add-conversion :mm :cm div-10 *10)
(add-conversion :cm :dm div-10)

The conversion :dm -> :mm isn't spécified but using both strategies Converso does this:

(search-conversion :dm =mm) ;=> (comp *10 *10) ; using the composition of the following properties
  (search-conversion :dm :cm) ;=> div-10 (using the inverse :dm -> :cm)
  (search-conversion :dm :cm) :=> div-10 (user specified)

A more complicated is used in converso.core_test.clj:

(defn *10 [n]
  (* n 10))

(defn div-10 [n]
  (/ n 10))

(defn *1000 [n]
  (* n 1000))

(defn div-1000 [n]
  (/ n 1000))

(add-conversion :mm :cm    div-10)
(add-conversion :cm :dm    div-10)
(add-conversion :cm :decam div-1000 *1000)
(add-conversion :hm :dm    *1000)
(add-conversion :hm :km    div-10)

(search-conversion :mm :km) ;=> (comp div-10 div-1000 div-10 div-10)
  (search-conversion :mm :cm) ;=> div-10 spec
  (search-conversion :cm :dm) ;=> div-10 spec
  (search-conversion :dm :hm) ;=> div-1000 inverse
  (search-conversion :hm :km) ;=> div-10 spec

(search-conversion :dm :hm)
<=> (inverse (search-conversion :hm :dm))
<=> (inverse *1000)
<=> (inverse (search-conversion :decam :cm))
<=> (search-conversion :cm :decam)
<=> div-1000

Note

If we supress the use of the inverse functions Converso is some kind of graph traversing tool with types as nodes and conversions as arcs.

License

Copyright © 2013 Jérémy Schoffen.

Distributed under the Eclipse Public License, the same as Clojure.

converso's People

Contributors

jerems 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.