Skip to content

Boon Slice Notation

RichardHightower edited this page Feb 15, 2014 · 12 revisions

Boon Home | Boon Source | If you are new to boon, you might want to start here. Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!

Java Boon - Boon Slice Notation

Many languages have slice notation (Ruby, Groovy and Python). Boon adds this to Java.####

Boon has three slc operators: slc, slc (start only), and slcEnd.

With Boon you can slice strings, arrays (primitive and generic), lists, sets, tree sets, tree map's and more.

The boon slice operators works like Python/Ruby slice notation:

Ruby

    arr = [1, 2, 3, 4, 5, 6]
    arr[2]    #=> 3
    arr[-3]   #=> 4
    arr[2, 3] #=> [3, 4, 5]
    arr[1..4] #=> [2, 3, 4, 5]

Python

    string = "foo bar" 
    string [0:3]  #'foo'
    string [-3:7] #'bar'

What follows is derived from an excellent write up on Python's slice notation:

The basics of slice notations are as follows:

Python Slice Notation

           a[ index ]       # index of item
           a[ start : end ] # items start through end-1
           a[ start : ]     # items start through the rest of the array
           a[ : end ]       # items from the beginning through end-1
           a[ : ]           # a copy of the whole array

Java Slice Notation as follows using Boon:

            idx( index )         // index of item
            slc( a, start, end ) // items start through end-1
            slc( a, start )      // items start through the rest of the array
            slcEnd( a, end )     // items from the beginning through end-1
            copy( a )            // a copy of the whole array
  • slc stands for slice
  • idx stands for index
  • slcEnd stands for end slice.
  • copy stands for well, err, um copy of course

The key point to remember is that the end value represents the first value that is not in the selected slice. So, the difference between end and start is the number of elements selected.

The other feature is that start or end may be a negative number, which means it counts from the end of the array instead of the beginning. Thus:

Python slice notation with negative index

               a[ -1 ]    # last item in the array
               a[ -2: ]   # last two items in the array
               a[ :-2 ]   # everything except the last two items

Java negative index

               idx   ( a, -1)     # last item in the array
               slc   ( -2 )       # last two items in the array
               slcEnd( -2 )       # everything except the last two items

Python and Boon are kind to the programmer if there are fewer items than you ask for. Python does not allow you to go out of bounds, if you do it returns at worse an empty list. Boon follows this tradition, but provides an option to get exception for out of bounds. In Python and Boon, if you go to far, you get the length, if you try to go under 0 you get 0 (under 0 after calculation). Conversely, Ruby gives you a null pointer (Nil). Boon copies Python style as one of the goals of Boon is to avoid ever returning null (you get an exception, Option). (Boon has second operator called zlc which throws an out of bounds index exception, but most people should use slc.)

For example, if you ask for slcEnd(a, -2) (a[:-2]) and a only contains one element, you get an empty list instead of an error. Sometimes you would prefer the error, and with Boon you have that option.

More slicing

===

Here are some basic Java types, list, array, veggies, primitive char array, and a primitive byte array.

    //Boon works with lists, arrays, sets, maps, sorted maps, etc.
    List<String> fruitList;
    String [] fruitArray;
    Set<String> veggiesSet;
    char [] letters;
    byte [] bytes;
    NavigableMap <Integer, String> favoritesMap;
    Map<String, Integer> map;

    //In Java a TreeMap is a SortedMap and a NavigableMap by the way.

Boon comes with helper methods that allow you to easily create lists, sets, maps, concurrent maps, sorted maps, sorted sets, etc. The helper methods are safeList, list, set, sortedSet, safeSet, safeSortedSet, etc. The idea is to make Java feel more like list and maps are built in types.

    veggiesSet  =  set( "salad", "broccoli", "spinach");
    fruitList   =  list( "apple", "oranges", "pineapple");
    fruitArray  =  array( "apple", "oranges", "pineapple");
    letters     =  array( 'a', 'b', 'c');
    bytes       =  array( new byte[]{0x1, 0x2, 0x3, 0x4});

There are even methods to create maps and sorted maps called map, sortedMap, safeMap (concurrent) and sortedSafeMap (concurrent). These were mainly created because Java does not have literals for lists, maps, etc.

     favoritesMap = sortedMap(
            2, "pineapple",
            1, "oranges",
            3, "apple"
     );


     map =    map (
        "pineapple",  2,
        "oranges",    1,
        "apple",      3
     );

You can index maps, lists, arrays, etc. using the idx operator.

     //Using idx to access a value.

     assert idx( veggiesSet, "b").equals("broccoli");

     assert idx( fruitList, 1 ).equals("oranges");

     assert idx( fruitArray, 1 ).equals("oranges");

     assert idx( letters, 1 ) == 'b';

     assert idx( bytes, 1 )      == 0x2;

     assert idx( favoritesMap, 2 ).equals("pineapple");

     assert idx( map, "pineapple" )  == 2;

The idx operators works with negative indexes as well.

               //Negative indexes

                assert idx( fruitList, -2 ).equals("oranges");

                assert idx( fruitArray, -2 ).equals("oranges");

                assert idx( letters, -2 ) == 'b';

                assert idx( bytes, -3 )   == 0x2;

Ruby, Groovy and Python have this feature. Now you can use this in Java as well. The Java version (Boon) works with primitive arrays so you get no auto-boxing.

Something that Ruby and Python don't have is slice notation for SortedSets and SortedMaps.

You can use slice notation to search sorted maps and sets in Java

Slice notations works with sorted maps and sorted sets.

Here is an example that puts a few concepts together.

                set = sortedSet("apple", "kiwi", "oranges", "pears", "pineapple")

                slcEnd( set, "o" )      //returns ("oranges", "pears", "pineapple")
                slc( set, "ap", "o" )   //returns ("apple", "kiwi"),
                slc( set, "o" )         //returns ("apple", "kiwi")

You are really doing with slicing of sorted maps and sorted sets is a between query of sorts.

What item comes after "pi"?

                after(set, "pi") //pineapple

And before pineapple?

                before(set, "pi")

Ok, let go through it step by step....

        NavigableSet<String> set =
                sortedSet("apple", "kiwi", "oranges", "pears", "pineapple");

        assertEquals(

                "oranges", idx(set, "ora")

        );

TreeSet implements NavigableSet and SortedSet.

We can look up the first fruit in the set that starts with 'o' using:

idx(set, "o")

Here is is with the set of fruit we created earlier (set is a TreeSet with "apple", "kiwi", "oranges", "pears", "pineapple" in it).

        assertEquals(

                "oranges", idx(set, "o")

        );

We found oranges!

Here it is again but this time we are searching for fruits that start with "p", i.e., idx(set, "p").

        assertEquals(

                "pears",
                idx(set, "p")

        );

Yeah! We found pears!

How about fruits that start with a "pi" like "pineapple" - idx(set, "pi")

        assertEquals(

                "pineapple",
                idx(set, "pi")

        );

You could also ask for the item that is after another item. What is after "pi"?

after(set, "pi")

        assertEquals(

                "pineapple",
                after(set, "pi")

        );

The "pineapple" is after the item "pi". after and idx are the same by the way. So why did I add an after? So I can have a before!!! :)

What if you want to know what is before "pi"?

before(set, "pi")

        assertEquals(

                "pears",
                before(set, "pi")

        );

How about all fruits that are between "ap" and "o"? As I promised there is slice notation!

slc(set, "ap", "o")

        assertEquals(

                sortedSet("apple", "kiwi"),
                slc(set, "ap", "o")

        );

How about all fruits after "o"?

slc(set, "o")

        assertEquals(

                sortedSet("apple", "kiwi"),
                slc(set, "o")

        );

So all fruits after "o" is "apple" and "kiwi".

How about all fruits up to "o"? (slcEnd read it as I am slicing off the end.)

slcEnd(set, "o")

        assertEquals(

                sortedSet("oranges", "pears", "pineapple"),
                slcEnd(set, "o")
        );

So all fruits up to and including "o" are "oranges", "pears" and "pineapple".

Safe slicing for list like things

These operators throw an exception if the index is out of bounds:

Java Slice Notation as follows using Boon:

            ix( index )         // index of item
            zlc( a, start, end ) // items start through end-1
            zlc( a, start )      // items start through the rest of the array
            zlcEnd( a, end )     // items from the beginning through end-1
  • zlc stands for zero tolerance slice
  • ix stands for zero tolerance index
  • zlcEnd stands for zero tolerance end slice.
  • copy stands for well, err, um copy of course

Works with Primitives too so no auto-boxing

Indexing primitives

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d');

    assertEquals(
            'a',
            idx(letters, 0)
    );


    assertEquals(
            'd',
            idx(letters, -1)
    );


    assertEquals(
            'd',
            idx(letters, letters.length - 1)
    );

    idx(letters, 1, (byte)'z');

    assertEquals(
            (byte)'z',
            idx(letters, 1)
    );

The method len and idx are universal operators and they work on lists, arrays, sets, maps, etc.

  • len give me the length of an array-like, list-like, map-like, thing.
  • idx give me the item at the location of an "index" in the array-like, list-like, map-like, thing.

Conclusion:

Slice notation has always been a real boon to me when I used it with Python and Groovy. I plan to use slice notation with Java for years to come. I hope you enjoy Boon Slice Notation.

Thoughts

Thoughts? Write me at richard high tower AT g mail dot c-o-m (Rick Hightower).

Further Reading:

If you are new to boon start here:

Why Boon?

Easily read in files into lines or a giant string with one method call. Works with files, URLs, class-path, etc. Boon IO support will surprise you how easy it is. Boon has Slice notation for dealing with Strings, Lists, primitive arrays, Tree Maps, etc. If you are from Groovy land, Ruby land, Python land, or whatever land, and you have to use Java then Boon might give you some relief from API bloat. If you are like me, and you like to use Java, then Boon is for you too. Boon lets Java be Java, but adds the missing productive APIs from Python, Ruby, and Groovy. Boon may not be Ruby or Groovy, but its a real Boon to Java development.

Core Boon Philosophy

Core Boon will never have any dependencies. It will always be able to run as a single jar. This is not just NIH, but it is partly. My view of what Java needs is more inline with what Python, Ruby and Groovy provide. Boon is an addition on top of the JVM to make up the difference between the harder to use APIs that come with Java and the types of utilities that are built into Ruby, Python, PHP, Groovy etc. Boon is a Java centric view of those libs. The vision of Boon and the current implementation is really far apart.

===

Contact Info

blog|[twitter](https://twitter.com/RickHigh|[infoq]http://www.infoq.com/author/Rick-Hightower|[stackoverflow](http://stackoverflow.com/users/2876739/rickhigh)|[java lobby](http://java.dzone.com/users/rhightower)|Other | richard high tower AT g mail dot c-o-m (Rick Hightower)|work|cloud|nosql

Clone this wiki locally