Skip to content
Martin Trojer edited this page Aug 25, 2013 · 28 revisions

Using the Calculator

If you haven't looked at the example calculations yet, start there. It will show the most common calculation patterns you might encounter.

Frinj values (or numbers) are slightly different from normal Clojure ones. They also hold the a unit of measure. Frinj uses a defrecord called fjv to represent the number + unit-of-measure data. All Frinj operators and converters operate on fjv-s.

One of the main goals Frinj is to marry Clojure idiomatic calculations with the fluent syntax provided by Frink. To do this, the frinj.calc namespace provides some helper functions to easily build and convert fjv's. The main function for this purpose is simply called fj.

Operators

Frinj comes with a standard set of operators for fjv's.

fj*, fj_, fj+, fj-, fj**, fj=, fj<, (fj<=), fj>, (fj>=)

Please note that these operators also work on normal Clojure numbers.

fj

fj takes a parameter list which consist of numbers, units and operators. Here is some examples

  • (fj 1) give a unit-less value of one
  • (fj 1 :inch) gives a value representing one inch
  • (fj 10 :miles :per :hour) 10 miles/hour

Please note the multiplication is implicit if not :per is used, so (fj 10 :miles :hour) will give a value with a m*s unit instead of a m/s unit

You can also convert with fj:

  • (fj :cm :to :inch) give the value of how much 1 cm is in inches

adding, dividing, comparing

So what if you want to add some values? Frinj has Clojure idiomatic functions for add, sub, mul, div, power and compare of fjv's.

  • (fj+ (fj 2 :inches) (fj :cm)) adds 2 inches and one cm

  • (fj_ (fj 25 :miles) (fj 2 :hours)) divides, in this case calculates a velocity

  • (fj= (fj :inches) (fj :meters) (fj :feet)) false; inches, meters and feet are not the same

The frinj operator will take normal numbers as parameters aswell and convert to unit-less fjv on the fly.

(fj* (fj :pi) 10) gives 10*pi

to

The :to operator is quite limited, if you want to convert to more advanced types you need to use the to function.

to takes multiple parameters, the first is the fjv you want to convert from. The rest are a list operands (very much like one for fj.

;; If you took the matter in a teaspoon of water, and converted that to energy, how many gallons of gasoline would that equal?
(-> (fj :teaspoon :water :c :c) (to :gallons :gasoline) str)

If you want to convert the result of a f+, f* etc you cannot do it with (fj :to) but rather use the to function.

;; What if you knew that your floor could only support 2 tons? How deep could you fill the room with water?
(-> (fj_ (fj 2 :tons)
         (fj 10 :feet 12 :feet :water))
    (to :feet))

Dates

fj have a specific operator for expressing dates, :#yyyy-MM-dd. This will be converted to a value of units "s" representing the number of seconds since EPOC.

(fj- (fj :#2001-06-30) (fj :#2000-12-31)) give the time delta between those two dates

The operator :#now gives the current time.

Finally there is a special function for transforming a the fjv back to a date string; to-date

(to-date (fj :#2001-06-30))

Implicit inversion

Frinj will do implicit inversion when converting fjv's.

(-> (fj 10 :hours :per :mile) (to :miles :per :hour)) gives 1/10.

Other than in this simple case, the units must match when converting.

(override-operators!)

If you're starting on a Frinj REPL session, consider running the function (override-operators!).

This will override clojure built in +, - etc operators with fj+, fj- etc. This will in effect make all REPL operations have units.

It also makes fjv print nicely.

Clone this wiki locally