stz revisiting pub/private/package

stz revisiting pub/private/package
Photo by Simon Hurry / Unsplash

I don't like #scope: private. One of the main reasons I don't like it is private and package have 7 letters and public only has 6. Also it's just plain ugly. I miss the days (a week or so ago) when I could just write private and be done with it.

Also we need easy ways to concatenate lists together. We have easy ways to do it with strings now, eg:

string1 = 'Hello'
string2 = `~{string1} World`

So along those lines let's use ellipsis inside lists as a prefix. This is reusing the deferred statement syntax but I think it won't be a problem. A deferred statement inside of a list constructor doesn't make much sense. I hope.

list1 = (1, 2, 3)
list2 = (...list1, 4, 5, 6)

That allows us to insert list1 where-ever we want in the list. Let's also apply it to maps:

map1 = (a: 'a', b: 'b')
map2 = (a: 'x', ...map1, 'b': 'z')

Cool! and the type of map1 helps dictate the inferred type of map2. Because it's a list it knows not to defer the resolution of map1 until the end of the list, as opposed to (... defer-this-thing) which isn't in a list (no ,).

Back to public, private, package. I could change the names to public, hidden, module. That would require renaming packages to modules. Module is a cool word but it sounds.. old. The three-p's has a nice ring to it. May be I live with public being 1 letter shorter.

We have import, so what if we also had export? If we make package scope the default then you'd have to indicate you want something revealed to the world. Export could be used for that. That doesn't help with private which would still be 1 letter longer.

Also we have no way of making specialisations of a class public, package, or private. It'd be nice if that were possible too.

Let's try a rewrite of list and see how it looks:

export
list = (
  export #specialise: [ of: element-class | object-t -> class ]
  #traits: ( iterable-t of: element-class, sequential-t of: element-class )

  export length: uint
  export allocator: &memory-allocator
  elements: (array of: element-class )

Yeah I'm not too pleased with that. It feels like it makes more sense to me to indicate something is private rather than public. Hiding something away should be done with malice after all.

With that in mind, if we remove the public keyword entirely and only have package and private the 1 character difference goes away:

list = (
  #specialise: [ of: element-class | object-t -> class ]
      #traits: ( iterable-t of: element-class, sequential-t of: element-class )

  package elements: (array of: element-class)
  length: uint
  allocator: &memory-allocator )

We could invest in some new syntax. Something like elements(package): but that puts more load on the parser. Right now the parser parses each element in the list the same way as it does anything else. It would ambiguously see that as package receiver, element: method, (array of element-class) argument. It's the compiler that reinterprets it in to a class definition.

We could add a syntax for defining a class that alters the parser behaviour; such as <...> but again that's just more noise. We could slap a # in front of package and private. And may be we should do that, but everything that starts with a # right now makes the rest of the line meta-information. Only part of the line is meta information for a member declaration.

I think we're better off avoiding more symbols at this point. Though should package actually be privileged - ugh no typing that is a pain in the butt. It can't be shared either since that sounds a lot like exporting.

I'm going to go with what's written above for now.