Skip to content

Instantly share code, notes, and snippets.

@wildermuthn
Last active October 15, 2015 15:52
Show Gist options
  • Save wildermuthn/1cab5a35b6351e35c706 to your computer and use it in GitHub Desktop.
Save wildermuthn/1cab5a35b6351e35c706 to your computer and use it in GitHub Desktop.
Porting OOP command-pattern in JavaScript to FP in ClojureScript
(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))))
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