What is the difference between the VarIsEmpty and VarIsEmptyParam functions - delphi

Working in Delphi7 just now, I noticed that not only a VarIsEmpty function exists, but also a VarIsEmptyParam.
Since the help of Delphi does not give much explanation:
VarIsEmptyParam returns true if the given variant represents an unassigned
optional parameter.
If the variant contains any other value, the function result is false.
I was just wondering if anyone has used this function, and if so, how this function is meant to be used.

In COM it is possible to have optional parameters in a method call at any position, while in Delphi this is only possible at the end. So if you want to omit the parameter you can write EmptyParam instead. EmptyParam is a global variable initialized with the correct values.
Now when you are implementing a COM interface you have to deal with these optional parameters, too. The way to find out these omitted parameters is VarIsEmptyParam.
Note that even an empty variant given as a parameter yields VarIsEmptyParam = false, because the param is not omitted. It is just empty, but it is there.
So normally there is:
VarIsEmpty(v) ==> not VarIsEmptyParam(v)
and
VarIsEmptyParam(v) ==> not VarIsEmpty(v)

Related

OLE automation: How to check if a variant references an automation object

I would like to know how can i determine, whether a variant is referencing an OLE automation object, or not.
I'm exporting some Excel graphs to Powerpoint.
I have this code:
var PptFile: Variant;
....
// PptFile _might_ be initialized:
PptFile:=pptApp.Presentations.Open(pptFilename);
// It depends on whether the export has items which need to be exported to
// Powerpoint or not
....
// I would like to determine if PptFile does reference an OLE automated object or not
PptFile.SaveAs(excelFileName+'.pptx');
I know, it could be done by placing the last line of the code (with saveAs) between try...except...end, but i don't feel that approach is good enough.
I was reading about VarIsEmpty, VarIsEmptyParam, Nothing, this question, but i'm not sure about this.
You should use VarIsClear for this test.
Indicates whether the specified variant has an undefined value.
VarIsClear returns true if the given variant's value is undefined. The
value can be undefined for any of several reasons:
The Variant may have had its value set to Unassigned.
The Variant's value may be an interface type that has been set to nil (Delphi) or NULL (C++).
The Variant may be a custom variant that returns true from its IsClear method.
In all other cases, the function result is false.
Note: Do not confuse an unassigned variant with a Null variant. A Null variant is still assigned, but has the value Null. Unlike
unassigned variants, Null variants can be used in expressions and can
be converted to other types of variants.
However, I question whether or not it is needed. How could it be that PptFile was not assigned? That can only happen if the call to pptApp.Presentations.Open() fails, and that would raise an exception. Or am I mis-understanding this? I cannot at the present see any scenario in which you could reach the call to PptFile.SaveAs() for which PptFile had not been assigned.

What's the difference between "var" and "out" parameters?

What's the difference between parameters declared with var and those declared with out? How does the compiler treat them differently (e.g., by generating different code, or by changing which diagnostics it issues)? Or do the different modifiers merely allow the programmer to document intended use of the parameters? What effect do the types of the parameters have on the matter?
A var parameter will be passed by reference, and that's it.
An out parameter is also passed by reference, but it's assumed that the input value is irrelevant. For managed types, (strings, Interfaces, etc,) the compiler will enforce this, by clearing the variable before the routine begins, equivalent to writing param := nil. For unmanaged types, the compiler implements out identically to var.
Note that the clearing of a managed parameter is performed at the call-site and so the code generated for the function does not vary with out or var parameters.
There is not much difference, for the compiler that is. See Mason's answer for that.
Semantically, there is a big difference:
var tells the programmer that the routine could work with its current value,
out tells the programmer that the routine will ignore/discard its current value.
Slightly late but just for the record, I came across a case where var or out made a big difference.
I was working on a SOAP web service which exported the following method:
function GetUser( out User :TUser ) :TResult;
which was getting imported into C# as the equivalent of
function GetUser( out Result :TResult) :TUser;
when I changed the out to a var it it imported correctly.
I'm guessing that the Delphi SOAP invoker treats the function result as an out parameter and that having two out parameters confuses the Delphi SOAP routines. I'm not sure if there is a workaround to allow you to use out parameters.
I read earlier that out parameter is set to default by called function, but today I realized that it is not completely true. Value of out parameter is discarded by called routine, but if that routine does not change its value, caller can still get it initial value, which was assigned before passing to called thread.
For example:
procedure JustNothing(out x : integer);
begin
// do nothing
end;
procedure TestOutVar;
var i : Integer;
begin
i := 100;
JustNothing(i); // after this call, i will still be 100
end;

Retrieve TProc from Generic Container

Just discovered something rather funny:
var
Queue : TQueue <TProc>;
MyProc : TProc;
...
MyProc := Queue.Dequeue;
I think you see what is intendend here. However, the compiler thinks I want to store the Queue.Dequeue method (type "procedure of object") in MyProc and reports an error
E2010 Incompatible Types: 'TProc' und 'Procedure of object'
The workaround I came up with goes like this
MyProc := TProc (Pointer (Queue.Dequeue));
Is there a more elegant solution?
There's a bit of syntactical ambiguity there about whether the name "Dequeue" refers to the function itself, or the function's return value. And since you're dealing with an anonymous method pointer which you can assign a normal function to, it's trying to interpret that as a function assignment, not a function result assignment. Casting it to a pointer is the wrong solution, as that would force the function assignment to go through, which would then cause all sorts of fun errors when you attempt to invoke MyProc.
The correct way to fix it is by removing the syntactical ambiguity. Put an empty parenthesis after Dequeue, so that the compiler is sure that you're calling the function and not simply referencing it by name, and then it'll work.
MyProc := Queue.Dequeue();
As Mason said, there's an ambiguity in the Delphi syntax. Where TFoo.Bar is a method, it's not clear that FooValue.Bar means to refer to the result of calling TFoo.Bar, or a method pointer (or reference) TFoo.Bar itself (with implied Self argument of FooValue).
In the comments of Mason's answer, Rob Kennedy seems to suggest that the compiler simply figure this out based on the types of everything involved. This isn't simple; the compiler already does a lot of work to figure out whether you mean to refer to a method pointer value or a method call. It actually parses expressions in a different way when the expected receiver is a method pointer (or reference, or function pointer) type. The effort is especially involved when overloads are brought into the picture: the compiler scans through every overload candidate and checks for method pointer types in every parameter position, and then parses arguments differently depending on whether or not that parameter position contains a function pointer in one of the overloads. Then, if an overload that expects a function pointer isn't matched, the compiler changes the parse tree from function pointer to method call. The overloading mechanism itself needs to figure out which to use when its doing value to parameter comparisons. It's pretty messy, and it would be great if we didn't make it messier.
A prefix-style operator like # or Addr() isn't much help in resolving this ambiguity, not least because functions may return function pointers, and so on; how many # do you need to inhibit implicit (no () necessary) calling to grab the right value out? So when anonymous methods were introduced, a change in the expression parsing was made: I introduced the possibility of using () to force an invocation.
You can read more about it here:
http://blog.barrkel.com/2008/03/odd-corner-of-delphi-procedural.html
and here:
http://blog.barrkel.com/2008/03/procedurally-typed-expressions-redux.html

Named/optional parameters in Delphi?

In one of the Delphi demo applications, I've stumbled upon some syntax that I didn't know the Delphi compiler accepted:
// ......\Demos\DelphiWin32\VCLWin32\ActiveX\OleAuto\SrvComp\Word\
// Main.pas, line 109
Docs.Add(NewTemplate := True); // note the assignment
I can't seem to reproduce this type of parameter passing in my own code, and I never see anyone use it. So these are my questions:
Can i use this in "normal" methods and is it part of "the Delphi Language", or is this some compiler hack for automation objects?
What's needed in order to be able to use this?
Is this anything like C#4's named and optional parameters?
Additional information: I usually pass
records or simple classes when there
are many optional parameters to
methods, but it looks like I wouldn't
need that with this syntax. I'm aware
of default parameter values, but their
usefulness is limited because you
cannot provide any parameters to the
right of an omitted one. In JavaScript
I'm using this named parameter style
all the time (be it with different
syntax), and it's powerful.
Clearly the Delphi language supports named parameters since they appear right there in sample Delphi code. Delphi supports named parameters on automation objects, which are objects that implement the IDispatch interface. There are restrictions on the types the parameters and return types can have; in particular, they can't be Delphi classes.
I don't think the convenience you seek from named parameters would outweigh the performance hit you'd take by having every method call routed through the IDispatch.Invoke method. A call may also need to use GetIDsOfNames first. You don't see this in more code because late binding is usually something people try to avoid. Use early binding whenever possible to avoid the cost of looking up dispatch IDs and indirect method invocations.
Delphi supports optional parameters in non-automation code by allowing default values. You can omit the actual parameters for any parameter with a default value as long as you also omit the actual parameters of all subsequent parameters — the compiler ensures that a function's declaration allows for that.
I think optional parameters are overrated. They save time for the (one) person writing the code, but not for the (many) people reading the code. Whoever's reading it needs to know what the default values will be of any unspecified parameters, so you may as well just provide all the values explicitly anyway.
If you declare your procedure like so:
procedure DoSomething(AParam : integer = 0);
... it will assume a value of 0 for the parameter if it isn't given. As I recall, parameters with default values have to be at the end of the call, so like this:
procedure DoSomething(AFirstParam : string; AParam : integer = 0);
not like this:
procedure DoSomething(AParam : integer = 0; ASecondParam : string);
It is basically "some compiler hack for automation objects". I sometimes have to use it for Excel and Word automation.
e.g.
MSExcel.Application.Cells.Replace(What:='', Replacement:='', LookAt:=xlPart,
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=True, ReplaceFormat:=True);
Is equivalent to VBA
Application.Cells.Replace(What='', Replacement='', LookAt=xlPart, _
SearchOrder=xlByRows, MatchCase=False, SearchFormat=True, ReplaceFormat=True)

Scope of anonymous methods

One nice thing about anonymous methods is that I can use variables that are local in the calling context. Is there any reason why this does not work for out-parameters and function results?
function ReturnTwoStrings (out Str1 : String) : String;
begin
ExecuteProcedure (procedure
begin
Str1 := 'First String';
Result := 'Second String';
end);
end;
Very artificial example of course, but I ran into some situations where this would have been useful.
When I try to compile this, the compiler complains that he "cannot capture symbols". Also, I got an internal error once when I tried to do this.
EDIT I just realized that it works for normal parameters like
... (List : TList)
Isn't that as problematic as the other cases? Who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed?
Var and out parameters and the Result variable cannot be captured because the safety of this operation cannot be statically verified. When the Result variable is of a managed type, such as a string or an interface, the storage is actually allocated by the caller and a reference to this storage is passed as an implicit parameter; in other words, the Result variable, depending on its type, is just like an out parameter.
The safety cannot be verified for the reason Jon mentioned. The closure created by an anonymous method can outlive the method activation where it was created, and can similarly outlive the activation of the method that called the method where it was created. Thus, any var or out parameters or Result variables captured could end up orphaned, and any writes to them from inside the closure in the future would corrupt the stack.
Of course, Delphi does not run in a managed environment, and it doesn't have the same safety restrictions as e.g. C#. The language could let you do what you want. However, it would result in hard to diagnose bugs in situations where it went wrong. The bad behaviour would manifest itself as local variables in a routine changing value with no visible proximate cause; it would be even worse if the method reference were called from another thread.
This would be fairly hard to debug. Even hardware memory breakpoints would be a relatively poor tool, as the stack is modified frequently. One would need to turn on the hardware memory breakpoints conditionally upon hitting another breakpoint (e.g. upon method entry). The Delphi debugger can do this, but I would hazard a guess that most people don't know about the technique.
Update: With respect to the additions to your question, the semantics of passing instance references by value is little different between methods that contain a closure (and capture the paramete0 and methods that don't contain a closure. Either method may retain a reference to the argument passed by value; methods not capturing the parameter may simply add the reference to a list, or store it in a private field.
The situation is different with parameters passed by reference because the expectations of the caller are different. A programmer doing this:
procedure GetSomeString(out s: string);
// ...
GetSomeString(s);
would be extremely surprised if GetSomeString were to keep a reference to the s variable passed in. On the other hand:
procedure AddObject(obj: TObject);
// ...
AddObject(TObject.Create);
It is not surprising that AddObject keeps a reference, since the very name implies that it's adding the parameter to some stateful store. Whether that stateful store is in the form of a closure or not is an implementation detail of the AddObject method.
The problem is that your Str1 variable is not "owned" by ReturnTwoStrings, so that your anonymous method cannot capture it.
The reason it cannot capture it, is that the compiler does not know the ultimate owner (somewhere in the call stack towards calling ReturnTwoStrings) so it cannot determine where to capture it from.
Edit: (Added after a comment of Smasher)
The core of anonymous methods is that they capture the variables (not their values).
Allen Bauer (CodeGear) explains a bit more about variable capturing in his blog.
There is a C# question about circumventing your problem as well.
The out parameter and return value are irrelevant after the function returns - how would you expect the anonymous method to behave if you captured it and executed it later? (In particular, if you use the anonymous method to create a delegate but never execute it, the out parameter and return value wouldn't be set by the time the function returned.)
Out parameters are particularly difficult - the variable that the out parameter aliases may not even exist by the time you later call the delegate. For example, suppose you were able to capture the out parameter and return the anonymous method, but the out parameter is a local variable in the calling function, and it's on the stack. If the calling method then returned after storing the delegate somewhere (or returning it) what would happen when the delegate was finally called? Where would it write to when the out parameter's value was set?
I'm putting this in a separate answer because your EDIT makes your question really different.
I'll probably extend this answer later as I'm in a bit of a hurry to get to a client.
Your edit indicates you need to rethink about value types, reference types and the effect of var, out, const and no parameter marking at all.
Let's do the value types thing first.
The values of value types live on the stack and have a copy-on-assignment behaviour.
(I'll try to include an example on that later).
When you have no parameter marking, the actual value passed to a method (procedure or function) will be copied to the local value of that parameter inside the method. So the method does not operate on the value passed to it, but on a copy.
When you have out, var or const, then no copy takes place: the method will refer to the actual value passed. For var, it will allow to to change that actual value, for const it will not allow that. For out, you won't be able to read the actual value, but still be able to write the actual value.
Values of reference types live on the heap, so for them it hardly matters if you have out, var, const or no parameter marking: when you change something, you change the value on the heap.
For reference types, you still get a copy when you have no parameter marking, but that is a copy of a reference that still points to the value on the heap.
This is where anonymous methods get complicated: they do a variable capture.
(Barry can probably explain this even better, but I'll give it a try)
In your edited case, the anonymous method will capture the local copy of the List. The anonymous method will work on that local copy, and from a compiler perspective everything is dandy.
However, the crux of your edit is the combination of 'it works for normal parameters' and 'who guarantees that the reference is still pointing to an alive object whenever the anonymous method is executed'.
That is always a problem with reference parameters, no matter if you use anonymous methods or not.
For instance this:
procedure TMyClass.AddObject(Value: TObject);
begin
FValue := Value;
end;
procedure TMyClass.DoSomething();
begin
ShowMessage(FValue.ToString());
end;
Who guarantees that when someone calls DoSomething, that the instance where FValue points to still exists?
The answer is that you must guarantee this yourself by not calling DoSomething when the instance to FValue has died.
The same holds for your edit: you should not call the anonymous method when the underlying instance has died.
This is one of the areas where reference counted or garbage collected solutions make life easier: there the instance will be kept alive until the last reference to it has gone away (which might cause instance to live longer than you originally anticipated!).
So, with your edit, your question actually changes from anonymous methods to the implications of using reference typed parameters and lifetime management in general.
Hopefully my answer helps you going in that area.
--jeroen

Resources