Skip to content

Instantly share code, notes, and snippets.

@AKJAW
Created May 17, 2018 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AKJAW/9b7fe4f13c1c79f01470a9077ea112f4 to your computer and use it in GitHub Desktop.
Save AKJAW/9b7fe4f13c1c79f01470a9077ea112f4 to your computer and use it in GitHub Desktop.
c = console.log
//Mathematical Idempotence
function toPower0(x) {
return Math.pow( x, 0 );
}
function snapUp3(x) {
return x - (x % 3) + (x % 3 > 0 && 3);
}
toPower0( 3 ) == toPower0( toPower0( 3 ) ); // true
snapUp3( 3.14 ) == snapUp3( snapUp3( 3.14 ) ); // true
var x = 42, y = "hello";
String( x ) === String( String( x ) ); // true
Boolean( y ) === Boolean( Boolean( y ) ); // true
function upper(x) {
return x.toUpperCase();
}
function lower(x) {
return x.toLowerCase();
}
var str = "Hello World";
upper( str ) == upper( upper( str ) ); // true
lower( str ) == lower( lower( str ) ); // true
function currency(val) {
var num = parseFloat(
String( val ).replace( /[^\d.-]+/g, "" )
);
var sign = (num < 0) ? "-" : "";
return `${sign}$${Math.abs( num ).toFixed( 2 )}`;
}
currency( -3.1 ); // "-$3.10"
currency( -3.1 ) == currency( currency( -3.1 ) ); // true
//Programming Idempotence
var obj = {}
var a = [1]
var person = {name:'pawel'}
// idempotent:
obj.count = 2;
a[a.length - 1] = 42;
person.name = upper( person.name );
// non-idempotent:
obj.count++;
a[a.length] = 42;
person.lastUpdated = Date.now();
var hist = document.getElementById( "orderHistory" );
var order = {latestUpdate: 1}
// idempotent:
hist.innerHTML = order.historyText;
// non-idempotent:
var update = document.createTextNode( order.latestUpdate );
hist.appendChild( update );
//Purely Relative
function rememberNumbers(nums) {
return function caller(fn){
return fn( nums );
};
}
var list = [1,2,3,4,5];
var simpleList = rememberNumbers( list );
function median(nums) {
return (nums[0] + nums[nums.length - 1]) / 2;
}
//c(simpleList( median )); // 3
// ..
list.push( 6 );
// ..
//c(simpleList( median )); // 3.5
//NAPRAWA
//tworzymy kopie parametru
function rememberNumbers(nums) {
// make a copy of the array
nums = [...nums];
return function caller(fn){
return fn( nums );
};
}
var list = [1,2,3,4,5];
var simpleList = rememberNumbers( list );
// yes, a silly contrived example :)
function firstValue(nums) {
return nums[0];
}
function lastValue(nums) {
return firstValue( nums.reverse() );
}
//c(simpleList( lastValue )); // 5
//c(list); // [1,2,3,4,5] -- OK!
//c(simpleList( lastValue )); // 1
function rememberNumbers(nums) {
return function caller(fn){
// send in a copy!
return fn( [...nums] );
};
}
var list = [1,2,3,4,5];
var simpleList = rememberNumbers( list );
//c(simpleList( lastValue )); // 5
//c(list); // [1,2,3,4,5] -- OK!
//c(simpleList( lastValue )); // 5
simpleList( function impureIO(nums){
//c( nums.length ); //5
} );
//Performance Effects
var cache = [];
function specialNumber(n) {
// if we've already calculated this special number,
// skip the work and just return it from the cache
if (cache[n] !== undefined) {
return cache[n];
}
var x = 1, y = 1;
for (let i = 1; i <= n; i++) {
x += i % 2;
y += i % 3;
}
cache[n] = (x * y) / (n + 1);
return cache[n];
}
//specialNumber( 6 ); // 4
//specialNumber( 42 ); // 22
//specialNumber( 1E6 ); // 500001
//specialNumber( 987654321 ); // 493827162
//memoizacja
var specialNumber = (function memoization(){
var cache = [];
return function specialNumber(n){
// if we've already calculated this special number,
// skip the work and just return it from the cache
if (cache[n] !== undefined) {
return cache[n];
}
var x = 1, y = 1;
for (let i = 1; i <= n; i++) {
x += i % 2;
y += i % 3;
}
cache[n] = (x * y) / (n + 1);
return cache[n];
};
})();
//Purifying zwiekszenie widocznosci efektow ubocznych
function addMaxNum(arr) {
var maxNum = Math.max( ...arr );
arr.push( maxNum + 1 );
}
var nums = [4,2,7,3];
addMaxNum( nums );
nums; // [4,2,7,3,8]
//=>
function addMaxNum(arr) {
var maxNum = Math.max( ...arr );
return maxNum + 1;
}
var nums = [4,2,7,3];
nums.push(
addMaxNum( nums )
);
nums; // [4,2,7,3,8]
//Containing Effects
var users = {};
function fetchUserData(userId) {
ajax( `http://some.api/user/${userId}`, function onUserData(user){
users[userId] = user;
} );
}
//=>
function safer_fetchUserData(userId,users) {
// simple, naive ES6+ shallow object copy, could also
// be done w/ various libs or frameworks
users = Object.assign( {}, users );
fetchUserData( userId );
// return the copied state
return users;
// ***********************
// original untouched impure function:
function fetchUserData(userId) {
ajax(
`http://some.api/user/${userId}`,
function onUserData(user){
users[userId] = user;
}
);
}
}
//Covering Up Effects -- only sync code
var nums = [];
var smallCount = 0;
var largeCount = 0;
function generateMoreRandoms(count) {
for (let i = 0; i < count; i++) {
let num = Math.random();
if (num >= 0.5) {
largeCount++;
}
else {
smallCount++;
}
nums.push( num );
}
}
function safer_generateMoreRandoms(count,initial) {
// (1) Save original state
var orig = {
nums,
smallCount,
largeCount
};
// (2) Set up initial pre-side effects state
nums = [...initial.nums];
smallCount = initial.smallCount;
largeCount = initial.largeCount;
// (3) Beware impurity!
generateMoreRandoms( count );
// (4) Capture side effect state
var sides = {
nums,
smallCount,
largeCount
};
// (5) Restore original state
nums = orig.nums;
smallCount = orig.smallCount;
largeCount = orig.largeCount;
// (6) Expose side effect state directly as output
return sides;
}
var initialStates = {
nums: [0.3, 0.4, 0.5],
smallCount: 2,
largeCount: 1
};
safer_generateMoreRandoms( 5, initialStates );
// { nums: [0.3,0.4,0.5,0.8510024448959794,0.04206799238...
nums; // []
smallCount; // 0
largeCount; // 0
//Evading Effects
function handleInactiveUsers(userList,dateCutoff) {
for (let i = 0; i < userList.length; i++) {
if (userList[i].lastLogin == null) {
// remove the user from the list
userList.splice( i, 1 );
i--;
}
else if (userList[i].lastLogin < dateCutoff) {
userList[i].inactive = true;
}
}
}
function safer_handleInactiveUsers(userList,dateCutoff) {
// make a copy of both the list and its user objects
let copiedUserList = userList.map( function mapper(user){
// copy a `user` object
return Object.assign( {}, user );
} );
// call the original function with the copy
handleInactiveUsers( copiedUserList, dateCutoff );
// expose the mutated list as a direct output
return copiedUserList;
}
//this Revisited
var ids = {
prefix: "_",
generate() {
return this.prefix + Math.random();
}
};
function safer_generate(context) {
return ids.generate.call( context );
}
// *********************
safer_generate( { prefix: "foo" } );
// "foo0.8988802158307285"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment