Droid2Notes

These are features that should be considered for Droid when the base language works.

For Each

It is more general to provide an iterator than to provide a map or each method - yet those methods are very convenient to have. This means that most container structures will end up implementing all three, which is really a waste of effort and code duplication. A for-each loop is familiar to most programmers, and it only needs that the data structure is Iterable . It can be generalized to cover filter and map, but first a simple example:

val list = ["hello", "world"]
for(s in list) {
    Console.writeLine(s)
}

This loops through the list and prints out each item. This common form of the for-each construct is highly geared towards side effect-ful programming. However, it could collect the results of evaluating it's body into a list and become map .

val list = ["hello", "world"]
val upperList = for(s in list) { s.toUpperCase() }
# Result: upperList == ["HELLO", "WORLD"]

This converts each of the strings in the list to upper case and returns the resulting list. Sometimes you need to exclude certain elements, for example, all numbers below some threshold. This is done through the where clause, that removes all elements for which it returns false.

val list = [7, 5, 9, 1, 4, 10, 4, 2]
val atLeastFive = for(n in list where n >= 5) { n }
# Result: atLeastFive == [7, 5, 9, 10]

Reflection

Doc Comments & Annotations

Annotations are a special kind of comment that can be acted upon at compile time. The most common use of these are documentation comments.

## This is a description.
## @param x the description of the @c{x} parameter
## @returns the description of the return value
class MySymbol(x: Int) {
    # Normal comment
}

Dependant Types

It's possible to eliminate bounds checking and avoid runtime indexing out of bounds exceptions by using a simple form of dependent types. If we write the type of an array of x elements of the type T as T*x , and the integer type {m | 0 <= m < j} is written j , we get:

index[n, k](array: Int*n, i: k): Int where k <= n { array(i) } 

In this example, we have an array that has n elements. We also have a variable i that is less than k . The where clause tells us that anything of the type k can index a list with n elements. Thus it is safe to index array by i without any bounds checks. Actually it could be shorter in this case:

index[n](array: Int*n, i: n): Int { array(i) } 

Object Persistence

Marshalling or serializing objects is useful to save objects for later runs of a program, or for sending data to other processes (possibly on other computers). One approach is to save any kind of object, but here I'll talk about serialization of JavaBean-like objects. That is, objects that have getters for all the fields that are to be persisted as well as either setters for them or a constructor that takes them in.

namespace my_pack

class Point(x: Int, y: Int)

Json.fromObject(Point(5, 8)).toString()
# Returns a string:
# {
#     "_type": "my_pack_Point",
#     "x": 5,
#     "y": 8
# }

This format might be friendly enough for people to write:

{
    "_type": "gui_Window",
    "text": "Hello, Persistence!"
    "container": {
        "_type": "gui_Panel",
        "components": [
            {
                "_type": "gui_Button"
                "id": "helloButton"
                "text": "Say Hello"
            }
        ]
    }
}

Regular Expression Patterns

Matching on strings are convenient, and it would fit well into the general pattern matching.

match(myString) {
    /[Hh]ello/ { Console.writeLine("Hello back") }
    /I[']m ([a-z]+$name)/ { Console.writeLine("Hello " ~ name) }
}

Dictionary Literals

val curent = HashMap([(1, "One"), (2, "Two"), (3, "Three")])
val sugar = [|1| "One" |2| "Two" |3| "Three"]

This would also allow a corresponding syntax for pattern matching on dictionaries.

match(myDictionary) {
    [|] { "An empty dictionary" }
    [|"x"| x |"y"| y] { "A dictionary with x => " ~ x ", y => " ~ y }
    [|"a"| a] @ r { "A dictionary with a => " ~ a ", and the rest of the map is " ~ r }
}

Key patterns that are not constants may be very expensive to search for (linear in the size of the map). This should probably be a syntax error.

Scripting

Files that only contains using statements + an expression. A lot of commonly used namespaces are imported by default and anything that can't get a static type automatically will be dynamically typed. This makes it easy to write small scripts that you need for some small task, like a batch script.