Saturday, 20 June 2009

Functions passed to functions (delegates)


def turnNumbersToEven() = {
val nums = 1 to 20
println( nums.map(a => addOneToNumberIf(a % 2 == 1)( a)) )
}
def addOneToNumberIf( test : => Boolean)( i : Int) : Int = {
if (test) {
return i + 1
} else {
return i
}
}


Note because we used addOneToNumberIf(a)(b) notation instead of addOneToNumberIf(a,b) notation we are allowed to write scripts {} like this:


def turnNumbersToEven() = {
val nums = 1 to 20
println( nums.map(a => addOneToNumberIf {a % 2 == 1} (a)) )
}

Wednesday, 17 June 2009

You can use loops instead of compex maps

For example:

Using this 'for' loop the 'yield' function acts like a flatmap:

def loopMe() = {
val numbers = for( i <- 1 to 10; if i % 2 == 0;
j <- i to 10 if j % 2 == 1) yield i * j
println(numbers)
}


Here is the equivalent with traditional maps and filters:

def mapMe() = {
val num2 = (1 to 10).filter( a => a % 2 == 0)
val num3 = num2.flatMap( a => (a to 10).filter(b => b % 2 == 1).map(c => c * a ) )

println(num3)
}

Option[T]

Option[T] can be either a Some[T] or None

use this for things that can flatmap!

Xml demos

Basic XML with scala:
Note you can also use the CDATA command but blogger didn't like me having that here!

def xmlDemo() : Unit = {
val xml = <>my xml
<>1< /val >
<>2< /val >
< /b >
println( xml.length )
}


Filtering XML:
loads XML,
finds how many 'para' tags are in the XML
prints all the 'id' attributes of the 'sect2' tag
Note: \\ means find anywhere \ means find one level down

val xml3 = XML.load("http://www.linux.sgi.com/LDP/authors/template/Sample-HOWTO.xml")
println( (xml3 \\ "para").length )
println( (xml3 \\ "sect2").map(_ \ "@id").map(_.text) )


Transforming XML:

find any nodes which have an 'id=copyright' attribute and remove them

val moveIt = new RewriteRule {
override def transform(n : Node) : NodeSeq = n match {
case e:Elem if (e \"@id").text == "copyright" => NodeSeq.Empty
case e => e
}
}
println( new RuleTransformer(moveIt).transform(xml3) )

Sunday, 14 June 2009

String parsing thru lists

Filter numbers from strings.

println( "there are 7 numbers 8 in 2 here"
.toList.filter(Character.isDigit) )


Load the first word only.

println(("first word only".toList.takeWhile(c => c != ' ') ).mkString)

Funky stuff with for loops & prepopulating lists

You can pre populate a list with a loop like "val list = 1 to 20"

You can return stuff from a for loop with the "yield" command

def looping() = {
val myList = (1 to 20 by 3)
println(myList)

val list2 = for( i <- myList if i % 2 == 0 ) yield i
println(list2)
}

Functions apply and update

If you have an object with an 'apply' method you dont need to specify apply when calling it. ie: a.apply(20) === a(20)

Similar behavior with 'update' except you can use an '='. I'm currently baffled as to why you'd want to do this: a.update(6, "str") === a(6) = "str"


object Functions {

def main(args :Array[String]) = {
val a = new Ap(6)
println( a.apply(20) + " == " + a(20))
println( a.update(6, "str") + " == " + (a(6) = "str") )
}

}

class Ap(i : Int) {
def apply(in : Int) = (in + i).toString
def update(in : Int, v : String) = println("hey "+in+" "+v)
}