You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Put links here that are particularly useful for learning scala.

Not intended to be a comprehensive sea of Scala-related links.

Not intended to replace searching the web for scala information.

Just the gems please.

Patterns

This section is for design notes about Scala usage.

There are separate pages about some 'big' patterns. E.g., see OOLAG - Object-Oriented Lazy Attribute Grammars which we use extensively.

There is discussion of some coding style issues that one might think of as small patterns in Coding Style & Guidelines for Contributors. In particular: the uniform return-type principle.

Traits as 'Mixins' Pattern

Scala provides powerful multiple inheritance. Consider:

trait M extends M2 with M3 { self : B => ... }

The above is a trait with a 'self type'. The English of what this means is: "M can be mixed into any class that extends abstract class B in order to produce a variant of B". Code within the methods of M can depend on the fact that this is of type B.

About the notation: Please ignore the notational awkwardness of the above idiom. Somebody in the Scala community is in love with the fact that the implementation of all this mechanism ultimately boils down to yet more clever use of higher-order functions, and that's why the => notation is used.  To me this notation is terribly over-used in Scala. Users of this pattern are not thinking about higher-order functions or functions at all really. They are thinking about object composition. But this is something we just have to get used to.

We use this pattern extensively in Daffodil for a few different reasons

Traits for Sharing

It allows us to avoid redundant code, or equivalently increase sharing of code.

Consider I have an abstract class B, and two "characteristics" which I'll call A-like, and C-like, represented by traits A and C. I wish to create concrete classes AB, CB, and ABC. This is done via:

abstract class B {...}
trait A { self : B => ... }
trait C { self : B => ...}
class AB extends B with A
class CB extends B with C
class ABC extends B with A with C

Lest this appear unmotivated, this is exactly what we do to handle XSD's 3 schema components that are the concrete subtypes of element. These are GlobalElementDecl, LocalElementDecl, and ElementRef. Each of these extends ElementBase, but mixes in either ElementDeclMixin, LocalElementMixin, or both.

Traits for Separation of Concerns

Traits with self-types allow us to just separate the parts of a single class into different files to address different concerns.

Consider I have a large class such as ElementBase. The Daffodil compiler front end code for ElementBase is in dsom/Element.scala.

abstract class ElementBase extends Term with ElementBaseGrammarMixin {{... front end code ...}

The middle tier of the compiler is based on the grammar rules system. The code for the parts of the ElementBase class that make up this middle tier are in a separate file, in the mixin:

trait ElementBaseGrammarMixin { self : ElementBase => ...middle tier/grammar code... }

This trait is single-purpose. It is used in exactly one place, which is in the declaration of ElementBase. It could be replaced by just taking the entire contents of the trait, and just adding it to the ElementBase class. The whole purpose of this trait is to just let us break up and label the code differently, identifying this aspect of the ElementBase functionality as part of the grammar/middle-tier of the compiler.

(TBD: perhaps a naming convention to not call these "Mixins", but to specifically call them out as intended-to-be-single-use. E.g., replace the suffix "Mixin" with "Extension" or "Part" or "Aspect")

 

 

 

  • No labels