Sign in Join

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

Mailing lists / fpc-devel / 2018-06

FPC Macros: Could it be used for unit aliases?

7 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

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

Marcos Douglas B. Santos

In another thread[1] Sven Barth explained to me how to use macros properly following my example before.
However, I think this could be used as a syntax sugar for unit aliases on the code — not about paths.

Graeme and me have already proposed[2] this years ago. I am against to include more features in the Language, but in that case looks like simple because the compiler already has the functionality.

This code looks pretty simple using the classic Pascal:
=== code begin ===
uses
   Windows, Graphics; // both have a type TBitmap
var
  B1: Windows.TBitmap;
  B2: TBitmap;
=== code end ===

There is nothing wrong, of course, but nowadays we have more complex systems that use more units and that units should be unique in entire system. So, using namespaces (I know that units are namespaces) turns the code beautiful without (in theory) unit conflict names. But we still have classes with the same name. We can use the same approach above, which is using the unit as a prefix, however this could be inconvenient because units (nowadays) could have a long name.

Hypothetically, let's suppose that Windows and Graphics unit belongs to `FPC.RTL.` namespace, a "long name".
Using a syntax sugar to macros, I propose to implement the "as" keyword in units declarations:

=== code begin ===
uses
   FPC.RTL.Windows as Win,
   FPC.RTL.Graphics as Graph;
var
  B1: Win.TBitmap;
  B2: Graph.TBitmap;
=== code end ===

if I understood right, the compiler "just" need to replace this syntax to use macros:

=== code begin ===
uses
   {$macro on}
   FPC.RTL.Windows,
   {$define Win := FPC.RTL.Windows}
   FPC.RTL.Graphics as Graph;
   {$define Graph := FPC.RTL.Graphics}
var
  B1: Win.TBitmap;
  B2: Graph.TBitmap;
=== code end ===

In my company we are used to use namespaces like
`Acme.SysFoo.Finances.Billing.Utils.Classes` (just an example). Depending on the context, I could code `uses ... as Billing;` Using `Billing` as prefix for all interfaces/classes that has the same names in others units.

[1] http://lists.freepascal.org/pipermail/fpc-pascal/2018-June/054255.html [2] http://wiki.freepascal.org/Namespaces#The_.22uses.22_clause

Best regards,
Marcos Douglas

PS. If it might be accepted, please, make it usable in objfpc and delphi mode. I use the last one because the syntax (eg. generics) is simpler.

Reply by email

Sven Barth
to Marcos Douglas B. Santos
Marcos Douglas B. Santos wrote 34 lines
Hypothetically, let's suppose that Windows and Graphics unit belongs to `FPC.RTL.` namespace, a "long name". Using a syntax sugar to macros, I propose to implement the "as" keyword in units declarations: === code begin === uses FPC.RTL.Windows as Win, FPC.RTL.Graphics as Graph; var B1: Win.TBitmap; B2: Graph.TBitmap; === code end === if I understood right, the compiler "just" need to replace this syntax to use macros: === code begin === uses {$macro on} FPC.RTL.Windows, {$define Win := FPC.RTL.Windows} FPC.RTL.Graphics as Graph; {$define Graph := FPC.RTL.Graphics} var B1: Win.TBitmap; B2: Graph.TBitmap; === code end === In my company we are used to use namespaces like `Acme.SysFoo.Finances.Billing.Utils.Classes` (just an example). Depending on the context, I could code `uses ... as Billing;` Using `Billing` as prefix for all interfaces/classes that has the same names in others units.

You can make use of default namespaces using -FN<x>.

For your first example you'd use -FNFPC.RTL and then you could simply put the units Windows and Graphics into the uses sections.

For your other example let it be said that with default namespaces you can use any part of the name to resolve ambiguities: E.g. with -FNAcme.SysFoo.Finances.Billing.Utils and a "uses Classes" (though I wouldn't recommend that one due to potential conflict with the RTL unit :P ) you could use any of the following to refer to the "Classes" unit:

Classes
Utils.Classes
Billing.Utils.Classes
Finances.Billing.Utils.Classes
SysFoo.Finances.Billing.Utils.Classes
Acme.SysFoo.Finances.Billing.Utils.Classes

Other than that I think the task of reducing typing for this is better put into the hands of the code completion of a capable IDE.

Regards,
Sven

Reply by email

Marcos Douglas B. Santos
to Sven Barth
Sven Barth wrote 41 lines
Am 24.06.2018 um 16:49 schrieb Marcos Douglas B. Santos: > > Hypothetically, let's suppose that Windows and Graphics unit belongs > to `FPC.RTL.` namespace, a "long name". > Using a syntax sugar to macros, I propose to implement the "as" > keyword in units declarations: > > === code begin === > uses > FPC.RTL.Windows as Win, > FPC.RTL.Graphics as Graph; > var > B1: Win.TBitmap; > B2: Graph.TBitmap; > === code end === > > if I understood right, the compiler "just" need to replace this syntax > to use macros: > > === code begin === > uses > {$macro on} > FPC.RTL.Windows, > {$define Win := FPC.RTL.Windows} > FPC.RTL.Graphics as Graph; > {$define Graph := FPC.RTL.Graphics} > var > B1: Win.TBitmap; > B2: Graph.TBitmap; > === code end === > > In my company we are used to use namespaces like > `Acme.SysFoo.Finances.Billing.Utils.Classes` (just an example). > Depending on the context, I could code `uses ... as Billing;` > Using `Billing` as prefix for all interfaces/classes that has the same > names in others units. You can make use of default namespaces using -FN<x>. For your first example you'd use -FNFPC.RTL and then you could simply put the units Windows and Graphics into the uses sections.

Sorry, but I'm not talking about a global identifier. This could be achieve using a long unit name, as Java developers do. If we put the company name as a prefix for all units, I believe, it may be very difficult to has a name conflict with another projects/libraries.
However, the "issue" using this approach is that the code will be much more verbose, if we need to use unit names as a prefix to solve some name conflict, which could happens with classes that belongs to the same project.

I'm talking about a local identifier per unit.
IMHO, to have both pros above — long names with no conflict; short identifiers — we can use the idea of macros as you've already explained to me.

Show quoted text 12 lines
For your other example let it be said that with default namespaces you can use any part of the name to resolve ambiguities: E.g. with -FNAcme.SysFoo.Finances.Billing.Utils and a "uses Classes" (though I wouldn't recommend that one due to potential conflict with the RTL unit :P ) you could use any of the following to refer to the "Classes" unit: Classes Utils.Classes Billing.Utils.Classes Finances.Billing.Utils.Classes SysFoo.Finances.Billing.Utils.Classes Acme.SysFoo.Finances.Billing.Utils.Classes

IMO this is too ambiguous.
I've shown just an example. There are many other units with the same prefix (or group of names). The only difference is the last part. I will have "Classes" sufix in many others unit names. E.g:
Acme.SysFoo.Finances.Billing.Classes
Acme.SysFoo.Finances.Billing.Utils.Classes

I need to think:
"Could I use just `Billing.Classes`?"
"Maybe `Finances.Billing.*` is better to prevents some name conflict?"

Instead, I prefer using fully qualified names and just adjust in some contexts that *there is* already a conflict name.
In other words, `uses foo as bar;` will be use per unit. It is not to intent "renaming" a unit name for all project as Delphi namespaces approach uses.

Other than that I think the task of reducing typing for this is better put into the hands of the code completion of a capable IDE.

It's not about reducing typing, but improve the readability of the code. In the uses clause, I don't care if an unit gets a 100 chars length. But inside the algorithm, it reduce the readability.

We can control these names and conflicts locally... it's only depends on you now :)

Best regards,
Marcos Douglas

Reply by email

Marcos Douglas B. Santos
to Marcos Douglas B. Santos
Marcos Douglas B. Santos wrote 5 lines
Instead, I prefer using fully qualified names and just adjust in some contexts that *there is* already a conflict name. In other words, `uses foo as bar;` will be use per unit. It is not to intent "renaming" a unit name for all project as Delphi namespaces approach uses.

The Delphi namespaces approach is a good feature to reduce the redundancy of unit names.
For example, if my company name is Acme and the project name is SysAbc, why do I need to type the same prefix in all units? It's redundant.
So, I can set a NS as "Acme.SysAbc" for my units, but I will continue use the fully qualified names for 3rd units.

Best regards,
Marcos Douglas

Reply by email

Marcos Douglas B. Santos
to Sven Barth
Sven Barth wrote 8 lines
Marcos Douglas B. Santos schrieb am Mi., 27. Juni 2018, 14:37: > > Sven and all, > Is there any change to implement this? Not from me. I don't care about that.

Thanks for your sincerity.

Regards,
Marcos Douglas

Reply by email