Skip to content

Instantly share code, notes, and snippets.

@subzey
Forked from 140bytes/LICENSE.txt
Created June 3, 2011 14:51
Show Gist options
  • Save subzey/1006455 to your computer and use it in GitHub Desktop.
Save subzey/1006455 to your computer and use it in GitHub Desktop.
chaining average

Chaining average

The averaging function itself is not such interesting. This is a demo of chaining, «this» and duck typing magic. Function gets arbitrary number of arguments and returns a function that gets arbitrary number of arguments that… etc. Until cast into number or string is happened, then it returns the average value of all arguments supplied.

137 bytes between { and }.

Example

var avg = function(){/** code in index.js **/};
var average = avg(1).apply(this,[2,3,4])(5,6)()(7);
alert(average); /* "4" as in average of 1, 2, 3, 4, 5, 6 and 7 */
function(){ /* outer function */
/* Defining vars in usual way. We need arguments unchanged */
/* Each time function is called it has new scope, so we don't have to worry about interference */
var
a=0, /* average */
c=0, /* count of items */
i, /* to-be iterator in inner func */
u, /* to-be arguments alias in inner func */
n = function(){ /* inner function */
for(
/* Store arguments (very long var name!) into u */
/* Then i is count of arguments passed */
i=(u=arguments).length;
/* And right after that i is length-1, i.e. max argument index */
/* Note post-decrement */
i--;
/* Empty block */
/* Appending new item, incrementing count */
/* Note the pre-increment */
) a = (u[i] + a * c) / ++c;
/* Return the average primitive if func is called as a method of itself */
/* Return the func itself otherwise */
/* Comments follows */
return n==this ? a : n
};
/* Passing thru arguments to inner function. Use random garbage as this. */
/* It will return itself, so this is the same as n.toString=n; return n.apply({},arguments) */
/* Then - a trick! - make inner func's toString method is the inner func itself */
/* so we can check this to tell if func is called as toString */
/* (toString method is called implicitly when converting object into primitive) */
return n.toString=n.apply({},arguments)
/* And finally return the inner function */
}
function(){var a=0,c=0,i,u,n=function(){for(i=(u=arguments).length;i--;)a=(u[i]+a*c)/++c;return n==this?a:n};return n.toString=n.apply({},arguments)}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "chainingAverage",
"description": "Returns average of multiple numbers in a bizarre way",
"keywords": [
"chaining",
"average",
"this"
]
}
<!DOCTYPE html>
<title>Foo</title>
<div>Expected value: <b>4</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
// write a small example that shows off the API for your example
// and tests it in one fell swoop.
var myFunction = function(){var a=0,c=0,i,u,n=function(){for(i=(u=arguments).length;i--;)a=(u[i]+a*c)/++c;return n==this?a:n};return n.toString=n.apply({},arguments)}
document.getElementById( "ret" ).innerHTML = myFunction(1).apply(this,[2,3,4])(5,6)()(7)
</script>
@jed
Copy link

jed commented Jun 3, 2011

you should probably be using valueOf instead of toString.

@subzey
Copy link
Author

subzey commented Jun 3, 2011

Ehm... Maybe.
toString is used when valueOf is not defined and vice versa. So I'm pretty unsure which one is better.

@jed
Copy link

jed commented Jun 3, 2011

given that your return value is a number, it would seem better to return a number through valueOf than return a string that gets coerced into a number.

@subzey
Copy link
Author

subzey commented Jun 3, 2011

I suppose you're right. Thank you!

@subzey
Copy link
Author

subzey commented Jun 4, 2011

It doesn't work with valueOf.
Function.prototype has its own toString so it is used instead of Object.prototype.toString

@jed
Copy link

jed commented Jun 4, 2011

ah, interesting! good catch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment