Slices in Groovy

import groovy.transform.CompileStatic

@CompileStatic
class Slices {
    static void main(String[] args) {
        // Unlike arrays, lists in Groovy are dynamically sized.
        // An uninitialized list is empty and has length 0.
        def s = []
        println "uninit: $s ${s == null} ${s.size() == 0}"

        // To create a list with non-zero length, we can use a list literal
        // or the `Collections.nCopies` method.
        s = ['', '', '']
        println "emp: $s len: ${s.size()} cap: ${s.size()}"

        // We can set and get just like with arrays.
        s[0] = 'a'
        s[1] = 'b'
        s[2] = 'c'
        println "set: $s"
        println "get: ${s[2]}"

        // `size()` returns the length of the list as expected.
        println "len: ${s.size()}"

        // In addition to these basic operations, lists support
        // several more that make them richer than arrays.
        // One is the `addAll` method, which adds one or more elements.
        s.addAll(['d', 'e', 'f'])
        println "add: $s"

        // Lists can also be copied. Here we create a new list
        // and copy into it from `s`.
        def c = s.collect()
        println "cpy: $c"

        // Lists support a "slice" operator with the syntax
        // list[start..end]. For example, this gets a slice
        // of the elements s[2], s[3], and s[4].
        def l = s[2..4]
        println "sl1: $l"

        // This slices up to (but excluding) s[5].
        l = s[0..<5]
        println "sl2: $l"

        // And this slices up from (and including) s[2].
        l = s[2..-1]
        println "sl3: $l"

        // We can declare and initialize a variable for list
        // in a single line as well.
        def t = ['g', 'h', 'i']
        println "dcl: $t"

        // Groovy has built-in methods for list comparison.
        def t2 = ['g', 'h', 'i']
        if (t == t2) {
            println "t == t2"
        }

        // Lists can be composed into multi-dimensional data
        // structures. The length of the inner lists can
        // vary, unlike with multi-dimensional arrays.
        def twoD = []
        3.times { i ->
            def innerLen = i + 1
            twoD[i] = []
            innerLen.times { j ->
                twoD[i][j] = i + j
            }
        }
        println "2d: $twoD"
    }
}

This Groovy code demonstrates concepts similar to Go’s slices using Groovy’s dynamic lists. Here’s a breakdown of the key differences and similarities:

  1. Groovy uses dynamic lists instead of slices. These lists can grow and shrink dynamically.

  2. There’s no need to explicitly import a package for basic list operations in Groovy.

  3. The make function in Go is replaced by list literals or Collections.nCopies in Groovy.

  4. Groovy’s addAll method is used instead of Go’s append.

  5. Groovy uses the collect() method to create a shallow copy of a list, similar to Go’s copy.

  6. Groovy’s range operator (.. or ..<) is used for slicing, which is similar to Go’s slice syntax.

  7. Groovy has built-in equality comparison for lists, so we don’t need a separate utility function.

  8. Multi-dimensional lists in Groovy work similarly to multi-dimensional slices in Go.

To run this Groovy script, save it as Slices.groovy and execute it using the groovy command:

$ groovy Slices.groovy

This will output the results of the various list operations, demonstrating how Groovy’s lists can be used in ways similar to Go’s slices.