Last active
October 15, 2015 15:52
-
-
Save wildermuthn/1cab5a35b6351e35c706 to your computer and use it in GitHub Desktop.
Porting OOP command-pattern in JavaScript to FP in ClojureScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn calculator [init-value] | |
(let [current-value (atom [init-value]) | |
ch (chan) | |
get-value #(-> @current-value | |
peek) | |
undo #(swap! current-value pop)] | |
(go-loop [{:keys [op data]} (<! ch)] | |
(let [f (case op | |
:add + | |
:sub - | |
:mul * | |
:div / | |
identity) | |
f-data (f (get-value) data)] | |
(swap! current-value conj f-data) | |
(recur (<! ch)))) | |
[ch get-value undo])) | |
(go (let [[op-ch get-calc undo] (calculator 0)] | |
(>! op-ch {:op :add | |
:data 10}) | |
(>! op-ch {:op :mul | |
:data 2}) | |
(>! op-ch {:op :div | |
:data 5}) | |
(undo) | |
(undo) | |
(js/console.log (get-calc)))) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function add(x, y) { return x + y; } | |
function sub(x, y) { return x - y; } | |
function mul(x, y) { return x * y; } | |
function div(x, y) { return x / y; } | |
var Command = function (execute, undo, value) { | |
this.execute = execute; | |
this.undo = undo; | |
this.value = value; | |
} | |
var AddCommand = function (value) { | |
return new Command(add, sub, value); | |
}; | |
var SubCommand = function (value) { | |
return new Command(sub, add, value); | |
}; | |
var MulCommand = function (value) { | |
return new Command(mul, div, value); | |
}; | |
var DivCommand = function (value) { | |
return new Command(div, mul, value); | |
}; | |
var Calculator = function () { | |
var current = 0; | |
var commands = []; | |
function action(command) { | |
var name = command.execute.toString().substr(9, 3); | |
return name.charAt(0).toUpperCase() + name.slice(1); | |
} | |
return { | |
execute: function (command) { | |
current = command.execute(current, command.value); | |
commands.push(command); | |
log.add(action(command) + ": " + command.value); | |
}, | |
undo: function () { | |
var command = commands.pop(); | |
current = command.undo(current, command.value); | |
log.add("Undo " + action(command) + ": " + command.value); | |
}, | |
getCurrentValue: function () { | |
return current; | |
} | |
} | |
} | |
function run() { | |
var calculator = new Calculator(); | |
// issue commands | |
calculator.execute(new AddCommand(10)); | |
calculator.execute(new MulCommand(2)); | |
calculator.execute(new DivCommand(5)); | |
// reverse last two commands | |
calculator.undo(); | |
calculator.undo(); | |
console.log(calculator.getCurrentValue()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment