
-----------------------------------
wtd
Tue Jun 05, 2007 11:43 am

[Scala] A little code
-----------------------------------
// A simple expression

5 * 2

// A character

'h'

// A string

"Hello"

// An Object object

new Object

// A constant, inferred typing

val message = "Hello"

// A variable, inferred typing

var message = "hello"

// A variable, explicit typing

var message: String = "hello"

// Assigning a new value to that variable

message = "Yo"

// A very simply method that returns a String (inferred)

def foo = "bar"

// The same thing, explicitly typed return type

def foo: String = "bar"

// The same thing, with parentheses

def foo(): String = "bar"

// Method with a parameter

def timesTwo(n: Int) = n * 2

// Conditional expression

if (foo == 2) 
   42
else
   27

// With braces

if (foo == 2) {
   42
}
else {
   27
}

// Conditionally assign value to variable using conditional as a statement

var foo: Int = 0

if (bar == 36) 
   foo = 42
else
   foo = 27

// Do the same using conditional as expression

var foo: Int = if (bar == 36) 42 else 27

// Do the same, but make foo constant

val foo: Int = if (bar == 36) 42 else 27

// And use type inferencing

val foo = if (bar == 36) 42 else 27

// Now, a method that uses a conditional expression

def foo(bar: Boolean) = if (bar) 42 else 27

// A method that calls an object's method

def len(s: String) = s.length

// The same, with postfix method syntax

def len(s: String) = s length

// A class that extends Object, but does nothing additional

class Foo

// Override the toString method from Object

class Foo {
   override def toString = "A Foo object"
}

// A singleton object, with the toString method overriden

object Bar {
   override def toString = "A Bar object"
}

// Assigning a Foo object to a constant 

val f = new Foo

// Assigning its String representation to a constant

val s = f toString

// Skipping the middle-man

val s = new Foo toString

// With parens to disambiguate the precedence rules

val s = (new Foo) toString

// Another class, with a constructor, and two constant fields

class MyRange(val start: Int, val end: Int)

// A MyRange object

val r = new MyRange(1, 4)

// Assigning its start and end to constants

val s = r.start
val e = r.end

// Using postfix syntax

val s = r start
val e = r end

// Giving it a toString method

class MyRange(val start: Int, val end: Int) {
   override def toString = start + ".." + end
}

// Extending the class

class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
   override def toString = start + "..." + end
}

// We need a way to iterate over a range.  Let's create a simple Iterator trait.

trait IntIterator {
   def start
   def current: Int
   def atEnd: Boolean
   def advance
}

// A class which implements this

class MyRangeIterator(val target: MyRange) extends IntIterator {
   private var _current = target.start
   def start { _current = target.start }
   def current = _current
   def atEnd = current > target.end
   def advance { _current += 1 }
}

// A method for MyRange which gets us one of these

class MyRange(val start: Int, val end: Int) {
   override def toString = start + ".." + end
   def iterator = new MyRangeIterator(this)
}

// We can use an anonymous class

class MyRange(val start: Int, val end: Int) {
   override def toString = start + ".." + end
   def iterator = new IntIterator {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current > end
      def advance { _current = _current + 1 }
   }
}

// Now we can loop over and print the range using the Console object's println method

val r = new MyRange(1, 4)
val i = r.iterator

while (!i.atEnd) {
   Console.println(i)
   i.advance
} 

// The !i.atEnd bit looks ugly.  Let's provide a hasMore method with a default implementation.

trait IntIterator {
   def start
   def current: Int
   def atEnd: Boolean
   def hasMore = !atEnd
   def advance
}

// Now, to rewrite the loop.

val r = new MyRange(1, 4)
val i = r.iterator

while (i.hasMore) {
   Console.println(i)
   i.advance
} 

// Now, that IntIterator trait might be better as a generic trait.

trait Iterator[A] {
   def start
   def current: A
   def atEnd: Boolean
   def hasMore = !atEnd
   def advance
}

// And now...

class MyRange(val start: Int, val end: Int) {
   override def toString = start + ".." + end
   def iterator = new Iterator[Int] {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current > end
      def advance { _current = _current + 1 }
   }
}

// But MyRange should probably extend some kind of trait to indicate that it has an iterator method.

trait Iterable[A] {
   def iterator: Iterator[A]
}

// ...

class MyRange(val start: Int, val end: Int) extends Iterable[Int] {
   override def toString = start + ".." + end
   def iterator = new Iterator[Int] {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current > end
      def advance { _current = _current + 1 }
   }
}

// A blast from the past.

class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
   override def toString = start + "..." + end
   override def iterator = new Iterator[Int] {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current >= end
      def advance { _current = _current + 1 }
   }
}

// All together now!

trait Iterator[A] {
   def start
   def current: A
   def atEnd: Boolean
   def hasMore = !atEnd
   def advance
}

trait Iterable[A] {
   def iterator: Iterator[A]
}

class MyRange(val start: Int, val end: Int) extends Iterable[Int] {
   override def toString = start + ".." + end
   def iterator = new Iterator[Int] {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current > end
      def advance { _current = _current + 1 }
   }
}

class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
   override def toString = start + "..." + end
   override def iterator = new Iterator[Int] {
      private var _current = start
      def reset { _current = start }
      def current = _current
      def atEnd = current >= end
      def advance { _current = _current + 1 }
   }
}

-----------------------------------
wtd
Wed Jun 06, 2007 12:55 pm

Re: [Scala] A little code
-----------------------------------
// Let's add a method to Iterable.  It takes, as a paremeter, a function.

trait Iterable[A] {
   def iterator: Iterator[A]
   def doForAll(f: A => Unit) { 
      val i = iterator
      while (i.hasMore) {
         f(i.current)
         i.advance
      }
   }
}

// Now, let's rewrite the loop.

val r = new MyRange(1, 4)
r.doForAll((x: Int) => Console.println(x))

// Or perhaps...

val r = new MyRange(1, 4)
r.doForAll { case x => Console.println(x) }

// Or using special syntax for binary methods, we can get rid of all of the periods.

new MyRange(1, 4) doForAll { case x => Console println x }

-----------------------------------
richcash
Wed Jun 06, 2007 10:03 pm

Re: [Scala] A little code
-----------------------------------
Great introduction! :)

I like the keywords override and trait.

// Or using special syntax for binary methods, we can get rid of all of the periods. 

new MyRange(1, 4) doForAll { case x => Console println x }
Wow, that is cool. But isn't doForAll a unary method, not a binary method? :?

-----------------------------------
wtd
Wed Jun 06, 2007 11:12 pm

RE:[Scala] A little code
-----------------------------------
I suppose you might classify it that way as well.  Binary in this case because it has both a receiver and an argument.

-----------------------------------
richcash
Thu Jun 07, 2007 12:58 am

Re: [Scala] A little code
-----------------------------------

I suppose you might classify it that way as well.  Binary in this case because it has both a receiver and an argument.

Oh, now I see what you mean. Thanks for clarifying.

-----------------------------------
wtd
Thu Jun 07, 2007 10:54 am

RE:[Scala] A little code
-----------------------------------
Another possibility for that last one:

new MyRange(1, 4) doForAll (Console println _)

-----------------------------------
wtd
Thu Jun 07, 2007 2:57 pm

RE:[Scala] A little code
-----------------------------------
// Turns out, there're generic Iterable and Iterator traits already
// defined as part of Scala's standard library.

class MyRange(val start: Int, val end: Int) extends Iterable[Int] {
   def elements = new Iterator[Int] {
      private var current = start
      def hasNext = current 
         if (x % 2 == 0)
            Console println x
         else 
            Console println "Better luck next time."
   }
}

// Or perhaps...

new MyRange(1, 4) foreach {
   case 42 => Console println "42!  The answer!  But what is the question?"
   case _ =>
      if (x % 2 == 0)
         Console println x
      else 
         Console println "Better luck next time."
}

-----------------------------------
Clayton
Thu Jun 07, 2007 3:28 pm

RE:[Scala] A little code
-----------------------------------
I must ask, I've noticed you use an underscore quite a bit, like in here:

case _ =>
      if (x % 2 == 0)
         Console println x
      else
         Console println "Better luck next time." 

What exactly does it mean?

-----------------------------------
wtd
Thu Jun 07, 2007 3:31 pm

RE:[Scala] A little code
-----------------------------------
In that context, it is a nameless pattern that matches anything that a previous pattern has not.

-----------------------------------
Clayton
Thu Jun 07, 2007 3:32 pm

RE:[Scala] A little code
-----------------------------------
So in essence a safeguard for something that slips through?

-----------------------------------
wtd
Thu Jun 07, 2007 3:33 pm

RE:[Scala] A little code
-----------------------------------
Yes.  Essentially analogous to "default" in Java's "switch" statement.

-----------------------------------
Clayton
Thu Jun 07, 2007 3:35 pm

RE:[Scala] A little code
-----------------------------------
Ah, excellent.

Now, I may have missed something about this earlier, but this:

val x  Unit) {
        for (val teacher  Unit) {
        for (val student  Unit) {
        for (val teacher 