Although in the manual it is mentioned that this is under consideration, I did not see any issue about it, so I am opening a new one.

Rationale

When each and every strategy definition “pollutes” global namespace this is an argument for developers to make bigger strategies, resulting in less readable code. As a slightly better alternatively he/she may still make global strategies, but then has to give them longer names or accept the risk for name clashes.

When modifying foreign Stratego code that uses only global strategies, in particular libraries, it is now impossible to change the semantics of any strategy - even internal/helper strategies - with a guarantee that code using that library keeps working.

If all internal/helper strategies were written as module-local strategies, then a single glance over the code would reveal it is completely safe to refactor it without considering external code ever. (As long as you make sure the few external strategies keep the same behaviour of course.) This is similar to how you immediately know in a OO language that it is safe to rename some private field (when considering a single class in isolation), while for a protected or public field you will need to find all references in the project.

In short, when there is a way to limit the effect of a global strategy definition to a single module, there are no rational arguments anymore (as far as I can think of) against splitting up code in many small readable strategies with short to-the-point names, without a fear of name clashes.

It is currently possible to split a big strategy in many small local strategies by using a let binding. While this does solve the mentioned problems of namespace pollution and risk for name clashes it:

  • introduces more syntactic noise and an extra indentation level
  • requires explicit scoping as with let bindings no variable scope is inserted (which, in turn, introduces even more syntactic noise)

Solution

I suggest the following solution:

Add an optional “hidden” keyword before “strategies” or “rules”.

E.g.

module foo
strategies
  my-external-interface = foo
hidden strategies
  foo = ...
hidden rules
  bar: t -> t

Implementation wise, the strategies could be hidden from the rest of the project by renaming them so they become unique (i.e. using newname). In Stratego/C the strategies could be hidden from other modules by generating them as static functions. In Stratego/J the strategies could be hidden from other packages by making the generated classes private to the package.

Dynamic rules defined in a hidden section should be hidden from other modules too. I think this is a bit harder to implement, but maybe some good old name mangling would be sufficient.


Sorry for the long report, I hope I made a compelling argument and someone will do it =)

Related issue, about explicitly exporting strategies: https://yellowgrass.org/issue/StrategoXT/365

Submitted by Tobi Vollebregt on 11 January 2011 at 12:42

On 12 January 2011 at 13:53 Lennart Kats commented:

I’ve wanted something like this for a long time. One thing we now though have is the internal modifier:


strategies

internal foo = fail

It hides strategies from other libraries rather than other modules though. However, it currently looks like we may replace the modules system by a packages system, where each package has its own namespace, similar to the libraries we have now. That would make internal more useful for this scenario. But I guess an additional local or hidden modifier could still be useful.


On 14 January 2011 at 17:55 Lennart Kats tagged rfc


On 14 December 2011 at 18:05 Adil Akhter tagged !adil

Log in to post comments