Friday, April 17, 2009

And Now for Something Completely Different

One of the pragmatic programmer tenets is to learn a new programming language every year. I'm a bit behind on that, I haven't learn a new language since 2002 (I don't count objective C because I hate it and have only learnt the bare minimum necessary to get by). Unfortunately the need to earn a living has gotten in the way of random learning.

However I have now been programming in Delphi for 15 years. It's starting to get a bit boring and it's time to kick-start the brain again. While Delphi will be my main language for the near future, I am going to make the effort to learn something different.

The main things I am looking for in my language de jour are
  • Dynamically typed (I have done statically typed languages for decades)
  • Popular (general rule of thumb, should be at least as popular as delphi)
  • Object Orientated
  • Cross platform
  • Batteries included
This pretty much narrows it down to Perl, Php, Python and Ruby. I was initially tempted by Ruby as I don't yet have an R on my alphabetical list of programming languages. However I have settled on Python instead.

Part of the reason for going with Python is the presence of the Python for Delphi components. These promise to let you use python as a scripting language inside delphi apps. These components are used in the PyScripter ide.

The easiest way I have found to get started is to use Portable Python. This will put Python and a few tools (inc. PyScripter) into a portable drive along with a few tools and useful modules such as Django. This is considerably easier for a python newbie than sourcing and installing the packages separately.

Some useful links to get started with:
Official website
Official python tutorial (v2.6)
Dive onto python online book (useful but a bit old)
Pycon US 2009 videos
Reddit python feed

Monday, March 9, 2009

Filtering generic collections with anonymous methods

I have recently been adding generics to the ti Object Persistence Framework. As part of that I was asked to add enumerator filtering. I did this using a similar technique to that shown here by Malcolm Groves.

I ended up with code used like this:

for item in Flist.FilteredEnumerator(function (TestObject: TtiOPFTestIntegerProp): Boolean
begin
result:= TestObject.IntField mod 2 = 1;
end) do
begin
inc(intCount);
intSum:= intSum + item.IntField;
end;


I was happy enough with the result, but I wasn't happy with the implementation. I wanted something that was, well, more generic. What I ended up doing was wrapping the existing enumerator into one containing a filter. This will work with any generic collection that descends from TEnumerable. I.e. TList, TQueue, TStack, TDictionary and the TObjectXXX variations

To implement an enumerator, a class must have a GetEnumerator function. This returns an object (or a record) that has the Current property and the MoveNext function. Delphi does a fair amount of work behind the scenes to wrap this all up nicely. See The Delphi Geek's series on enumerators here for more background.

Wrapping an existing enumerator meant I could use the existing GetCurrent and MoveNext for accessing the collection. Filtering then becomes as simple as:

function TFilteredEnumerator<T>.MoveNext: Boolean;
begin
while FEnumerator.MoveNext do
begin
if FPredicate(FEnumerator.Current) then
exit(true);
end;
result:= false;
end;
The full code is as follows:
unit FilteredEnumeratorU;

interface

uses Sysutils, generics.collections;

type
TFilteredEnumerator = class
private
FEnumerator: TEnumerator;
FPredicate: TPredicate;
protected
function DoGetCurrent: T;
public
constructor Create(AEnumerable: TEnumerable; APredicate: TPredicate);
destructor Destroy;
function GetEnumerator: TFilteredEnumerator;
property Current: T read DoGetCurrent;
function MoveNext: Boolean;
end;

implementation

{ TFilteredEnumerator }

constructor TFilteredEnumerator.Create(AEnumerable: TEnumerable; APredicate: TPredicate);
begin
inherited create;
FEnumerator:= AEnumerable.GetEnumerator;
FPredicate:= APredicate;
end;

destructor TFilteredEnumerator.Destroy;
begin
FEnumerator.Free;
inherited Destroy;
end;

function TFilteredEnumerator.DoGetCurrent: T;
begin
result:= FEnumerator.Current;
end;

function TFilteredEnumerator.GetEnumerator: TFilteredEnumerator;
begin
result:= self;
end;

function TFilteredEnumerator.MoveNext: Boolean;
begin
while FEnumerator.MoveNext do
begin
if FPredicate(FEnumerator.Current) then
exit(true);
end;
result:= false;
end;

end.

To use filtering in action, simply do something like:


for xxx in TFilteredEnumerator<T>.Create(queue, function (Arg1: T): Boolean
begin
result:= ...;
end)
do
...


eg


var
queue: TQueue<string>;
cur, combined: string;
filter: TFilteredEnumerator<TTestObject>;
begin
queue:= TQueue<string>.Create;
try
...

for cur in TFilteredEnumerator<string>.Create(queue, function (Arg1: string): Boolean
begin
result:= Arg1 < 'A';
end)
do
begin
combined:= combined + cur;
end;



If you are deriving from a collection, you could also wrap this into a method:


function TFilterableList.Filter(APredicate: TPredicate<ttestobject>): TFilteredEnumerator<ttestobject>;
begin
result:= TFilteredEnumerator<ttestobject>.Create(self, APredicate);
end;
Source can be downloaded from here.

Monday, January 19, 2009

Garbage collection - it's not about lazyness

There seems to be a common belief amongst a number of Delphi programmers (and c++ programmers etc) that garbage collection is all about being too lazy to do your own clean-up.

E.g. Babnik asks "What is it about Garbage Collection?" (kudos for actually asking the question) and his post has the implicit assumption that advocates are trying to avoid doing a bit of minor work.

Others have posted far more stronger comments (check the responses to Babnik's post) straight out stating that gc = lazyness, bad coding and a slack attitude to life. I find this attitude condescending and offensive. The reason I want gc, is not because I write bad code, but because i want to write better code.

I would like to see garbage collection in native Delphi, not as a mandatory feature, but as an option. It's not something I am holding my breath for, but if there was one thing I could add, that would be it.

I know I am repeating myself, but here are my main reasons for wanting a gc (expanded from an earlier post on the subject):

  • Better code: In a non gc language, you end up with a number of idioms and practices to guard against memory leaks. Delphi has several of these.
    E.g.:
    It is rare to return an object from a function. Typically you would create an object and then pass it to a procedure to be modified.
    The use of assign rather than :=
    The use of Owner, Owned and the like to solve object destruction problems)

  • Less code: I performed a naive analysis on my most recent project by removing most .Free calls and the supporting destructors and try … finally blocks. The result was about 4% fewer lines of code. More importantly, the code I removed was boring, boilerplate which solved no business problems and added no value (other than preventing leaks)

  • Faster development: There are some minor time savings to be had simply by typing less code. However when I was regularly programming in c# I found my productivity improved due to the change of coding style that gc allowed.

  • Fewer memory leaks: By reducing the need for manually freeing memory, a gc significantly reduces the scope for memory leaks. It is still possible to leak memory, but much harder.
  • There are some problems that it is difficult to solve without a GC. Linq is often given as an example. Class operators (as opposed to record operators) is another
One of the main reasons I see for Delphi to have a gc, is that it's competitors have it. If we are to persuade people to write applications in Delphi as opposed to C#, Java etc then requiring manual memory is at best a speed bump.

Finally garbage collection definitely falls into the "Your kilometreage may vary" category. If you are working in memory constrained environments then manual management is the way to go. If you are writing database driven business apps or web apps (as I usually am) then manual management offers little or no advantage over a garbage collector.

Friday, December 12, 2008

Zombie Mansion released for the iPhone

Zombie Mansion is first person shooter game I have been developing for the past few months (and the cause of my receding hairline). It got finally got approved yesterday.

See here for screenshots and more info.
See here for the App store page.

Sunday, November 23, 2008

iPhone Dev: "The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate."

I finally finished my iPhone game this week (Zombie Mansion). All I had to do on Saturday was upload the it into the App store and spend the rest of the weekend relaxing at the beach.

Not so fast. I have spent all weekend battling the dreaded "The binary you uploaded was invalid. The signature was invalid, or it was not signed with an Apple submission certificate." error. As is often the case with error messages, the message itself was on no use what so ever in solving the problem. It was in fact a positive hindrance as I spent several hours redoing my distribution certificates, provisioning profiles and waving dead chickens (frozen) over my keyboard.

In the end I resolved it by moving my dev folder off the thumb drive (fat 32 formatted) and onto the main Mac partition (Mac OS ext format) and rebuilding.

For the benefit of any other poor buggers in the same straits, here is a list of tips I picked up while investigating this:

  • Build on a Max OS Est formated drive (you only need to do this for the App store build)
  • Make sure you have a 57*57 icon called (case sensitive) "Icon.png"
  • Check the spelling of the code signing identity
  • make sure your bundle app id is correct
  • Make sure the app bundle contains the following:
    CodeResources
    _CodeSignature
    embedded.mobileprovision

One think I found helpful was having an ad-hoc version. That let me sort out problems with certificates much more easily than doing continuous uploads.

Links:
iPhone Dev forums discussion: https://devforums.apple.com/message/12311#12311
Zombie Mansion: http://sourceitsoftware.com/zombie.html


Monday, October 13, 2008

Getting line numbers in dunit test

I forget this every time:(

By default, dunit gives the the address of where your unit tests failed.
To get the line numbers instead, do the following:

  1. Install the JCL from http://sourceforge.net/projects/jcl
  2. In your test project settings, add the conditional define USE_JEDI_JCL (Directories/Conditionals page)
  3. In your test project settings, set Map File to detailed (Linker page)
  4. Rebuild your project