Lazarus

Announcements => Third party => Topic started by: michalis on June 22, 2016, 07:00:30 pm

Title: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 22, 2016, 07:00:30 pm
Over the last few days, I wrote a document describing many features of the modern Object Pascal language. It is available on:

http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html

http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.pdf

The document covers the easy language concepts, and then jumps quickly into more "advanced" stuff, like class references, generics, class helpers and so on. I hope that this is informative:)

This is directed at programmers (who know a bit of some programming language, though not necessarily Pascal). Which is really an excuse to not explain in detail some basic stuff ("what is a variable", "what is a class"). I tried to explain more the "advanced" stuff, and illustrate everything with examples.

The source code is in AsciiDoc and available on GitHub https://github.com/michaliskambi/modern-pascal-introduction . Please share and redistribute it freely:) All comments are welcome:)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on June 22, 2016, 08:00:00 pm
I think it is a bit light on the module/unit system.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on June 22, 2016, 08:39:03 pm
I think it is a bit light on the module/unit system.

And on string types (compared to C) and why they are faster to evaluate and have some distinct advantages over just only zero terminated strings.. I noticed that when answering a different question and I am now reading it more thoroughly.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 22, 2016, 10:40:56 pm
Quote
I think it is a bit light on the module/unit system.

What would you like to add specifically?:)

Quote
And on string types (compared to C) and why they are faster to evaluate and have some distinct advantages over just only zero terminated strings.. I noticed that when answering a different question and I am now reading it more thoroughly.

This I would like to keep simple. For programmers coming from Java or C# or modern C++ (with std::string) or PHP or Python or..., it's not news that using strings is easy, and they can be just concatenated with an operator, and you don't need to worry about memory management. I think that only for programmers that never used anything else than bare C, such strings are "news":)

So I would like to keep string "description" to a short comment "strings are automatically managed". Numerous examples show that we simply add strings, and pass them around to/from functions. I feel that the description of inner-workings (reference counting, copy on write etc.), are better left for a proper language manual like http://freepascal.org/docs-html/current/ref/refsu10.html . Same for alternatives (ShortString, WideString) -- for simple string manipulation, using {$H+} and "string" should suffice, IMHO.

In unrelated news, stuff that I'd still like to add is

- (maybe) Basic RTTI example.
- Example of streaming of the published properties - simple read/write example of a custom class.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: shobits1 on June 23, 2016, 04:45:14 am
good read  :)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: shobits1 on June 23, 2016, 05:12:09 am
found small typo at
Quote
7.1. Local (nested) routines
....
....
Another version, where we let the local routine Square to access I directly:]
Code: Pascal  [Select][+][-]
  1. ...
  2.   for I := 0 to N do
  3.     Result := Result + Square(I);
  4.  
should be
Code: Pascal  [Select][+][-]
  1. ...
  2.   for I := 0 to N do
  3.     Result := Result + Square;
  4.  
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 23, 2016, 05:29:14 am
found small typo at
Quote
7.1. Local (nested) routines
....
....
Another version, where we let the local routine Square to access I directly:]
Code: Pascal  [Select][+][-]
  1. ...
  2.   for I := 0 to N do
  3.     Result := Result + Square(I);
  4.  
should be
Code: Pascal  [Select][+][-]
  1. ...
  2.   for I := 0 to N do
  3.     Result := Result + Square;
  4.  

Ah yes! Thank you, fixed!
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on June 23, 2016, 11:58:05 am
Quote
I think it is a bit light on the module/unit system.

What would you like to add specifically?:)


I reread it again (initially a bit in a hurry), and I see there is some coverage about circular inclusion, which would be the number one priority.  I think that should be extracted to a separate paragraph, and add something about mitigation (e.g. extract some of the needed parts to a separate unit, use a base class in case of classes etc)

I also would remove the apologetic "reasonable", and refer to Pascal's  "declare before usage" principle. ( I assume it is somewhere mentioned near the beginning).

Qualified identifier usage, and, related, type aliases.  (type xx = unity.xx)

The latter is also a mitigation strategy for the case where you need to move types because of circular dependencies, or simply while they belong to unit X, some other, deeper units exist too.


Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on June 23, 2016, 02:10:30 pm
I like the section about (good and ugly ;) ) interfaces.
But I am confused now:

FPC Reference Guide (topic about class operators) (http://www.freepascal.org/docs-html/current/ref/refsu52.html) says that "is" operator can be used only on com interfaces!

However, In your example for good (corba) interfaces, you use "is" operator to check if class implements an interface and it works (I tried the example).

Is the documentation wrong? I remember I had problems in past when tried using "is" operator with corba interfaces, but, as I said, now I can confirm that your example works...

 %)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 23, 2016, 02:15:35 pm
says that "is" operator can be used only on com interfaces!

Is the documentation wrong?
huh ?

No, you are simply not reading _all_ :-)

Quote
An expression containing the is operator results in a boolean type. The is operator can only be used with a class reference or a class instance.
and
Quote
The as and is operators also work on COM interfaces.
:D
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on June 23, 2016, 02:21:39 pm
says that "is" operator can be used only on com interfaces!

Is the documentation wrong?
huh ?

No, you are simply not reading _all_ :-)

Quote
An expression containing the is operator results in a boolean type. The is operator can only be used with a class reference or a class instance.
and
Quote
The as and is operators also work on COM interfaces.
:D

Hello, Molly,
But in the example the is operator is used for CORBA interface. Isn't that in contrast to the documentation?

Also note the final sentece in this Reference Guide topic: "Although the interfaces must be COM interfaces, ..."
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 23, 2016, 02:32:28 pm
Hello, Molly,
But in the example the is operator is used for CORBA interface. Isn't that in contrast to the documentation?
Ah ok. Your question was specifically with regards to corba interfaces. I interpreted that wrongly.

No i believe it is not in contrary to the documentation only because corba interfaces are not mentioned specifically.

Quote
Also note the final sentece in this Reference Guide topic: "Although the interfaces must be COM interfaces, ..."
Selective reading always deliver nice results :-)

Please also read directly after that:
Quote
...the typecast back to a class will only work if the interface comes from an Object Pascal class.
Which explains, i guess, why it works for corba interfaces as well ?

See also this (http://www.freepascal.org/docs-html/ref/refse46.html)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 23, 2016, 02:56:53 pm
@michalis
That is a very nice read, my compliments.

You already expressed that you did not wanted to start off with variables, types and the like but from a pure personal perspective i always like the: types -> structured types -> advanced records -> classes, as a nice progressive way to use as guideline, because of the overlap.

Or to put it into other words: i thought the record/advanced record chapter was a bit small and a bit tucked away.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: circular on June 23, 2016, 04:11:59 pm
Quite a nice format to read  :)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on June 23, 2016, 04:48:55 pm
Quote
Also note the final sentece in this Reference Guide topic: "Although the interfaces must be COM interfaces, ..."
Selective reading always deliver nice results :-)

Sorry, I don't think that I read it selectively, I read it thoroughly several times.

Please also read directly after that:
Quote
...the typecast back to a class will only work if the interface comes from an Object Pascal class.
Which explains, i guess, why it works for corba interfaces as well ?

The whole sentence is:
Code: Pascal  [Select][+][-]
  1. Although the interfaces must be COM interfaces, the typecast back to a class will only work if the interface comes from an Object Pascal class. It will not work on interfaces obtained from the system by COM.
But, please...
You really think that it says to the reader that CORBA interfaces can use "is" operator, as well as COM interfaces?

See also this (http://www.freepascal.org/docs-html/ref/refse46.html)
There is nothing about "is" operator and corba.

I am still confused...  %)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on June 23, 2016, 04:54:13 pm
 
  Numerous examples show that we simply add strings, and pass them around to/from functions.

It is a trap.

You make all your functions for string, and then you get a pchar and cannot use it with any of them

Better use only pchar for functions

Quote
The as and is operators also work on COM interfaces.
:D

But it is a bad idea to use them

They are too slow
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 23, 2016, 05:32:49 pm
Sorry, I don't think that I read it selectively, I read it thoroughly several times.
Oops, sorry. that might have come across as an accusation (which it was not meant to be).

I'm more then positive that you've read the documentation thoroughly.

Quote
You really think that it says to the reader that CORBA interfaces can use "is" operator, as well as COM interfaces?
No, it does not say that nor did i ever mentioned that it does.

There is a shitload more things not written in the official documentation so that it does not get mentioned. Does that mean it is wrong on all those accounts simply because it ain't mentioned ?

Quote
There is nothing about "is" operator and corba.
That wasn't my point. Point was that it explains that support for corba interfaces is present.

Quote
I am still confused...
1. The official documentation regarding the class operator is does not specifically mention corba interfaces
2. The official documentation regarding the class operator is does specifically mention COM interfaces
3. You asked why corba interfaces work with is operator
4. i tried to explain why by reading the official documentation and point out what _might_ be the reason for that.
5. In the process i confused user Zoran

I really don't have any idea what more i could add to be able to lift the confusion.

In case you feel 'betrayed' because the official documentation regarding the is operator does not state specifically that it also works with corba, then please feel free to file a bugreport on mantis ?

But it is a bad idea to use them

They are too slow
Well, if i remember correctly i did not mention explicitly that you should use it :)

Thanks for the warning.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 24, 2016, 02:32:32 am
Wow, thank you everyone for the comments! Here's a large answer:)

Quote from: marcov
I also would remove the apologetic "reasonable", and refer to Pascal's  "declare before usage" principle. ( I assume it is somewhere mentioned near the beginning).

I reworded and shortened this part a bit. Thanks:)

It was apologetic, because indeed other languages do not have this limitation --- e.g. in Java you also usually need to declare stuff before using it, and yet two classes, in two separate files, can freely use each other. In exchange, in Java you can easily get a run-time error if you don't recompile everything after changing some class. The compiler does not track dependencies, you decide what and when to recompile.

Clearly, the Pascal has advantages here, giving you a compilation that is fast and also guaranteed to be correct, with all identifier references checked at compile-time. But for this, we sacrifice the possibility of circular dependencies, and I felt it should be explained:)

Anyway, my clumsy reasoning in the document was probably not helpful here, so I shortened it.

Quote from: marcov
Qualified identifier usage, and, related, type aliases.  (type xx = unity.xx)

Good idea, thank you - I described both these things in new sections:

http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html#_qualifying_identifiers_with_unit_name

http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html#_exposing_one_unit_identifiers_from_another

Quote from: Zoran
FPC Reference Guide (topic about class operators) says that "is" operator can be used only on com interfaces!

There were some things that didn't work with CORBA interfaces in the past. With FPC 3.0.0 things just work, and I would focus on that:) The "is" and "as" operators work as expected on both COM and CORBA interfaces now. Since they are consistent with classes and wotk for both interface types now, I would advice just using them.

Note that for COM, you can also use the "Supports" function, but for CORBA the only way to check is to use "is" (as far as I know).

It seems that this part of the FPC documentation was simply not updated.

Quote from: molly
Or to put it into other words: i thought the record/advanced record chapter was a bit small and a bit tucked away.

That is deliberate indeed. I wanted to focus on our main concept, which is "class".

As mentioned, the document is directed at programmers, who usually already know what a "class" is from other programming languages. They know it from Java, C#, C++, Python... everybody has a "class" now:) That's why introducing an "intermediate" concept of a record did not seem necessary in my eyes.

So I treated the record types as "use only if you need to squeeze more performance / particular memory layout". That's also how e.g. structures are treated in C#, and that's also how I find most modern Pascal code looks like. (This is of course biased by my own code.) You use classes, for their flexibility, and think about records only when performance matters, when you really have lists of thousands of somethings.

If this was an introduction to the language for beginners (not people already familiar with the concept of "class"), I would possibly do it differently, more like you describe. Introducing records could be a nice "launching point" for the beginners indeed, to not burden them with the need to construct / destruct explicitly and all the extra class features.

Quote from: BeniBela
It is a trap.

You make all your functions for string, and then you get a pchar and cannot use it with any of them

Better use only pchar for functions

Sorry, but I don't agree with this. The usual type to use for text in Pascal is "string" -- not "PChar". Functions that take and return "string" (usually equal to "AnsiString") are consistently introduced across RTL, FCL, LCL...

I definitely do not want to use PChar in all my functions, it would mean throwing away all the comfort that AnsiString brings.

And I prefer not even talking about PChar in this document -- as it is useful mainly for interfacing with libraries written in other languages. And you can, with some safety cautions (UniqueString etc.) convert AnsiString to PChar. That's one of the advantages of AnsiString. So you're not "locked" even if you used AnsiStrings in all your code.

Quote from: BeniBela
Quote
The as and is operators also work on COM interfaces.

But it is a bad idea to use them

They are too slow

That's a too general statement, in my opinion.

Sure, it's good to avoid run-time checking with "is", and casting with "as". Not only faster, but also the code is safer. But it's not possible to avoid it entirely in real, large applications. That's why every OOP language has a syntax to check the class type, and perform a checked typecast to a descendant. This applies to both classes and interfaces.

You should not reject a useful language construct because "it has a performance cost", in my opinion. A lot of things have a performance cost. But the conclusion to optimize, or even avoid them, should come after you profile the speed of a concrete code, and indeed see that the bottle-neck lies within is / as operators.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 24, 2016, 03:08:49 am
Quote from: michalis
Sure, it's good to avoid run-time checking with "is", and casting with "as". Not only faster, but also the code is safer.

Hm, I realized that my document did not mention that you can typecast to interfaces without using "as" operator. I added a section "Typecasting interfaces without "as" operator" that remedies that:)

http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html#_typecasting_interfaces_without_as_operator
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on June 24, 2016, 02:31:42 pm
Quote
There is nothing about "is" operator and corba.
That wasn't my point. Point was that it explains that support for corba interfaces is present.

Okay, the thing is that I believe that it actually didn't work in the past, so I was confused when I saw the example and tried to compile it and it just worked.

In case you feel 'betrayed' because the official documentation regarding the is operator does not state specifically that it also works with corba, then please feel free to file a bugreport on mantis ?

Okay, bug report 30308. (http://bugs.freepascal.org/view.php?id=30308)

Quote from: Zoran
FPC Reference Guide (topic about class operators) says that "is" operator can be used only on com interfaces!

There were some things that didn't work with CORBA interfaces in the past. With FPC 3.0.0 things just work, and I would focus on that:) The "is" and "as" operators work as expected on both COM and CORBA interfaces now. Since they are consistent with classes and wotk for both interface types now, I would advice just using them.

Note that for COM, you can also use the "Supports" function, but for CORBA the only way to check is to use "is" (as far as I know).

It seems that this part of the FPC documentation was simply not updated.

Thanks, yes, it seems that it is a new feature of FPC 3.0. However, FPC New Features wiki page (http://wiki.freepascal.org/FPC_New_Features_3.0) says nothing about it.

Now we have really usable interfaces in FPC.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on June 24, 2016, 03:42:38 pm

I definitely do not want to use PChar in all my functions, it would mean throwing away all the comfort that AnsiString brings.

I did not want it either, but now I am doing it


And you can, with some safety cautions (UniqueString etc.) convert AnsiString to PChar. That's one of the advantages of AnsiString.

Yes, that is the advantage of having ansistring, you can call the functions who takes pchars.

But not the other way around, thus it is better, if all your functions take pchars.

Or you need to have both variants





You should not reject a useful language construct because "it has a performance cost", in my opinion. A lot of things have a performance cost.

Yes, but it is extremly slow on interfaces.

You can make a function getSelf: TObject; begin result := self; end and then cast the class instead the interface.

Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Cyrax on June 24, 2016, 03:50:31 pm
BeniBela : You do realize that converting constant strings to PChars include slight penalty in FPC 3.x series?
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on June 24, 2016, 04:31:17 pm
BeniBela : You do realize that converting constant strings to PChars include slight penalty in FPC 3.x series?

It is rather slight

What I just realized last week, when you use strings the entire function gets wrapped in a try .. finally block, at least on linux amd64. That is really bad.

The real issue are slices. E.g. you have a 1000 character string s and want to do something with the middle, characters s[400] to s[600]. With a pchar, you can just point in the middle and use a smaller length. With a string, everything in that range needs to be copied.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on June 24, 2016, 05:30:30 pm
What I just realized last week, when you use strings the entire function gets wrapped in a try .. finally block, at least on linux amd64. That is really bad.

Reading documentation is an art. You can turn that behavior off... If you really don't want it.
Code: Pascal  [Select][+][-]
  1. {$IMPLICITEXCEPTIONS OFF}
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on June 24, 2016, 05:33:01 pm
The real issue are slices. E.g. you have a 1000 character string s and want to do something with the middle, characters s[400] to s[600]. With a pchar, you can just point in the middle and use a smaller length. With a string, everything in that range needs to be copied.

Huh? Why? Of course not! Example please....
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on June 24, 2016, 05:50:55 pm
Reading documentation is an art. You can turn that behavior off... If you really don't want it.
Code: Pascal  [Select][+][-]
  1. {$IMPLICITEXCEPTIONS OFF}

That is hard to find

Huh? Why? Of course not! Example please....

https://github.com/benibela/bbutils/blob/master/bbutils.pas#L2566-L2588
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on June 24, 2016, 06:00:27 pm
That is hard to find
It is in the programmer's manual? So it is easy to find....

Huh? Why? Of course not! Example please....
Quote
https://github.com/benibela/bbutils/blob/master/bbutils.pas#L2566-L2588
I' ll look into it..
[edit] I did. Conclusion: you actually wish C had a decent string type, but you accuse Object Pascal of having too many? 
That code is by the way the biggest piece of bull I have seen in a very long time and is refused for production ;) But KOL is worse.... I grant you that.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Awkward on June 24, 2016, 06:19:50 pm
Thaddy, you know, i used pascal strings a lot in past but when needed to write code compatible with C code, turned to PChar uses. And using of PChar is much simpler for me, i can control all things, i clearly know what happens...
And about documentation. FPC documentation still don't have article what objects can use properties, not classes and records only. What to say about single things which you don't knows where to search?
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: graemex on June 24, 2016, 07:47:13 pm
I found it extremely helpful. I was curious about modern Pascal, and it gave me as much of a feel for it as I am going to get until I start learning it properly - and it will make that a bit easier as well.

One minor correction. "As in all object-oriented languages", should be "most" instead of "all" in section 4.5
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 24, 2016, 10:24:06 pm
Wow, thank you everyone for the comments! Here's a large answer:)
Well, thank you very much for the write-up. The least a person could do is giving it a read :hint hint:  :D

Quote from: michalis
Quote from: molly
Or to put it into other words: i thought the record/advanced record chapter was a bit small and a bit tucked away.

That is deliberate indeed. I wanted to focus on our main concept, which is "class".
....
Fair enough, especially since you have a particular reader in mind.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: molly on June 24, 2016, 10:27:11 pm
Okay, the thing is that I believe that it actually didn't work in the past, so I was confused when I saw the example and tried to compile it and it just worked.
In understand and i apologize for the confusion i might have caused.

Quote
In case you feel 'betrayed' because the official documentation regarding the is operator does not state specifically that it also works with corba, then please feel free to file a bugreport on mantis ?
Okay, bug report 30308. (http://bugs.freepascal.org/view.php?id=30308)
Thank you very much Zoran. It seems it is already addressed as well.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 24, 2016, 11:17:01 pm
Quote from: BeniBela
Yes, that is the advantage of having ansistring, you can call the functions who takes pchars.

But not the other way around, thus it is better, if all your functions take pchars.

You *can* convert PChar to AnsiString easily. But it involves copying the characters (if you want to do it 100% safely), so it may have a speed penalty.

RTL and LCL convert back and forth between PChar and AnsiString, to interface with WinAPI, GTK... It definitely works. The only question is performance, but it's not as critical in my experience.

Quote from: BeniBela
What I just realized last week, when you use strings the entire function gets wrapped in a try .. finally block, at least on linux amd64. That is really bad.

It has always been this way, and is necessary on all platforms. You can turn it off like Thaddy writes, but be careful -- if the routine exits with exception, the AnsiString will not be correctly finalized.

See also http://wiki.freepascal.org/Avoiding_implicit_try_finally_section (man, an old wiki page that I myself started > 10 years ago...:)

Quote from: BeniBela
The real issue are slices. E.g. you have a 1000 character string s and want to do something with the middle, characters s[400] to s[600]. With a pchar, you can just point in the middle and use a smaller length. With a string, everything in that range needs to be copied.

If you do it naively, using Copy on a string, then indeed it will have a cost.

Then again, doing it naively on PChar also has a cost.

Your solution with addressing something in the midde can be used with PChar or AnsiString, no matter. You can take a pointer to the middle of AnsiString contents, and iterate over it. In all cases, it requires special treatment, since the result has to be bounded by some variable specifying slice length, not by a #0 character.

In general, I do agree that PChars can achieve higher performance. As often, if you do things manually, then you can squeeze much better performance than a solution that tries to manage memory automatically.

I just don't feel that doing this for the whole application, and resigning from AnsiStrings everywhere, is justified. I would limit this only to the actual bottle-neck in your application.

Anyway, this depends on the type of applications you're writing (whether your bottle-neck does any string processing).

Quote from: graemex
One minor correction. "As in all object-oriented languages", should be "most" instead of "all" in section 4.5

Fixed. Indeed, at least Python doesn't have them:)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: mangakissa on June 30, 2016, 09:50:46 am
I like the idea to have documentation online for beginners.

I'm not a beginner and I'm still confused by some paragraphs. Sometimes you're talking deeply into subjects and otherwise its very compact. Why TList, ObjectList and (packed) records are discouraged your're not telling. As far As I know it's still uses for over 80% of applications by many developers.

I still don't understand why all examples are written in console. Ask a beginner what console/DOS/cmd/command is and they look at you like a crazy person. My point of view should using GUI demo's

 
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: rvk on June 30, 2016, 10:36:52 am
I still don't understand why all examples are written in console. Ask a beginner what console/DOS/cmd/command is and they look at you like a crazy person. My point of view should using GUI demo's
I do see a lot of beginners (I mean real beginners to programming) using the command line. Usually they come in contact with Pascal through lessons and are instructed to use fp.exe or even Dev-Pascal (or similar).

But in the second chapter there is an explanation:
Quote
The rest of this article talks about the Object Pascal language, so don’t expect to see anything more fancy than the command-line stuff. If you want to see something cool, just create a new GUI project in Lazarus (Project → New Project → Application). Voila — a working GUI application, cross-platform, with native look everywhere, using a comfortable visual component library.

And even in the first post it is explained that this document is for programmers (so not beginners) who are not that familiar with Pascal. For those users it becomes clear at chapter 2 that this document only covers the language basics and not the GUI.
This is directed at programmers (who know a bit of some programming language, though not necessarily Pascal). Which is really an excuse to not explain in detail some basic stuff ("what is a variable", "what is a class"). I tried to explain more the "advanced" stuff, and illustrate everything with examples.

Look at it another way... think of a language you don't know that well (java, C++. C# or anything) and think of how you want a document like this to be for that language. I think first covering the basics about the language constructs is a really nice way to get to know the language. After that, if you take the GUI-IDE from that language a lot become clear at once.

Maybe GUI-elements could be described in another document :)
And yet another document could go deeper into some elements not mentioned in this one because they are too complex (or confusing at this point).
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Graeme on June 30, 2016, 10:45:14 am
I like the idea to have documentation online for beginners.
I prefer offline documentation I can read at a location where I might not have internet access. eg: 30,000 feet on a long haul flight, night time reading while on vacation, on a train to work or meetings etc. And its incredible [in this day and age] how often I am at a location where there is no internet access.

Quote
I'm not a beginner and I'm still confused by some paragraphs.
From what I've seen, reading that text should be taken with a pinch of salt - meaning in is the personal opinion of the author. Your and my oppinions might be different. eg: I see absolutely nothing wrong with using TList, TObjectList and packed records. In fact I have code where the usage of them are vital.

Quote
I still don't understand why all examples are written in console. ...snip... My point of view should using GUI demo's
It is very simple. Is it a tutorial about the Object Pascal language or a GUI toolkit? It's the former. Introducing a GUI toolkit into the sample code means you are now speaking only to say Lazarus LCL developers. What about FPC developers using Web Services, Unix daemons, MSEgui, fpGUI etc?  Console demos don't introduce an extra [unnecessary] dependency or complexity. The information is about Free Pascal's programming language, Object Pascal, and the RTL and FCL. Console demos make perfect sense and should not be changed. This is also why FPC includes only console demos.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on June 30, 2016, 10:53:04 am
Wow, thank you everyone for the comments! Here's a large answer:)

Quote from: marcov
I also would remove the apologetic "reasonable", and refer to Pascal's  "declare before usage" principle. ( I assume it is somewhere mentioned near the beginning).

I reworded and shortened this part a bit. Thanks:)

It was apologetic, because indeed other languages do not have this limitation --- e.g. in Java you also usually need to declare stuff before using it, and yet two classes, in two separate files, can freely use each other.

Yes, and that part in Java is thus not declare before use. It is an exception.

I quickly scanned over the new unit system sections and that looks nice!
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on June 30, 2016, 11:25:56 am
Thaddy, you know, i used pascal strings a lot in past but when needed to write code compatible with C code, turned to PChar uses. And using of PChar is much simpler for me, i can control all things, i clearly know what happens...

(btw, Proper modern C code works with a pchar and a max count (the -n- functions))


Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on June 30, 2016, 12:59:12 pm
Thaddy, you know, i used pascal strings a lot in past but when needed to write code compatible with C code, turned to PChar uses. And using of PChar is much simpler for me, i can control all things, i clearly know what happens...

(btw, Proper modern C code works with a pchar and a max count (the -n- functions))
Yup ;) But that still does not allow #0 in the middle. These are simply overflow protections. A standard  C string library  (well, array of byte ultimately) breaks on its terminator which happens to be zero or $0 or 0x0 or naught. You know that. Hence the max count... doesn't work ;)

A Pascal Ansi string in {$H+} mode will respect the ultimate length for which it was defined, because that is stored and known. A pascal string in {$H-} state does the same but can overflow if the limit of 255 bytes is exceeded.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Awkward on June 30, 2016, 01:03:25 pm
But that still does not allow #0 in the middle.

so, lucky we what we can get #0 char in the middle of text in too rare cases.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on June 30, 2016, 02:18:12 pm
Quote from: Graeme
From what I've seen, reading that text should be taken with a pinch of salt - meaning in is the personal opinion of the author. Your and my oppinions might be different. eg: I see absolutely nothing wrong with using TList, TObjectList and packed records. In fact I have code where the usage of them are vital.

Indeed, in some places I felt an advice "what to use, if you have these two alternatives" was necessary. I found myself unable to mention both generic lists and non-generic lists without an advice "which one to preferably use" (any why). The argument for using generic lists is type-safety: with generics, you can effectively say "this is a list of TMyClass instances". Compiler will then prevent inserting instances of other classes, and you will be able to access items on the list as ready TMyClass instances (no need to downcast them from TObject to TMyClass).

The other place where I definitely expressed my opinion are interfaces -- I explicitly encourage CORBA interfaces over COM in the article. They are closer to C# and Java interfaces. And they do not bring "automatic reference counting" (which I feel should be an orthogonal feature of the language, not entangled with interfaces).

I hope that these cases of "my opinion" are justified. And in both these cases, I do try to mention alternatives. I mention TObjectList, and dynamic arrays, and COM interfaces have their own section. So I hope it sounds fair -- I do have some opinions indeed, but they are hopefully explained, and the alternatives are presented too:)

For records -- I don't discourage them. I just suggest that "class" is the default feature-rich structural type which one usually uses in Object Pascal. I think this is generally accepted among Object Pascal programmers. Records definitely have their use when it comes to performance or predictable memory layout -- I do use records (and some old-style objects) in my game engine for this purpose. Records have their own section where I document them, mentioning also advanced records. Records are also taken into account when talking about lists (TFPGList), operator overloading etc.

Even C# language, designed much later than Pascal, has records. Much like our "advanced records", and for the same purpose: it can give more performance than a class, in certain uses.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Graeme on July 01, 2016, 12:28:52 pm
Indeed, in some places I felt an advice "what to use, if you have these two alternatives" was necessary.

I personally have no problems with that. I simply felt it should be pointed out that some of that text is opinion based. Maybe such text could be added as a "side note" or something - giving it separation from "documentation" and "opinion". Just a though. ;-)

Quote
For records -- I don't discourage them. I just suggest that "class" is the default feature-rich structural type which one usually uses in Object Pascal. I think this is generally accepted among Object Pascal programmers. Records definitely have their use...
There are indeed cases where Records are the best or only choice. eg: reading a binary file (eg: an INF help file), it is hugely beneficial to use a record structure to read such binary data. I would not dream of using a class in such a situation.

The bottom line... use the correct tool (language feature) for the job. :)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on July 01, 2016, 02:21:55 pm


The other place where I definitely expressed my opinion are interfaces -- I explicitly encourage CORBA interfaces over COM in the article. They are closer to C# and Java interfaces. And they do not bring "automatic reference counting" (which I feel should be an orthogonal feature of the language, not entangled with interfaces).

Perhaps it is time to add a third kind of interfaces to FPC

Reference counted like COM, but otherwise like CORBA, without any of the COM overhead
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: jwdietrich on July 02, 2016, 12:54:13 am
This is a very good introduction.

Could you add (perhaps in the "About" section at the end) a notice about the version of the document and the date of last change? This would make life easier for readers, by providing a hint if it is worthwhile to download a new version.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on July 02, 2016, 01:46:04 am
This is a very good introduction.

Could you add (perhaps in the "About" section at the end) a notice about the version of the document and the date of last change? This would make life easier for readers, by providing a hint if it is worthwhile to download a new version.

Thank you!

There is a "Last updated" date at the very bottom of the HTML version, see http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html . And the exact history of the document may be seen in the GitHub repository on https://github.com/michaliskambi/modern-pascal-introduction . The commits on https://github.com/michaliskambi/modern-pascal-introduction/commits/master document precisely what and when changed:) I update the HTML/PDF output after every commit.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on July 02, 2016, 11:08:35 am
The COM part is still not correct as I explained in my email to you, because it reflects the only way you should not ever never use COM.
I will do a follow up (as per email) this weekend. For starters: there are no memory leaks....

COM should be used through interface instances, not class instances as in your book. And you should respect the reference counting. TComponent is a really bad example...
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: jwdietrich on July 02, 2016, 01:10:30 pm
This is a very good introduction.

Could you add (perhaps in the "About" section at the end) a notice about the version of the document and the date of last change? This would make life easier for readers, by providing a hint if it is worthwhile to download a new version.
There is a "Last updated" date at the very bottom of the HTML version, see http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html . And the exact history of the document may be seen in the GitHub repository on https://github.com/michaliskambi/modern-pascal-introduction . The commits on https://github.com/michaliskambi/modern-pascal-introduction/commits/master document precisely what and when changed:) I update the HTML/PDF output after every commit.

This is great. Version information should also be added to the PDF edition, however.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: guest58172 on July 02, 2016, 03:35:44 pm

Otherwise I find this doc quite usefull but here you preach to converted people. What you should do is post this on r/programming where ignorant ppl still see Pascal as it was in 1988, when they were at school and when they've made a "cutting-edge" mastermind program...

Also on stack overflow there are often guys who land with some homework and you clearly see that the teacher still uses the same book since 1990...so annoying.

Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on July 02, 2016, 06:35:02 pm
Quote from: Thaddy
The COM part is still not correct as I explained in my email to you, because it reflects the only way you should not ever never use COM.

I will do a follow up (as per email) this weekend. For starters: there are no memory leaks....

COM should be used through interface instances, not class instances as in your book. And you should respect the reference counting. TComponent is a really bad example...

As for memory leaks: In my example, there are no memory leaks, indeed. In the example you send me through email, there were memory leaks. Simply checking with "-gl -gh" shows this. You probably wanted to use there TInterfacedObject instead of TComponent.

As for the TComponent, with it's _AddRef implementation that disables reference-counting: it is not my invention. It's part of a standard Pascal library, and a basis for countless classes. Showing how TComponent interacts with COM interfaces seems justified.

I agree that, if you just never use class instances to interact with things that are also accessed through COM interfaces (and always descend from TInterfacedObject, with proper _AddRef implementations), then you're safe. If you *want* the reference-counting of COM interfaces, then COM interfaces are a good deal. I'm open to improvements, my example and wording could probably be improved.

My current example is a way to show how to make something equivalent to previous CORBA example using COM -- it's referred to in the next section (about typecasting of interfaces too). It could be moved to a separate section ("Hacky usage of COM interfaces without reference-counting"), and the basic COM section could describe the "proper" COM usage.

Quote from: BBasile
"GOOD" and "UGLY" interfaces is really not serious in a technical writing. You're not the guy who decides that. Some people have to work with COM as a constraint, your opinion does not matter, they have to do it. dot.

I know that my opinion doesn't change the language -- that's why there is a description of both COM and CORBA interfaces in the article.

But, for some weird reason, I still do have some opinion:) The reasons why I feel that COM interfaces are "ugly" is clearly explained in the article.

I also know how interfaces look like in C# and Java. As it happens, C#, Java and CORBA interfaces are the same. The COM interfaces are different, and I heard a "WTF?" reaction when telling programmers that in Pascal we have interfaces entangled with reference-counting ("WTF -- these are two completely different language features, with different use-cases, should be orthogonal"). So it seems that I'm not alone in my opinion. And to explain interfaces to programmers coming from other languages, CORBA interfaces are more natural. (Regardless whether CORBA or COM are better.)

Quote from: BBasile
You could put a paragraph about class var, class properties, class constructor and class destructor.

Good idea! And thanks for good comments -- you're welcome to post about the article everywhere:)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on July 02, 2016, 08:12:18 pm
If you *want* the reference-counting of COM interfaces, then COM interfaces are a good deal. I'm open to improvements, my example and wording could probably be improved.

Following my own advice, I reworked the part about COM interfaces a bit. At the beginning I show the "non-hacky" usage of them, using TInterfacedObject, and relying on COM reference-counting to deallocate their memory. This was based on the example modifications send by Thaddy - thanks!

There's a section lower that shows "Using COM interfaces with reference-counting disabled", clearly warning of dangers of this approach.

I still consider CORBA interfaces as more suitable for my purposes -- they give me the functionality I need (which is casting a class to any interface it supports), without any unnecessary feature (reference-counting, magic GUIDs and the need to implement _AddRef). As mentioned, CORBA interfaces are also consistent with Java and C# interfaces, which I see as a confirmation that this approach to interfaces makes sense. But I also do understand that COM interfaces are useful when you want reference-counting. Both uses should be now addressed more fairly in the article.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Paulo França Lacerda on September 02, 2016, 03:22:05 pm
Great stuff, even for experienced programmers!
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 02, 2016, 03:25:56 pm

Perhaps it is time to add a third kind of interfaces to FPC

Reference counted like COM, but otherwise like CORBA, without any of the COM overhead

Perhaps it is better to study what there is first :-)

The COM overhead part is in its implementation (iow TInterfacedObject and/or descendants) not the interface itself.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 02, 2016, 03:44:08 pm
You still have no clue about interfaces. It's a piece of shit that part. Do I make myself clear.
Dont ever mix up class instantiation with interface instantiation. It is still the same mistake I already reported. Is that SO difficult to understand?

It really is time to get rough and ... rude..
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on September 02, 2016, 05:16:46 pm

Perhaps it is better to study what there is first :-)

The COM overhead part is in its implementation (iow TInterfacedObject and/or descendants) not the interface itself.


There is quite some overhead, because the value of the interface instance is not the same value as self of the class instance.

So on every usage it needs to calculate self from the interface variable. The same calculation again and again.
Or the inverse calculation when the interface is created.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on September 02, 2016, 08:03:33 pm
Dont ever mix up class instantiation with interface instantiation. It is still the same mistake I already reported. Is that SO difficult to understand?

Being rude doesn't help you convince me (or anyone, I suppose). So please let's discuss it in a civilized manner.

The idea to use COM interfaces with hacked _AddRef methods is not my invention. It is part of the standard TComponent implementation. Every time you instantiate TComponent, or any descendant of it, you're creating a class instance of something that is also a COM interface. The language does allow instantiating a class that is also a COM interface, and people use it (goodle "delphi interfaces no reference counting" if you want), and it's mentioned in various books. People in 2016 are still inventing solutions to this, like here: http://blog.marcocantu.com/blog/2016-april-weak-unsafe-interface-references.html .

That is why my article documents this.

As for what is "proper", I even agree with you in some way: it's a bad idea to instantiate a class that is also a COM interface. It opens a can of worms. My suggestion to such usecase is to use a CORBA interface, that was my point all along. It is explicitly written in the article http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html#_using_com_interfaces_with_reference_counting_disabled : "You need to be careful in this case to not free the class instance when some interface variable may refer to it. .... To avoid this mess, it’s usually better to use CORBA interfaces, if you don’t want reference-counting with your interfaces."

So, I'm not sure what do you expect of me. If you want to abolish creating object instances when the class has a COM interface, persuade language designers to do so (and you better have some good idea how to change TComponent then, without breaking compatibility). What I can do, is to clearly document the dangers / disadvantages of some constructions, and I feel I have already done so.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on September 05, 2016, 10:52:35 am
You still have no clue about interfaces. It's a piece of shit that part. Do I make myself clear.
Dont ever mix up class instantiation with interface instantiation. It is still the same mistake I already reported. Is that SO difficult to understand?

It really is time to get rough and ... rude..

I really don't understand who are you addressing here? Because Michalis is absolutely clear in his article about what he thinks about this.
Just use CORBA interfaces unless you use interfaces for real COM support.
With CORBA interfaces, you can get real advantage without reference counting overhead (as explained in java tutorial, see http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html, and good example of usage in their collections library is here: http://docs.oracle.com/javase/tutorial/collections/interfaces/index.html).
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 05, 2016, 11:28:56 am
Zoran, He - and by proxy, you too - has no clue about both types of interfaces. The text is simply nonsensical and opiniated. And because he has no clue the examples are wrong. That should be corrected.
I already gave him decent example code some time ago. And a sketch for an adapted text. Reference counted interfaces are becoming more and more important, not just for COM, but also for  Smartpointers and ARC support in trunk that is being written by Maciej Izak. Now those are "modern object pascal" features! Smartpointers already work in trunk with the patch in bug report 0030534 applied.

To show you how this is important:
Code: Pascal  [Select][+][-]
  1. program smartpointers;
  2. {$ifdef fpc}{$mode delphi}{$endif}
  3. uses
  4.   classes,smartptrs;
  5. var
  6.   L:TStringlist;
  7.   PL:TSmartPointer<TStringList>;
  8. begin
  9.   // Auto create
  10.   L:= PL.Value;
  11.   L.Add('Testme');
  12.   writeln(L.Count);
  13.   // Nothing
  14.   L:=PL.Value;
  15.   L.Add('foo');
  16.   L.Add('foo2');
  17.   L.Add('Foobar');
  18.   Writeln(L.Count);  
  19.   writeln(L.Text);
  20.   // Auto cleanup
  21. end.

This is no pseudocode, this is working code.

Here's one possible implementation of a smartpointer, based on Marco Cantu's book, it relies on reference counted interfaces:
Code: Pascal  [Select][+][-]
  1. unit smartptrs;
  2. {$ifdef fpc}{$mode delphi}{$endif}
  3. interface
  4. type
  5.   TSmartPointer<T:class, constructor> = record
  6.   strict private
  7.     FValue:T;
  8.     FFreeTheValue:IInterface;
  9.     function GetValue:T;
  10.     type
  11.       TFreeTheValue = class(TInterfacedObject)
  12.       private
  13.         fObjectToFree:TObject;
  14.       public
  15.         constructor Create(anObjectToFree: TObject);
  16.         destructor Destroy;override;
  17.       end;
  18.    public
  19.      constructor Create(AValue: T);overload;
  20.      procedure Create;overload;
  21.      class operator Implicit(AValue: T):TSmartPointer<T>;
  22.      class operator Implicit(smart: TSmartPointer<T>):T;
  23.     property value: T read GetValue;
  24.    end;
  25.  
  26. implementation
  27.    
  28.    constructor TSmartPointer<T>.TFreeTheValue.Create(anObjectToFree:TObject);
  29.    begin
  30.      self.fObjectToFree := anObjectToFree;
  31.    end;
  32.    
  33.    destructor TSmartPointer<T>.TFreeTheValue.Destroy;
  34.    begin
  35.      fObjectToFree.Free;
  36.      inherited;
  37.    end;
  38.    
  39.    constructor TSmartPointer<T>.Create(AValue:T);
  40.    begin
  41.      FValue := AValue;
  42.      FFreeTheValue := TFreeTheValue.Create(FValue);
  43.    end;
  44.    
  45.    procedure TSmartPointer<T>.Create;
  46.    begin
  47.      TSmartPointer<T>.Create(T.Create);
  48.    end;
  49.    
  50.    class operator TSmartPointer<t>.Implicit(AValue:T):TSmartPointer<T>;
  51.    begin
  52.      Result := TSmartPointer<T>.Create(AValue);
  53.    end;
  54.    
  55.    class operator TSmartPointer<T>.Implicit(smart: TSmartPointer<T>):T;
  56.    begin
  57.      Result := Smart.Value;
  58.    end;
  59.  
  60.    function TSmartPointer<T>.GetValue:T;
  61.    begin
  62.      if not Assigned(FFreeTheValue) then
  63.        Self := TSmartPointer<T>.Create(T.Create);
  64.      Result := FValue;
  65.    end;
  66. end.


Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 05, 2016, 12:52:00 pm
There is quite some overhead, because the value of the interface instance is not the same value as self of the class instance.
So on every usage it needs to calculate self from the interface variable. The same calculation again and again.
Or the inverse calculation when the interface is created.

In the working case I presented above this is nonsense as well. The overhead is in creation/release and that is all. You could have known that, you are not a nobody. (Although you are trolling "a bit" lately IMO :) )
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on September 05, 2016, 03:04:46 pm
In the working case I presented above this is nonsense as well. The overhead is in creation/release and that is all. You could have known that, you are not a nobody. (Although you are trolling "a bit" lately IMO :) )

Perhaps it changes with smartpointers

Look at how it calls a COM function, e.g. _Addref:

Code: [Select]
0000000000400208 488b00                   mov    (%rax),%rax
000000000040020B ff5008                   callq  *0x8(%rax)

WRPR_$SYSTEM_$$_TINTERFACEDOBJECT_$_IUNKNOWN_$_1_$_SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT
0000000000422C50 4883ef10                 sub    $0x10,%rdi
0000000000422C54 e90706ffff               jmpq   0x413260 <SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT>

That is four times the amount of calling an ordinary method of a class:

Code: [Select]
00000000004001F0 e88b300100               callq  0x413280 <SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT>

And the creation overhead is enormous, too, as it calls:

Code: [Select]
      procedure InitInterfacePointers(objclass: tclass;instance : pointer);

        var
          ovmt: PVmt;
          i: longint;
          intftable: pinterfacetable;
          Res: pinterfaceentry;
        begin
          ovmt := PVmt(objclass);
          while assigned(ovmt) and (ovmt^.vIntfTable <> @emptyintf) do
            begin
              intftable:=ovmt^.vIntfTable;
              if assigned(intftable) then
              begin
                i:=intftable^.EntryCount;
                Res:=@intftable^.Entries[0];
                while i>0 do begin
                  if Res^.IType = etStandard then
                    ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
                      pointer(Res^.VTable);
                  inc(Res);
                  dec(i);
                end;
              end;
              ovmt:=ovmt^.vParent;
            end;
        end;
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 05, 2016, 04:37:59 pm
That's in any language. Nothing to do with Object Pascal. You know that too ;)
Look at calls through variants that's even worse.
OTOH, otherwise the programmer needs to do a lot of that stuff.
And yes, my smartpointer example is a view into the very near future when that overhead is just on creation and destroy. Just try it.
Any automatic memory maintenance comes with its problems, including garbage collected languages.
Under ARC, of which the smartpointer example is a part of preliminary necessity (before it ends up in system and used through compiler magic) , this is less so than with sweep/release as under Java and .Net.

Also note that e.g. for Lazarus GUI's atm it suffices to have TAppication under smartpointer control since the design governs that ultimately all GUI objects are owned by the application and as such its smartpointer. And release is by Owner, just as it is now. What overhead ;) (Ok, that's trolling by me  8-) O:-) )
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Cyrax on September 05, 2016, 04:41:13 pm
In the working case I presented above this is nonsense as well. The overhead is in creation/release and that is all. You could have known that, you are not a nobody. (Although you are trolling "a bit" lately IMO :) )

Perhaps it changes with smartpointers

Look at how it calls a COM function, e.g. _Addref:

Code: [Select]
0000000000400208 488b00                   mov    (%rax),%rax
000000000040020B ff5008                   callq  *0x8(%rax)

WRPR_$SYSTEM_$$_TINTERFACEDOBJECT_$_IUNKNOWN_$_1_$_SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT
0000000000422C50 4883ef10                 sub    $0x10,%rdi
0000000000422C54 e90706ffff               jmpq   0x413260 <SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT>

That is four times the amount of calling an ordinary method of a class:

Code: [Select]
00000000004001F0 e88b300100               callq  0x413280 <SYSTEM$_$TINTERFACEDOBJECT_$__$$__ADDREF$$LONGINT>


I only see one call and then a jump to right method.

And the creation overhead is enormous, too, as it calls:

Code: [Select]
      procedure InitInterfacePointers(objclass: tclass;instance : pointer);

        var
          ovmt: PVmt;
          i: longint;
          intftable: pinterfacetable;
          Res: pinterfaceentry;
        begin
          ovmt := PVmt(objclass);
          while assigned(ovmt) and (ovmt^.vIntfTable <> @emptyintf) do
            begin
              intftable:=ovmt^.vIntfTable;
              if assigned(intftable) then
              begin
                i:=intftable^.EntryCount;
                Res:=@intftable^.Entries[0];
                while i>0 do begin
                  if Res^.IType = etStandard then
                    ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
                      pointer(Res^.VTable);
                  inc(Res);
                  dec(i);
                end;
              end;
              ovmt:=ovmt^.vParent;
            end;
        end;

Nowadays CPU's are quite fast so there shouldn't have noticeable slowdowns on (massive) usage of interfaces.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 05, 2016, 04:53:32 pm
@Cyrax
He is trolling. But has made huge and valuable contributions, so he is partially forgiven :)
Our posts crossed. I made an addition.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: BeniBela on September 05, 2016, 05:10:16 pm
That's in any language. Nothing to do with Object Pascal. You know that too ;)
Look at calls through variants that's even worse.

That is why I wrote my own variants with COM-interfaces

I should have used records

And yes, my smartpointer example is a view into the very near future when that overhead is just on creation and destroy. Just try it.

I am not updating to trunk now. It is still broken from the last update (http://forum.lazarus.freepascal.org/index.php/topic,33931.0.html)



I only see one call and then a jump to right method.

Four instructions rather than one

On modern CPUs the memory-read is slower than the call



Nowadays CPU's are quite fast so there shouldn't have noticeable slowdowns on (massive) usage of interfaces.

I only found that function, because it was the slowest function of them all (http://i.imgur.com/4ipQHix.png)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 05, 2016, 06:09:05 pm
@Benibela
If that is the case, you know the drill: attach some sourcecode that reproduces the bug.

But let's focus on the fact that somebody is trying to write a book on "Modern Object Pascal" and doesn't know jack sh*t about both types of interfaces, which renders the book unusable.
Which is a pity because it has many merits. He's also very stubborn on the matter. I send him what to do in private sometime ago. He knows that. (I knew about Maciej's work at that point)
Maybe the smartpointer stuff convinces him of his evil ways/wrong doings. Otherwise I will be glad to write that chapter in an unopiniated way. I offered that too, I believe.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on September 05, 2016, 09:17:20 pm
As for the interfaces --- Thaddy, your corrections were actually applied to the article. The first COM interfaces example was changed to show the "correct" usage, based on your example. And the example with using COM interfaces through class instances was clearly marked as "dangerous, don't do it" (and moved to a lower section). Where is the factual inaccuracy in my article, which exactly sentence is wrong?

Throwing insults at everyone who doesn't agree with you doesn't help.

I guess that what you *really* want is to for me to say that "COM interfaces are better than CORBA". But I don't agree with this, I still like CORBA interfaces better. And I think I have explained my preferences very clearly. See the links, to Java and C# interfaces, which are equal to how CORBA interfaces work. If you want to convince me otherwise, give some concrete arguments. Address the arguments in my article. Explain how *all* programming languages (and CORBA interfaces in Pascal) have a bad approach to interfaces, while the COM interfaces in Pascal are the right path.

And do it with normal tone, without some baseless accusations of my person.

The incredible advantages of smartpointers do not have weight here, they do not make the disadvantages of COM interfaces disappear in any way.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 05, 2016, 09:30:54 pm
There is quite some overhead, because the value of the interface instance is not the same value as self of the class instance.

This goes for every pure interface because the instance might not be a known form of class
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on September 06, 2016, 12:03:31 am
Zoran, He - and by proxy, you too - has no clue about both types of interfaces.

Okay, I don't know much.

However, why don't we finally make clear what actually interfaces are for?
I believe that the purpose of interfaces is creating abstraction for classes which do not have common ancestor. In C++ a class can have more than one parent, so interfaces aren't needed there. In Object Pascal, Java and C#, there is not multpile inheritance; that is why interfaces are introduced in these languages.

Now it seems that people think that interfaces should have other purposes. Perhaps I never understood that.
But please, let's see what tutorials say:

Please read what Delphi Basics say - http://www.delphibasics.co.uk/Article.asp?Name=Interface - under "The reason for interfaces".
Please read Delphi tutorial (on Embarcadero site) - Using Interfaces - http://docwiki.embarcadero.com/RADStudio/en/Using_Interfaces
Please read FPC Reference manual - http://www.freepascal.org/docs-html/current/ref/refse41.html

Plus, you can read what Java tutorial say - http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

So, let me quote you again,
no clue about both types of interfaces.

Do you want to say that interfaces just are not actually what all tutorials say?
Do you want to say that their purpose should not be just to make abstraction for two or more classes which have different parents?

And, if it is their purpose (and if it isn't, then what do all these tutorials are talking about), what reference counting has to do with it?
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 06, 2016, 09:38:16 am
Okay, I don't know much.

However, why don't we finally make clear what actually interfaces are for?
I believe that the purpose of interfaces is creating abstraction for classes which do not have common ancestor. In C++ a class can have more than one parent, so interfaces aren't needed there.

(well, what about a class without a (C++) class as parent?)

The Delphi basics bit is IMHO revisionism. Interfaces were introduced for easy COM (or foreign class in general) interfacing, not for some  MI language purpose. Yes, you can (ab)use them for it, but that was not the original purpose.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 06, 2016, 09:48:23 am
Here's a text I wrote out of sheer frustration that gives a little more insight in what interfaces are and how to use them.
There is still some work to do: GUIDS, Typelibraries, CORBA's ORB-like model, Async etc, but here you go, it is not
 complete yet, but covers the basics.

-----------------------------------------
Interface support in modern object pascal
Reference counted vs non-reference counted interfaces
-----------------------------------------
  Modern Object Pascal supports both COM and CORBA interfaces,
but actually there is a third type of interface that is native to
Object Pascal. There are many misunderstandings about interfaces so
let's try and categorise them by traits.

  The most common misconception is that you can distinguish a COM
interface from a CORBA interface because the first is reference counted
and the second is not. Let me put you out of your dreams: that is wrong!
Both COM and CORBA interfaces can be implemented without reference count.
Both COM and CORBA interfaces can be implemented with reference count.
This is to a large extend implementation detail and not a part of core
specifications, e.g. with a little thought you can implement AddRef and Release on a CORBA
interface!
From the programmers' manual:
"The {$INTERFACES} directive tells the compiler what it should take as the parent interface of an
 interface declaration which does not explicitly specify a parent interface. By default the Windows
 COM IUnknown interface is used. Other implementations of interfaces (CORBA or Java) do not
 necessarily have this interface, and for such cases, this directive can be used."

  So where does that misunderstanding come from?
Well, actually, you may not know that but is is to a certain extend
rather Object Pascal specific: Delphi implemented COM interfaces with
a default implementation that used the reference counted part of the COM
specification by default. So almost everybody that uses COM interfaces
in Object Pascal started to see COM interfaces in that light: reference
counted. And Delphi implemented CORBA interfaces without reference counting.
Let me explicitly state that was also the common practice in both camps,
it just isn't the whole of the story.
  Here we introduce the third type of interface that Object Pascal supports:
An interface type that is neither COM nor CORBA, loosly based on COM and
local to an application. It does not expose an interface to the outside
world. It does not rely on extra software or OS level support.
To make myself clear: All these three types of interface can support
reference counting or not!

So what are the most important traits of the different types of interfaces
in Object Pascal from a programmers point of view?
Well, by no means complete, but for this purpose I define them like this:
1. We have interfaces that expose themselves to the outside world
2. We have interfaces that are local to a process or application.
3. We have interfaces that are reference counted
4. We have interfaces that are not reference counted.

ad 1. requires a mechanism to talk to other processes.
      In COM that is the typelibrary. (META-language, inhibited)
      In Corba that is the interface repository. (ORB-like, centralized)

ad 2. does not need 1. but may implement it anyway, often by accident
      or lack of knowledge.

ad 3. the most important trait of reference counted interfaces is that it
      allows for automatic memory management provided correcty used.

ad 4. non-reference counted interfaces have no memory management support
      by themselves.

For the purpose of its use, let's explain how to work with reference
counted interfaces versus non-reference counted interfaces.

----------------------------
Reference counted interfaces
----------------------------
Provided you use them properly, reference counted interfaces are a bit
like strings: when an object supports a reference counted interface
it will be automatically destroyed when the reference count is zero.
But this is ONLY the case when you use them properly:
1. An object that supports a reference counted interface needs to be
   instatiated through an interface variable instead of an object variable
   for automatic memory management to work. If automatic memory management
   of an object is your goal, never instantiate such an object through
   an object or class variable.
   
   Example:
   {$INTERFACES COM}  // only partially true!
   type
     TMyobject = class(TinterfacedObject);
     
   // WRONG: memory leak, no automatic memory management occurs.
   var
     Myobject:TmyObject;
   begin
     MyObject := TMyObject.Create;
     // If you relied on automatic management, well, you have a leak!
   end. 
   
   // Better, but still wrong:
   var
     Myobject:TmyObject;
   begin
     MyObject := TMyObject.Create;
     try
     ...
     finally
       MyObject.Free;  //Yup, you do this by hand. Bit silly
     end;
   end.

So what's wrong in the second example?
Well, you have to free by hand. It is easy to forget that reference counting
does not work when you instantiate through an object variable. This is one
of the most common causes of memory leaks in an application that uses reference
counted interfaces. DON'T DO THAT! Keep that for classes and objects that do not
support a reference counted interface.

   // RIGHT, PROPER, GOOD, EXCELLENT, YOU GOT IT
   var
     Myobject:IInterface;  // instantiate through interface variable
   begin
     MyObject := TMyObject.Create as IInterface;
     // Guaranteed automatic memory management, no leaks!
     // No try/finally, nothing
   end. 
 
 So never ever forget that if you use a reference counted interface type
 you MUST instantiate through an interface variable.  NEVER through a
 class variable. Then you mix things up and you are asking for trouble.
 Pay special attention to that when you use them in your code.
 
 COM interfaces and COM-like native Object Pascal interfaces in default
 mode support reference counting by default. If you want to use any of
 these two types non-reference counted you have to do a little work: you will need to override
 the implementation of AddRef and Release:
 
   type
     TMyObject = class(TInterfacedObject)
       function _Addref:Integer;stdcall;override;
       function _Release:integer;stdcall;override;
     end;
 
     function TMyObject._AddRef:integer;
     begin
     //Keep refcount on 1
       Result := 1;
     end;
     
     function TMyObject. _Release:integer;
     begin
       Result := 1;
     end;
     
A CORBA interface does not have a refcount mechanism by default, but you can
implement it! Here's part of it. (You actually have to do a bit more, like operator support for this to work)

   {$INTERFACES CORBA}
   type
     IRefcountedCorbaInterface = interface
       function _AddRef:integer;
       function _Release:integer;
     end;
     
     TMyRefcountedCorbaObject = class(Tobject, IRefcountedCorbaInterface)
     private
       fRefcount:integer;
     public
       function _Addref:integer;virtual;
       function _Release:integer;virtual;
     end;
 
 As you can see there really is only the difference between refcounted or not,
 the difference between CORBA and COM can be made to disappear. 
 
 There's lot's more to learn about interfaces, like type libraries and
 dispatch handling but that is for a different chapter.
 I hope you have learned that:
 1. You have refcounted and non-refcounted interfaces. COM and CORBA
    can implement both.
 2. A refcounted interfaced object should be instantiated through an
    interface variable.
 3. A non-refcounted interfaced object should be instantiated through
    an object (class) variable.
 4. Never ever mix-up interface and class variables on the same object!
    That is a recipe for disaster.
 5. Object Pascal implements COM and CORBA like interfaces on ALL
    platforms.

Next time Is and As and QueryIntterface.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 06, 2016, 10:43:21 am
And, if it is their purpose (and if it isn't, then what do all these tutorials are talking about), what reference counting has to do with it?

Well. Read my write up.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Patito on September 06, 2016, 12:52:23 pm
Dont ever mix up class instantiation with interface instantiation. It is still the same mistake I already reported. Is that SO difficult to understand?

Being rude doesn't help you convince me (or anyone, I suppose). So please let's discuss it in a civilized manner.

Don't let yourself get demotivated by the residual trolls.
Interfaces are an advanced topic, and there aren't many people in the pascal-world who understand the basics.

From what Thaddy wrote I think it's pretty clear, that he has no clue about the basics of interfaces.
(ignores need to mix object and interface-Reference(TComponent, ...), ignores overhead, ...)
He will never get it, and it's not worth discussing with him. (He also doesn't have much clue about strings...
and supports people that vandalize the string-type. The next big thing he will support is probably the vandalization of pascal
memory-management with some arcane ARC stuff..)

Anybody who says that 'Interfaces and Object-References' should never be mixed usually doesn't grasp any basics
about  design-patterns and polymorphism... (and has selective amnesia regarding TComponent)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 06, 2016, 01:10:37 pm
Thaddy's writeup is mostly OK, but I'm still interested about the third type, how Delphi implements corba interfaces.

And yes, FPC's corba interface is kind of the root of iunknown, so you can manually implement iunknown (exact or not) on top of it. But the compiler will only manage it for you if the methods match iunknown (in signature and place in the IVMT)

However there is more to interfaces than refcounting, namely:

- the identity of the interface
- what the interface knows about its parent.
- how you can find an interface that belongs to an object (iow the interface tables in the object).

Besides that there are the advanced topics like "implements" and the assigning of methods to implement a signature.

Patito: this is a lazarus forum, not a design patterns and polymorphism forum.

As said you seem to assume things about interfaces (like knowing anything about its root, which is not necessarily a proper class) that the current implementation doesn't. One could make something like IInterfaceComponentReference if you want to know the root.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 06, 2016, 01:41:29 pm
From what Thaddy wrote I think it's pretty clear, that he has no clue about the basics of interfaces.
Take it or leave it. You are wrong.
Read the theory behind the concepts. Don't ever do that again without studying the concepts behind it thorougly.
You will look like an idiot. The same kind of idiots I am trying to prevent to write a chapter in a book that has merits but is completely, utterly wrong about the heart of the matter of interfaces.
What I wrote is vested in theory, not for screen-drawers.

@Marco
I am busy writing the remaining parts and softly correcting some of the really bolds (which were necessary in the context of this thread).
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Zoran on September 06, 2016, 02:09:03 pm
Thaddy, thank you for this post!

Helps a lot, for a start... Now please let me start asking questions:

1. What is the third interface type in FPC you are talking about? You say there is the third type, but I don't see that you use it later in your post.

2. For COM type -- see the part where you are saying this:
COM interfaces and COM-like native Object Pascal interfaces in default
 mode support reference counting by default. If you want to use any of
 these two types you have to do a little work: you will need to override
 the implementation of AddRef and Release:
 
   type
     TMyObject = class(TInterfacedObject)
       function _Addref:Integer;stdcall;override;
       function _Release:integer;stdcall;override;
     end;
 
     function TMyObject._AddRef:integer;
     begin
     //Keep refcount on 1
       Result := 1;
     end;
     
     function _Release:integer;
     begin
       Result := 1;
     end;
     

What is the purpose of setting these results to 1? Did you actually mean to explain how to turn off reference counting? If so, you didn't say it, read the quoted part carefully.

EDIT: I see that meanwhile you edited what I quoted here, so yes, I assumed well, you meant how to turn off reference counting. Thanks.

3. About your first classification (first two types) -- interfaces for outside world and Interfaces for using inside the application.
I don't know much about the "outside" interfaces and I am not talking here about it. But the second usage (local application usage - this is what I think I know and how I want to use interfaces), isn't CORBA type just appropriate to use for this purpose? When you say:
ad 2. does not need 1. but may implement it anyway, often by accident
      or lack of knowledge.
What should we know to avoid implementing 1. by accident or lack of knowledge? Isn't using CORBA type (the way michalis uses it in his tutorial) just enough?

4. In part where you talk about implementing reference counting in CORBA interfaces - you mean just adding the two methods with these names will make FPC call these methods implicitly whenever in code it (correctly initialized interface variable) gets assigned to a new interface variable, and when the variable goes out of scope (just like it does automatically with COM interfaces)?
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: hnb on September 06, 2016, 02:22:53 pm
COM interfaces and COM-like native Object Pascal interfaces in default
 mode support reference counting by default. If you want to use any of
 these two types non-reference counted you have to do a little work: you will need to override
 the implementation of AddRef and Release:
 
   type
     TMyObject = class(TInterfacedObject)
       function _Addref:Integer;stdcall;override;
       function _Release:integer;stdcall;override;
     end;
 
     function TMyObject._AddRef:integer;
     begin
     //Keep refcount on 1
       Result := 1;
     end;
     
     function TMyObject. _Release:integer;
     begin
       Result := 1;
     end;

That is not true. For non-reference-counted  IInterface implementation we have dedicated class: TSingletonImplementation in "Generics.Defaults" module.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 06, 2016, 04:50:16 pm

That is not true. For non-reference-counted  IInterface implementation we have dedicated class: TSingletonImplementation in "Generics.Defaults" module.
As far as I am concerned that is implementation detail, Maciej. What I wrote is perfectly in line with the theory.
Let's not get detracted from the subject. A singleton is not a non-reference counted interface, it is a completely different pattern.
The TSingletonImplementation happens to be one that avoids reference counting but on the wrong assumptions that you could not legally do that
without relying on _AddRef, and _Release. That part is nonsense.
It is like removing a wheel from a car and claim you can drive it legally with a motorcycle license because it has just three wheels  ;) (Sorry, but true)
There is a high risk he writes actual bull-shit regarding interfaces, no he has actually written bullshit already!.
That's what I am trying to prevent.
If you read his examples in his "book" , he actually assigns COM interfaces to object / class variables and then states he doesn't like them.
That's what gets me so angry. He has no clue.

I am sorry, but even you confuse theory with practice if you insist that what you suggest is the same. It isn't You know that.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: hnb on September 06, 2016, 07:13:02 pm
A singleton is not a non-reference counted interface, it is a completely different pattern.
The TSingletonImplementation happens to be one that avoids reference counting but on the wrong assumptions that you could not legally do that
without relying on _AddRef, and _Release. That part is nonsense.

TSingletonImplementation is not my idea, my post is just pure information that we have class which can be used and is sometimes handy. You can find description and comment in Delphi implementation "A non-reference-counted IInterface implementation"... To be clear : calling non-reference counted interface implementation as singleton is IMO bad idea, but that nomenclature exist for a long time in Generics.Default module (which is bad, bad, bad, but it exist - nothing less or more).

I regret that I mentioned TSingletonImplementation :P.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on September 07, 2016, 04:39:53 am
Quote from: Thaddy
If you read his examples in his "book" , he actually assigns COM interfaces to object / class variables and then states he doesn't like them.
That's what gets me so angry. He has no clue.

I once again have to start by reminding that the first COM interface example (ref-counted) in my article does not assign interfaces to class variables. So the point you raise was addressed a long time ago. Just check the example in http://michalis.ii.uni.wroc.pl/~michalis/modern_pascal_introduction/modern_pascal_introduction.html#_ugly_com_interfaces and notice how C1, C2 are only used through IMyInterface.

Only the next section "Using COM interfaces with reference-counting disabled" shows the usage through class references. But there we're deadling with non-ref-counted COM interfaces, and your own writeup says "A non-refcounted interfaced object should be instantiated through an object (class) variable.".

And I still don't appreciate your tone -- learn to speak without insulting other people, otherwise it's just difficult to discuss.

Quote from: Thaddy
Reference counted vs non-reference counted interfaces

The information that you can add reference-counting to CORBA interfaces is interesting, thank you. I will change the article to mention it, to make it clear that all interfaces can be ref-counted, just CORBA is by default not ref-counted.

Still, the CORBA interfaces are easier (and safer -- see below) way of achieving interfaces without ref-counting. The COM / CORBA difference is still not as independent from the ref-counted / non-ref-counted decision, like you suggest. The reason:

On COM interfaces, calling _AddRef and _ReleaseRef is not optional (because IUnknown already declares them). They have to be called always, regardless if _Add/ReleaseRef implementation follow the ref-counting concept or remove it.

So even if you turn off the reference counting for COM interfaces, it is still dangerous to use them through class instances. You need to take special care to never leave any temporary interface variable "hanging" behind when you free the instance. I mentioned it explicitly in the article, with links to http://freepascal.org/docs-html/ref/refse47.html . That's why the section "Using COM interfaces with reference-counting disabled" says it's not advised.

This is different from CORBA interfaces: you can use them through class instances safely (unless you add reference counting, of course). An extra reference to a non-ref-counted CORBA interface doesn't worry you (just like an extra reference to a class instance through a class variable), as long as it's not explicitly dereferenced in code.

So if you want non-ref-counted interfaces, it's easier to go with CORBA, than "COM + special _Add/ReleaseRef implementations". That is my point, and I don't see how your writeup changes anything here.

I will change the article to note that you can make the CORBA with reference counting. The rest of the point still stands: if you want to have interfaces similar to what Java/C# offers, then go with CORBA interfaces (and do not add ref-counting).
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 07, 2016, 08:11:43 am
The information that you can add reference-counting to CORBA interfaces is interesting, thank you. I will change the article to mention it, to make it clear that all interfaces can be ref-counted, just CORBA is by default not ref-counted.

(actually real Corba interfaces are, just not via unknown, and typically managed manually. The name was always bad, please mention that :-))

Stress that non reference counted interfaces are more "bare" and deemphasize the link to corba and java. Note that iunknown doesn't just do refcounting though, it also plays a part in identity (queryinterface (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521(v=vs.85).aspx)) that allows to get other interfaces supported by the object from the object. (e.g. to see if you can "upcast" an interface to a newer version)
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: michalis on September 08, 2016, 01:34:20 pm
The information that you can add reference-counting to CORBA interfaces is interesting, thank you. I will change the article to mention it, to make it clear that all interfaces can be ref-counted, just CORBA is by default not ref-counted.

(actually real Corba interfaces are, just not via unknown, and typically managed manually. The name was always bad, please mention that :-))

Stress that non reference counted interfaces are more "bare" and deemphasize the link to corba and java. Note that iunknown doesn't just do refcounting though, it also plays a part in identity (queryinterface (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521(v=vs.85).aspx)) that allows to get other interfaces supported by the object from the object. (e.g. to see if you can "upcast" an interface to a newer version)

Roger. The way I understand, the better names would be "always-descend-from-IUnknown" vs "don't-always-descend-from-iUnknown", not "COM" vs "CORBA". That would certainly be clearer for someone who is not interested in interacting with outside services (neither COM nor CORBA) and just wants a language feature (with the purpose of casting two classes to a common interface, because they share a common API, similar to interfaces in Java/C#).
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: marcov on September 08, 2016, 01:39:39 pm
Yes or bare and com/iunknown with com/iunknown inheriting from bare.
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: Thaddy on September 08, 2016, 05:10:19 pm
Ok. This is somewhat going in the right direction.... O:-) >:D
Title: Re: Quick Modern Object Pascal Introduction, for Programmers
Post by: kupferstecher on June 08, 2017, 10:34:07 pm
It's a year now since the TO published his book. It seems to got stuck after the fights about the interface features.

Thats really a pity I think, because such a document can be quite helpful for people new to FPC. So I hope it will get further promoted and also optimised in its content.

Some notes, based on my opinion:
- The title should explicitly contain the words "FPC" and ("syntax" or "language feature"). As this is a document for learning and not an article about modernity.

- The usage of classes should be described better. Especially that the variables of type of a class are only references and the constructor reserves the according memory and the destructor frees it. That classes only work with dynamic memory allocation. For pros this is clear, but its a concept which is not intuitive and a lot of beginners stumble over this.

- The wording 'old style object' is unfortunate. There are use cases where type object is quite useful, also in modern applications. And describing the object 'in range' to the class can help understanding classes.

As said, I hope it goes on~
Regards
TinyPortal © 2005-2018