Sunday, December 7, 2014

Arrays and Indexers in Xtend



Today's post is about Arrays and Indexers in Xtend. Here below you will find a very easy to follow program, that demonstrate arrays and indexer, by implementing some simple tasks that will make you grasp the idea of those 2 features real quick. The main goal of this post, is not really teaching arrays because, come on, you probably already know "all" about them, in fact, it is more to show you how you do that in Xtend, in this case, compared to all other 22 languages on future posts, which essentially, is the real aim behind this blog.

By the way, if you missed my (not so) recent post (anymore), "New Series - Arrays and Indexers", check it out. It has more details about the following program, and a bunch of definitions for the concepts used on this, and the following, posts. Or you can check my previous posts about arrays in Java just to compare.

I encourage you to copy the code below and try it yourself, normally, all programs you find in this blog are source code complete, just paste it on your IDE and run it.

There is room for improvement of the code, using generics is one example, but Generics, Collections, lambdas, etc. will have their own "series" of posts.


"Xtend does not support Multidimensional Arrays out-of-the box. You can add support by declaring a Java class like this : " by Sven Efftinge - Google Groups: Xtend Programming Language
// ArrayLiterals2.java
package xtendarrays;

import org.eclipse.xtext.xbase.lib.Inline;

public class ArrayLiterals2 {
 @Inline("new int[$1][$2]")
 public static int[][] new2DIntArrayOfSize(int outerSize, int innerSize) {
  throw new UnsupportedOperationException();
 }
}

"@Inline tells the compiler to replace any calls to the annotated method with the to-be-inlined Java expression (the 'value' template). Note that the @Inlined is not stable API (flagged as @Beta) and will likely be removed once Xtend has support for more powerful method-macros." by Sven Efftinge - Google Groups: Xtend Programming Language
// XtendArrays.xtend
package xtendarrays

import java.util.Random
import java.lang.StringBuffer
import static extension xtendarrays.ArrayLiterals2.*

class XtendArrays {
 def static void main(String[] args) {
  // Single-dimensional Array(s)  
        printTitle("Reverse Array Elements")
        
        // Declare and Initialize Array of Chars  
        val char[] letters = newCharArrayOfSize(5)
        letters.set(0, 'A')
        letters.set(1, 'E')
        letters.set(2, 'I')
        letters.set(3, 'O')
        letters.set(4, 'U')
        
        printArrayChar(letters)  
        val char[] inverse_letters = reverseChar(letters)  
        printArrayChar(inverse_letters)
        
        printTitle("Sort Integer Array Elements")  

        // Declare and Initialize Array of Integers   
        val int[] numbers = #[10, 8, 3, 1, 5]
        printArrayInt(numbers)
        val int[] ordered_numbers = bubbleSortInt(numbers)
        printArrayInt(ordered_numbers)

        printTitle("Sort String Array Elements")  

        // Declare and Initialize and Array of Strings  
        val String[] names = #[                       
                "Damian",   
                "Rogelio",  
                "Carlos",   
                "Luis",                       
                "Daniel"  
            ]
        printArrayString(names)
        val String[] ordered_names = bubbleSortString(names)
        printArrayString(ordered_names)

        // Multi-dimensional Array (Matrix row,column)  

        printTitle("Transpose Matrix")

        /* Matrix row=2,col=3 
         * A =  [6  4 24] 
         *      [1 -9  8] 
        */  
        val int[][] matrix = #[#[6, 4, 24],   
                               #[1, -9, 8]]  
        printMatrix(matrix)
        val int[][] transposed_matrix = transposeMatrix(matrix)  
        printMatrix(transposed_matrix)

        // Jagged Array (Array-of-Arrays)  

        printTitle("Upper Case Random Array & Graph Number of Elements")
        
        /*              
         * Creating an array of string arrays using the String.Split method 
         * instead of initializing it manually as follows: 
         *  
         * val text = #[  
         *      #[ "word1", "word2", "wordN" ],  
         *      #[ "word1", "word2", "wordM" ],  
         *      ... 
         *      ] 
         *  
         * Text extract from: "El ingenioso hidalgo don Quijote de la Mancha" 
         *  
         */  
        val String[][] text = #[   
        "Hoy es el día más hermoso de nuestra vida, querido Sancho;".split(' '),  
        "los obstáculos más grandes, nuestras propias indecisiones;".split(' '),  
        "nuestro enemigo más fuerte, miedo al poderoso y nosotros mismos;".split(' '),  
        "la cosa más fácil, equivocarnos;".split(' '),  
        "la más destructiva, la mentira y el egoísmo;".split(' '),  
        "la peor derrota, el desaliento;".split(' '),  
        "los defectos más peligrosos, la soberbia y el rencor;".split(' '),  
        "las sensaciones más gratas, la buena conciencia...".split(' ')   
        ]       
        printJaggedArray(text)
        upperCaseRandomArray(text)  
        printJaggedArray(text)
        graphJaggedArray(text)  

        // Array Exceptions  

        printTitle("Common Array Exceptions")  
        
        printCommonArrayExceptions(null)  
        printCommonArrayExceptions(text)  

        // Accessing Class Array Elements through Indexer  

        printTitle("Alphabets")
        
        val vowels = new Alphabet(5)
        vowels.set(0, 'a')  
        vowels.set(1, 'e')  
        vowels.set(2, 'i')  
        vowels.set(3, 'o')  
        vowels.set(4, 'u')
        
        println(String.format("\nVowels = {%s}",  #[vowels.get(0), 
         vowels.get(1), vowels.get(2), vowels.get(3), vowels.get(4)].join(',')))
         
        var en = new Alphabet("abcdefghijklmnopqrstuvwxyz")
        println('''English Alphabet = «en.toString»''') 
        
        println('''Alphabet Extract en[9..19] = «new Alphabet(en.slice(9, 10))»''')   
     
      var word1 = #[en.get(6), en.get(14), en.get(14), en.get(3)].join('')
      var word2 = #[en.get(1), en.get(24), en.get(4)].join('')
      var word3 = #[en.get(4), en.get(21), en.get(4), en.get(17), 
           en.get(24), en.get(14), en.get(13), en.get(4)].join('')
  
      println
      println('''«word1» «word2», «word3»!''')                      
 }
 
 def static char[] reverseChar(char[] arr) {  
        val char[] reversed = newCharArrayOfSize(arr.length)  
        for (var i = 0, var j = arr.length - 1; j >= 0; i++, j--) {
            reversed.set(i, arr.get(j))  
        }
        return reversed
    }  
    
    def static int[] bubbleSortInt(int[] arr) {  
        var int swap = 0  
        for (var i = arr.length - 1; i > 0; i--) {  
            for (var j = 0; j < i; j++) {  
                if (arr.get(j) > arr.get(j + 1)) {  
                    swap = arr.get(j)  
                    arr.set(j, arr.get(j + 1))
                    arr.set(j + 1, swap)
                }  
            }  
        }  
  return arr;  
    }  
    
    def static String[] bubbleSortString(String[] arr) {  
        var String swap = ""
        for (var i = arr.length - 1; i > 0; i--) {  
            for (var j = 0; j < i; j++) {                  
                if (arr.get(j).charAt(0) > arr.get(j + 1).charAt(0)) {  
                    swap = arr.get(j)  
                    arr.set(j, arr.get(j + 1))  
                    arr.set(j + 1, swap)
                }  
            }  
        }  
        return arr;  
    }
    
    def static int[][] transposeMatrix(int[][] m) {  
        /* Transposing a Matrix 2,3  
         *  
         * A =  [6  4 24]T [ 6  1]  
         *      [1 -9  8]  [ 4 -9] 
         *                 [24  8] 
        */  
        val int[][] transposed = new2DIntArrayOfSize(m.get(0).length, m.length)   
        for (var i = 0; i < m.length; i++) {  
            for (var j = 0; j < m.get(0).length; j++) {  
                transposed.get(j).set(i, m.get(i).get(j))  
            }  
        }  
        return transposed
    }    
    
    def static void upperCaseRandomArray(String[][] arr) {  
        val r = new Random
        var int i = r.nextInt(arr.length)
        for (var j = 0; j < arr.get(i).length; j++) {
            arr.get(i).set(j, arr.get(i).get(j).toUpperCase)
        }
    }
 
 def static printArrayChar(char[] arr) {
  println
  println('''Print Array Content «arr.class.name» «arr.class.name.class.name»[«arr.length»]''')
  
     for(var i = 0; i < arr.length; i++) {
      println(String::format(" array [%2d] = %2s", i, arr.get(i)))
     }
 }
 
 def static printArrayInt(int[] arr) {
  println
  println('''Print Array Content «arr.class.name» «arr.class.name.class.name»[«arr.length»]''')
  
     for(var i = 0; i < arr.length; i++) {
      println(String::format(" array [%2d] = %2s", i, arr.get(i)))
     }
 }
 
 def static printArrayString(String[] arr) {
  println
  println('''Print Array Content «arr.class.name» «arr.class.name.class.name»[«arr.length»]''')
  
     for(var i = 0; i < arr.length; i++) {
      println(String::format(" array [%2d] = %2s", i, arr.get(i)))
     }
 }
 
 def static void printMatrix(int[][] m) {  
        println(String.format("\nPrint Matrix Content %s[%d,%d]\n",  
            m.class.name.class.name,
            m.length,  
            m.get(0).length))

        for (var i = 0; i < m.length; i++) { 
            for (var j = 0; j < m.get(0).length; j++) {
                println(String.format(" array [%2d,%2d] = %2d", i, j, m.get(i).get(j)))
            }
        }    
 }
 
 def static void graphJaggedArray(String[][] arr) {  
        /* When using Arrays, we can use foreach instead of for:  
         *  
         * for (var i = 0; i < arr.length; i++) 
         *   for (var j = 0; j < arr.length; j++)                 
         *  
        */  
        println("\nPrint Text Content " + arr.class.name.class.name)
        var lineCount = 1
        for(s : arr) {  
            print(String.format("Line%2s|", lineCount))
            for(w : s) {  
                print(String.format("%3s", '*'))
            }  
            print(String.format(" (%d)\n", s.length))  
            lineCount++
        }  
    }  
    
    def static void printJaggedArray(String[][] arr) {  
        var StringBuffer line
        println("\nPrint Jagged Array Content " + arr.class.name + 
         " " + arr.class.name.class.name + "[]") 
        for (var i = 0; i < arr.length; i++)  {  
            line = new StringBuffer 
            for (var j = 0; j < arr.get(i).length; j++) {  
                line.append(" ").append(arr.get(i).get(j)) 
            }
            if (line.toString.equals(line.toString.toUpperCase)) {
                line.append(" <-- [UPPERCASED]")
            }
            println(line)
        }  
    }  
    
    def static void printCommonArrayExceptions(String[][] arr) {  
        try {  
            arr.get(100).set(100, "hola") 
        }  
        catch (NullPointerException ex) { 
         println(String.format("\nException: \n%s\n%s\n", 
                    ex.class.name, ex.message))
        }
        catch (ArrayIndexOutOfBoundsException ex) {  
            println(String.format("\nException: \n%s\n%s\n", 
                    ex.class.name, ex.message))  
        }  
    }  
 
    def static printTitle(String message) {
        println
        println("======================================================")
        println(message)
        println("======================================================")
    }
}


class Alphabet {
 // Array Field
    var char[] letters
    
    // Indexer Getter/Setter 
    def char get(int index) {
     return letters.get(index)
    }
    def void set(int index, char value) {
     this.letters.set(index, value.toString.toUpperCase.charAt(0))
    }
    
    // Getter
    def int length() {  
        return this.letters.length  
    }  
    
    // Constructors  
    new(int size) {  
        this.letters = newCharArrayOfSize(size)  
    }  

    new(String list) {  
        this.letters = list.toUpperCase.toCharArray
    }  

    new(char[] list) {  
        this.letters = list  
    }  
    
    // Overridden Method  
    override String toString() {  
        return this.letters.join(",")
    } 
    
    // Method  
    def char[] slice(int start, int length) {  
        val char[] result = newCharArrayOfSize(length)  
        for (var i = 0, var j = start; i < length; i++, j++) {  
            result.set(i, this.letters.get(j))  
        }  
        return result
    }  
}


The output:








Voilà, that's it. Next post in the following days.

3 comments:

  1. While I don’t know Kotlin at all, my brief glance at it suggests that it is at least superficially similar to Scala, which I do know, although Kotlin appears to lack most of Scala’s functional programming character, most significantly its capability to do static type inference.

    While a familiarity with the Java Virtual Machine ecosystem and the Java standard runtime libraries will be a requirement to writing substantial applications in Kotlin, just as it is when writing applications in Scala, these are things that one can learn as part of learning Kotlin.

    java training in chennai

    ReplyDelete
  2. Lol, he is talking about Xtend Lang

    ReplyDelete