Continuing the theme of recent – and upcoming – posts about new (and not so new) syntax in modern (and not so modern) variations on the Pascal language, I just have to comment on what I regard as yet another stunningly good job that the guys at RemObjects have done in their “Nougat” flavoured Oxygene. Specifically in relation to how they have implemented the named method parts syntax in Objective-C.
The example that Marc Hoffman provides in his recent blog post, is the constructor method for a string, stringByPaddingToLength:withString:startingAtIndex:.
This would be called in Objective-C thusly:
[myString stringByPaddingToLength: 9 withString: @"." startingAtIndex:0];
How on earth can you contrive to make such a call in a Pascal derived language ?
Well, as Marc describes, there are a number of possible approaches, most of which are dictated by whether you are extending the language or merely providing a bridge from the language into the runtime.
The bridge approach results in the most cumbersome – and imho downright ugly – solutions but remains strictly and technically within the limits of the existing Pascal language.
A first cut at providing a bridge to this Objective-C API might simply ignore named method parts by implementing them as simple parameters to the base method name, overloading where necessary:
myString.stringByPaddingToLength(9, '.', 0);
Or you might encode the method part names in the method itself either by preference or by necessity (if there are methods whose method parts differ in name, but not type – though I am not as yet away of any such examples in the Objective-C runtime):
myString.stringByPaddingToLengthWithStringStartingAtIndex(9, '.', 0);
Not Your Daddy’s Pascal
Whilst both of these are demonstrably “Pascal”, within the existing syntax of the language, neither maps very comfortably or intuitively to the Objective-C runtime.
Extending the language, by contrast, creates something that is arguably not Pascal at all – by definition, since it involves changes or additions to the syntax – but which is, ironically, the most Pascal-like in terms of preserving elegance and clarity not only in the language but in way that it exposes the underlying RTL:
// [myString stringByPaddingToLength: 9 withString: @"." startingAtIndex:0];
myString.stringByPaddingToLength(9) withString('.') startingAtIndex(0);
imho, not only is this cleaner code and closer to the underlying RTL, but it is, if anything, an improvement even on the “native platform” code for that RTL!
Whilst some might rail at this, crying “But this isn’t Pascal!!“, I would ask whether this would be considered more or less “Pascal-ish” than:
TMyWindowClass = class(TMyBaseControl)
procedure WMPaint(var aMessage: TWMPaint); message WM_PAINT;
end;
Colour Me Excited
For myself, I am increasingly excited to see how RemObjects approach targeting new platforms with the language that I am most familiar with, in the same way that I was excited when I first saw Delphi 1.0 and how the language was adapted to suit Windows, back in the day.
Tags: language, objective-c, pascal
-
Replacing spaces with dots results in:
myString.stringByPaddingToLength(9).withString(‘.’).startingAtIndex(0);
There also exists a named arguments syntax:
myString.stringByPaddingToLength(9, withString := ‘.’, startingAtIndex := 0);
This syntax is only available for Variants in Delphi, but indeed, it looks pretty Pascalish and it’s an ordinary thing present in Ada from the beginning
-
Indeed, as already Jolyon pointed out, using dots to concat the parts of the method call would be highly ambiguous, and thus not feasible.
We did explore a wide variety of options, including the second “named parameter” approach that you suggest, but our main issue with that one was exactly that: these ARE NOT named parameters, and that is the wrong way to think about these names.
All parts together form the core name of the method. If you look at the docs, or into the implementation details of how a method call is encoded, you will see that the name, literally, is “stringByPaddingToLength”withString:startingAtIndex:”. The first part is indeed no more important than the other parts — and we wanted a syntax that properly reflected that.
-
Then you don’t need delimiters at all. If it is all the single name – then be it.
Object.MethodX(11)withOption(‘ABC’)havingVoidFlag()overSource(DataSet1);
-
indeed, you don’t need the spaces.
-
-
-
-
I guess I’d have preferred : mystring.StringByPaddingToLength(9) & withString(‘.’) & startingAtIndex(0)
that is, an actual operator character but NOT A DOT, instead of Space being used to combine the parts. Then the “selectorBegins(arg) & selectorContinues” is visibly more different. As it is, it looks like a typo.
Especially when you format it on multiple lines, and then someone gets confused and starts adding semicolons. Pain. Pain. Pain.W
-
Dunno why they chosen to extend language with those spaces looking kinda infix notation, when they could just use their colon operator and do fluent-style.
-
“(if there are methods whose method parts differ in name, but not type – though I am not as yet away of any such examples in the Objective-C runtime)”
Objective-C does not support method overloading my parameters — i.e. the same method signature and name, but distinguished by different types passed to it — but Objective-C APIs will quite frequently do the oposite — i.e. have variations of the same method with different descriptions for what the second and further parameters do. for example, consider these two delegate methods of NSURLCopnnection:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data -
The problem arises due to the fact Objective-C distinguishes methods by parameter name whereas Delphi (and, for that matter, C++, Java, C# etc.) by parameter type. Nevertheless, in most cases, there’s no need to force a special syntax as there isn’t a clash, partly because the name of the first parameter in an Objective-C message is not part of its signature.
That said, a special syntax is still ultimately needed for when clashes do happen (using type aliases in XE2/XE3 is a bit of a hack). Personally I quite like FPC’s approach (though I dislike the apparent enforcement of the special syntax even when it isn’t needed). I don’t care for your point that the message syntax is a Delphi-ism not Pascal-ism, since I’ve never used a pre-Delphi Pascal derivative and never will do.
-
It’s a message …
>procedure WMPaint(var aMessage: TWMPaint); message WM_PAINT;
message in this context is an ‘abuse’ of the well defined term in 00. Method call in the ‘C’ world is a function call + dynamic address lookup. More or less a response to the time consuming string compare, simply a technical necessity. In practice the string compare did not hurt – a rule of thumb suggests, have 4 levels of inheritance and a balanced inheritance tree. The string lookup had been replaced by an ‘integer’ lookup at runtime.In pure OO an object asks the other via messages. In the C++ world the OO world is turned around 180 degree in most cases, not only but also because of the ‘.’ operator. The ‘.’ operator sent a wrong message to the developers, used to procedural languages, to see the class as summary of functions. COM/ActiveX was not very helpful, it made things worse from this perspective.
-
My only real objection is the space as conjunection syntax – it violates the spirit of the language, and possibly leads to some seriously strange bugs with name space conflicts if a semicolon gets forgotten/deleted.
A non-space conjunction would make me much happier, a(1)::b(2) would tell the compiler they are meant to be together a(1) b(2) could mean I forget a semicolon, and until the right conditions could compile… oddly.
Similar to
if (condition) then
trueclause1;
trueclause2;looks right, but the compiler does not read indention and trueclause2 always runs regardless of condition. Yes, yes, I am one of those who believe begin/end SHOULD be manditory. (besides, in delphi, begin it changes how the debugger traces an if statement, so it really is in your best interest to use them all the time)
Comments are now closed.


DelphiFeeds
47 comments