JavaScript: Curried Conversion Functions

We can create a JavaScript function that will convert Fahrenheit to Centigrade:
alert(f2c(59)) //15
If we add a "false" parameter, it converts in the opposite direction: 
alert(f2c(15,false))//59
The f2c() function is curried from a converter function, so you can create as many conversion functions as you like. The offset
parameter is -32 for Fahrenheit to Centigrade, for most conversions offset will be 0.

The curry function is from Curry: cooking up tastier functions

Function.prototype.curry = function () {
   if (arguments.length < 1)
      return this //nothing to curry with - return function
   var __method = this
   var args = toArray(arguments)
   return function () {
      return __method.apply(this, args.concat(toArray(arguments)))
   }
}
var converter = function (ratio,  offset, input,mul) {
   if (mul===false)
      return (input / ratio) - offset
   else
      return (input + offset) * ratio
}

var kilo2pound = converter.curry(2.2, 0)
var mile3kilometer = converter.curry(1.62, 0)
var f2c = converter.curry(0.555556, -32)
var yard2meter = converter.curry(1 / 1.0936132983377077865267, 0)
var inch2mm = converter.curry(25.399999999972568, 0)

alert(inch2mm(12.5,false))//0.492
alert(inch2mm(12,true)) //304.8
alert(inch2mm(12)); //304.8
alert(f2c(59)) //15
alert(f2c(15,false))//59

Roxy Music - Pyjamarama, Opening Tab

I bought the single in 1973, tempus fugit alors, as th' Lone Groover might say.
e---------------------------------------|
B---------------------------------------|
G--0-0-3--0-0-0--0-0-0--0-0-0-----------|
D#-0-0-0--0-0-0--0-0-0--0-0-0-----------|
A--6-6-6--5-5-5--4-4-4--3-3-3-----------|
E#--------------------------------------|
The 3rd fret G is on some of the arpeggio work, not the power chords.
Sounds like the D string is tuned to D#, E to E#, and Phil plays a descending line with one finger on the A string, with the D# and G strings as an open drone. The tuning won't interfere with the solo.




The Javascript Pyramid Model, gather classes into a Pyramid and seal it up forever

The builders of the pyramids were killed and buried within the pyramid as an early form of architectural design  encapsulation.
So shall it be with Javascript.

Problem: your program has 30 classes in an unstructured mess.
Solution: gather related classes into sealed "Pyramids", forcing strict structure upon your unruly code.

Here I present the Pyramid model, each Javascript Class is surrounded by stone, and the occupants are forced to communicate by radio. Stone is an anonymous closure, radio is a pubsub. When a constructor is called, its last act is to delete its own scope.
  1. Organises your classes into privately scoped groups "Pyramids"
  2. Nothing outside a Pyramid may access anything inside the Pyramid, the Pyramids are loosely coupled.
  3. Each Pyramid publishes selected methods so that other Pyramids may subscribe to them.
  4. One line of code per class, and one line per Pyramid.

Here we have an "Pyramid Object" that represents the constructors for a group of classes.
 models = {Model: null, Scenario: null, Turret: null, Targets: null, GunRange: null}, 
Each null is replaced with the real class constructor when it is declared.

controllers = {Clicks: null, Controller: null, Events: null},  
Our "controllers" Pyramid Object is composed of the class constructors for Clicks, Controller and Events.

This organises our classes into 2 "Pyramid Object" packages, "models" and "controllers". It not only documents the design, it will encapsulate them in stone. Nothing in "models" may reference anything in "controllers", and vice versa.

 (function () {//Anonymous Closure  
 models.Model = jsface.Class(function () {  //add constructor to Pyramid Object

 var t  
   return (BallModel, {  
    constructor: function (controller) {  
      t = this  
      t.scenario = new models.Scenario(t, controller)//use the "model" constructor  
      t.targets = new models.Targets(t, controller)  
      t.elevation = new models.Turret('elevationTurret', 20)  
      t.gunRange = new models.GunRange(t, controller)  
      radio("elevationSpriteEvent").subscribe([t.elevation.setSprite, t.elevation]) //pubsub  
      delete models.Model  
    }  
   });  
 })()  
 }()); //END CLOSURE  
Our Model class instantiates itself and the other member of the Pyramid Object. The last act of the constructor is to delete itself from the "models" object. Since there is an anonymous closure around Model is is now cemented shut. Nothing can reference it at all.


 (function () {//Anonymous Closure  
 models.Scenario = jsface.Class(Sbox, function () {  //add constructor to Pyramid Object
   function isLastScenario(scenarioNum) {  
    if (firstTime)  
      return false  
    else  
      return scenarioNum === t.arr.length  
   }  
   return {//t.theRange, t.targets.arr,  
    constructor: function (modelP, controllerP) {  
      t = this  
      model = modelP  
      controller = controllerP  
      radio("nextTargetEvent").subscribe([nextTarget, this])  
      radio("startScenarioEvent").subscribe([startScenario, this])  
      delete models.Scenario //remove the "model" constructor,   
    }  
 });  
 }()); //END CLOSURE  
All the classes in the "models" object delete themselves from the object.
Now the Pyramid object is empty:

 models = {}  
So nothing can reference anything outside its own class. Which isn't much good, so we use a Publish–subscribe pattern "radio.js" so the occupants of the pyramids can call each other.
The classes here use the jsface.js library, it doesn't matter how you implement classes here.

As shown, you can only have one instance of each class. If you want several instances of one class, leave out the "delete" in the classes constructor and clear the Pyramid object later on:


deleteProperties: function (obj) {
   for (var x in obj)
      if (obj.hasOwnProperty(x))
         delete obj[x];
}
t.deleteProperties(models)
t.deleteProperties(controllers)