GNU Pascal Homepage - gpc - gpc-announce - gpc-de - gpc-doc
This page in English

Mail #8125

Zurück zur Archiv-Hauptseite

Vorige Mail   Nächste Mail   Unformatiert/Volle Header
Übersicht  10 Tage   Betreff   Datum   Thread   Autor  

Von: Grant Jacobs
Betreff: Weird type/identifier conflicts
Datum: 1.3.2003, 21:05:41

At 5:43 PM -0500 28/2/03, CBFalconer wrote:
>Grant Jacobs wrote:
>>  At 10:10 AM -0800 28/2/03, Russell Whitaker wrote:
>>  >On Fri, 28 Feb 2003, CBFalconer wrote:
>  > >> Grant Jacobs wrote:
>>  >>  .. snip ...
>>  >> >
>>  >> > Since these uses statements were within the interface section, I
>>  >> > presumed the definitions would propagate upwards so that they
>>  >> > form a hierarchy. Or, put another way, I assumed the interface of
>>  >> > a unit is extended by any units it uses in its interface section.
>>  >>
>>  >> That would be very poor practice, since it would expose routines,
>>  >> types, variables in areas where one wishes to keep them
>>  >> inaccessible.  Uses does not, and should not, mean export.
>>  >>
>  > >Not quite. given:
>>  >
>>  >Unit foo;
>>  >interface
>>  >uses bar;
>>  >implementation
>>  >uses nobar;
>>  >begin
>>  >end.
>>  >
>>  >In any user of foo, anything in the interface section of bar
>>  >should be visable; unit nobar remains hidden.
>>
>>  Thanks, this is exactly what I meant. I need to do a little testing:
>>  it may be that --automake not "drilling down" the units or some
>>  other silly thing is confusing me. I'll get back once I'm done.
>>
>>  Note that its not the uses that does the export (I never meant to
>>  suggest or imply that!), but the interface. Uses only does an import.
>>  If the uses is placed in the interface, the interface of that unit
>>  gets inherited/propagated/call-it-what-you-will.
>
>Let's try a little analogy:
>
>   PROCEDURE foo;
>
>      PROCEDURE bar;
>
>         PROCEDURE baz;
>            BEGIN END; (* baz *)
>
>         BEGIN END; (* bar *)
>
>      BEGIN
>      (* baz is totally invisible here *)
>      END; (* foo *)
>
>   (* If the earlier bar were visibile, we couldn't *)
>   PROCEDURE bar;
>      BEGIN END;
>
>   BEGIN
>   (* baz is invisible here *)
>   (* bar is locally defined, nothing to do with foo *)
>   END.
>
>Now think about the name conflicts that can arise if everything is
>visible everywhere.  Consider foo ensconced in a separate module,
>which in turn uses a module holding bar.
>The point is to enable break up into separate compilations without
>causing inexplicable errors.

Firstly, you're "cheating" in that you're using nested procedures and 
I'm sure you realise units and modules aren't designed to be tied to 
procedures and functions so this e.g. is purely academic from my 
point of view. You can't create the equivalent of nested procedures 
with units or modules, as that would require putting the uses inside 
the outer procedure (i.e. tying the unit to the procedure), e.g. you 
can't do:

   procedure foo;

     uses barthingy;

   begin
   end; { foo }

Units/modules are tied to other units/modules, not to procedures or 
functions, at least in the implementations I know of! (And even if 
you could, you'd still have the issues I discuss below).

So... while this example is interesting as its impossible to directly 
implement in units/modules, its not a practical problem to me. It 
*is* an interesting limitation of units/modules, though.


Secondly, I never meant to imply everything is visible everywhere nor 
that it ought to be. Obviously, what you expose depends on the 
application at hand. On the note of hiding/exposing, a little 
philosophy FYI (at the risk teaching grandmother suck eggs, so to 
speak):

If a unit doesn't want something to be visible to code that imports 
the unit, the programmer simply doesn't place that thing in the 
interface section of the unit. Done. To hide procs./fns. from other 
procs./fns. in the same implementation unit, used nesting.

The importing units can choose to import all, some or none of the 
things offered up for import by any unit it uses, assuming there is a 
mechanism to selectively import items (obviously importing nothing of 
something you use doesn't make sense, but it *is* conceptually an 
option!).

This places more control in the hands of the code using units. In the 
procedure-based code, higher levels have no option but to accept what 
is defined at lower levels. If two different units offered bar(), 
higher-level code could choose which unit to import bar() from. There 
is no way to achieve this with procedures/functions; only one bar() 
could be offered.

So it really is a difference in philosophy. Should the power be with 
the lower levels to dictate the higher levels or vice versa? Should 
lower levels insist only one bar() is available, or can several 
alternatives be offered and one chosen by the importing code? You can 
argue for both in different cases.

What you seem to want is for units/modules to be able to choose to 
dictate what units/modules can use them (this is in effect what 
nesting does). We could come up with a construct like 'export bar 
only to foothingies, specialthingies;'. [This isn't a suggestion, 
Frank!! :-)] Thought of in a larger scale, this blocks re-use of 
lower level code as you'd be forever editing import restrictions in 
the lower-level units. That said, there probably is the odd case 
where it'd be useful.


The only way to make your example work under current schemes (as I 
understand them) is to move the inner bar outside foo; as I was 
saying units/modules are not designed for nested procedures. But if 
you accept this you can make it work (an equally academic example 
back to you! :-) ):

unit innerbarthingy;

interface

     procedure bar;

implementation

     procedure bar;

       procedure baz;
       begin end; { baz }

     begin end; { bar }

end.


unit foothingy;

interface

   { export only foo }
   procedure foo;
   begin end;

implementation

   { get the "inner" bar }
   uses innerbarthingy;

   procedure foo;

   begin end; { foo }

end.


unit barthingy;

interface

     procedure bar;

implementation

     procedure bar;
     begin end; { bar }

end.


unit getthingies;

interface

implementation

   { get foo() from foothingy and bar() from barthingy }
   uses foothingy, barthingy;

end.


The only "danger" is that the importing code needs to take 
responsibility for importing the right things (e.g. that we don't 
import bar() from innerbarthingy). Which comes back to the philosophy 
question again. With power comes responsibility...

There are a long list of other issues tied with this, but I'd rather 
get back to solving my practical problems...! If you want to ruminate 
on your own, you could consider (a) that most modern OOP languages 
share this issue in various ways (b) how hierarchial naming schemes 
(e.g. getthingies.bar vs. getthingies.foo.bar) figure in the mix, (c) 
polymorphism... and, err, I've got work to do...! Its fun mulling 
over all this, though.

BTW, my original questions weren't "how to program" but rather how 
does this particular implementation (GPC) work, esp. as the docs are 
are a tad thin.

Cheers,

Grant

Vorige Mail   Nächste Mail   Unformatiert/Volle Header
Übersicht  10 Tage   Betreff   Datum   Thread   Autor  


Antworten auf diese Mail

Autor Betreff Datum
Frank Heckenbach Weird type/identifier conflicts 1.3.2003, 19:25:21
Grant Jacobs Weird type/identifier conflicts 2.3.2003, 15:08:45
Peter N Lewis Weird type/identifier conflicts 2.3.2003, 22:42:27
CBFalconer Weird type/identifier conflicts 2.3.2003, 12:48:25
Grant Jacobs Niggardly little error in error detection 3.3.2003, 15:21:51
Grant Jacobs Weird type/identifier conflicts 3.3.2003, 19:19:37
Grant Jacobs Unit name vs. filename mismatch warning? 2.4.2003, 21:46:42

Antwort auf

Autor Betreff Datum
Russell Whitaker Weird type/identifier conflicts 28.2.2003, 10:10:02
Grant Jacobs Weird type/identifier conflicts 1.3.2003, 10:48:46
CBFalconer Weird type/identifier conflicts 28.2.2003, 17:43:54

Zurück zur Archiv-Hauptseite


Hinweis: Diese Seite enthält Informationen, die nicht vom Betreiber dieser Website, sondern von den Autoren der archivierten Mails stammen. Der Betreiber dieser Website ist nicht für den Inhalt dieser Informationen verantwortlich. Die weitere Verwendung dieser Informationen bedarf des Einverständnisses des jeweiligen Autors.

Sofern WWW-Adressen (URLs) in den archivierten Mails als Hyperlinks hervorgehoben werden, so geschieht dies ausschließlich zur Annehmlichkeit für den Leser. Der Inhalt der auf diese Weise angelinkten Webseiten spiegelt nicht notwendigerweise die Meinung des Betreibers dieser Webseite oder der Autoren der archivierten Mails wider. Der Betreiber dieser Webseite ist nicht für den Inhalt solcher Webseiten verantwortlich. Diese Seiten sind ausdrücklich nicht als Teil des Inhalts dieser Seite zu betrachten, sondern lediglich als Referenzen.


Diese Seite wurde erzeugt von Crystal 0.999 (Linux 2.4.27/i686).