On Tuesday 22 January 2008 21:36, Marco van de Voort wrote: > > > type tmyopaguetype = type pointer; > > > > > > Since the interface must 100% define the interface so that it can > > > be used, which is a hard rule with Pascal and Modula2. > > > > Hmm, what if > > > > --- 8< --- > > > > interface > > > > type > > tMyOpaqueType; // Incomplete. > > > > private > > > > type > > // Complete type declaration, but privately. > > tMyOpaqueType = record ... end; > > > > --- 8< --- > > > > would be possible? > > > > The type is still declared in the interface part; yet, because it's > > in the private part of the interface, no other module can use it's > > inner structure. > > No. Completely defines (most notably its size, probably also its > alignment if it applies). In practice, nearly all M2 compilers only > support pointers
Yes, but that's what it does, defining it, I mean. The "private" keyword would only mark it as "can't use, if you're not a child unit". It is still in the interface, and thus "completely defined" AFAICS. > > > This makes e.g. the operator overloading already hard, since it > > > can't be a record (even variant). > > > > Well, yes and no. As I wrote, you'd need to store that information > > in the unit file. > > You can't. Sb might already be needing the interface before the > implementation is compiled. Yes, I know that. (Ada is a lot more strict about it, where interface (spec) and implementation (body) are even in different files and you can actually compile your code without the body available.) You may have overlooked it, but the "incomplete type" is already completed while still in the interface part. To be more clear on the subject, let me try a more complete example again: --- 8< --- unit Foo; interface type Bar = record; // Incomplete for now. procedure FooBar (Arg : Bar); private type Bar = record X : Integer; Y : Double; end; implementation ... end; --- 8< --- So it's still in the interface, the compiler has all the information it needs (even if only the interface is available at time of compilation), only that the inner working of the type is marked as sort of "non-public". It's more a question of the type system, rather than trickery with the symbol tables. Or you may view it as a special form of a forward declaration. > > > It is a bit the .NET class helper (partial classes) trick in a > > > modular setting. > > > > From what I understood, those partial classes are different. They > > don't extend functionality, they split it (or maybe, the call it > > "delegation of responsibility"). > > As far as I see it they add functionality to a base container. In > partial classes case a class, and in Ada's case a module. Maybe. I'm not a .NET-expert, but then the name is confusing at least. I understood that a class could be implemented in several different modules (I understood "functionality sets") and only upon completion of all modules/functionality, the resulting class as a whole is usable. If that understanding is wrong, then I fail to see what "partial classes" do differently than a normal class. In the end, classes are there for extending them, that's more or less the whole point of OOP. > Both also seem to require to include the relevant "helper" module > explicitely to unlock the extension. Well, in Ada there are no "helper" modules, so this must be wrong for at least this case. ;) > > > I don't like that either. The gain you get from your > > > old and trusted code, you loose in complexity and clarity of > > > overview in the module system > > [...] > > > > I mean, I'm quite sure, you're not argueing for an "all source in > > one large file" approach... so instead of (shared) include files, > > child package would provide compiler checked extensibility. > > I don't like the idea of modules being mutable (even if it only means > extension of the container) The modules do *not* change in any way. You can extend them only by declaring it that way and need to put them in the "uses" clause if you want to use that "extended functionality". It's no more "mutable" than adding "Math_Complex" as another unit to your source file as "extension" to the "Math" unit. Actually, it only takes the modularization to another level and makes it even more flexible. > > IMO, it's much like the package system for the compiler. At least > > how it's laid out: You have FCL that consists of FCL.Base, FCL.XML, > > ... > > I don't see any relation. Well, I do. YMMV. > FCL only exists as parts of names and in > documentation. On src level there are only the packages, and they are > not spelled above (where they imply some hierarchic system), but with > dashes that aren't separators. Yes, I tried to make an example, how such a system would look at source level. For me, I 1:1 relation between the documentation of an intended hierarchy and its appropriate source would be a good thing. > > > (an import of complexnumbers in one place might > > > suddenly react differently due to the partial module/classhelper) > > > > But that's the case already. Even the order of imports is > > semantically relevant (or well, it might be > > But does exuse throwing out all restraint? On the contrary, I'm trying to throw it in by making it possible to make some things more private than they are now. > > Or what's with that "reuse" keywords for the uses clause? > > I'm no fan of that. Glad to hear. > But at least it doesn't require scanning and > indexing all files up front. (though, admitted, neither do child > packages, I just fail to see their use) Well, I used child packages to a great extend, so I am bound to see their use. And I missed them, because a hierarchical source layout for certain modules is sometimes very desirable, even if only in respect to possible name clashes. > They do have in common that a use case that would interest me could > swing me. And reuse seems to make some sense in breaking up large > header sets, though I'm not really convinced yet. It saves about 5 minutes of typing work in a typical project. But this gets lost in the noise once you're trying to find out, which import fails your compile. While I'm at it, I ran into an interesting issue yesterday: -- 8< -- random.pas -- unit Random; interface implementation end {Random}. -- 8< -- -- 8< -- bp.pas -- unit BP; uses Random; interface implementation end {BP}; -- 8< -- -- 8< -- main.pas uses BP; begin WriteLn (Random (1.0)); end {Main}. -- 8< -- |Compiling main.pas |main.pas(5,13) Error: Identifier not found "Random" |main.pas(5,20) Error: Illegal expression Is this a bug in the compiler (I used fpc2.0.0)? Or is there any reason, why this should happen? The unit "Random" has not been used by the main program, so I would expect it to only find the "System.Random" identifier here, not the identifier of a unit, I haven't even put in the "uses" clause. If I move the "uses Random" from the interface into the implementation part of unit "BP", it compiles again, so it seems to be a problem with the interface/implementation visibility. > (I assumed a child package would be autoloaded into a module that > imported the base package. Apparantly I'm wrong there) Yes, you are. Of course this is not allowed to happen. Only explicitely declared "uses" are allowed. Vinzent. _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal