Friday Programming Quiz
-
Step[] steps = new[]
{
new Step(
()=>Console.WriteLine("step 0"),
()=>Console.WriteLine("reset 0")
),
new Step(
()=>Console.WriteLine("step 1"),
()=>Console.WriteLine("reset 1")
),
new Step(
()=>Console.WriteLine("step 2"),
()=>Console.WriteLine("reset 2")
),
new Step(
()=>Console.WriteLine("step 3"),
()=>Console.WriteLine("reset 3")
),
new Step(
()=>Console.WriteLine("step 4"),
()=>Console.WriteLine("reset 4")
),
};bool DoSteps(IEnumerable<step> steps)
{
Step step=steps.FirstOrDefault();
if(step==null || (step.Action() && DoSteps(steps.TakeAfter(0)))
return true;
step.Reset();
return false;
}//EDIT: oops, forgot to define the step class! :o)
public class Step
{
public Step(Action action, Action reset)
{Action=action; Reset=reset;}public Action Action{get;set;}
public Action Reset{get;set;}
}
public delegate bool Action();To use it:
DoSteps(steps);
The neat thing about TakeAfter() is that it returns an enumerator method that iterates the existing array, rather than creating a new array. This saves on performance while still allowing elegance.
Last modified: 15mins after originally posted --
--Justin, Microsoft MVP, C#
C# / DHTML / VG.net / MyXaml expert available for consulting work[^] Get Quality Portraits Drawn From Your Photos[^]
bool DoSteps(IEnumerable steps)
{
Step step=steps.FirstOrDefault();
if(step==null || (step.Action() && DoSteps(steps.TakeAfter(0))))
return true;
step.Reset();
return false;
}could be changed to:
bool DoSteps(IEnumerable steps)
{
Step step=steps.FirstOrDefault();
return (step==null || (step.Action() && DoSteps(steps.TakeAfter(0)))|| (step.Reset() && false));
}and btw, you forget a bracket there ;)
:badger:
-
A common problem, a simple problem of compensating transactions. There are variety of different solutions. There are 5 steps an application need to perform in sequence. Call them
Step1
,Step2
,Step3
,Step4
, andStep5
. Assume them to be functions that return boolean and take no arguments.bool Step()
There are corresponding reset or rollback functions that undo the effects of the steps. Call themResetStep1
,ResetStep2
,ResetStep3
,ResetStep4
, andResetStep5
. If a step fails, theReset
methods of all the previous steps should be called and none of the new steps should execute. For example, ifStep3
fails (returns false), thenResetStep2()
andResetStep1()
should be called (in that order). Here is a sample code written poorly so that you can get an idea. BTW There are several creatve solutions: RAII, boolean algebra etc.if (Step1())
{
if (Step2())
{
if (Step3())
{
if (Step4())
{
//.....
//You get the idea
}
else
{
ResetStep2();
ResetStep1();
}
}
else
{
ResetStep1();
}
}Co-Author ASP.NET AJAX in Action
In the K.I.S.S. tradition:
void (*step[])() = { Step1, Step2, Step3, Step4, Step5 };
void (*reset_step[])() = { ResetStep1, ResetStep2, ResetStep3, ResetStep4, ResetStep5 };int index = 0;
int step_count = sizeof(step) / sizeof(step[0]);while ((index < step_count) && step[index]()) index++;
if (index < step_count) {
while (index >= 0) reset_step[--index];
}
Software Zen:
delete this;
-
I'm feeling nostolgic... bwa ha ha... -- Ian ---------
bool Step1() {printf("Step1\n"); return true;} bool Step2() {printf("Step2\n"); return true;} bool Step3() {printf("Step3\n"); return true;} bool Step4() {printf("Step4\n"); return false;} bool Step5() {printf("Step5\n"); return true;} void ResetStep1() {printf("ResetStep1\n");} void ResetStep2() {printf("ResetStep2\n");} void ResetStep3() {printf("ResetStep3\n");} void ResetStep4() {printf("ResetStep4\n");} void ResetStep5() {printf("ResetStep5\n");} typedef bool (*steptype)(); steptype steplist[] = {Step1,Step2,Step3,Step4,Step5}; typedef void (*resetsteptype)(); resetsteptype resetsteplist[] = {ResetStep1,ResetStep2,ResetStep3,ResetStep4,ResetStep5}; int main(int argc, char* argv[]) { int i=0; while (i<5 && (*(steplist[i]))()) i++; if (i<5) while (i>0) (*(resetsteplist[--i]))(); return 0; }
--------- Step1 Step2 Step3 Step4 ResetStep3 ResetStep2 ResetStep1Teach me not to read the whole thread... :-O Aha! Your solution doesn't work quite correctly. It will never call
ResetStep1()
.
Software Zen:
delete this;
-
Teach me not to read the whole thread... :-O Aha! Your solution doesn't work quite correctly. It will never call
ResetStep1()
.
Software Zen:
delete this;
-
[]
is an empty array. In this case, i'm using it as shorthand forArray.prototype
. Why? Becausearguments
isn't actually a proper array - while it does array-like things (indexed access to the current function's parameters), it's a separate type of object, one that also does other, function-specific things. So, it doesn't have aslice()
method, which i wanted - slice() extracts a portion of an array (i want the second item and everything after it).call()
andapply()
are members of every function.call()
takes at least one argument, which will becomethis
when the function executes, while each subsequent argument becomes an argument to the function itself. In this way, i can call a function defined forArray
objects on an arbitrary array-like object (arguments
) and everything works just fine.apply()
is very similar to call(), except that it takes two parameters, with the second being an array of arguments to the function. In this way,Transact()
handles recursion with a variable (but ever-decreasing) number of arguments. A simpler definition for Transact might look like this:function Transact(ops)
{
if ( ops.length < 1 )
return true;
var op = ops[0];
if ( op() && Transact(ops.slice(1)) )
return true;
eval("Reset"+op.name)();
return false;
}Transact([Step1, Step2, Step3, Step4]);
...while a slightly more confusing implementation could take this form:
function Transact()
{
if ( arguments.length < 1 )
return true;
var op = arguments[0];
if ( op() && arguments.callee.apply(this, [].slice.call(arguments, 1)) )
return true;
eval("Reset"+op.name)();
return false;
};)
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
Shog9 wrote:
call() and apply() are members of every function.
I'm still shocked by this. In Javascript, functions have members. That is very strange to me, coming from a "classical" object-oriented background of C++ and C#. Do you commonly find a use for the members of functions, or is it an abstruse niche that you happen to be savvy about?
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
In the K.I.S.S. tradition:
void (*step[])() = { Step1, Step2, Step3, Step4, Step5 };
void (*reset_step[])() = { ResetStep1, ResetStep2, ResetStep3, ResetStep4, ResetStep5 };int index = 0;
int step_count = sizeof(step) / sizeof(step[0]);while ((index < step_count) && step[index]()) index++;
if (index < step_count) {
while (index >= 0) reset_step[--index];
}
Software Zen:
delete this;
-
Shog9 wrote:
call() and apply() are members of every function.
I'm still shocked by this. In Javascript, functions have members. That is very strange to me, coming from a "classical" object-oriented background of C++ and C#. Do you commonly find a use for the members of functions, or is it an abstruse niche that you happen to be savvy about?
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
It's just part of how Javascript works - there isn't the same distinction between functions, classes, and objects that you get with, say, C++. All functions are objects, derived from Function and inheriting whatever methods are defined for it. You can actually add methods to Function and immediately use them on any other function (this also works for other base types such as Array and Object; it's great for filling in the gaps of a sub-par (*cough*IE*cough*) JS engine). And you make your own types by - wait for it - defining a function that creates them! That said, you don't really get things like inheritance in the classical sense, although the language is flexible enough you can make it work with a bit of discipline. Honestly, it's a lot of fun. ;)
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
-
It's just part of how Javascript works - there isn't the same distinction between functions, classes, and objects that you get with, say, C++. All functions are objects, derived from Function and inheriting whatever methods are defined for it. You can actually add methods to Function and immediately use them on any other function (this also works for other base types such as Array and Object; it's great for filling in the gaps of a sub-par (*cough*IE*cough*) JS engine). And you make your own types by - wait for it - defining a function that creates them! That said, you don't really get things like inheritance in the classical sense, although the language is flexible enough you can make it work with a bit of discipline. Honestly, it's a lot of fun. ;)
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
Shog9 wrote:
And you make your own types by - wait for it - defining a function that creates them!
:wtf: Do Javascript developers have to drink the special Kool-aid before being "initiated"??? :)
Shog9 wrote:
Honestly, it's a lot of fun.
Sounds like it.
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
Shog9 wrote:
And you make your own types by - wait for it - defining a function that creates them!
:wtf: Do Javascript developers have to drink the special Kool-aid before being "initiated"??? :)
Shog9 wrote:
Honestly, it's a lot of fun.
Sounds like it.
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
:) Btw - if you're interested, check out this link[^]. He demonstrates most of what i was talking about, and does a better job of explaining it.
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
-
:) Btw - if you're interested, check out this link[^]. He demonstrates most of what i was talking about, and does a better job of explaining it.
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
Shog9 wrote:
if you're interested, check out this link[^].
Thanks, I'll check it out. Going to see some apartments now (sigh).
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
bool DoSteps(IEnumerable steps)
{
Step step=steps.FirstOrDefault();
if(step==null || (step.Action() && DoSteps(steps.TakeAfter(0))))
return true;
step.Reset();
return false;
}could be changed to:
bool DoSteps(IEnumerable steps)
{
Step step=steps.FirstOrDefault();
return (step==null || (step.Action() && DoSteps(steps.TakeAfter(0)))|| (step.Reset() && false));
}and btw, you forget a bracket there ;)
:badger:
Anton Afanasyev wrote:
could be changed to: [...]
Yeah... but it's less readable. ;)
Anton Afanasyev wrote:
and btw, you forget a bracket there ;)
Oops! :-O
--Justin, Microsoft MVP, C#
C# / DHTML / VG.net / MyXaml expert available for consulting work[^] Get Quality Portraits Drawn From Your Photos[^]
-
Teach me not to read the whole thread... :-O Aha! Your solution doesn't work quite correctly. It will never call
ResetStep1()
.
Software Zen:
delete this;
-
:) Btw - if you're interested, check out this link[^]. He demonstrates most of what i was talking about, and does a better job of explaining it.
----
I don't care what you consider witty, but at least I do not blather on posting nonsense like Jim Crafton.
-- Stringcheese, humbled by Crafton's ability to string together multiple sentences
Shog9 wrote:
He demonstrates most of what i was talking about, and does a better job of explaining it.
That's a very clear explanation of how JavaScript provides OO. I thought the prototype idea was cool, but using it seems rather verbose. The one thing I wasn't impressed by is JavaScript's support for, or maybe just his example of, polymorphism. What he demonstrated is not really polymorphism, but just calling functions on two objects that happen to have the same name and parameter list. No virtual/override was involved, so it's not truly polymorphic from the caller's perspective. Here's the example:
function A(){this.x = 1;}
A.prototype.DoIt = function()
// Define Method
{this.x += 1;}function B(){this.x = 1;}
B.prototype.DoIt = function()
// Define Method
{this.x += 2;}a = new A;
b = new B;
a.DoIt();
b.DoIt();
document.write(a.x + ', ' + b.x);:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
A common problem, a simple problem of compensating transactions. There are variety of different solutions. There are 5 steps an application need to perform in sequence. Call them
Step1
,Step2
,Step3
,Step4
, andStep5
. Assume them to be functions that return boolean and take no arguments.bool Step()
There are corresponding reset or rollback functions that undo the effects of the steps. Call themResetStep1
,ResetStep2
,ResetStep3
,ResetStep4
, andResetStep5
. If a step fails, theReset
methods of all the previous steps should be called and none of the new steps should execute. For example, ifStep3
fails (returns false), thenResetStep2()
andResetStep1()
should be called (in that order). Here is a sample code written poorly so that you can get an idea. BTW There are several creatve solutions: RAII, boolean algebra etc.if (Step1())
{
if (Step2())
{
if (Step3())
{
if (Step4())
{
//.....
//You get the idea
}
else
{
ResetStep2();
ResetStep1();
}
}
else
{
ResetStep1();
}
}Co-Author ASP.NET AJAX in Action
Rama Krishna Vavilala wrote:
Assume them to be functions that return boolean
No, I'll insist that they throw an Exception. As such, I'd simply alter the sample to use try/catch rather than if/else.
try
{
Step1() ;try { Step2() ; // etc. } catch ( System.Exception err ) { ResetStep1() ; throw ( err ) ; }
}
catch ( System.Exception err )
{
// Log message
} -
Rama Krishna Vavilala wrote:
Assume them to be functions that return boolean
No, I'll insist that they throw an Exception. As such, I'd simply alter the sample to use try/catch rather than if/else.
try
{
Step1() ;try { Step2() ; // etc. } catch ( System.Exception err ) { ResetStep1() ; throw ( err ) ; }
}
catch ( System.Exception err )
{
// Log message
}Well you can wrap the step in an exception throwing function.
void StepWithException(Step step)
{
if (!step())
throw new StepFailedException();
}Co-Author ASP.NET AJAX in Action
-
Rama Krishna Vavilala wrote:
Assume them to be functions that return boolean
No, I'll insist that they throw an Exception. As such, I'd simply alter the sample to use try/catch rather than if/else.
try
{
Step1() ;try { Step2() ; // etc. } catch ( System.Exception err ) { ResetStep1() ; throw ( err ) ; }
}
catch ( System.Exception err )
{
// Log message
}As I was finishing up that post I remembered another tactic that I learned while doing embedded PL/SQL in the '90s. Adjusted for C# and again using Exceptions rather than booleans:
int step = 0 ;
try
{
Step1() ;
step = 1 ;Step2() ; step = 2 ; Step3() ; step = 3 ; Step4() ; step = 4 ; Step5() ; step = 5 ;
}
catch ( System.Exception err )
{
// Log messageswitch ( step ) { case 4 : { ResetStep4() ; goto case 3 ; } case 3 : { ResetStep3() ; goto case 2 ; } case 2 : { ResetStep2() ; goto case 1 ; } case 1 : { ResetStep1() ; break ; } }
}
-
Shog9 wrote:
He demonstrates most of what i was talking about, and does a better job of explaining it.
That's a very clear explanation of how JavaScript provides OO. I thought the prototype idea was cool, but using it seems rather verbose. The one thing I wasn't impressed by is JavaScript's support for, or maybe just his example of, polymorphism. What he demonstrated is not really polymorphism, but just calling functions on two objects that happen to have the same name and parameter list. No virtual/override was involved, so it's not truly polymorphic from the caller's perspective. Here's the example:
function A(){this.x = 1;}
A.prototype.DoIt = function()
// Define Method
{this.x += 1;}function B(){this.x = 1;}
B.prototype.DoIt = function()
// Define Method
{this.x += 2;}a = new A;
b = new B;
a.DoIt();
b.DoIt();
document.write(a.x + ', ' + b.x);:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
It's a different way of inheritance. JavaScript has something called "Prototype based inheritance". It's a different way now you can extend it all the way you want. For example here is one way of doing that: http://www.asp.net/ajax/documentation/live/tutorials/EnhancingJavaScriptTutorial.aspx[^]
Co-Author ASP.NET AJAX in Action