Monday, August 24, 2009

=)

Happy birthday to me,
Happy birthday to me,
Happy birthday dear... meeeee...
Happy birthday to me!

...

I need a life... Lol

Thursday, August 20, 2009

Lambdas and Anonymous Delegates pt 2

So I did exactly what I suggested to myself, and sent an email to Eric Lippert regarding the inline lambda and anonymous delegate business I blogged about earlier today. He's quick - here's his reply:

Ah, good question.

You can make this work by casting to a delegate type.

((Func<bool>)()=>M()).Invoke();
((Func<bool>)(delegate (){return M();}).Invoke();

For lambdas, we don't know whether the lambda is to be converted to a delegate or an expression tree. Since an expression tree cannot be invoked, we cannot allow you to invoke it before we know what you intend.

For anonymous methods, yeah, I suppose we could have designed C# 2.0 to allow invoking them directly. But what would the point be? Why say (delegate(){return M();}).Invoke()" when you could just say "M()"? I agree that for reasons of generality and consistency it would be nice to have, but I don't think disallowing this actually disables many scenarios.


He's right - it's not like this is some sort of necessary functionality. On the one hand, it's great that I can get exactly this functionality by casting to a delegate type first, but on the other hand it's extra cruft. All the same, if some inspired or courageous EverDroid user needs this sort of functionality, it's there.

Thanks, Eric! =)

Inline execution of a lambda expression or anonymous delegate

I had an idea I wanted to try to exploit that would make my VB.NET expression a bit more, well, expressive.

The way I built my expression builder, essentially you pass in a valid VB.NET expression and the expression builder sticks it onto the end of a Return statement inside a static method of a new class, which it then compiles with the stock VB.NET code compiler. Then I use reflection to dig out the compiled method and returns a Func<bool> that invokes the method, returning the result.

This works great for its intended purpose, but it unfortunately restricts my expressions to being, well, expressions. Boolean expressions. Which means they can't do a whole lot of processing, or whatever. That's okay - I don't really *need* all that much. But I enjoy a challenge, and I thought to myself 'Self, why don't we try to use an inline lambda!'

Great idea - except you can't INVOKE a lambda inline. Example:

bool x = ( () => true ).Invoke();

Doesn't work. Operator '.' cannot be applied to operand of type 'lambda expression'. 'Fine,' says I, 'I'll use an anonymous delegate!'

bool x = ( delegate { return true; } ).Invoke();

Operator '.' cannot be applied to operand of type 'anonymous delegate'. Argh. So as far as i'm aware, this is impossible, probably by design. I'll have to ask Eric Lippert about it, since he's been doing his C# design rationale posts lately.

Progress thus far

Truth be told, at this point, progress is slow going. I've been doing a lot of work for my friend Brian, and as it pays more immediately than Macrocrafter work I have to focus on that. It's been calming down of late (unfortunately) so that should afford me more time to work on this stuff.

I've been slowly organizing the work I need to do on this system. So far I've divided it up into several main components that I'll need to build before I can start stitching them together.

Also I've decided to skip the intermediate step and just make a damned hunter bot out of this, so I'll also need to integrate targeting and walking into the system.

Anyway - one of those systems includes a VB.NET compiler, as I mentioned before. All I need to do with this is to take my proof of concept code and make a proper system out of it - something reusable. I'm going to add it to Autocrat. I'll also need a timer that can produce timing events in 150ms intervals - that's the interval at which I'm going to have the system pull down updated EQ2 data. Any of the .NET timers should be capable of doing this so I'm not too worried here. I'm also going to need a state machine engine that can be configured via XML - this will be responsible for persisting the user-editable 'scripts' that will make up the brains of the bot itself. I've got a schema all figured up; all that remains is actually putting the work into it - and then I get to build a UI on top of it, because the last thing I want to require is for people (or myself) to have to hand-edit XML to get it to work.

Coupled with the timer is going to be a system for describing stateful property changes. Here's the problem: my bot engine is going to be evaluating event trigger expressions every 150ms. The expressions are boolean, so they'll be testing data based on the content of the current tick's EQ2 properties. If an expression looks similar to: "Return EQ2.GroupMember(2).Health < 50" - then when group member 2's health drops below 50%, it will trigger the event. This is desired - BUT it will ALSO trigger once every 150ms tick until group member 2's health rises to or above 50. This is NOT desired, so I need a way to expose the concept of state changes: for example, I'd like to rewrite the same expression as: "Return EQ2.GroupMember(2).Health.DroppedBelow(50)". That would return True if, and only if, the previous tick's Health was at or above 50 AND the current tick's Health is below 50.

So I'll need to figure out an efficient system of encapsulating old state and exposing it via these state descriptors. I'm sure I'll figure it out.

But you can see why I've been making slow progress here. =) In between kids, contract work, looking for full-time work, EQ2 updates, and other life, I don't have much time for experimentation, which is a shame.

Saturday, August 1, 2009

Happy Birthday baby girl =) And some other stuff.

So my daughter just turned 2 years old today. We had a party at CiCi's, and fun, pizza, and cake was had all around. =)

A friend of mine in NYC has a lot of extra work he's unable to do himself, due to having his own full-time job, family, etc., so he's farming it out to me. It's a great situation as I currently have a work deficit, so taking it off his hands helps me out a lot. So far I've updated three websites owned by the same company - took me the better part of a day to get it all completed, but it wasn't terribly hard. Mostly grunt-work, but it pays, and it's not brainless. I am by no means complaining. =)

Finding work in Charleston, SC has been difficult - the two large development companies out here have both rejected me as being "not quite what they want" - I don't have any team-oriented experience, or large enterprise experience, which is all they're looking for out here. My argument is that if everyone wants to hire people with prior team experience, how can anyone who doesn't have it get it? Eventually there'll be nobody left except people *without* team experience, and then what will they do?

Bah. Perhaps I'm bitter - I need a job so I can put food on the table and pay rent and all that rot. It's frustrating. I'm actually hoping I find a computer / network tech job I can do, rather than programming - I think I'll have more fun doing that, since I'll get to work with people, help solve their immediate problems, etc.

Maybe I'll see if I can find investors for that computer recycling business I've been thinking of starting.

Anyway - very little work has occurred on my next EQ2 project, which one of my friends has dubbed EverDroid - a name I think I'll use. I need to build an Eval system into Autocrat, because this is something I'm going to use a lot in projects to come, for the sake of configuration and behavior customization. That won't be hard - I've got a simple console proof of concept working just fine, compiling expressions in VB.NET (which I think non-programmers will find easier to reason about - Microsoft agrees, and has done the same thing for their expression compiler in Windows Workflow 4).

EverHarvest had a good month last month - decent sales, despite the economic issues. Not nearly what it used to be, but then again I never expected it to be. Most people seem to be happy with it, when it works - which it's not at the moment; I've been working on the next update in response to Sony's latest changes, but they're doing their rapid-fire patching again, which always makes me want to wait... I was half-way through the last set of updates when they patched again yesterday, ruining my work. Ah well - such is the price to pay. Overall it's nothing to complain about - I work on it maybe two days total out of every month.

So, that's my update today. I'll get back to the millstone again and crank out the EH update. I really need to write some helper tools for this thing...