Sign in Join
Wiki copytemporary

Namespaces: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Since [[FPC New Features 3.0|FPC 3.0.0]] unit namespaces with dots are supported.
22
33## Namespaces in FPC
44
55This page contains proposals and ideas, which could lead to the a better implementation of namespaces that what Delphi currently has. These ideas may or may not work, that's the whole point of this wiki page. Throw ideas around until we find something that could work.
66
77## Why?
88
99Namespaces are not perfect, but they do work, and they do greatly reduce the chances for Unit name or Class name conflicts. Other languages and frameworks (Java, .NET, C++ etc) have already seen the problem and introduced namespace support.
1010
1111How visible is the unit name conflict problem? Just think, how many projects are there that use the unit names (or would like to use these common names):
1212
13-` constants.pas`\
14-` utils.pas`\
15-` etc...`
13+```text
14+ constants.pas
15+ utils.pas
16+ etc...
17+```
1618
1719Extremely common names, and are really good names for what they contain (they describe the purpose of the unit clearly), so why can't we use them in our projects? Namespaces will resolve such problem.
1820
1921- To reduce the chances of conflicting unit names
2022- Allow developers to use ideal names for units without the worry of conflicting unit names with the FPC compiler or other component libraries. eg: constants.pas or utils.pas or strutils.pas
2123- No need for cryptic 2 or 3 letter prefixes to unit names.
2224
2325## Interested Parties
2426
2527- Graeme Geldenhuys
2628- Marcos Douglas
2729
2830## Usage Examples
2931
3032Please add any new ideas to the end of the list.
3133
3234### Suggestion 1 - "dotted unit name notation"
3335
3436Use the same style as implemented in Delphi 2009 onwards.
3537
3638#### Pros
3739
3840- Extends the syntax in Pascal where units are already namespaces (disambiguating two names by prefixing the unit name)
3941- Similar to the Ada approach of packages, much more robust than namespaces
4042- Delphi compatible
4143
4244#### Cons
4345
4446- The force rather long unit names. eg: freepascal.rtl.classes.pas
4547- Unit names now contain a '.' character which doesn't make them truly valid identifiers.
4648- Ambiguities could appear, but they are rather easy to overcome with a simple language rule. Object Pascal already have many language rules, this will just be a new one. See the following Mantis report for details: [Mantis report 14439](http://bugs.freepascal.org/view.php?id=14439)
4749
4850### Suggestion 2 - new keyword & new compiler parameter
4951
5052This idea works similar to Compiler Defines. They can be applied to a unit, or to a project as a whole. Add a new keyword **namespace \<value\>** to the Object Pascal language that gets added to the *unit* line of a source file. Also add a new **-namespace=\<value\>** compiler parameter to apply a namespace to a whole project
5153
5254#### Example
5355
54-`   // per unit`\
55-`  unit utils namespace companyxyz;`\
56-`  uses`\
57-`    ...`\
58-`  end.`
56+``` pascal
57+ // per unit
58+ unit utils namespace companyxyz;
59+ uses
60+ ...
61+ end.
62+```
5963
6064...or applied at compile time to all units being compiled.
6165
62-`   // our sample unit - as normal, nothing new`\
63-`   unit utils;`\
64-`   uses`\
65-`     ...`\
66-`   end.`
66+``` pascal
67+ // our sample unit - as normal, nothing new
68+ unit utils;
69+ uses
70+ ...
71+ end.
72+```
6773
68-`   $ fpc -namespace=companyxyz utils.pas constants.pas ...`
74+```text
75+ $ fpc -namespace=companyxyz utils.pas constants.pas ...
76+```
6977
7078... if a conflict occurs, then you reference the unit with the full namespace.
7179
72-`     uses`\
73-`        companyxyz.utils;  // because unit names must be valid identifier and thus,`\
74-`                           // can't contain dots, when the compiler sees this, it knows`\
75-`                           // companyxyz. is a namespace reference.`
80+``` pascal
81+ uses
82+ companyxyz.utils; // because unit names must be valid identifier and thus,
83+ // can't contain dots, when the compiler sees this, it knows
84+ // companyxyz. is a namespace reference.
85+```
7686
7787#### Pros
7888
7989- Namespaces can be applied per unit or for a whole project. The unit specific namespace takes preference compared to the namespace declared as a compiler parameter.
8090
81-` unit buttons namespace fpgui;`\
82-` uses`\
83-`   Classes`\
84-`  ...`\
85-` end.`
91+``` pascal
92+ unit buttons namespace fpgui;
93+ uses
94+ Classes
95+ ...
96+ end.
97+```
8698
8799- Namespaces can be applied via the compiler command line parameter so no need to modify each individual unit.
88100
89-` fpc -namespace=fpgui buttons.pas groupbox.pas panel.pas`
101+```text
102+ fpc -namespace=fpgui buttons.pas groupbox.pas panel.pas
103+```
90104
91105- Least amount of intrusion to existing code.
92106- Unit names still stay short
93107- Unit names are still valid identifiers (unlike the "dotted" notation of Delphi).
94108- If no explicit namespace is declared in the unit, or per compiler parameter, then in automatically get added to the "global" namespace, and works like FPC and Delphi prior to v2009.
95109- The usage of the namespace is only required when you get a unit name conflict. All other times, simply using the unit name as-is will suffice.
96110- When a unit references a unit in a uses clause without the namespace, then the following search priority is taken.
97111 - "global" (or undefined) namespaces take preference. For example the RTL in FPC will not be compiled with a namespace to get higher priority. So if a project also contains a SysUtils.pas unit, the RTL's SysUtils will take preference, and the developer will have to introduce a project wide namespace.
98112 - Then units part of a project.
99113 - Then units defined in a namespace.
100114
101-`// our project also has a SysUtils unit, but because RTL already has one, we`\
102-`// must define a namespace for it.`\
103-`unit SysUtils namespace myproject;`\
104-`uses`\
105-`  ...`\
106-`end.`\
107-` `\
108-`unit mytools;`\
109-`uses`\
110-`  SysUtils,             // from the RTL`\
111-`  myproject.SysUtils,   // from this project / the myproject namespace.`\
112-`  Classes;`
115+``` pascal
116+// our project also has a SysUtils unit, but because RTL already has one, we
117+// must define a namespace for it.
118+unit SysUtils namespace myproject;
119+uses
120+ ...
121+end.
122+
123+unit mytools;
124+uses
125+ SysUtils, // from the RTL
126+ myproject.SysUtils, // from this project / the myproject namespace.
127+ Classes;
128+```
113129
114130#### Cons
115131
116132- In corner cases, some ambiguities could appear (if the developer doesn't understand the preferences of namespaces).
117133- The name of a common RTL unit (e.g: sysutils) can be redefined. And while being fully qualified in the uses-clause "myproject.SysUtils", it could occur unqualified in the source (if only the one SysUtils was used): "SysUtils.Foo" or "SysUtils.Exception" (Exception could be redefined in myproject)
118134
119135
120136This would be confusing to any reader (other than the original author). As reading "SysUtils" will always trigger the assumption RTL
121137
122138- how will the compiler know what file contains myprojects.sysutils ? It will have to index all files in the search path on every compiler start. The Java solution solves at least that, check all classpath roots for a fixed directory. ( for x in classpaths do check(x+'/myproject/sysutils').
123139
124140### Suggestion 3 - directory layout
125141
126142Similar to what JAVA does, by using the directory hierarchy to define the namespace.
127143
128144#### Pros
129145
130146- Keeps the unit names short, while still mapping the full namespace qualified name directly to a path name
131147
132148- Only need a single search path to include all packages, since each package is automatically mapped to its own subdirectory
133149
134150#### Cons
135151
136152- I see lots of issues with this idea because FPC supports multiple search and library paths per project. So this is probably the crappiest idea. :-)
137153
138154### Mapping Namespace to each search path
139155
140156Each installed "package" (set of units) usually resides in a directory, and has it's own /lib or units folder for pre-compiled ppu.
141157
142158This directory is added to the list of search paths.
143159
144160#### Definitions / Proposals
145161
146162- Terms used:
147163
148164:* Package: A collection of units, grouped in one directory. (Since FPC as no real packages yet)
149165
150166
151167
152168Examples: RTL, FCL, LCL, SynEdit, CodeTools, RxLib, ....
153169
154170- Notes:
155171
156172:* Unit names:
157173
158174
159175
160176It is not encouraged to call a unit Utils. It should still be attempted to use names with a likelihood for uniqueness (such as RxUtils). The described proposal is a last resort to resolve remaining conflicts
161177
162178#### Adding / Creating a Namespace / SearchPath-Alias
163179
164180
165181Current Situation; Any package used in a project must be known to FPC at compile time of the project. that is archived by adding an -Fu to either the command-line or fpc.cfg file
166182
167183- Proposal 1: Extending -Fu
168184
169185
170186Allowing to specify Namespace/SearchPath-Alias together with the Path in the -Fu (or alternative a new directive -FU)
171187
172188Since there is no char, that can not already be part of a directory name in a path, -Fu cannot easily be extended, so that an alias would always be detected.
173189
174190Using -FU would tell the compiler, that an alias is always expected. The alias always ends at the first occurence of the separator char. e.g -FU LCL : /path/to/lcl (spaces are for readability =\> real directive, would not have spaces)
175191
176192- Proposal 2: Adding a default namespace to the Lazarus *.lpk file (Lazarus would add it to the -FU)
177193
178194
179195This would be set by the supplier of the package, e.g when downloading rxlib, the people who are in charg of rxlib, would have set the default to "rxlib"
180196
181197This can create conflicts in namespace,. but the user can easily change the default
182198
183199
184200If the user changes the default, and hiscode refers to the changed default, he must change the default on all installations where he uses this.
185201
186202Maybe the ability override defaults, in the project settings instead should be discussed? Separate discussin...
187203
188204- Proposal 3: Adding a default namespace inside one/each unit of the package (using a namespace directive, after the unit declaration)
189205
190206
191207
192208Instead of a namespace in -FU or lpk; a namespace can be defined inside the unit(s)
193209
194210Because there is no package file, this would be needed in every unit. (alternatively a unit with special name (e.g equal to the last directory name in the path ?)
195211
196212Example
197213
198214
199215Unit Utils; Namespace 'RxLib'; \[1\]
200216
201217Cons: As there currently is no package concept, this would be required for each unit, here would be no way to ensure all units in the path have the same (a consistent) Namespace.
202218
203219Multiple namespaces in one packages may not be desirable .
204220
205221- Mixing of Proposals:
206222
207223
208224
209225-Fu (1, 2) and namespace (3) can work in parallel, -FU takes priority.
210226
211227- Multiply Namespace: Needed ?
212228
213229- Project overrides for conflicting Namespaces: Todo
214230
215231#### The "uses" clause
216232
217233- Proposal 1: using "in"
218234
219235
220236
221237uses Utils in RxLib;
222238
223239
224240Note ther e are no quotes around the namespace, this disambiguates it from a directory of the same name, present in the project folder.
225241
226242uses Utils in RxLib alias RxUtils, utils in LCL alias LCLUtils;
227243
228244uses Utils in RxLib as RxUtils, utils in LCL as LCLUtils;
229245
230246
231247alias (or as / to be decided) can be used, if several units of the same name exist across several namespaces, and should all be imported.
232248
233249- If no alias is given the unit is known by it's own name
234250- If an alias is given the unit is known by the alias, and the alias only
235251
236252No 2 units must resolve to the same name
237253
238254- It may be proposed, that if 2 units Utils exists, both must be aliased. Even though, if only one was aliased, they would have different names already.
239255
240256
241257But that might lead to unnecessary changes in a unit if a unit name is already used to distinguish types like in the following example:
242258
243-`uses`\
244-`  Windows, Graphics; // both have a type TBitmap`\
259+``` pascal
260+uses
261+ Windows, Graphics; // both have a type TBitmap
245262
246-`(...)`\
263+(...)
247264
248-`var`\
249-` b1: TBITMAP; // from Windows`\
250-` b2: Graphics.TBitmap; // Note: for this example I assume that the first unit "wins". If FPC handles this different, then please exchange the unit in the uses clause ^^`
265+var
266+ b1: TBITMAP; // from Windows
267+ b2: Graphics.TBitmap; // Note: for this example I assume that the first unit "wins". If FPC handles this different, then please exchange the unit in the uses clause ^^
268+```
251269
252270
253271
254272Assuming there are more usages of "Graphics.TBitmap" in that unit the addition of another Graphics unit would lead to unnecessary changes if both units must be aliased:
255273
256-`uses`\
257-` Windows, Graphics in LCL, Graphics in SomeGraphicsPkg as SomeGraphics;`\
258-` // Note: I just picked one of the syntaxes for this example`
274+``` pascal
275+uses
276+ Windows, Graphics in LCL, Graphics in SomeGraphicsPkg as SomeGraphics;
277+ // Note: I just picked one of the syntaxes for this example
278+```
259279
260280- Proposal 2: Using "." (dot)
261281
262282
263283
264284uses RxLib.Utils;
265285
266286uses RxLib.Utils as RxUtils;
267287
268288- Proposal 3: Using alternatively "as"/"alias" syntax
269289
270290
271291
272292uses RxUtils=RxLib.Utils;
273293
274294uses RxUtils(RxLib.Utils);
275295
276296#### References in the code
277297
278298In the code the unit can only be referenced by it's alias (or it's own name, if it was not aliased.
279299
280300Namespace qualifiers should not be allowed in the code
281301
282302Namespace qualifiers in the code can cause ambiguity, since a unit and a name of the same namespace can exist. See [Mantis report 14439](http://bugs.freepascal.org/view.php?id=14439)
283303
284304Namespace qualifiers are not native pascal. Keeping their effect as low as possible (quarantined to the "uses" clause, maybe the "unit" declaration) would be desirable
285305
286306#### Pros
287307
288308#### Cons
289309
290310### Suggestion 123 - all together
291311
292312#### Proposal
293313
294314Use dotted unit names with additional keywords and mapped to directory layout.
295315
296316#### Example
297317
298318E.g. the current classes unit would become freepascal.rtl.classes.pas
299319
300320But you can also store it in a directory freepascal/rtl/classes.pas or freepascal.rtl/classes.pas to avoid cluttering a directory with a lot of files and long names.
301321
302322When using it, you can use a new keyword to not write the full name for every unit.
303323
304324E.g.
305325
306-`  uses with freepascal.rtl do begin classes, sysutils end, with lazarus.lcl do begin ...  end, ...;`
326+``` pascal
327+ uses with freepascal.rtl do begin classes, sysutils end, with lazarus.lcl do begin ... end, ...;
328+```
307329
308330or allow multiple uses
309331
310-`  with freepascal.rtl do uses classes, syutils;`\
311-`  with lazarus.lcl do uses ...`\
312-`  ...`
332+``` pascal
333+ with freepascal.rtl do uses classes, syutils;
334+ with lazarus.lcl do uses ...
335+ ...
336+```
313337
314338#### Pros
315339
316340- Combines the pros of each suggestion(see above)
317341
318342#### Cons
319343
320344- uses with needs to be repeated in every unit + some extra keywords (WITH, DO BEGIN.. END). Savings not that great, unless you really need a lot of units from one namespace. But since FPC/Delphi allows multiple classes per unit, this will be not the case as often as in e.g. C# or Java.
321345
322346## see also
323347
324348- [§ “Namespaces: Dotted Units” in the *Free Pascal reference guide*](https://www.freepascal.org/docs-html/ref/refse112.html)
325349
326350---
327351*From the Free Pascal wiki, page "Namespaces", as it stood on 2020-08-03 after a change by BrainChemistry, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
328352Category: Proposals

Back to history