A DSL, Domain Specific Language (DSL), is a programming Language that gives developers the ability to write code that appears to be detached from its original syntax structure to build a proprietary syntax structure.

In Kotlin, the way DSLS are implemented is not fixed. The main learning goal here is to implement DSLS in the form of higher-order functions, which is the most common way DSLS are implemented in Kotlin.

On Android, Gradle is a Groovy-based build tool, so when we add dependencies to build. Gradle, we write the DSL functionality provided by Groovy. The following uses Kotlin’s DSL to implement a similar syntax:

Example (Kotlin) :

fun main(a) {
    / / sample 1
    // Get all added dependencies by returning the value
    val libraries = dependencies {
        implementation("Com. Squareup. Retrofit2: retrofit: 2.6.1." ")
        implementation("Com. Squareup. Retrofit2: converter - gson: 2.6.1." ")}for (lib in libraries) {
        println(lib)
    }

    // Print the result:
    / / com. Squareup. Retrofit2: retrofit: 2.6.1
    / / com. Squareup. Retrofit2: converter - gson: 2.6.1
}  

/** * Example 1: a syntax similar to build.gradle for adding dependent libraries */
class Dependency {
    /** * use collections to hold all dependent libraries */
    val libraries = ArrayList<String>()

    fun implementation(lib:String){
        libraries.add(lib)
    }
}

/** * Define a higher-order function * After DSL design, you can use the following syntax structure in your project: * dependencies {* implementation (" androidx recyclerview: recyclerview: 1.1.0 ") *} * /
fun dependencies(block: Dependency. () - >Unit):List<String>{
    val dependency = Dependency()
    dependency.block()
    return dependency.libraries
}
Copy the code

Example (Kotlin) : HTML code that dynamically generates a table

fun main(a) {
    // Example 2:
    val html = table {
        tr {
            td { "Apple" }
            td { "Grape" }
            td { "Orange" }
        }
        tr {
            td { "Pear" }
            td { "Banana" }
            td { "Watermelon"}}}Other syntax features of Kotlin can also be used in DSLS.
    val html1 = table {
        repeat(2) {
            tr {
                val fruits = listOf("Apple"."Grape"."Orange")
                for (fruit in fruits) {
                    td { fruit }
                }
            }
        }
    }

    println(html)
    println(html1)

    // Print the result:
    // <table>
    // 
    // Apple
    // Grape
    // Orange
    // 
    // 
    // Pear
    // Banana
    // Watermelon
    // 
    // </table>
    // <table>
    // 
    // Apple
    // Grape
    // Orange
    // 
    // 
    // Apple
    // Grape
    // Orange
    // 
    // </table>
}

/** * Example 2: HTML code for dynamically generating a table */
class Td {
    // the < TD > tag represents a cell that must contain content.
    var content = ""
    // Return an HTML code for the < TD > tag.
    // Use \n and \t escape characters for line breaks and indentation to make input more intuitive.
    // This is because browsers ignore line breaks and indentation when parsing HTML code.
    fun html(a) = "\n\t\t<td>$content</td>"
}

class Tr {
    // The  tag represents a table row, which can contain more than one < TD >
    private val children = ArrayList<Td>()
    // This function takes a function type argument defined in the Td class and returns a String.
    // When called, the Td object is created, its function type argument is called, its return value is obtained, and the value is assigned to the CONTENT field of the Td class.
    // Assign the return value of the Lambda expression passed in when td() is called to the Content field.
    fun td(block: Td. () - >String) {
        val td = Td()
        td.content = td.block()
        children.add(td)
    }
    // Return HTML code for a  tag. Each TR may contain multiple TDS, so loop through the collection to concatenate all TDS into tr.
    fun html(a): String {
        val builder = StringBuilder()
        builder.append("\n\t<tr>")
        for (childTag in children) {
            builder.append(childTag.html())
        }
        builder.append("\n\t</tr>")
        return builder.toString()
    }
}
class Table {
    private val children = ArrayList<Tr>()

    fun tr(block: Tr. () - >Unit) {
        val tr = Tr()
        tr.block()
        children.add(tr)
    }

    fun html(a): String {
        val builder = StringBuilder()
        builder.append("<table>")
        for (childTag in children) {
            builder.append(childTag.html())
        }
        builder.append("\n</table>")
        return  builder.toString()
    }
}

// Take a function type argument defined in the Table class. When Table () is called,
// A Table object is created and the function type argument is called so that the code in the Lambda expression can be executed,
// Finally call HTML () to get the generated HTML code, the final return value.
fun table(block: Table. () - >Unit): String {
    val table = Table()
    table.block()
    return table.html()
}
Copy the code

note

References:

Line 1 of code (Version 3)

Welcome to follow wechat official account:No reason also