Having fun with ooc

👋 This page was last updated ~12 years ago. Just so you know.

Unfortunately, the ooc language could have better documentation. In the meantime, I'd like to blog about about some features that might not be very well-known.

Nested functions

Here's a program that prints 1, 3, 5, 7, 9:

import structs/ArrayList

main: func {

  list := ArrayList<Int> new()

  addIfOdd := func (i: Int) {
    if (i % 2 != 0) list add(i)
  }

  for (i in 0..10) {
    addIfOdd(i)
  }

  list map(|i| i toString()) join(", ") println()

}

If you're doing something repeatedly, and it won't be too readable with a closure, you can simply declare a nested function! Note that we don't make use of the GNUC extension here, the ooc compiler unwraps it as a proper closure, with a context and all.

Filter, map, join, backslash line continuations

That program prints exactly the same thing, but it does it in fewer lines:

import structs/ArrayList

main: func {

  list := ArrayList<Int> new()
  for (i in 0..10) list add(i)

  list filter(|i| i % 2 != 0) \
       map(|i| i toString()) \
       join(", ") \
       println()

}

As in most languages, you can call the filter (only retain element if the condition is true) and map (create a new list with elements returned by the function) methods on lists.

join also works on List, which is why we have to map from Int to String before calling it.

Extending classes and covers

Always with the same output, this program is a bit more convoluted:

import structs/[ArrayList, List]

extend Range {
  list: func -> ArrayList<Int> {
    list := ArrayList<Int> new()
    for (i in min..max) list add(i)
    list
  }
}

extend List<Int> {
  filterEven: func -> List<T> {
    filter(|i| i as Int % 2 != 0)
  }

  println: func {
    map(|i| i as Int toString()) join(", ") println()
  }
}

main: func {
  (0..10) list() filterEven() println()
}

The point of this example is to show that even though ooc is a static language, and even if you use types defined in external libraries, you can add methods to it. They'll only be accessible from modules where you import the module containing the extends, and they aren't overloadable by subclasses, etc. etc.

They're basically syntactic sugar! Sweet, sweet syntactic sugar.

Note that in that example, we extend both a cover, ie. Range, and a generic class, ie. List<T>. As a reminder, covers are by-value, and they usually have a 1-1 mapping with underlying C types (e.g. Int, Float, Double are all covers), or they define a structure (like Range, in this case).

As you can see, extending a cover works quite well, but for generic classes, the compiler ignores the Int in extend List<Int>, so within filterEven and println we have to cast i to Int ourselves. Not very clean if you ask me, but it does work.

Conclusion

You've seen three ways to have fun with ooc. It doesn't stop there of course, I might continue blogging about fun features you can benefit from in your ooc programs.

Comment on /r/fasterthanlime

(JavaScript is required to see this. Or maybe my stuff broke)

Here's another article just for you:

I won free load testing

Long story short: a couple of my articles got really popular on a bunch of sites, and someone, somewhere, went "well, let's see how much traffic that smart-ass can handle", and suddenly I was on the receiving end of a couple DDoS attacks.

It really doesn't matter what the articles were about — the attack is certainly not representative of how folks on either side of any number of debates generally behave.