Closed liufengyun closed 7 years ago
The design of Apply
and ApplyType
is also against this principle, thus can be improved from this perspective.
The design of Match
and Case
is against this principle as well, though it doesn't pose a problem in practice, as there are not many Scala implementations, they are all similar.
I came across another example of this with New(AnonymousClass(...))
and New(InitCall(...))
. New
is redundant, it does not mean anything on its own. NewAnonymousClass(...)
and NewInstance(...)
should work better. Will send a PR fixing new instance creation with this change soon.
As mentioned above, each abstract constructor and extractor is an assumption on compiler. Minimise the number of constructors and extractors certainly boosts portability.
Avoid providing extractors for problematic constructs, avoid constructors for deprecated language feature, avoid/delay constructors for rare & complex language features.
A common mistake here is to support everything in the language specification.
The design of constructors and extractors is mostly driven by syntax of the language. But syntax is not the only concern. Semantically, f(1)
in f(1) = 3
is not a function call. Representing the left-hand side by a functional call potentially harms portability. That justifies the introduction of Update
, Pat.Var
, Pat.Ascribe
, Pat.Tuple
, Pat.Infix
, Self
, InitCall
, NewInstance
, etc.
Close, already in the paper.
I'll try to document some of the thoughts in the design of constructor/extractors in this issue.
Prefer macro-structure over micro-structure
A good example is the design of
Class
andForYield/ForDo
. An alternative design forClass
is to have primary constructors and templates. An alternative design forForYield/ForDo
is to haveFor/Yield
.The current design in gestalt is superior because they are more high-level, which will make it easier for different platform implementations. Each constructor/extractor is an assumption about some shape, it's better to have assumptions on the overall shape to minimise micro assumptions which are fragile.
For example,
ForYield/ForDo
only assumes the compiler being able to representfor/yield
andfor/do
, whileFor/Yield
assumes the compiler being able to represent the micro-structureyield
, which could make some platform implementation more complex, while doesn't bring any benefits to meta-programmers.The same consideration justifies the removal of template and primary constructor: the macro-assumptions are much easier to satisfy by platforms. Meanwhile, they make usage easier. The design consideration for
InitCall
is similar.Note that currently
import
is against this principle, they should be improved.