Skip to content

Instantly share code, notes, and snippets.

@normanzb
Created April 28, 2011 03:53
Show Gist options
  • Save normanzb/945765 to your computer and use it in GitHub Desktop.
Save normanzb/945765 to your computer and use it in GitHub Desktop.
the C# 'yield' implementation in javascript
// the C# 'yield' implementation in javascript
!function(){
window.yield = function(func){
this._bodyFunc=null;
};
var p = yield.prototype;
p.body = function(func){
this._bodyFunc = func;
};
p.calc = function(func){
this._calcFunc = func;
};
p.enum = function(){
try{
this._calcFunc.apply(this, arguments);
}
catch(ex){
if (ex.type != 'yield.break'){
throw ex;
}
}
};
p.ret = function(value){
this._bodyFunc.call(this, value);
};
p.brk = function(){
throw {type: 'yield.break'};
};
}();
!function(undef){
"use strict";
var noConflict = null;
var chn = function(obj){
return new wrapperCtor(obj);
};
chn.noConflict = function(){
if (noConflict){
window._0 = noConflict;
}
return chn;
};
var wrappers = {
func: function(context, propName){
return function(){
var ret = context[propName].apply(context, arguments);
// if no return value, return myself
if (ret === undef){
return this;
}
return ret;
};
},
prop: function(context, propName){
return function(value){
if (value === undef){
return context[propName];
}
else{
context[propName] = value;
return this;
}
};
}
};
/**
* Wrapper Private Methods
*/
var wrapperPrvt = {
/**
* @function init
* Copy over all members from obj and create corresponding chain-style
* wrapping function.
*/
init: function(obj, enableYield){
this._0_target = obj;
var type;
for(var name in obj){
type = Object.prototype.toString.call(obj[name]).toUpperCase();
if (type.indexOf('FUNCTION') > 0){
this[name] = wrappers.func(obj, name);
}
else{
this[name] = wrappers.prop(obj, name);
}
}
}
};
var wrapperCtor = function(obj, enableYield){
wrapperPrvt.init.call(this, obj, enableYield);
};
wrapperCtor.prototype = {
_0_rebuild: function(){
wrapperPrvt.init.call(this, this._0_target);
return this;
}
};
// shorthand method
if (window._0 != null){
noConflict = window._0;
}
window._0 = chn;
window.chainit = chn;
}();
// Example
chainit(new yield).body(function(i){if (i > 16) {this.brk()} console.log(i)}).calc(function(num, exp){var counter=0; result=1; while(counter++<exp){result*=num; this.ret(result)}}).enum(2, 8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment