Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-06

which "managed" result types require extra work?

7 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

David Emerson

Okay, making a new thread here, to ask one question:

Which types do we need to initialize to null/nil/zero/'' when they are a function result?

- dynamic arrays

- ansistring
- unicodestring
- string, with {$H+} (but not string[length])

- records containing any of them

- anything else???

I understand COM-style interfaces are also managed types, do they also need a manual initialization to nil if a function result?

And, I'll ask again because it never got answered:

Is there any compiler switch or option that we can use to do this automatically? (which won't be disabled with any optimization level)

...

As a note... practically, this is a huge pain; if I have a record type that I use extensively, and then I add an ansistring or dynamic array field to that record type, then I'm going to have to look all over my code for functions returning that result type, and fix the initialization.

Anyway...

Thanks,
David

Reply by email

Dimitrios Chr. Ioannidis
to David Emerson
David Emerson wrote 17 lines
Okay, making a new thread here, to ask one question: Which types do we need to initialize to null/nil/zero/'' when they are a function result? - dynamic arrays - ansistring - unicodestring - string, with {$H+} (but not string[length]) - records containing any of them - anything else??? I understand COM-style interfaces are also managed types, do they also need a manual initialization to nil if a function result?

As a rule of thumb i follow barry kelly answer, and then specific for fpc if / when the need arise, ask here ....

PS:
http://stackoverflow.com/questions/861045/which-variables-are-initialized-when-in-delphi/861178#861178

regards,

Reply by email

Jonas Maebe
to David Emerson: Okay, making a new thread here, to ask one question: Which types do we need to initialize…
David Emerson wrote
Which types do we need to initialize to null/nil/zero/'' when they are a function result?

Results of all types (managed or not) need to be set to "empty" if you want them to return an "empty" result.

I understand COM-style interfaces are also managed types, do they also need a manual initialization to nil if a function result?

Even if they didn't/don't, that would only be an implementation detail. As a rule of thumb, function results do not contain a predictable value on function entry.

Is there any compiler switch or option that we can use to do this automatically? (which won't be disabled with any optimization level)

No.

As a note... practically, this is a huge pain; if I have a record type that I use extensively, and then I add an ansistring or dynamic array field to that record type, then I'm going to have to look all over my code for functions returning that result type, and fix the initialization.

If a record type does not contain an ansistring or a dynamic array, you also have to initialise results of functions returning such a type to get them to return a "empty" value. If you add a field that is not a managed type, you will also have to go through your code to add initialisation code for that field everywhere.

So I'm not sure how this is different from any other type.

Jonas

PS: there is an intrinsic that can help you in this process: the "default" intrinsic. Default(TSomeType) returns an instance of a particular type completely initialised to "empty" (0 for ordinal and floating point types, empty for strings, nil for pointers etc). You can assign this to e.g. your function results on entry, so that even when you add fields (of any type) to records you don't have to add additional initialisation code.

Reply by email

David Emerson
to Jonas Maebe
Jonas Maebe wrote 7 lines
PS: there is an intrinsic that can help you in this process: the "default" intrinsic. Default(TSomeType) returns an instance of a particular type completely initialised to "empty" (0 for ordinal and floating point types, empty for strings, nil for pointers etc). You can assign this to e.g. your function results on entry, so that even when you add fields (of any type) to records you don't have to add additional initialisation code.

This is very helpful, thank you.

I also tried Initialize, but this does not seem to work effectively in all cases; Default seems to work with everything I've thrown at it.

Show quoted text 7 lines
If a record type does not contain an ansistring or a dynamic array, you also have to initialise results of functions returning such a type to get them to return a "empty" value. If you add a field that is not a managed type, you will also have to go through your code to add initialisation code for that field everywhere. So I'm not sure how this is different from any other type.

The source of my confusion -- and I suspect that of many others -- is that I always assumed a function result was treated like a local variable within the function, rather than a parameter to the function.

Since managed types are automatically initialized when they are local variables, I assumed a function result was the same.

Unfortunately, the documentation does not make this sufficiently clear in describing managed types. I guess I should file a documentation bug.

Thanks,
David

Reply by email

Jürgen Hestermann
to David Emerson
David Emerson wrote
The source of my confusion -- and I suspect that of many others -- is that I always assumed a function result was treated like a local variable within the function, rather than a parameter to the function. Since managed types are automatically initialized when they are local variables, I assumed a function result was the same. Unfortunately, the documentation does not make this sufficiently clear in describing managed types. I guess I should file a documentation bug.

Exactly my opinion too.
Especially, because it behaved differently with Free Pascal versions prior to 3!

And it does not behave like a function parameter, it behaves like a *var* parameter. All other types of parameters behave differently!
And while a var parameter can *only* be assigned to a variable (so that it is clear that an existing variable is used) a function result can also be used in an expression which makes it silently mutate into a global variable! What a mess!

And for local variables I can easily set a default value in the declaration but not for the function result. I have to remind me not to forget this in the code.

It is so logical that managed types are managed (therefore the wording!). That a function result can inherit old values from prior calls is just the same as for local constants of TP. But in TP it was at least documented and it was predictable. Now everybody ostracizes such behaviour but instead intruduces the same for function results.

I used this behaviour of managed types over many years. Now we all (most of us) had to find out the change the hard way (by debugging). Many may not even have found this yet because their functions with managed type results are used seldomly. That's quite ignorant C style (where you also have nothing to rely on but need to check every compiler (version)). So yes, "modern" Pascal is no longer the "old" Pascal, but has it become better? Meanwhile I doubt this.

And what about perfomance? In most of the cases I am now initializing what is already initialized. Very strange.

Reply by email

Michael Van Canneyt
to Jürgen Hestermann
Jürgen Hestermann wrote 25 lines
Am 2016-06-28 um 01:13 schrieb David Emerson: > The source of my confusion -- and I suspect that of many others -- is that I always assumed a function result was treated like a local variable within the function, rather than a parameter to the function. > Since managed types are automatically initialized when they are local variables, I assumed a function result was the same. > Unfortunately, the documentation does not make this sufficiently clear in describing managed types. I guess I should file a documentation bug. Exactly my opinion too. Especially, because it behaved differently with Free Pascal versions prior to 3! And it does not behave like a function parameter, it behaves like a *var* parameter. All other types of parameters behave differently! And while a var parameter can *only* be assigned to a variable (so that it is clear that an existing variable is used) a function result can also be used in an expression which makes it silently mutate into a global variable! What a mess! And for local variables I can easily set a default value in the declaration but not for the function result. I have to remind me not to forget this in the code.

This has been so since day 1 in Pascal.

Any behaviour other than that was entirely coincidental.

Michae.

Reply by email