Thursday, November 12, 2009

Power Tip: 'With'-Helpers


In the previous article, I mentioned that Delphi includes a 'with' statement, and although it seems like an unimportant for a language to have, I'm going to teach you something that will make you stand back and give you an alternate perspective on this simple mechanism. Sorry all you C++ fans, this power tip applies only to languages that have a 'with' statement.

With statements are the most useful for one thing: 'with'-helpers.

What is a 'with'-helper?

Yeah, I knew you were thinking that: a 'with'-helper is a class or data structure that is designed to be more convieniently used via a 'with' statement in Delphi. It's one of the most Ruby-like features that Delphi has to offer, brining a greater increase of convenience and fun to Delphi programming. The most quick way to demonstrate is through examples, so come on, let's take a look...

Examples

Let's start with a simple example: a work-around for variables. In Dephi, one normally has to explicitly declare variables before the block of code that uses them begins, like so:
procedure ReportMyError(Code: integer);
var
  //we're declaring the variable here in the "var" block
  vMsg: string;
begin
  if Code > 0 then
    if GetErrorMsgStr(Code, vMsg) then
      PrintLn('Error!'#13#10 + vMsg);
end;

This can quickly become inconvenient, so, why don't we create a 'with'-helper that provides a temporary string variable:
type
  TStringValue = record
    Value: string;
  end;

function StringValue: TStringValue;
begin
  Result.Value := '';
end;

And then use it like so:
procedure ReportMyError(Code: integer);
begin
  if Code > 0 then
    //calling the StringValue() function to create a new string value,
    //which is put into the context with the "with" statement:
    with StringValue do
      if GetErrorMsgStr(Code, Value) then
        PrintLn('Error!'#13#10 + Value);
end;

Did you notice where identifier called 'Value' came from? 'Value' was implicitly referenced from the TStringValue record returned by the StringValue() call and implicitly put in scope by the 'with' statement. Get all that? Thanks to Delphi's built-in support for records, we don't do any memory management! Yay! Delphi is better!

We can do much better than this, however. Let's create a nice 'with'-helper for providing the effect of a 'let' statement: create and compute a value, sort of like a closure:
type
  TFloatValue = record
    Value: extended;
  end;

function FloatValue(AValue: extended): TFloatValue;
begin
  Result.Value := AValue;
end;

Now we use it:
function EmitRatios(A, B: extended);
begin
  with FloatValue(Sqrt(Sqr(A)+Sqr(B))) do
    begin
      PrintLn(FloatToStr(Value/A));
      PrintLn(FloatToStr(Value/B));
    end;
end;

Sweet! The value passed to FloatValue() was only computed once! Yay for the extra efficiency boost! Records can do some good and come in handy-dandy using them. Along with what we've seen, we can also return multiple results from functions, capture them with a 'with' statement, and leverage them thus. But there's one problem with this last example: records can only do so much: their fields are mutable and cannot be protected from writing to them. This could cause horrible bugs in a program if we're not careful. Thus, we move on up to using classes as 'with'-helpers. Here's our previous example modified:
type
  TFloatValue = class
  private
    FValue: extended;
  public
    property Value: extended read GetValue;
  end;

function FloatValue(AValue: extended): TFloatValue;
begin
  Result := TFloatValue.Create;
  Result.FValue := AValue;
end;

//using it:

function EmitRatios(A, B: extended);
begin
  with FloatValue(Sqrt(Sqr(A)+Sqr(B))) do
    try
      PrintLn(FloatToStr(Value/A));
      PrintLn(FloatToStr(Value/B));
    finally
      Free;
    end;
end;

Notice the try-finally block for freeing the created class called by and provided for the 'with' statement. Delphi knows that the structure used by the 'with' statement should have its members in the enclosing scope, so this technique will also work even if the 'with' statement is already inside a class method.

Now that we're using classes, we can do more sophisticated stuff, seeing as classes provide not only properties, but methods. As a last example:
type
  TTokens = array of TToken;

procedure Append(AToken: TToken; var Tokens: TTokens);
begin
  SetLength(Tokens, Succ(Length(Tokens)));
  Tokens[High(Tokens)] := AToken;
end;

function ScanTokens(AStr: string): TTokens;
begin
  SetLength(Result, 0);
  //constructs a TScanner class, giving it the 
  //string to scan: TScanner = token iterator
  with Scanner(AStr) do
    try
      while ReadNextToken do //TScanner.ReadNextToken method
        Append(CurToken, Result); //TScanner.CurToken property
    finally
      Free;
    end;
end;

Conclusion

Thanks for learning. Hope you enjoyed this power tip. Happy coding!

Tuesday, November 3, 2009

Be Advised: C++ vs Delphi

While thinking about what knowledge would be of most use to the rest of programmerdom, I realized that an objective, non-biased, experienced, comparison between C++ and Delphi would provide valuable information to one and all, that all may be more educated as to the tradeoffs of these languages, their pros and cons, and perhaps be able to glean valuable insight to pass on to the next generation of programming languages.

I hear that everybody loves flamewars. If you’ve come for that, please leave now.

Still here? Ok, nice. If you’re like me, you know that anyone who is wedded to programming language X, has not spent enough time in their lives programming nor studying programming languages, to have serious experience with or understanding of programming languages. However, if you are one who has come for an experienced comparison of C++ and Delphi, well, you will not have wasted your time (inasmuch as I’m not restating what you already know). Let me just give 1 caveat: I have much more experience with Delphi than with C++, so I may have left a couple of advantageous features of C++ out. If I do so, please remind me, and I will be sure to include such (provided they meet the criteria of being exclusive, marked advantages.) Now, enough with the fluff, let’s get down to the meat. The following lists features that vary from Delphi to C++, listing the winning language:

FeatureWinnerExplanation
ClosuresDelphiC++ just doesn't have closures. Closures are an advantageous way to organize long procedures of code into smaller, more reusable pieces.
Operator OverloadingC++Delphi doesn't have this feature. Operator overloading is useful for terse arithmetic libraries over different kinds of quantities, such as intervals, bignums, and others, instead of having to invoke a bunch of method calls by name. In addition, expressions can be semantically overloaded and more reusable via OOP.
InterfacesDelphiC++ doesn't have interfaces. Interfaces are like mixins without implementations: they provide a description of a set of methods that a class would need to implement to be compatible with the interface. Subroutines can use interfaces to be more generic and reusable, by accepting, as a parameter, any object that implements a specified interface. Classes in Delphi can implement as many interfaces as they like. This provides a simple alternative to multiple inheritance.
Multiple InheritanceC++Delphi just doesn't have multiple inheritance. Multiple inheritance is where an object can inherit fields and methods from more than one base class. In practice, this is very complicated and is usually overkill, but for those situations in which it makes sense, C++ provides this alternative.
PropertiesDelphiIn C++, one must use getters and setters to write to the properties of a class. In Delphi, one describes properties, and can direct reading and writing to either a field or a getter and setter method, or describe whether a property can even be read from or written to. In addition, one can reference a property via the dot notation. e.g. "GoButton.Enabled" and use such an expression for reading and writing, without having to directly invoke getters and setters. This provides better abstraction.
Module SystemDelphiIn C++, you have header files and C++ files. The header file declares what code is available to other C++ files. The preprocessor is assigned with the task of providing each C++ and header file with knowledge of its dependencies. In Delphi, a module is a single file called a unit. The unit lists what code is public to other units (called the interface of the unit), as well as housing the implementation of the public declarations. Units lists their dependency on other units via the "uses" clause. In addition, Delphi provides optional initialization and finalization sections, so that the unit can initialize or free any internal state it uses. These features all provide for a much more robust seamless module system, giving each unit airtight encapulation facility. Of course, Delphi is a member of the Pascal family of languages, which are all known for their robust module systems.
Constructors and Stack ObjectsC++C++ has a standard system for copying objects, in addition to the normal constructor used for creating objects. This streamlines this utility. In addition, C++ then provides a way to declare object variables that are automatically created and managed on the stack. This provides better abstraction for temporary helper objects, which can then be treated as data types. In Delphi, however, all objects are created on the stack, and must be explicitly created and freed. Object variables are actually assignable, nullable references to object instances. Also, Delphi does not have a built-in system for copying objects or assigning their values around, although there is a standard method convention used for assigning objects to each other.
Templates and Generic ClassesC++Delphi does not have templates, nor does it have generic classes. This means that algorithms and data structures must be implemented differently for objects and primitive types. C++ provides templates, which allow any piece of code to be reused for different, but compatible, types, primitive or not.
Method PointersDelphiDelphi provides well-developed facilities for managing pointers to methods and subroutines. This comes in handy for event-handling code and other related uses. C++ on the other hand, is very messy, requiring one to get into some hairy types. Generally, using pointers to methods or subroutines, is not recommended. Instead, C++ relies on templates to facilitate the coupling of objects to event handlers.
Error MessagesDelphiC++'s error messages are often cryptic and do not provide intuitive or simple feedback to the programmer. Delphi always provides simple, direct error messages (although both languages use programming-centric terminology).
Encapsulated Class DefinitionsC++C++ allows one to declare a class inside a class. This is useful in some cases, so C++ provides the option. As far as I know, Delphi does not.
HackerinessC++C++ is more all-around hacker-frendly, and relies more on the use of symbols and operators, making it, in comparison to natural language, more cryptic. Delphi uses alot more english words and alot less symbols, for its code. Of course, experience with either, will render this difference negligible, but hackers tend to enjoy symbols more.
ReferencesC++C++ has references as a type. References are a more abstract version of pointers, and have lean implementations. Thus, they can come in handy for simplifying code and making it more readable. Delphi, while allowing one to pass parameters around by reference, does not have a reference type -- just pointers.
Dynamic ArraysDelphiDelphi has built-in, leanly-implemented, runtime-resizeable arrays of any dimension. These can come in handy in many situations, since Delphi lacks generics. C++ has no such thing, instead relying on its generics to achieve the same functionality.
Strings and String ManagementDelphiDelphi has built-in, leanly-implemented, memory-managed strings. Thus, using strings in Delphi is a breeze. The same is not so true for C++, but it covers most all of the ground, in ease-of-use, with its String class.
Compilation TimeDelphiDelphi was designed to compile fast, and to only compile the units that have changed since their last compile. Thanks to its module system, this is more easily achievable. In practice, this means that the compile-run cycle is quick, since the compiler will only compile the units you make changes to.
In-block VariablesC++C++ allows one to declare variables anywhere inside a block of code. This is much more convenient for writing code than in Delphi, which requires all variables to be declared in the declarations section, preceding the implementation blocks of code. Although one might argue that there's a trade-off between more readable code and more writable code. But I'd prefer C++'s choice on this one.
VariantsDelphiDelphi provides a primitive type called a Variant, which is simply a data type that can only any other primitive type (no compound types, pointers, objects, or dynamic arrays). This can be useful in situations where one would otherwise have to write lots of type-handling code. This type as evolved into the OLEVariant type, which allows Delphi programmers a choice when coding for COM and OLE automation, between early-bound and late-bound style.
SetsDelphiDelphi's equivalent to C++'s enumeration type, is much more well-abstracted. Delphi provides set union and difference operators.
Open Array ParametersDelphiIn addition to dynamic arrays, Dephi provides a way to pass arrays as parameters. It even provides a notation for declaring array-literals as parameters. e.g. "PrintLn(["hi",a,"two",x])" This is extremely handy when developing and using DSL-like libraries, such as parsers. C++ doesn't quite have this functionality.
"with" statementDelphiC++ does not have "with" statements. "With" statements are very useful for unraveling repeated object references and putting the referenced object's properties and methods automatically in the local scope. This seems like a trivial convenience, but we'll see later on why it's such an important ingredient to the repertoire of delphi's constructs.

Conclusion

So, after looking over this list of features, there's a couple of patterns that stand out -- consistent language design choices made. Delphi is intended to be an applications programming language, seeking to provide for more abstraction in many common areas -- strings, modules, open array parameters, late-bound COM programming. This is a common thread running through the design decisions of Delphi. Don't get me wrong, it's also intended to create programs of competitive efficiency with C++, but the point is that Delphi is focused on providing more abstraction for applications programmers. C++ is a systems programming language, designed to not trade a single bit of efficiency away for abstraction. It tries to do what it can for abstraction, but the guiding principle, indeed, the constraint, upon C++, is that there is nothing in the language that prevents the programmer from hand-optimizing efficiency. Language design choices are a different subject altogether, though. Just remember that language differences don't necessarily imply general superiority or inferiority. C++ is a better systems language, and Delphi is a better applications language. Each has its own optimal role.

Introduction

Hi!

Welcome to the overcoded! blog. My name is Winheim Raulsh. I am the writer of this blog and will be your guide, that you may better navigate this trove of information I periodically gather together and spill onto pages. I am a Delphi programmer by birth, and have come to know many languages like C++, Lua, and others, but mainly I will stick to my native language: Delphi.

Delphi is my default choice, as I have been programming in it for years, and it has served me well. Delphi is a systems and desktop programming language available for developing on the Win32 platform, hence it is very fast (comparable to C++) so that programs can scale without having to be rigorously optimized, yet it is a more high-level language. Delphi, ah, Delphi. It has its limitations, and isn’t anything particularly spectacular, but it can do many good things. I’ve learned most everything I ever would need to know about Delphi, and then some — all this knowledge wrapped up in my head, with nothing to do with it, so I started this blog for really no reason, except simply to kill time and do fun things with Delphi, just because I can. That’s where the name for this blog comes from: excess pointless Delphi coding for no great, grand reason — my life is overcoded.

Sometimes, I wish I could program in Lua instead. Lua is different; it doesn’t scale; you can’t write 20k LOC programs in it, you run very complex or tight computations in it, without the speed bogging down; nor is it a systems programming language with access to all of the Win32 api, nor does it come with all the useful, pre-developed gui libraries, database access, and other stuff that comes with Delphi. It’s only a scripting language, all by itself, so I’m stuck with Dephi. And that, ladies and gentlemen, is a classic case in a high barrier-to-entry, in the world of software development.

Now, where was I? Ah, yes: let me give a grand tour of how we do things around here. As I was thinking about what kinds of articles to do, I liked the idea of having different series of ongoing articles, so pretty much all articles are a part of one series or another. How did I come tho that? Basically, I narrowed down the basic purposes of different articles I would write to only a handful. It really helps one to quickly determine what the articles are throwing at you. As a blogger, I will stick close to the purpose and subject of my entries, so don’t expect much philosophical discussion, unless you’re forewarned with a title or section header, ’cause I’ll be keepin’ it on-topic.

Series

The following is a tour-guide of the different types of entries I’ll write.

Be Advised

These articles contain relatively refined knowledge and experience of practical things pertaining to software development. If I have been there, studied the issues, and have a well-developed knowledge of the situation, then consider these articles as troves of useful information to take into consideration while making decisions, or for future reference.

Power Tip

These articles contain various useful coding tricks and practical techniques for improving your development experience. They are very narrow, focused, specific things you can do. These tips are straightforward and easy to wrap your head around; they don’t require pondering to understand.

Goodies

These articles introduce free code libraries & other such stuff that I provide online! They will document such things as why, basic usage, and a download link. Feel free to use the code according to the license embedded within its downloaded version, otherwise it implicitly falls under the Create Commons Attribution-ShareAlike 3.0 License.

Queries

These articles are an opportunity for me to ask you, the reader, to enlighten me with valuable insight or information on something I can’t quite seem to grok. Explain away! Comments welcome! (Not that they’re unwelcome in other situations.) BTW, thanks in advance!

Reflections

Obviously, if I have something I feel is very important to say — something I’ve reflected upon, probably theoretical or philosophical, that helps me understand or achieve insight into the vastly complex world of programming or programming languages — I will put it in this category. Feel free to express your thoughts (on-topic, of course). I guess I would really only expect two types of responses: affirmations & critiques. ‘Course, you can criticize the ideas all you like (I don’t mind). If you find the ideas useful, please comment on how exactly so.

Programming Recipes

Unlike Power Tips, these entries get deep into the nitty-gritty of larger code solutions to various problems — recipes to code. Perhaps some of the problems can be requested by you. First, I’ll start off with an explanation of the problem, followed by an overview of the solution, followed by a laid-out, detailed walkthrough of the coding. Think of the programming version of a chef show on TV, and you have a good idea of what these articles are for. Please feel free to evaluate my solutions and suggest corrections! All your constructive feedback will especially help!

Enlightenment

Enlightenment is my explanations of concepts when I finally grok them, that is, not just what they are, but why they are, where they come from, and what they do for us. These are the kinds of things I wished computer scientists and instruction materials (all on the internet) had explained to me in terms that are familiar and clear, so feel free to learn new things, and hopefully, you can find enlightenment as well!

Conclusion

So, that’s the tour! Thanks for stopping in, now, enjoy the journey as your life becomes overcoded!