[Grace-core] Library Structures

Michael Homer mwh at ecs.vuw.ac.nz
Mon May 26 17:14:40 PDT 2014


On Tue, May 27, 2014 at 10:46 AM, Kim Bruce <kim at cs.pomona.edu> wrote:
>>> Right now our library system is totally tied to files and file names as we have to write something like
>>> import "ListFile" as list
>>> where ListFile.grace is the name of the file.
>> "Where ListFile is an opaque string interpreted in an
>> implementation-defined manner, which may map onto a file path in some
>> way".
> I understand that is minigrace only.  Actually the main point of the email (which I might not have made clear) was to have an internal identifier for the name of the module, where this internal name could be used for importing files.  Admittedly, names could be provided by just adding a comment to the header of each file that lists the file name.  However I was hoping for something that was actually part of the syntax and that could be used in an import statement.  Perhaps something like (and I'm just thinking out loud, throwing out ideas), the following for the module header:
>
>    module listlibrary
>
> and then using it in another library by writing one of:
>     import listlibrary
> or
>    import listlibrary as newName  // if there was a name conflict
>
> The main motivation here is pedagogical.  I have no serious problem with the functionality, I just want to have a name for all the pieces of a program that is not just a file name when I am talking about them in the text.
It's not "just" a file name if you use it for something else as well -
make it the real name if you want. A name is what you make it.

A comment, or a system for structuring comments (like JavaDoc) that
lets you give a human-readable name to an entity, works too. A comment
won't have any in-language semantic meaning, but I don't think it
should either. If you like you can define a method module(_) {} in
your dialect and write:
  module "The list module"
at the top, which is essentially the same with slightly more syntactic
support. That is potentially a nice option for integrated
documentation anyway, so if you want to invent a convention it's not a
bad one. I think there's still verbiage in the spec about semantics
and attachment of comments too, so that may have some support too.

I think a system that requires indexing every file in existence to
find any "module x" lines inside them is impractical. It's also prone
to unresolvable name conflicts, and it means you can't actually have
these innately interchangeable modules like you want - they all have
to have different names and you'd have to edit the files to activate
them.

Alternatively, you can configure the bindings externally, but then
there's nothing syntactic like you wanted, and your actual code is
meaningless without the out-of-band configuration information (but,
see below for how you can do that now).

The final option is some (very) local search path for each program
where all files are combined together and searched for module
declarations. That definitely does involve changing filenames to move
things though, so it doesn't help you much.

(The final final option is Smalltalk- or Self-style worlds where
everything just exists permanently - they're not much use here.)

I don't think any of those fits the goals of the language in practice
either - if I get some code from a book it should make sense on its
own, without my having to configure anything else.

Java uses RDNS package declarations to root individual files, but that
doesn't play nicely with your desire to minimise prefixes or renaming.
I can't think of a way to make this work that doesn't ultimately
reduce to reimplementing a filesystem, poorly.
>>> If we were to be able to generalize this then we could actually include several modules in a file (if we wanted)
>> So I think what you're thinking of here is just "an object"…
> Yeah, only difference is how many prefixes are needed get access.  I was trying not to equate modules with files, but it may be easiest to do that in practice.
If you're in the same file, there is no difference in prefixing. If
you're in a different file, it doesn't matter a monkey's where the
module came from; put it in its own file and it's one level of prefix.

Potentially binding names for multiple parts of a module in one go is
useful, but I'm not sure if it's worth the semantic load. Something
like Python's:
  from "somemodule" import a, b, c
for some defs a, b, c in that module would essentially be syntactic
sugar for the original import and three lines of aliases, but the
unrolled version is more direct and clearer to me anyway.
>>> or just have a single one per file.
>>> Having a module name would allow us to have a logical name for libraries as opposed to a hard wired one.  This both makes it easier to talk about modules and allows us the flexibility to have several modules with the same name that could be swapped in and out of a system
>>> Of course this means we would have to redo how the implementation keeps track of and imports modules, but I suspect it wouldn't be that hard to design such a system, but it would require some work on the implementation.
>> Can you sketch a design for that? Where do they come from?
> There are programming in the large languages that attach logical names to files where code is found.  I believe this is part of what "platform" does in Newspeak.  It serves as a guide as to where to find the physical files associated with module names.
platform is just an object you pass in; it doesn't really do anything,
and there are no physical files, because it's Newspeak.

On the other hand, if you really want that effect:
  mysetofmodules.grace:
    import "somemodule" as aname
    import "anothermodule" as anothername
    import "athirdmodule" as yetanothername
    def fred is public = aname
    def barney is public = anothername
    def dino is public = yetanothername
  Any other file:
    import "mysetofmodules" as platform
    // Congratulations, you now have a platform object to do with as you will!
    platform.fred.etc.etc
At that point you can change the implementation in use across many
modules with a single modification.
>>> Of course each module would continue to be imported as an object.  If we wanted (though I don't think this is necessary), we could even have modules that are parameterized by type parameters.  [I suspect this isn't necessary, because we can use type parameters on everything inside the module, but it might be desirable in some circumstances]
>>>
>>> By the way, I was pleased to see that the current implementation allows me to define a type Draggable and a class aFunnyFace in a file "FaceClass.grace"  as follows:
>>> type Draggable = {…}
>>> class aFunnyFace.at(locn:Location)on(canvas:Canvas) -> Draggable {…}
>>>
>>> (note I am using old class syntax), and then define a program using them with the following code:
>>>
>>> import "FaceClass" as fc
>>>
>>> type Draggable = fc.Draggable
>>> def aFunnyFace = fc.aFunnyFace
>>>
>>> and then be able to write
>>> aFunnyFace.at(someLocn)on(canvas)
>>> in that program.
>>>
>>> I'm not surprised that we can use Draggable, but I was pleasantly surprised that we could grab aFunnyFace
>>> and rename it without somehow including ".at()on()".  Nice job!
>> You can always alias an object. You can never alias a method.
>
> Yes, the (slight) surprise was that the prefix of the class was indeed recognized as an object.  Of course, that is the way we did the design, but I wasn't sure the implementation would recognize the surface syntax in that way.  I'm very glad it does.
I can't imagine how else it could work, but so long as you're happy
about it. It's just unrolling the sugar.
>  I presume if classes were interpreted as methods then we would need to write something like:
>    method aFunnyFaceAt(locn) on (canvas) -> Draggable {fc.aFunnyFaceAt(locn) on (canvas)}
> to get the alias.
You are going to have to get used to that eventually, though. Giving
up aliasing was an explicit part of the syntax decision.
-Michael



More information about the Grace-core mailing list