Programming DSLs in Kotlin by Venkat Subramaniam
Author:Venkat Subramaniam
Language: eng
Format: epub
Tags: Pragmatic Bookshelf
Publisher: Pragmatic Bookshelf
Use Multiple Contexts to Remove Ambiguity
We may want to create and use multiple context objects for two different reasons. By creating multiple contexts, we can gain these advantages:
Simplify code, reduce code bloat, make code more cohesive, honor the single responsibility principle, and make code easier to maintain
Reduce the chances of invalid or out-of-sequence function calls
We discussed the first benefit in the previous sections. In this section weâll focus on the second benefit. When a single context is used, it may be hard to keep the user from making an invalid sequence of calls. Letâs take a look at an example that exposes this issue and find a solution using multiple contexts.
Suppose weâre designing a register and want to implement an add facility. To introduce fluency, we may design an add() and an and() function, like so:
context/ambiguous.kts
â âobjectâ register {
â âvarâ total = 0
â
â âinfixâ âfunâ âaddâ(op1: Int): register {
â total += op1
â âreturnâ register
â }
â
â âinfixâ âfunâ âandâ(op2: Int) {
â println(â"adding $op2 to $total"â)
â total += op2
â }
â }
The benefit of this design is the functions may be used fluently, like so:
context/ambiguous.kts
â register add 4 and 3
Unfortunately, that design has a negative consequence. The design may not prevent a user from inadvertently making a few calls that may not make sense. For example, a user may make these unintended calls:
context/ambiguous.kts
â register and 3 add 4 â//ERRORâ
â register and 3 and 4 â//ERRORâ
â register add 3 add 4 â//oopsâ
A good design should enable ease of use and at the same time prevent users from inadvertently falling into traps. Ideally, an unintended or non-sensible use should result in an error instead of quietly misbehaving. Letâs examine how our design fared for catching these kinds of errors.
It turns out that the first call, invocation of and followed by add, thankfully results in a compilation error. The reason for this error is the result of and() being a Unit and having no add() function on it. Yay.
The second call also turned out to be an errorâkudosâbecause and() returns Unit, which doesnât have an and() function.
The last call, unfortunately, will execute without any error and produce an unexpected behavior. We should design in a way that such calls fail fast at compilation time. Letâs rework the design to achieve this goal.
In our modified design, weâll introduce two separate contexts, one for the add() function and the other for the and() function.
context/register.kts
â âobjectâ register {
â âinfixâ âfunâ âaddâ(op1: Int): AndOp {
â âreturnâ AndOp(op1)
â }
â
â âclassâ AndOp(âvalâ total: Int) {
â âinfixâ âfunâ âandâ(op2: Int) {
â println(â"adding $op2 to $total"â)
â }
â }
â }
Since only the add() function is present on register, we canât call the function and() directly on it anymore. Also, since add() returns AndOp, which doesnât have an add() function, we canât make another call to add() on the result of a call to add(). The following syntax is still valid, as weâd like it to be:
context/register.kts
â register add 4 and 3
However, all three of the following will fail quicklyâillustrating how splitting the context helps to deal with errors more reliably.
Download
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.
Ada | Ajax |
Assembly Language Programming | Borland Delphi |
C & C++ | C# |
CSS | Compiler Design |
Compilers | DHTML |
Debugging | Delphi |
Fortran | Java |
Lisp | Perl |
Prolog | Python |
RPG | Ruby |
Swift | Visual Basic |
XHTML | XML |
XSL |
Hello! Python by Anthony Briggs(9351)
OCA Java SE 8 Programmer I Certification Guide by Mala Gupta(9322)
The Mikado Method by Ola Ellnestam Daniel Brolund(9288)
Algorithms of the Intelligent Web by Haralambos Marmanis;Dmitry Babenko(7836)
Sass and Compass in Action by Wynn Netherland Nathan Weizenbaum Chris Eppstein Brandon Mathis(7385)
Grails in Action by Glen Smith Peter Ledbrook(7286)
Test-Driven iOS Development with Swift 4 by Dominik Hauser(7264)
The Well-Grounded Java Developer by Benjamin J. Evans Martijn Verburg(7096)
Secrets of the JavaScript Ninja by John Resig Bear Bibeault(5933)
Kotlin in Action by Dmitry Jemerov(4617)
Hands-On Full-Stack Web Development with GraphQL and React by Sebastian Grebe(3776)
Functional Programming in JavaScript by Mantyla Dan(3712)
Learning Java by Patrick Niemeyer & Daniel Leuck(2861)
Learning React: Functional Web Development with React and Redux by Banks Alex & Porcello Eve(2821)
Mastering Python for Finance by Weiming James Ma;(2786)
Mastering Java 9 by Dr. Edward Lavieri(2565)
Architecting Modern Java EE Applications: Designing lightweight, business-oriented enterprise applications in the age of cloud, containers, and Java EE 8 by Daschner Sebastian(2547)
Learning Concurrency in Python by Elliot Forbes(2540)
WordPress Plugin Development Cookbook by Yannick Lefebvre(2523)