{{{ #!python class Example def main is shared pass def bill(customers as Customer*) for c in customers c.billIfNeeded def foo(ints as int*) t = for i in ints where i > 0 print t def bar(ints as int*) t = List(t) t.sort t.reverse print t }}} * The general form of a stream type is "foo*" where "foo" is the element type. * The "*" suffix can be thought of as "zero or more". * The type "foo*" can be read as "foo stream". * Streams can be applied to both primitive and complex types such as "int*" and "Shape*". * Streams are portable between backends, whereas .NET's IEnumerable and JVM's Iterable are not. * Streams are two-way compatible with IEnumerable/Iterable: * Streams can be used whereever a compatible IEnumerable/Iterable is expected. * An IEnumerable/Iterable can be used whereever a compatible stream type is expected. * The term "compatible" means the same inner type: int* is compatible with IEnumerable/Iterable, but not IEnumerable/Iterable * However, compatibility does not mean that you can use the methods of IEnumerable or Iterable, since these vary between platforms. * Streams are an abstract type, so you cannot create them directly with a call on the type such as `int*()`. Instead, use a concrete class such as `List` or `yield` results out of a method. * Streams are defaulted to be empty rather than nil, so you don't have to guard their usage with an "if" statement. You can loop through them immediately. * Portability and readability are the main motivations for having streams in the Cobra language. * See also: [http://cobra-language.com/forums/viewtopic.php?f=4&t=216 "Streams" discussion], TypesOverview