"Rod" <9...@999.com> wrote in message news:44d2...@newsgroups.borland.com...
What about class constructors which require parameters?
- Danijel
I presume that DoSomething does not access any instance members? If so then
I can already do this. I also find it hard to believe your benefits as you
do not substantiate them. It's not enough to say things like "Less memory
leaks".
Pete
TMyClass = Class(TObject)
public
class function SayHello: string;
End;
{ TMyClass }
class function TMyClass.SayHello: string;
begin
Result := 'Hello';
end;
------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(TMyClass.SayHello);
end;
------------------------------------------------------------------
"Rod" <9...@999.com> escribió en el mensaje
news:44d2...@newsgroups.borland.com...
Forgive my ignorance, but ... what does C++ do then?
- Danijel
As you may have known, delphi already has static objects, using 'object' keyword. For example...
TStaticObject = object
end;
from the help file (emphasis mine):
"Since object types do not descend from TObject, they provide no built-in constructors, destructors, or other methods. You can create instances of an object type using the New procedure and destroy them with the Dispose procedure, or *you can simply declare variables of an object type, just as you would with records*.
Object types are supported for backward compatibility only. *Their use is not recommended*."
the difference being you cannot encapsulate private data when using class methods.
- Danijel
i think access to instance members are desired. in other words, Rod wants Delphi to create the object, allow instance members to be accessed, and ensure the object is freed at the end of the routine.
> I also find it hard to believe your benefits as you
> do not substantiate them.
> It's not enough to say things like "Less memory
> leaks".
Sounds like a good enough reason to me.
But as Danijel pointed out, some constructors require parameters to be passed, so in this case the proposed enhancement would not work.
correct.
>
>> I also find it hard to believe your benefits as you do not
>> substantiate them. It's not enough to say things like "Less memory
>> leaks".
>
> Sounds like a good enough reason to me.
> But as Danijel pointed out, some constructors require parameters to be
> passed, so in this case the proposed enhancement would not work.
>
>
How is C++ dealing with that?
You can in D2006 - even in Win32:
TMyClass = class
private
class var FPrivateState: integer;
public
...
end;
More details in Chapter 10 of:
http://hallvards.blogspot.com/2006/06/net-20-for-delphi-programmers.html
i think in C++, when you declare your object variable you also specify the parameters at the same time...
var
ASomeObject: TSomeObject(X, Y);
As far as I know, "static" in C++ equals global variables/objects in Delphi.
When you declare an object as static under C++, the compiler won't
instantiate it for you, you need to do it "manualy". And ... it will be a
global object, not local to your function/procedure (it won't be destroyed
until you explicitly say so).
In other words, a "static" declaration in C++ is nothing more than a global
variable/object in Delphi (not owned by the class or object, but a global
instance).
- Danijel
type
TMyRec = record
Value1: integer;
procedure ShowValue;
end;
"Rod" <9...@999.com> wrote in message news:44d2...@newsgroups.borland.com...
>
In C++, objects can be allocated with automatic extent. They are
automatically reclaimed when they go out of scope.
Cool. I thought there was a way to do that, but i'm still using D7 for now.
Even if it were so in C++ (which is the case in Java),
you still need to instantiate objects manualy.
- Danijel
I think this may not work in some cases as class variables are not specific to an instance. for example,
procedure Test2;
begin
TMyClass.FPrivateState := 2;
end;
procedure Test;
begin
TMyClass.FPrivateState := 1;
...
Test2; // nasty side effect here
...
ShowMessage(IntToStr(TMyClass.FPrivateState));
end;
This is the same as a global variable (there is only one instance, same as
"static" in C++). A similar effect can be achieved by declaring a variable
outside of the class (global variable), but it sure looks nicer if you can
declare global variables needed "only" by the class inside class
declaration.
- Danijel
In C++ you can create objects dynamically (using new) or statically. This introduces complications, such as when you return the statically created object from the function. This then involves the compiler invoking a copy constructor (if one has been defined), and everything that entails. Returning an object from a Delphi function simply returns the reference to the original. There are no hidden objects being created/destroyed.
Keep it simple!
I'd welcome it as an enhancement to delphi.
imagine having a class that creates a critical section, enters it, then in its destructor leaves and destroys the critical section. then you could write code like so...
procedure SynchedMethod;
var
ACriticalSection: TMyCriticalSection;
begin
// anything here happens within the critical section
// no need to enter and leave within try-finally
end;
on the other hand, you can get practically the same functionality using interfaces.
so its a cool idea, but i got other things to vote on for now.
--Charles
It won't work that way in Delphi.
Different from C++, where variables are declared in-between your code, (as
you know) Delphi separates declaration from code. Because C++ has a
completely different syntax, it gives you a lot more freedom in coding, but
it also allows producing a real mess (same as Java).
One such example is the use of = and == several times in the same line of
code. In other words, in Delphi you would need to instantiate your object
inside your code.
The only thing that Delphi could take care of safely and automaticaly is the
destruction of that object before function/procedure exists (in case the
object is declared that way), the same way it clears the stack from local
variables.
- Danijel
IFWTPICPPTPICPP.
;-)
--
Nick Hodges
Delphi/C# Product Manager - DevCo
http://blogs.borland.com/nickhodges
Thank you very much, but no. It is prone to bugs. If I would have to
maintain this kind of code, I would delete the variable without a blink
(being a variable "declared but never used"), especially when I might
not have the source for TMyCriticalSection.
I much prefer the try except finally blocks.
regards,
Lucian
Which is a waste of memory and CPU resources.
- Danijel
Critical Sections which are created and destroyed in the context of a
function/procedure would have no meaning, since you need to use the same
instance of a critical section object from all threads to call it "a
critical section" (section accessible only from 1 thread at a time).
Java has a declaration "synchronized" to handle this case, where a global
critical section is created for the class and used to synchronize method of
that class.
What you can do in Delphi to achieve the same is to declare a global
critical section variable, instantiate it from your units initialization
section, use it in your code, then destroy it from units finalization
section.
- Danijel
along that line of thought, simply don't allow the local instance to survive outside the scope of the procedure. if you copy the reference, you're doomed when the procedure exits as that reference always becomes stale.
how would this obsfucate the code anymore than the use of interfaces?
you wouldn't delete it presumably if you knew what the 'static' keyword meant as proposed...
var
ACriticalSection: TMyCriticalSection; static;
> I much prefer the try except finally blocks.
>
you know there's a point there too. no one would ever mistake what the try/finally was doing.
tell you what, you keep writing your try/finally's and i'll go on my merry way writing static class variables <G>.
>var
> ACriticalSection: TMyCriticalSection; static;
Obviously not the same. *Now* I would probably agree upon its usability
... but, if I don't have the code for TMyCriticalSection I will not be
able to understand your object enters and/or leaves a critical section,
so I would probably add a true Critical section if one was needed, thus
maintenance increased again.
still, no thanks.
regards,
Lucian
Ok how about this...
var
AClassThatEntersAndLeavesACriticalSection: TMyCriticalSection; static;
begin
end;
<G>
You're saying that to be more practical, Delphi would have to support inline variables
(note that TSomeObject requires an integer parameter)...
begin
for I := 0 to Count - 1 do
begin
var ASomeObject: TSomeObject(I);
ASomeObject.DoSomething;
//ASomeObject is freed here
end;
ASomeObject.DoSomething; // compile error here
end;
...i mean an integer parameter in its constructor
Much better :-), but in the end you typed a lot more. If clarity of
code means we have to resort to longer names for variables, I ain't
voting it <g>
Before we go too deep with this discussion, since this feature won't be
added to Delphi anyway, I will just say that it isn't "the Delphi way".
Delphi is a wonderful language which forces the developer to explicitly say
what he wants. In my opinion, that's a very good thing. Let's just keep it
that way.
- Danijel
> How is C++ dealing with that?
At the point of definition of the static member, if you supply
constructor parameters they will be used. Otherwise the object's
default constructor is used (which takes zero parameters.)
// header file:
class X
{
static std::string str1; // declaration
static std::string str2; // declaration
};
// .cpp file:
// (at file-scope)
// static member definitions
std::string X::str1;
std::string X::str2("foo");
--
Chris (TeamB);
by "this feature" you mean static instantiation of local classes, or inline variable declarations? or both?
as for static instantiation, we already have a solution of sorts by using reference counted interfaces. if i didn't have this i'd have thousands of try-finally's all over the place.
i don't want to sound like i'm complaining that static instantiation is missing -- i'm not. i'm just making a case for it being an advantage, however Nick's got bigger fish to fry. When he's done frying those big fish though, he shouldn't dismiss these features as not being 'the delphi way'.
for instance, inline variables limit scope, which being a form of information hiding is a good thing. it makes code more 'readable' not less.
yup. thats my point. Rod you're on your own.
Erm, this would create a critical section that this procedure and this
procedure alone can enter and exit and which doesn't exist outside of
that procedure (unless TMyCriticalSection is implemented in such a way
that it is a global singleton).
It's syntactically neat but functionally pointless.
Maybe that was your point?
<shrug>
--
Jolyon Smith
"Charles McAllister" <cha...@avimark.net> wrote in message
news:44d254c6$1...@newsgroups.borland.com...
?
Shouldn't that be IYWTPICPPTPICPP?
--
Thanks,
Brad.
> What does either one mean?
If you want to program in.....
> Shouldn't that be IYWTPICPPTPICPP?
Oooh, yes, thanks.
Indeed. There is an unsolved problem with parameterized constructors.
In C++ we can write TMyClaas c(x,y,z); within the code.
In Delphi, we have to declare the class within var section.
>
> http://qc.borland.com/wc/qcmain.aspx?d=32076
>
> Comments? Would you love such a new feature?
Yes as it would make RAII a reality
(http://www.research.att.com/~bs/bs_faq2.html#finally). I would,
however, want to see this paired with in-line variable support.
Great! That's my game!
The added bonus with RAII is that it's all worked out at compile time.
The fact is that I trust a complier more than a human when it comes to
resource management - humans forget, compliers don't.
Sorry, that's "compilers", not "compliers". But I guess if you are a
"complier" that it could imply that you wouldn't forget in the first
place. :)
Don't do it! Leave the language alone.
I don't want Delphi locked into the smart alec language group (like C++)
where more and more goes on behind the scenes until only experienced
programmers can get anywhere.
I realise that very clever people like to use clever languages, but the joy
of Pascal was its clarity - and Delphi has kept much of that.
I believe that even function overloading spoiled Delphi - if I want function
X, then I say function X. I don't want the compiler making choices for me.
Like the dreaded "with" statement.
I want to create something explicitly when I want and in the order I want.
I don't want to have to know the rules for automatic construction and
destruction.
The problem is that the barrier to entry gets higher and higher, until your
language is only used by the elite. You have a great language, but not
accessible. Delphi must occupy the simple but powerful territory.
Roger Lascelles
Further to this, I don't believe that these complications and improvements
help optimization. If Delphi is to be (for example) better able to cope
with parallelization, then features that emulate the explicitness of C++ may
actually get in the way of a better design language. Personally I'd like to
see Delphi take on those features of functional languages and similar higher
level languages that lower level ones. One big improvement to Delphi was
taking on the OLE Automation features of VB in a simple way. What would
Delphi look like if they had emulated C++ instead?
Oliver Townshend
> I don't want Delphi locked into the smart alec language group (like
> C++) where more and more goes on behind the scenes until only
> experienced programmers can get anywhere.
Amen!
> I realise that very clever people like to use clever languages, but
> the joy of Pascal was its clarity - and Delphi has kept much of that.
Preach it, Brother Roger!
> I want to create something explicitly when I want and in the order I
> want. I don't want to have to know the rules for automatic
> construction and destruction.
Hallelujah!!!!!
> The problem is that the barrier to entry gets higher and higher,
> until your language is only used by the elite. You have a great
> language, but not accessible. Delphi must occupy the simple but
> powerful territory.
Word up, my man.
Roger,
Everything you wrote, was perfectly worded. You get it. Thank you.
--
Lee
More behind the scenes like having a garbage collector? I might feel
more comfortable using the OP's solution as a compromise to relying on a
full blown GC.
In my project, Win32 by the way, i'm creating hundreds of interface
definitions only for the sake of getting automatic memory management.
The thing is though, interfaces as a concept have nothing to do with
memory management. Nonetheless i've saved my coworkers from writing
thousands of try/finallys and lots of time hunting down memory leaks by
requiring the use of interfaces on our domain objects. Its not a
perfect solution, and neither is the original poster's suggestion, but I
wouldn't be so quick to dismiss it as mere syntactic sugar.
We have that -
Application.Run;
The rest is just implementation detail.
lol
--
Jolyon Smith
> the OP's suggestion is no where near the level of obfuscation that
> can be caused by with statements.
Bless you, my son.
> http://qc.borland.com/wc/qcmain.aspx?d=32076
>
> Comments? Would you love such a new feature?
Records with methods already do that and in my view
should be further developed.
Regards!
Atmapuri
> We have that -
>
> Application.Run;
I use the improved version
Application.RunWithoutBugs;
:-)
--
Cheers,
David Clegg
dcl...@gmail.com
http://cc.borland.com/Author.aspx?ID=72299
QualityCentral. The best way to bug Borland about bugs.
http://qc.borland.com
"I didn't need that fact...now I forgot who won Bud Bowl 8." - Homer
Simpson
I prefer to add autoboxing capability and other useful enhancements
The semantics of Delphi aren't ideal for value objects because all object
variables are references.
Passing these as arguments would require either an additional const
reference on the stack (ugly) or something else.
A record with methods is much more suited to what you describe here.
grt, Bart
Is in Delphi for longer than it is Delphi. Use TP object model.
Wow! That's better than my own Application.RunWithoutShowingErrorMessages!
No-op.
Oliver Townshend
its more suited because you never have to destroy a record, so you don't
have to worry about a memory leak.
however the benefit of the OP's suggestion is that there are two methods
that are guaranteed to be invoked, create and destroy. those methods
could for example, open and close a file, or set the cursor to
crHourglass, then back to crDefault. i think the only feature that
comes close to this is interfaces. but as i said before, the concept of
interfaces has nothing to do with automatic memory management. its a
workaround that i can live with, and i'm sure Nick has plenty of work to
do.
Hey Nick i got a proposal for you. I'll write a free IDE plugin that will remove the with statement at the current cursor position in response to a hotkey, provided that the with statement is the innermost with statement among nested with statements, and that source code exists for all of the units in the uses clause. The plugin will correctly qualify each identifier within the scope of the with statement according to the rules of scope and visibility of class members etc. Some of the source code of the plugin will be open-source. And I will act in good faith to provide e-mail support for the plugin and fix bugs. I will support at least Delphi7, D2005 and D2006, and the next version of Delphi.
In exchange for this plugin, DevCo will write an inline variable declaration feature combined with a feature for automatic creation/destruction of objects within the current block of code.
Interested?
This isn't really worthy of a thread but this looks like a good place
to stick it. Pretty funny compiler messages from Apple's MPW C
compiler:
"String literal too long (I let you have 512 characters, that's 3
more than ANSI said I should)"
"...And the lord said, 'lo, there shall only be case or default
labels inside a switch statement'"
"a typedef name was a complete surprise to me at this point in
your program"
"'Volatile' and 'Register' are not miscible"
"You can't modify a constant, float upstream, win an argument with
the IRS, or satisfy this compiler"
"This struct already has a perfectly good definition"
"type in (cast) must be scalar; ANSI 3.3.4; page 39, lines 10-11
(I know you don't care, I'm just trying to annoy you)"
"Can't cast a void type to type void (because the ANSI spec. says
so, that's why)"
"Huh ?"
"can't go mucking with a 'void *'"
"we already did this function"
"This label is the target of a goto from outside of the block
containing this label AND this block has an automatic variable with an
initializer AND your window wasn't wide enough to read this whole
error message"
"Call me paranoid but finding '/*' inside this comment makes me
suspicious"
"Too many errors on one line (make fewer)"
"Symbol table full - fatal heap error; please go buy a RAM upgrade
from your local Apple dealer"
"Trailing comma not permitted in enum definition. (This time I'm
letting you off with a warning)"
Here is my 2p worth. I've not read every single posting on this thread
(life's too short) but here is my rationale for supporting this language
extension. My apologies if I'm going over old ground cover elsewhere on
this thread.
The current idiom:
procedure MyClass.MyMethod()
var
localObj : TSomeOtherClass;
begin
localObj := TSomeOtherClass.Create();
try
...
finally
localObj.Free;
end;
end;
Is far, far too wordy, is also introduces too much "noise" in to the
source code as every method that creates local objects (and many do) is
"polluted" with this house-keeping code. Code that has *nothing* to do
with what the method is doing.
I accept that as Delphi is a non-gc'ed language then we have to make
sure that we tidy up after ourselves, otherwise memory leaks occur. But
in this particular respect I think Delphi hampers productivity - thought
flow has to interrupted to write house keeping code - or worse, the
house keeping code is forgotten.
It would interesting to find out exactly what proportion of Delphi code
in an application was dedicated to this house keeping idiom. Surely the
fact that it is such a common concept means that the language/compiler
should take some of the strain for us?
I would like to stress that I'm not advocating any C++ memory model
features such as stack based objects or RAII (Resource Acquisition Is
Intialisation). A language extension like this should be possible using
heap based objects. And I don't see how an extension like this clouds
the clarity of code while the current idiom clearly does.
I also think that the current prevalence of Delphi developers using
sweeper interfaces to automatically free objects indicates that there is
a strong desire to have a language feature such as this.
My one criticism of the original proposal is the syntax. I think the use
if the *static* key word would lead to confusion and if I've interpreted
the gist of some of these postings, this seems to already be the case. I
think the syntax used by Chrome would be far better and would also allow
for inline variable declarations too (and we get some type inference
"for free"). Here is an example:
procedure MyClass.MyMethod(someParamter : integer)
var
localObj : TSomeOtherClass.Create( someParameter );
begin
if localObj.BoolProperty then begin
var o := THelperClass.Create(localObj);
...
end;
end;
I think that there is enough syntax here to enable the compiler to
figure out what is going on. The the compiler could either automatically:
1. insert a try...finally around the method or block
2. or, wrap objects like this in a standard sweeper interface so that
they get destroyed when they go out of scope.
By using the interface approach, using Delphi's built in interface
reference counting mechanism, objects created in this way could be
safely passed around and "escape" the method that created them. Once
their reference count reached zero they would be destroyed.
Its not as though there aren't any current precedents, either. Delphi
already manages string and interfaces for us, plus IIRC, Delphi also
inserts try...finallys into COM methods to ensure that HRESULT is set
correctly. I don't see way we can't ask (or expect) the compiler to help
us manage short lived objects.
Finally, this is not the first that this extension has been suggested. I
remember being on a beta programme for one of the earlier versions of
Delphi (I can't recall which one) and this extension was asked for back
then using the above Chrome style syntax.
Delphi was a cool language, but its looking old now (esp. compared to
Chrome, D and C#). It used to a be a cutting edge language, I no longer
feel that this is the case and hasn't been for about four versions. IMO,
Delphi for Win32 needs extensions like this (along with other language
features like generics, optional GC, type inference, code blocks, etc)
so that its developer community can meet the challenges of rising
software complexity and keep producing great software.
Cheers
Barry Carr
Ixian Software Components Ltd
Blairgowrie, Scotland.
... and i forgot to add DevCo will buy me robot legs too.
Of course, "better than 'with'" is not much of a recommendation... <g>
Not very Pascal-ish--a Delphi programmer doesn't expect code in a var
declaration section to run. That could be fixed, however:
var
myObj : TMyObject; transient;
begin
myObj := TMyObject.Create(..);
myObj.DoSomething;
end;
Any object instance var declared as transient would trigger an automatic
.Free call when leaving scope, just like an interface instance triggers an
automatic call to IInterface._Release;
Bottom line: don't think the basic idea is bad at all, but doesn't come to
the top of the wish-list stack for me either. I'd rather have the team
working on unicode, win64, .NET2.0, or any number of other things.
Try-finally blocks are just not that much bother. No vote from me.
bobD
> This isn't really worthy of a thread but this looks like a good place
> to stick it. Pretty funny compiler messages from Apple's MPW C
> compiler:
>
...
>
> "Call me paranoid but finding '/*' inside this comment makes me
> suspicious"
>
...
Are these real ? Huh, very funny compiler, why we dont have these type
of messages ?
>
> http://qc.borland.com/wc/qcmain.aspx?d=32076
>
> Comments? Would you love such a new feature?
static keyword is confusing and in your version if constructor of this
class has parameters it is useless.
e.g:
function ComponentToString(aComp:TComponent):string;
var
SS : TStringStream; static;
W : TWriter; static;
begin
// SS:=TStringStream.Create(''); ?
// W:=TWriter.Create(SS,BufLen); I think, this line is impossible in
your version
end;
So my version:
const
BufLen = 4096;
function GuardedComponentToString(aComp: TComponent): string;
var
MS : TMemoryStream; guard;
SS : TStringStream; guard;
W : TWriter; guard;
begin
MS:=TMemoryStream.Create;
SS:=TStringStream.Create('');
W:=TWriter.Create(MS,BufLen);
W.WriteRootComponent(aComp);
W.FlushBuffer;
MS.Position:=0;
ObjectBinaryToText(MS,SS);
Result:=SS.DataString;
end;
expand this to ->
function GuardedComponentToString(aComp: TComponent): string;
var
MS : TMemoryStream; guard;
SS : TStringStream; guard;
W : TWriter; guard;
begin
// begin Implicit (compiler generated) code
MS:=nil;
SS:=nil;
W:=nil;
try
//end
MS:=TMemoryStream.Create;
SS:=TStringStream.Create('');
W:=TWriter.Create(MS,BufLen);
W.WriteRootComponent(aComp);
W.FlushBuffer;
MS.Position:=0;
ObjectBinaryToText(MS,SS);
Result:=SS.DataString;
// begin Implicit (compiler generated) code
finally
W.Free;
SS.Free;
MS.Free;
end;
// end
end;
without Guarding (in current situation) you have to write this function
as expanded version above or as below. ->
function ComponentToString(aComp: TComponent): string;
var
MS : TMemoryStream;
SS : TStringStream;
W : TWriter;
begin
MS:=TMemoryStream.Create;
try
SS:=TStringStream.Create('');
try
W:=TWriter.Create(MS,BufLen);
try
W.WriteRootComponent(aComp);
W.FlushBuffer;
MS.Position:=0;
ObjectBinaryToText(MS,SS);
Result:=SS.DataString;
finally
W.Free;
end;
finally
SS.Free;
end;
finally
MS.Free;
end;
end;
AFAIK compiler already does something like that for ref-counting local
string vars
I like the keyword!
ms: TMemoryStream; guarded;
// begin Implicit (compiler generated) code
if (w <> nil) then w.Free;
if (ss <> nil) then SS.Free;
if (ms <> nil) then MS.Free;
end;
// end
Brought to you by The DevCo Delphi Revival Choir.
<g>
--
Wayne Niddery - Winwright, Inc (www.winwright.ca)
"True peace is not the absence of tension, but the presence of
justice." - Martin Luther King, Jr.
An oldie but a goodie.
--
Wayne Niddery - Winwright, Inc (www.winwright.ca)
"We've all heard that a million monkeys banging on a million
typewriters will eventually reproduce the entire works of Shakespeare.
Now, thanks to the Internet, we know this is not true." — Robert
Wilensky
> if (w <> nil) then w.Free;
> if (ss <> nil) then SS.Free;
> if (ms <> nil) then MS.Free;
TObject.Free also tests for <> nil. So the "if variable <> nil then" is
unneccessary
--
Regards,
Andreas Hausladen
(http://andy.jgknet.de/blog)
>
> In exchange for this plugin, DevCo will write an inline variable
> declaration feature combined with a feature for automatic
> creation/destruction of objects within the current block of code.
>
> Interested?
Alas, while I'd love to see the 'with' remover, I'd never go for the
compiler change. ;-)
> Alas, while I'd love to see the 'with' remover, I'd never go for the
> compiler change. ;-)
I know it's not quite the same as what Charles was asking for, but I
find using the 'var' code template very handy for declaring variables
on the fly. Simply type 'var'[TAB]{variable name}[TAB]{variable
type}[TAB] and you can continue on your road to glory, without ever
needing to switch to the var section of the current method.
And besides, the resulting output is much more Delphi, as my
implementation code isn't littered with pesky variable declarations. :-)
--
Cheers,
David Clegg
dcl...@gmail.com
http://cc.borland.com/Author.aspx?ID=72299
QualityCentral. The best way to bug Borland about bugs.
http://qc.borland.com
"'Distracted'. Now that's a funny word. Does anyone ever get 'tracted'?
I better call the suicide hotline and find out." - Homer Simpson
You still have to. e.g. pass a referen\ce to somewhere else and see how
automatic it is.
I don't see the point of automatisation if it is not fool proof. Better
define the try finally as a code-template if the typing bothers you.
If this was submitted to FPC, you'd get this answer:
http://www.freepascal.org/faq.html#extensionselect
Specially the second part. See if you can find possibly dangerous cases.
E.g. what if c.dosomething registers the class somewhere according to a
listener pattern. You'd get a crash. How do you debug?
Hi Marco!
I am not a great C++ expert. But I saw that wonderful feature
several times in C++ code. I have been coding since TP 5.5 and the
try-finally structure bothers me since Delphi 1.
> E.g. what if c.dosomething registers the class somewhere according to a
> listener pattern. You'd get a crash. How do you debug?
C++ is using it. I am able to debug C++ code. Delphi and C++Builder
share the same code generator. There's no drawback.
function GuardedComponentToString(aComp: TComponent): string;
var
MS : TMemoryStream;
SS : TStringStream;
W : TWriter;
begin
// new keyword CREATING (reminds of infamous WITH, though)
creating MS, SS(''), W(MS,BufLen) do
// creating automagically expands to:
// MS:=nil;
// SS:=nil;
// W:=nil;
// try
// MS:=TMemoryStream.Create;
// SS:=TStringStream.Create('');
// W:=TWriter.Create(MS,BufLen);
W.WriteRootComponent(aComp);
W.FlushBuffer;
MS.Position:=0;
ObjectBinaryToText(MS,SS);
Result:=SS.DataString;
end;
// end automagically expands to:
// finally
// W.Free;
// SS.Free;
// MS.Free;
// end;
end;
This also gives you the possibility to say exactly where in code should the
object be created and freed (in other versions mentioned here, it is always
created at start and freed at end of the procedure). In fact this approach
doesn't change anything, regarding the use of variables, just simplifies
coding by omitting try...finally in class creation cases.
or records...
> IFWTPICPPTPICPP.
... And of course, with BDS, you can!
While I find OP generally a much 'friendlier' language than CPP, there
are areas - like this - where CPP makes life SO much easier.
I just searched my entire CPP source for "__finally": just six uses of
it (of which five date from before I "discovered" RIIA properly).
- Roddy
> While I find OP generally a much 'friendlier' language than CPP, there
> are areas - like this - where CPP makes life SO much easier.
My view on this sort of thing is that it makes it easier for the short,
immediate future, but later, it makes maintenance harder.
Explicit creation and destruction of objects is, to me, a good thing.
I couldn't agree more! I've followed this thread but haven't commented
because I just, plain can't see the need for what the OP requested. For me,
try...finally is no big deal and it makes it very clear what's going on.
Ray Porter
> Roddy Pratt wrote:
>
> > While I find OP generally a much 'friendlier' language than CPP, there
> > are areas - like this - where CPP makes life SO much easier.
>
> My view on this sort of thing is that it makes it easier for the short,
> immediate future, but later, it makes maintenance harder.
In my opinion, a majority of all objects' lifetimes are bound by either
the call stack depth (i.e. created as a local somewhere) or a parent's
lifetime (i.e. created in the constructor, freed in the destructor).
Acknowledging this in a language can be useful. C++ does for both, while
C# does only for locals, via 'using'.
> Explicit creation and destruction of objects is, to me, a good thing.
I personally have a liking for the C# syntax, 'using'. For example, you
can use it to get RAII-style effects, which in turn permits a kind of
extensible block scoping / structuring syntax:
using (TransactionScope scope = new TransactionScope())
{
Foo();
Bar();
scope.Complete();
}
Or, something I made myself for working with ReaderWriterLock:
using (Lock.Reader(_lock))
DoReading();
using (Lock.Writer(_lock))
DoWriting();
These work well because the verbosity and redundancy of the
try/finally/end/TObject.Free call are eliminated, and the abstraction
level of the code is increased, moving away from mechanical details and
closer to a declarative statement of the desired semantics.
The abstraction quantities represented by TransactionScope or locking a
reader are both well defined (and thus not going to change drastically)
and yet extensible and amenable to good versioning: new overloads of the
constructors / methods can be added and the return type can add new
fields and methods. So, I don't buy the 'maintenance' argument.
C#'s 'using' can be a tool for adding new abstractions at a
statement-level, which is a good thing in my book. Anonymous delegates
can be used for this also, and they're even more flexible.
I don't like the OP's suggested syntax, though - for one thing, it's far
from clear what constructor is called.
-- Barry