티스토리 툴바


My Programing/Scala&Lift2010/09/17 11:05
안녕하세요? 이번에는 스칼라 관련 펑션들을 쭈욱 나열해 봤습니다.

직접 제가 실행해서 전부 된 내용이니까요. 한번쯤 쭉 돌려 보시면 이해가 되실 듯 합니다.

자 시작 ----

scala> import java.util._
import java.util._

scala> val d = new Date
d: java.util.Date = Tue Sep 14 15:35:47 JST 2010

scala> val te = "sss"
te: java.lang.String = sss

scala> val teleng = te.length
teleng: Int = 3

scala> println("hello")
hello

--for--
scala> for {i <- 1 to 3}
      print(i)         
123

scala> for {i <- 4 to 5                               
      j <- 90 to 91
      k <- 120 to 122}
      println(i + " " + j + " " + k) 

----scala----
scala> import scala.io._
import scala.io._

scala> def toInt(in: String): Option[Int] =  
      try {
      Some(Integer.parseInt(in.trim))
      } catch {
      case e: NumberFormatException => None
      }
toInt: (in: String)Option[Int]

----Sum.Scala----
import scala.io._

def toInt(in: String): Option[Int] =
  try {
    Some(Integer.parseInt(in.trim))
  } catch {
    case e: NumberFormatException => None
  }

def sum(in: Seq[String]) = {
  val ints = in.flatMap(s => toInt(s))
  ints.foldLeft(0)((a, b) => a + b)
}

print("enter some number and press ctrl-d")
val input = Source.fromInputStream(System.in)

// 2.7 (collect) -> 2.8 changed ().toSeq
val lines = input.getLines().toSeq

println("Sum "+ sum(lines))

-.-basic scala syntax-.-
Integer: 1882, -1
Boolean: true, falseDouble: 1.0d, 1d, 1e3
Long: 42L
Characters: 'b', '2', '?'
Strings: "hello, good"

--multi line--
scala> """Hello
     | multi Line
     | """
res2: java.lang.String = 
Hello
multi Line

--xml syntax--
scala> val xmlxml = <b>Foo</b><ul>{(1 to 4).map(aa => <li>{aa}</li>)}</ul>
xmlxml: scala.xml.NodeBuffer = ArrayBuffer(<b>Foo</b>, <ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>)


--callback and nonameMethod--
object Timer
{
  def oncePerSecond(callback: () => Unit): Unit =
  {
    while (true)
    {
      callback()
      Thread.sleep(1000)
    }
  }

  def timeFlies(): Unit = 
  { Console.println("Time flies when you're having fun(ctionally)..."); }

  def main(args: Array[String]): Unit =
  {
    oncePerSecond(timeFlies)
  }
}

====> 
object Timer
{
  def oncePerSecond(callback: () => Unit): Unit =
  {
    while (true)
    {
      callback()
      Thread.sleep(1000)
    }
  }

  def main(args: Array[String]): Unit =
  {
    oncePerSecond(() => 
      Console.println("Time flies... oh, you get the idea."))
  }
}

===>
object Timer
{
  def periodicCall(seconds: Int, callback: () => Unit): Unit =
  {
    while (true)
    {
      callback()
      Thread.sleep(seconds * 1000)
    }
  }

  def main(args: Array[String]): Unit =
  {
    periodicCall(1, () => 
      Console.println("Time flies... oh, you get the idea."))
  }
}

--define variable--
val msg:String = "Hello, World"
msg = "Good Bye"  <-error   val is do not change.

var greeting = "Hello, World"
greeting = "Good Byte" <-not error var is possible change.

-- if --
def max(x: Int, y: Int): Int = {
   if ( x > y ) x
   else y
}

-- class define and override --
class Rational(val n:Int, val d:Int) {

   override def toString() = {
       n + "/" + d
   }

}

scala> val half=new Rational(11, 22)
half: Rational = 11/22

scala> half.n
res2: Int = 11


--def function--
scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Int

scala> curriedSum(109)(19)
res7: Int = 128

-- recurrence --
scala> def sum(f: Int => Int) (start: Int, end: Int) : Int = {
        if ( start > end )
           0
        else
           f(start) + sum(f) (start + 1, end)
     }
sum: (f: (Int) => Int)(start: Int,end: Int)Int

scala> sum( x=> x*x)(1,10)
res12: Int = 385

-- sum() is referentially transparent --
scala> sum(x => x)(1, 8) 
res18: Int = 36

-- simply function --
scala> def plus(x: Int, y: Int) = {
         x + y
      }
plus: (x: Int,y: Int)Int

scala> plus(3,5)
res19: Int = 8



class Reference[a] {

     private var contents: a = _

     def set(value: a) { contents = value }

     def get: a = contents

}

-- simply interface --
    
scala> object Moose {
     | def bark = "wooff"
     | }
defined module Moose

scala> import Moose._
import Moose._

scala> bark
res49: java.lang.String = wooff

-- list define --
scala> val v=("ssss", 1122, 1.5) 
v: (java.lang.String, Int, Double) = (ssss,1122,1.5)

scala> List(v)
res55: List[(java.lang.String, Int, Double)] = List((ssss,1122,1.5))

-- Method Declaration --
1))
scala> def foo(a: Int): String = a.toString
foo: (a: Int)String

scala> foo(1000)
res60: String = 1000

2))
scala> def f2(a: Int, b: Boolean) = if (b) a.toString else "false"
f2: (a: Int,b: Boolean)java.lang.String

scala> f2(10, true)
res63: java.lang.String = 10

scala> f2(10, false)
res64: java.lang.String = false

3)) list of T
scala> def list[T](p: T): List[T] = p:: Nil
list: [T](p: T)List[T]

scala> list("11", "sss", 111)              
res69: List[(java.lang.String, java.lang.String, Int)] = List((11,sss,111))

4)) reduceLeft -->> many num -> largest 
scala> def largest(as: Int*): Int = as.reduceLeft((a, b) => a max b)
largest: (as: Int*)Int

scala> largest(2,4,5)
res70: Int = 5

5)) foldLeft -->> many String -> plus all String
scala> def mkString[T](as: T*): String = as.foldLeft("")(_ + _.toString)
mkString: [T](as: T*)String

scala> mkString("sss", "jsdj", "three", "s")                            
res75: String = sssjsdjthrees

6)) abstract
scala> abstract class Base { 
     | def thing: String
     | }
defined class Base

scala> class One extends Base {   
     | def thing = "moof"      
     | }
defined class One

scala> class Two extends One {
     | override val thing = (new java.util.Date).toString
     | }
defined class Two

scala> class Three extends One {
     | override lazy val thing = super.thing + (new java.util.Date).toString
     | }
defined class Three

scala> (new Three).thing
res7: java.lang.String = moofWed Sep 15 10:37:29 JST 2010


-- Variable Declaration --
1)) basic variable declaration
// var = modify ok, val = modify no
scala> var y: String = "Moff"
y: String = Moff
scala> val x: String = "moffX"
x: String = moffX

2) pair variable Declaration ( pair )
scala> val (i1: Int, s1: String) = Pair(33, "Mooff")
i1: Int = 33
s1: String = Mooff


-- code blocks --
scala> def meth4(): String = {
     | val d = new java.util.Date()
     | d.toString()
     | }
meth4: ()String

scala> meth4
res12: String = Wed Sep 15 10:54:22 JST 2010

-- call by name --
// diffed --> delayed(t: => long) and noDelayed(t: long)
1) delayed ( class reference )
scala> def delayed(t: => Long) = {
     | println("Indeleay")        
     | println("param: "+ t)      
     | t                    
     | }
delayed: (t: => Long)Long

scala> delayed(nano())
Indeleay
getting nano
param: 1284516216253827000
getting nano
res18: Long = 1284516216254443000

2) nodelayed ( var declaration )
scala> def nodeleayed(t: Long) = {
     | println("no delay")
     | println("param: "+ t)
     | t
     | }
nodeleayed: (t: Long)Long

scala> nodeleayed(nano())
getting nano
no delay
param: 1284516400999580000
res20: Long = 1284516400999580000

-- Method Invocation --
1) function method apply
scala> class Ap{
     | def apply(in: Int) = in.toString
     | }
defined class Ap

scala> val a = new Ap
a: Ap = Ap@7bb28246

scala> a(44)
res30: java.lang.String = 44

2) function method update
scala> class Up {
     | def update(k: Int, v: String) = println("Change: "+ k + " " + v)
     | }
defined class Up

scala> val u = new Up
u: Up = Up@63df0310

scala> u(44) = "yeah man"
Change: 44 yeah man

3) function overload
scala> class Update {
     | def update(what: String) = println("Singler: "+ what)
     | def update(a: Int, b: Int, what: String) = println("2d update")
     | }
defined class Update

scala> val u = new Update
u: Update = Update@ee01430

scala> u() = "Food"
Singler: Food

scala> u(3,40) = "ss"
2d update

-- Case Classes -- like struture?
1)) class define
scala> case class Stuff(name: String, age: Int)
defined class Stuff

scala> val s = Stuff("dada", 40)
s: Stuff = Stuff(dada,40)

scala> s.toString
res48: String = Stuff(dada,40)

2)) Variable diff
scala> s == Stuff("dada", 40)
res49: Boolean = true

scala> s == Stuff("dada", 41)
res50: Boolean = false

scala> s.name
res51: String = dada

scala> s.age
res52: Int = 40

3)) class and object declare
scala> class Stuff(val name: String, val age: Int) {            
     | override def toString = "Stuff("+name+","+age+")"        
     | override def hashCode = name.hashCode + age              
     | }
defined class Stuff

scala> object Stuff {                                         
     | def apply(name: String, age: Int) = new Stuff(name, age)
     | def unapply(s: Stuff) = Some((s.name, s.age))           
     | }                                                       
defined module Stuff

scala> val s = Stuff("nam", 100)
s: Stuff = Stuff(nam,100)

scala> s
res63: Stuff = Stuff(nam,100)

scala> s.age
res64: Int = 100

scala> s.name
res65: String = nam

-- Basic Pattern Matching --
1) basic
scala> 44 match {
     | case 44 => true
     | case _ => false
     | }
res66: Boolean = true

2) class match
scala> Stuff("David", 40) match {
     | case Stuff("David", 40) => true
     | case _ => false
     | }
res67: Boolean = true

3) any age class match
scala> Stuff("David", 40) match {     
     | case Stuff("David", _) => true 
     | case _ => false               
     | }
res68: Boolean = true

4) instance pattern matching
val x = "abc" // String

x match {
  case d: java.util.Date => "The Date is "+ d.getTime
  case u: java.net.URL => "The URL" + u.getPath
  case s: String => "String: " + s
  case _ => "some else"
}

previous code java
if (x instanceOf Date) return "The Date is "+ ((Date) x).getTime();
....


-- if/else and while --
1) basic if
scala> val exp = true
exp: Boolean = true

scala> if (exp) println("aaa")
aaa

2) basic if/else
scala> val i: Int = if (exp) { 19999 
     | } else {
     | val j = System.currentTimeMillis
     | (j%100L).toInt
     | }
i: Int = 19999

3) while
while(exp) {
println("gogogo")
}

-- for comprehension --
1)) basic for
scala> for { i <- 1 to 3} println(i)
1
2
3

2)) use 2 for
scala> for {i <- 1 to 3  
     | j <- 1 to 3} print(i + " " + j)
1 11 21 32 12 22 33 13 23 3
scala> for {i <- 1 to 3               
     | j <- 4 to 6} print(i +"and" + j + " ")
1and4 1and5 1and6 2and4 2and5 2and6 3and4 3and5 3and6 

3)) for use if
scala> def isOdd(in: Int) = in %2 == 1         
isOdd: (in: Int)Boolean

scala> for {i <- 1 to 5 if isOdd(i)} println(i)
1
3
5

scala> for {i <- 1 to 5 if (i % 2 == 1)} println(i)
1
3
5

scala> val lst = (1 to 18 by 3).toList
lst: List[Int] = List(1, 4, 7, 10, 13, 16)

scala> for {i <- lst; j<-lst if isOdd(i * j)} yield i * j
res110: List[Int] = List(1, 7, 13, 7, 49, 91, 13, 91, 169)

for (i <- 15 from 10) yield i

scala> for (i <- 10 to 15) yield i  
res113: scala.collection.immutable.IndexedSeq[Int] = Vector(10, 11, 12, 13, 14, 15)

-- throw, try/catch/finally, and synchronized --
1)) normal exception
scala> throw new Exception("sososo")
java.lang.Exception: sososo
at .<init>(<console>:13)
at .<clinit>(<console>)

2)) exception and finally 
scala> try {                      
     | throw new Exception("svsv")
     | } finally {                
     | println("gogogo")          
     | }                          
gogogo
java.lang.Exception: svsv
at .liftedTree1$1(<console>:7)
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
...

3)) try/catch
scala> try {Integer.parseInt("dododo")} catch 
     | { case _ => 0 }
res8: Int = 0

4)) synchronized
scala> def foo(): Int = synchronized {
     | 66
     | }
foo: ()Int

scala> foo
res11: Int = 66

-- comments --
/*
This is a multi line comment
*/
/* 
good
  /*
    good2
  */
goodend
*/
// one line comment

-- scala, ruby, java diff --
scala> def with42(in: Int => Int) = in(42)
with42: (in: (Int) => Int)Int

scala> with42(33 +)
res22: Int = 75

-- Scala List, Tuple, Option, and Map classes --
1)) List, Array, Map
scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)

scala> x.filter(a => a % 2 == 0)
res23: List[Int] = List(2, 4)
 - Array
scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)

scala> a(1)
res40: Int = 2

 - Map
scala> val m= Map("one" -> 1, "two" -> 2, "three" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map((one,1), (two,2), (three,3))

scala> m("one")
res41: Int = 1

 - to and by
scala> 0 to 20 by 2
res42: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
 
 - take
scala> (1 to Integer.MAX_VALUE - 1).take(6)  
res48: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6)

2)) List[T] linked list of type
scala> val ff = 1 :: 2 :: "3" :: Nil
ff: List[Any] = List(1, 2, 3)

scala> val inttest = new ::(1, new ::(2, new :: (3, Nil)))
inttest: scala.collection.immutable.::[Int] = List(1, 2, 3)

scala> inttest
res50: scala.collection.immutable.::[Int] = List(1, 2, 3)

scala> val intlist = List[Int](1,5,2)
intlist: List[Int] = List(1, 5, 2)

 -merge num + val
scala> 22 :: intlist
res51: List[Int] = List(22, 1, 5, 2)

 -merge val + val
scala> val xx = List(1,2,3)
xx: List[Int] = List(1, 2, 3)

scala> val yy = List(90,91,92)
yy: List[Int] = List(90, 91, 92)

scala> xx ::: yy
res52: List[Int] = List(1, 2, 3, 90, 91, 92)

3)) Getting Functional ( filter, remove )
scala> List(1,2,3).filter(x=> x % 2 == 1)
res53: List[Int] = List(1, 3)

scala> List(1,2,3).remove(x => x % 2 == 1)
res55: List[Int] = List(2)
-->
scala> def isOdd(x: Int) = x % 2 == 1
isOdd: (x: Int)Boolean
scala> List(1,2,3).filter(isOdd)     
res57: List[Int] = List(1, 3)

 -- isDigit
"99 Red Balloons".toList.filter(Character.isDigit)
res59: List[Char] = List(9, 9)

 === Character.isDigit etc ===
 isInstanceOf               isDefined                  isDigit
isHighSurrogate            isISOControl               isIdentifierIgnorable
isJavaIdentifierPart       isJavaIdentifierStart      isJavaLetter
isJavaLetterOrDigit        isLetter                   isLetterOrDigit
isLowSurrogate             isLowerCase                isMirrored
isSpace                    isSpaceChar                isSupplementaryCodePoint
isSurrogatePair            isTitleCase                isUnicodeIdentifierPart
isUnicodeIdentifierStart   isUpperCase                isValidCodePoint
isWhitespace
===             ===        ===

 -- takeWhile --
scala> "Elwood eats mice".takeWhile(c => c != 'a')
res65: String = Elwood e

 -- toLowerCase --
scala> List("A", "Cat").map(s => s.toLowerCase)
res0: List[java.lang.String] = List(a, cat)
 -->
scala> List("A", "Cat").map(_.toLowerCase)
res2: List[java.lang.String] = List(a, cat)
scala> List("A", "Cat").map(_.length)
res4: List[Int] = List(1, 3)

 4)) Functional Methods #2
scala> trait Person {def first: String }
defined trait Person

scala> val d = new Person { def first = "David" }
scala> val e = new Person { def first = "Jhon" }
scala> val a = new Person { def first = "Arcman" }

scala> List(a,d,e).map(_.first)                   
res9: List[String] = List(Arcman, David, Jhon)

List(a,d,e).map(n => <li>{n.first}</li>)
scala> List(a,d,e).map(n => <li>{n.first}</li>)
res10: List[scala.xml.Elem] = List(<li>Arcman</li>, <li>David</li>, <li>Jhon</li>)

 -- sort ( possible Int, String or etc)
scala> List(99, 2,1,45).sort(_ < _)
res12: List[Int] = List(1, 2, 45, 99)

 -- sort length
scala> List("bb", "a", "elwood", "archersss").sort(_.length > _.length)
res14: List[java.lang.String] = List(archersss, elwood, bb, a)

 -- list person valid --
scala> trait Person {
      def age: Int
      def first: String
      def valid: Boolean
      }
defined trait Person

scala> def validByAge(in: List[Person]) =
     | in.filter(_.valid).
     | sort(_.age < _.age).
     | map(_.first) 
 
scala> val p1 = new Person { def age = 12; def first = "ajajaj"; def valid = true}

scala> val p2 = new Person { def age = 22; def first = "bjbjbj"; def valid = true}

scala> val p3 = new Person { def age = 32; def first = "cjcjcj"; def valid = true}

scala> val listP = List(p1, p2, p3)                                               
listP:List[java.lang.Object with Person]=List($anon$1@4c56291a,$anon$1@3f29a75a,$anon$1@31d47845)

// sort age, filter valid, map first
scala> validByAge(listP)
res1: List[String] = List(ajajaj, bjbjbj, cjcjcj)

// max or min
scala> List(8,6,22,20).reduceLeft(_ max _)
res7: Int = 22
scala> List(8,6,22,20).reduceLeft(_ min _)
res8: Int = 6

// length diff
scala> List("Moose", "cow", "A", "da").reduceLeft((a, c) => if (a.length > c.length) a else c)
res36: java.lang.String = Moose

// foldLeft
scala> List(1,3,4).foldLeft(4)(_ - _) 
res45: Int = -4

scala> List("b", "a", "elwood", "archer").foldLeft(0)(_ + _.length)       
res48: Int = 14

// toList
scala> val n = (1 to 10 by 3).toList
n: List[Int] = List(1, 4, 7, 10)

// logical function ( d = 
scala> val nmapval = n.map(d => n.map(i => d*i))
nmapval: List[List[Int]] = 
List(List(1, 4, 7, 10), List(4, 16, 28, 40), List(7, 28, 49, 70), List(10, 40, 70, 100))

// isOdd, isEven, 1-10 filter and flatMap
scala> n.filter(isEven).flatMap(i => n.filter(isOdd).map(j => i * j))
res0: List[Int] = 
List(2, 6, 10, 14, 18, 4, 12, 20, 28, 36, 6, 18, 30, 42, 54, 8, 24...

scala> for {i <- n if isEven(i); j <- n if isOdd(j)} yield i * j
res1: List[Int] = 
List(2, 6, 10, 14, 18, 4, 12, 20, 28, 36, 6, 18, 30, 42, 54, 8, 24, 40, 56, 72, 10, 30, 50, 70, 90)

4)) tuples  (( Pair and Tuple2 )
scala> Tuple2(1,2) == Pair(1,2)
res4: Boolean = true

scala> Pair(1,2) == (1,2)
res5: Boolean = true

scala> (1,2) == 1 -> 2
res6: Boolean = true


5)) what is Map[K, V]  -- Key and value --> all of map type
scala> var p = Map(1 -> "David", 9 -> "Elwood")
p: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,David), (9,Elwood))

// map add data
scala> p += 8 -> "Archers"

scala> p
res23: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,David), (9,Elwood), (8,Archers))

// map get data
scala> p.get(88)
res26: Option[java.lang.String] = None

scala> p.get(8)
res27: Option[java.lang.String] = Some(Archers)

// map get or else
scala> p.getOrElse(8, "no Data")
res29: java.lang.String = Archers

scala> p.getOrElse(88, "no Data")
res30: java.lang.String = no Data

// loop Key
scala> 1 to 8 map(p.get)
res36: scala.collection.immutable.IndexedSeq[Option[java.lang.String]] = 
Vector(Some(David), None, None, None, None, None, None, Some(Archers))

scala> 1 to 8 flatMap(p.get)
res34: scala.collection.immutable.IndexedSeq[java.lang.String] = 
Vector(David, Archers)

// map delete data
scala> p -= 9

scala> p
res38: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,David), (8,Archers))

// map key find
scala> p.contains(8)
res44: Boolean = true

// max key value
scala> p.keys.reduceLeft(_ max _)
res46: Int = 9

// reduceLeft (key's max value)
scala> p.values
res47: Iterable[java.lang.String] = MapLike(David, Archers, john)

scala> p.values.reduceLeft((a, b) => if (a > b) a else b)
res48: java.lang.String = john

// map value find
scala> p.values.exists(_.contains("john"))
res65: Boolean = true

scala> p.values.exists(_.contains("charlse"))
res66: Boolean = false

// mapdata + mapdata
scala> p ++= List(5 -> "Cat", 6 -> "kirin")

scala> p
res72: scala.collection.immutable.Map[Int,java.lang.String] = 
Map((5,Cat), (1,David), (6,kirin), (9,john), (13,youngs), (8,Archers), (4,jason))

// mapdata - mapdata
scala> p
res72: scala.collection.immutable.Map[Int,java.lang.String] = 
Map((5,Cat), (1,David), (6,kirin), (9,john), (13,youngs), (8,Archers), (4,jason))

scala> p --= List(13,4)
scala> p
res74: scala.collection.immutable.Map[Int,java.lang.String] = 
Map((5,Cat), (1,David), (6,kirin), (9,john), (8,Archers))

scala> def removeInvalid(in: Map[Int, Person]) = in.filter(kv => kv._2.valid)
removeInvalid: (in: Map[Int,Person])scala.collection.immutable.Map[Int,Person]

6)) what is Option[T]
scala> import java.lang.{Boolean => JBool}
import java.lang.{Boolean=>JBool}

scala> def tryo[T](f: => T): Option[T] = try { Some(f)} catch { case _ => None }
tryo: [T](f: => T)Option[T]

scala> def toInt(s: String): Option[Int] = tryo(s.toInt)                        
toInt: (s: String)Option[Int]

scala> def toBool(s: String) = tryo(JBool.parseBoolean(s))                      
toBool: (s: String)Option[Boolean]

scala> def personFromParams(p: Map[String, String]): Option[Person] =
     for {name <- p.get("name")
       ageStr <- p.get("age")
       age <- toInt(ageStr)
       validStr <- p.get("valid")
       valid <- toBool(validStr)}
       yield new Person(age, first, valid)

// Some and getOrElse
scala> Some(3).get
res5: Int = 3

scala> None.get
java.util.NoSuchElementException: None.get

scala> None.getOrElse(123)
res12: Int = 123


---- XML Crreation and Manipulation ----
1)) basic
scala> <b>hello Xmls</b>
res14: scala.xml.Elem = <b>hello Xmls</b>

2)) xml multiple lines <span>

scala> <b id="hellos">                  
     | <span>hello hell WORLD!!!        
     | asdasdasd
     | </span>
     | </b>
res16: scala.xml.Elem = 
<b id="hellos">
<span>hello hell WORLD!!!
asdasdasd
</span>
</b>

3)) xml len
scala> def len(seq: Seq[_]) = seq.length
len: (seq: Seq[_])Int

scala> len(<b>hello</b><b>hello2</b>)   
res18: Int = 2

4)) xml in var data
scala> def now = System.currentTimeMillis.toString
now: java.lang.String

scala> <b time={now}>Hello man</b>
res20: scala.xml.Elem = <b time="1284550763149">Hello man</b>

// isOdd Xml express change
scala> def isOdd(in: Long) = in % 2L == 1L
isOdd: (in: Long)Boolean

scala> import scala.xml._
import scala.xml._

scala> def oddTime: Option[NodeSeq] = System.currentTimeMillis match {
     | case t if isOdd(t) => Some(Text(t.toString))
     | case _ => None 
     | }
oddTime: Option[scala.xml.NodeSeq]

scala> <b time={oddTime}>Sometimes</b>
res31: scala.xml.Elem = <b time="1284551334717">Sometimes</b>

scala> <b time={oddTime}>Sometimes</b>
res32: scala.xml.Elem = <b >Sometimes</b>

scala> <stuff>
     | {(1 to 3).map(i => <v id={i.toString}></v>)}
     | </stuff>
res37: scala.xml.Elem = 
<stuff>
<v id="1"></v><v id="2"></v><v id="3"></v>
</stuff>

scala> <stuff>{if (true) "dogs"}</stuff>
res38: scala.xml.Elem = <stuff>dogs</stuff>

scala> val info = """
     | var x = "";
     | if (true '' false) alert('Woof');
     | """
info: java.lang.String = 

var x = "";
if (true '' false) alert('Woof');
// PCData
scala> <script>{PCData(info)}</script>
res45: scala.xml.Elem = 
<script><![CDATA[
var x = "";
if (true '' false) alert('Woof');
]]></script>

// load xml ( xmlload)
scala> import scala.xml._
import scala.xml._

scala> val xml = XML.load("http://twib.jp/rss")

scala> xml \\ "title"

scala> (xml \\ "title").length  
res54: Int = 21

// simply xml Declaration
scala> val x2 = <x>{(1 to 3).map(i => <i>{i}</i>)}</x>
x2: scala.xml.Elem = <x><i>1</i><i>2</i><i>3</i></x>

scala> x2 \ "i"
res66: scala.xml.NodeSeq = NodeSeq(<i>1</i>, <i>2</i>, <i>3</i>)

scala> (x2 \ "i").map(_.text)
res67: scala.collection.immutable.Seq[String] = List(1, 2, 3)

scala> (x2 \ "i").map(_.text.toInt)     
res71: scala.collection.immutable.Seq[Int] = List(1, 2, 3)

scala> (x2 \ "i").map(_.text.toInt).foldLeft(0)(_ + _)
res73: Int = 6

// Modifyung xml
scala> import scala.xml._
import scala.xml._

scala> import scala.xml.transform._
import scala.xml.transform._

scala> val xmlBooks =       
     | <books instruction="update">
     | <book instruction="remove" name="book1" status="" />
     | <book instruction="add" name="book2" status="" />
     | </books>
xmlBooks: scala.xml.Elem = 
<books instruction="update">
<book instruction="remove" status="" name="book1"></book>
<book instruction="add" status="" name="book2"></book>
</books>

// remove Xml Node
val removeIt = new RewriteRule {
     |   override def transform(n: Node): NodeSeq = n match {
     |     case e: Elem if (e \ "@instruction").text == "remove" => NodeSeq.Empty
     |     case n => n
     |   }
     | }
removeIt: scala.xml.transform.RewriteRule{def transform(n: scala.xml.Node): scala.xml.NodeSeq} = <function1>

scala> new RuleTransformer(removeIt).transform(xmlBooks)
res74: Seq[scala.xml.Node] = 
<books instruction="update">

<book instruction="add" status="" name="book2"></book>
</books>

// add Xml Node
scala> val addIt = new RewriteRule {
     | override def transform(n: Node): NodeSeq = n match {
     | case e: Elem if (e \ "@instruction").text == "add" =>
     | new Elem(e.prefix, e.label, e.attributes.remove("instruction"), 
     | e.scope,
     | transform(e.child) ++ <added>I added this</added> :_*)
     | case n => n
     | }
     | }
addIt: scala.xml.transform.RewriteRule{def transform(n: scala.xml.Node): scala.xml.NodeSeq} = <function1>

scala> new RuleTransformer(addIt).transform(xmlBooks)
res77: Seq[scala.xml.Node] = 
<books instruction="update">
<book instruction="remove" status="" name="book1"></book>
<book status="" name="book2"><added>I added this</added></book>
</books>

// add and remove xml
scala> new RuleTransformer(addIt, removeIt).transform(xmlBooks)
res79: Seq[scala.xml.Node] = 
<books instruction="update">

<book status="" name="book2"><added>I added this</added></book>
</books>

---- Concurrency Without Synchronization ----
import java.util.concurrent.atomic.{AtomicReference => AtomR, AtomicLong}
import java.util.Random
import scala.collection.immutable.TreeHashMap

object Multics {
  // MT 型の定義。type を定義することで、タイピングの量が減らせる
  type MT = Map[String, Int]

  // 変数 info は イミュータブルな Map を保持する AtomicReference
  // AtomicReference は、同期化せずにどのスレッドからも更新ができる
  val info: AtomR[MT] = new AtomR(TreeHashMap.empty)
  // clashCnt は、AtomicLong で、スレッドが info への書き込みを行おうとして失敗した回数を保持する。
  // clashCnt は、同期化なしで、インクリメントできる
  val clashCnt = new AtomicLong

  // 新しいスレッドを作成し、repeatEvery のブロックを実行する。
  // repeatEvery(1000) は 1000 ミリ秒待ち、その後ブロックを実行する。
  // ブロックでは、clashCnt と info が持つ値の合計を出力する。
  // 同期処理なしで、info が持つ Map にアクセスできる。
  // Map はイミュータブルデータ型であり、変更されないことが分かっているからです。
  def main(arfv: Array[String]) {
    runThread {
      repeatEvery(1000) {
        println("Clash Count: " + clashCnt + " Total: " + info.get.foldLeft(0)(_ + _._2))
      }
    }

    // 次に、2000 スレッドを作成する
    for (i <- 1 to 2000) runThread {
      var cnt = 0
      val ran = new Random
      val name = "K" + i

      doSet(info) {old => old + (name -> 0)}
      // ループ処理を行う。それぞれのループ処理の中で、0から100ミリ秒間のランダムな待ち時間を設定する
      repeatEvery(ran.nextInt(100)) {
        doSet(info) {old => old + (name -> (old(name) + 1))}
        // スレッドに紐つけられているカウントを、インクリメントする
        cnt = cnt + 1
        // スレッドローカルのカウントと info の値が一致しなければ、並行処理に問題が発生したことになるため、例外の送出
        if (cnt != info.get()(name))
          throw new Exception("Thread: " + name + " failed")
      }
    }
  }

  // 新しいスレッドを作り、run メソッドに関数 f を設定後、スレッドを開始する。
  // スレッドの run メソッドが呼ばれると、関数 f が実行される。これはコードブロックを引数として渡す例。
  def runThread(f: => Unit) = (new Thread(new Runnable {def run(): Unit = f})).start

  // 同期処理なしで atom にアトミックな更新を行う。
  // 古い値を読み取り、update メソッドへ引数として渡し、
  // アトミックな更新を行います。
  // アトミックな更新が成功すれば(古い値は処理中に更新されません)、
  // 更新は最新バージョンのデータに対して行われ、更新は成功したことになる。
  // compareAndSet メソッドが失敗したら、clashCnt をインクリメントし、再度更新を試みる
  def doSet[T](atom: AtomR[T]) (update: T => T) {
    val old = atom.get
    if (atom.compareAndSet(old, update(old))) ()
    else {
      clashCnt.incrementAndGet
      doSet(atom)(update)
    }
  }

  // repeatEvery メソッドが制御フローの役割を果たす
  // repeatEvery は len と body の2つの引数を取り、
  // どちらも名前渡しです。repeatEvery のブロック内で参照されるたびに
  // 名前渡しで受け取ったコードが実行される
  def repeatEvery(len: => Int) (body: => Unit): Unit = {
    try {
      while(true) {
        Thread.sleep(len)
        body
      }
    } catch {
      case e => e.printStackTrace; System.exit(1)
    }
  }
}


----- Fun with Functions, and Never Having to Close That JDBC Connection -----

---- A function Is an Instance ----
scala> val f: Int => String = x => "Dude: "+x
f: (Int) => String = <function1>

scala> f(55)
res5: String = Dude: 55

scala> def w42(f: Int => String) = f(42)
w42: (f: (Int) => String)String

scala> w42(f)
res6: String = Dude: 42

scala> def fm(i: Int) = "fm "+i
fm: (i: Int)java.lang.String

scala> w42((i: Int) => fm(i))
res7: String = fm 42

---- Partial Application and Functions ----
scala> def plus(a: Int, b:Int) = "result is: "+(a + b)
plus: (a: Int,b: Int)java.lang.String

scala> plus(4,2) 
res13: java.lang.String = result is: 6

cala> val p = (b: Int) => plus(42, b)
p: (Int) => java.lang.String = <function1>

scala> p(4)
res15: java.lang.String = result is: 46

scala> def add(a:Int, b:Int)(c:Int) = "Result is: " + a + " " + b + " " + c
add: (a: Int,b: Int)(c: Int)java.lang.String

scala> add(19, 29)(38)
res18: java.lang.String = Result is: 19 29 38

// function and add function
scala> def add(a:Int)(b: Int) = "Result is "+ (a + b)
add: (a: Int)(b: Int)java.lang.String

scala> add(1)(2)
res25: java.lang.String = Result is 3

scala> add(1) {
     | var r= new java.util.Random
     | r.nextInt(100)
     | }
res26: java.lang.String = Result is 56

scala> w42(add(1))   
res27: String = Result is 43

scala> def f2 = add(1) _
f2: (Int) => java.lang.String

scala> w42 (f2)
res33: String = Result is 43

--- Functions and Type Parameters ---
scala> f(42)
res34: String = Dude: 42

scala> def t42[T](f: Int => T): T = f(42)
t42: [T](f: (Int) => T)T

scala> t42(f)
res35: String = Dude: 42

// input valList
scala> val intList: Int => List[Int] = i => (1 to i).toList
intList: (Int) => List[Int] = <function1>

scala> t42(intList)
res41: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42)

scala> t42[Int](1 +)
res42: Int = 43

--- Functions Bound to Variables in Scope ---
scala> val foo = "dog"
foo: java.lang.String = dog

scala> val whoTo = (s: String) => s+ " "+foo
whoTo: (String) => java.lang.String = <function1>

scala> whoTo("I Love man")
res45: java.lang.String = I Love man dog

scala> var strs: List[String] = Nil
strs: List[String] = List()

scala> val strF = (s: String) => {strs ::= s; s+ " Registered"}
strF: (String) => java.lang.String = <function1>

scala> strF("a")
res46: java.lang.String = a Registered

scala> strF("b")
res47: java.lang.String = b Registered

scala> strs
res48: List[String] = List(b, a)

scala> 

scala> List("p", "q", "r").map(strF)
res49: List[java.lang.String] = List(p Registered, q Registered, r Registered)

scala> strs
res51: List[String] = List(r, q, p, b, a)

--- Putting Functions in Containers ---
scala> def bf: Int => Int => Int = i => v => i + v
bf: (Int) => (Int) => Int

scala> val fs = (1 to 100).map(bf).toArray
fs: Array[(Int) => Int] = Ar...

scala> fs(0)(1)
res58: Int = 2

scala> fs(44)(3)
res59: Int = 48

--- Functions and Interactive Applications ---
scala> def randomName = "I"+Math.abs((new java.util.Random).nextLong)
randomName: java.lang.String

scala> trait JavaScript
defined trait JavaScript

scala> var callbacks: Map[String, () => JavaScript] = Map()
callbacks: Map[String,() => JavaScript] = Map()

scala> def register(f: () => JavaScript) = {
     | val name = randomName
     | callbacks += name -> f
     | <button onclick={"invokeSeverCall('"+ name+"')"}>ClcikMe</button>
     | }
register: (f: () => JavaScript)scala.xml.Elem


--- Building New Function ---
scala> sealed trait Expr
defined trait Expr

scala> case class Add(left: Expr, right: Expr) extends Expr
defined class Add

scala> case class Mul(left: Expr, right: Expr) extends Expr
defined class Mul

scala> case class Val(value: Int) extends Expr
defined class Val

scala> case class Var(name: String) extends Expr
defined class Var

scala> def calc(expr: Expr, vars: Map[String, Int]): Int = expr match {
     | case Add(left, right) => calc(left, vars) + calc(right, vars)
     | case Mul(left, right) => calc(left, vars) * calc(right, vars)
     | case Val(v) => v
     | case Var(name) => vars(name)
     | }
calc: (expr: Expr,vars: Map[String,Int])Int

scala> def buildCalc(expr: Expr): Map[String, Int] => Int = expr match {
     | case Add(left, right) =>
     | val lf = buildCalc(left)
     | val rf = buildCalc(right)
     | m => lf(m) + rf(m)
     | 
     | case Mul(left, right) =>
     | val lf = buildCalc(left)
     | val rf = buildCalc(right)
     | m => lf(m) * rf(m)
     | 
     | case Val(v) => m => v
     | case Var(name) => m => m(name)
     | }

--- call-by-name, call-by-value, and General Laziness ---
scala> def allStrings(expr: => String): List[String] = expr match {
     | case null => Nil                                            
     | case s => s :: allStrings(expr)                             
     | }                                                           
allStrings: (expr: => String)List[String]

scala> import java.io._
import java.io._

scala> val br = new BufferedReader(new FileReader("foo.txt"))
br: java.io.BufferedReader = java.io.BufferedReader@5f08edd0

scala> allStrings(br.readLine)
res9: List[String] = List(test file, hello secnod line, 3 line)

---- Pattern Matching ----
scala> def fibonacci(in: Int): Int = in match {    
     | case 0 => 0                                 
     | case 1 => 1                                 
     | case n => fibonacci(n - 1) + fibonacci(n -2)
     | }
fibonacci: (in: Int)Int

scala> fibonacci(8)
res0: Int = 21

scala> def fib2(in: Int): Int = in match {
     | case n if n <= 0 => 0
     | case 1 => 1
     | case n => fib2(n - 1) + fib2(n - 2)
     | }
fib2: (in: Int)Int

scala> fib2(4)
res3: Int = 3

--- matching any type ---
scala> def MyMules(name: String) = name match {
     | case "Elwood" | "Madeline" => Some("cat")
     | case "Archer" => Some("Dog")
     | case "Pumpking" | "Firetruc" => Some("Fish")
     | case _ => None
     | }
MyMules: (name: String)Option[java.lang.String]

scala> MyMules("Elwood")
res0: Option[java.lang.String] = Some(cat)

scala> object MyMules {
     | def myMules(name: String) = name match {
     | case "Elwood" | "Madeline" => Some("Cat")
     | case "Archer" => Some("Dog")
     | case "Pumpkin" | "Firetruck" => Some("Fish")
     | case _ => None
     | }
     | }
defined module MyMules

scala> MyMules.myMules("Elwood")
res6: Option[java.lang.String] = Some(Cat)

--- Testing Data Type ---
scala> def test2(in : Any) = in match {
     | case s: String => "String, Length "+ s.length
     | case i: Int if i > 0 => "Natural Int"
     | case i: Int => "Another Int"
     | case a: AnyRef => a.getClass.getName
     | case _ => "null"
     | }
test2: (in: Any)java.lang.String

scala> test2("s")
res7: java.lang.String = String, Length 1

scala> test2(0)
res8: java.lang.String = Another Int

scala> test2(4)
res9: java.lang.String = Natural Int

scala> test2(MyMules)
res10: java.lang.String = MyMules$

--- case classes ---
scala> case class Person(name: String, age: Int, valid: Boolean)
defined class Person

// default name, age, valid = Val
scala> case class Person(var name: String, var age: Int, var valid: Boolean)
defined class Person

scala> val mp = MPerson("jorge", 24) 
mp: MPerson = MPerson(jorge,24)

scala> mp.age = 25

scala> mp
res13: MPerson = MPerson(jorge,25)

scala> def older(p: Person): Option[String] = p match {
     | case Person(name, age, true) if age > 35 =>Some(name)
     | case _ => None
     | }
older: (p: Person)Option[String]

scala> older(p)
res15: Option[String] = Some(David)

scala> older(Person("Frank", 30, true)) 
res20: Option[String] = None

scala> older(Person("Frank", 40, true))
res21: Option[String] = Some(Frank)

scala> older(Person("Frank", 40, false))
res22: Option[String] = None

--- Pattern Matching ---
scala> val x = 1
x: Int = 1

scala> val rest = List(2,3,4)
rest: List[Int] = List(2, 3, 4)

scala> x :: rest
res23: List[Int] = List(1, 2, 3, 4)

scala> x :: x :: rest
res24: List[Int] = List(1, 1, 2, 3, 4)

scala> (x :: rest) match {                                            
     | case xprime :: restprime => println(xprime); println(restprime)
     | }
1
List(2, 3, 4)

-- patern matching and lists --
scala> def sumOdd(in: List[Int]): Int = in match{
     | case Nil => 0
     | case x :: rest if x % 2 == 1 => x + sumOdd(rest)
     | case _ :: rest => sumOdd(rest)
     | }
sumOdd: (in: List[Int])Int

scala> sumOdd(rest)
res27: Int = 3

scala> rest
res28: List[Int] = List(2, 3, 4)

scala> sumOdd(x :: rest)
res29: Int = 4

scala> def noPairs[T](in:List[T]): List[T] = in match {            
     | case Nil => Nil
     | case a :: b :: rest if a == b => noPairs(a :: rest)
     | case a :: rest => a :: noPairs(rest)
     | }
noPairs: [T](in: List[T])List[T]

scala> noPairs(List(1,2,3,3,3,4,1,1))
res30: List[Int] = List(1, 2, 3, 4, 1)

scala> def ignore(in: List[String]): List[String] = in match {
     | case Nil => Nil
     | case _ :: "ignore" :: rest => ignore(rest)
     | case x :: rest => x :: ignore(rest)
     | }
ignore: (in: List[String])List[String]

scala> def getStrings(in: List[Any]): List[String] = in match {
     | case Nil => Nil
     | case (s: String) :: rest => s :: getStrings(rest)
     | case _ :: rest => getStrings(rest)
     | }
getStrings: (in: List[Any])List[String]

scala> val xxx = List("a", 1, "b", 2L) 
xxx: List[Any] = List(a, 1, b, 2)

scala> getStrings(xxx)
res33: List[String] = List(a, b)


--- Nested Pattern Matching in case classes ---
scala> case class MarriedPerson(override val name: String,
     | override val age: Int,
     | override val valid: Boolean,
     | spouse: Person) extends Person(name, age, valid)
defined class MarriedPerson

scala> def mOlder(p: Person): Option[String] = p match {
     | case Person(name, age, true) if age > 35 => Some(name)
     | case MarriedPerson(name, _, _, Person(_, age, true))
     | if age > 35 => Some(name)
     | case _ => None
     | }
mOlder: (p: Person)Option[String]

scala> mOlder(p)
res36: Option[String] = Some(David)

scala> mOlder(sally)
res37: Option[String] = Some(sally)

--- Pattern Matching as Functions ---
scala> val list=List("aa", "bb", "cc", "dd", 11)
list: List[Any] = List(aa, bb, cc, dd, 11)

scala> list.filter(a => a match {               
     | case s: String => true                   
     | case _ => false                          
     | })                                       
res40: List[Any] = List(aa, bb, cc, dd)

scala> def handleRequest(req: List[String])(                       
     | exceptions: PartialFunction[List[String], String]): String =
     | if (exceptions.isDefinedAt(req)) exceptions(req) else       
     | "Handling URL "+ req+ " in the normal way"                  
handleRequest: (req: List[String])(exceptions: PartialFunction[List[String],String])String

scala> def doApi(call: String, params: List[String]): String =
     | "Doing Api Call" + call
doApi: (call: String,params: List[String])String

scala> handleRequest("foo" :: Nil) {                          
     | case "api" :: call :: params => doApi(call, params)    
     | }                                                      
res45: String = Handling URL List(foo) in the normal way


---- 다음 화에 계속..

다음화에서는 OOP라던지 Actor 등을 나열해 보도록 하겠습니다. 그럼 다음 기회에 :)
Posted by nkdk
My Programing/Scala&Lift2010/08/25 16:23
이번 글은 스칼라와 리프트의 전반적인 구성 및
서버 관련된 글인데요. 아마 앞 뒤가 안 맞을 것입니다. 자료 보관 용도이니..
잘 정리해서 보시길 :)


Scala_lift 기본 개념

 

/work/git/tokubuy/src/main/boot.scala

 

Scala/webApp -> 폴더를 만듬 -> 위 아래에 surrond를 붙여서 layout을 붙인다.

Webapp/template_hidden/default.html <- layout 입니다.

 

Vi 명령 set ff=unix

                                                                                  

컴파일 방법

Sudo mvn compile

 

/work/git/tokubuy/src/main/webapp/admin 이 뷰 부분이고

/com/com/groupon/snipet <- controller부분입니다.

 

BL만들기

/admin을 예제로 하면

/user.scala 접속성공시(homepage)가 디폴트로 된다. (snipet확인)

 

admin에서 Coupon.scala 이 모델 부분임.

Coupon.findAll 검색을 해서.. 해당하는 쿼리를 검색하는 기능 max값 및 뭘 검색할지를 결정

 

login관련은

 

ajax관련 부분은 liftrule.dispath.prepard? 참조

 

/admin/new 이렇게 url이 되는 지는 확인 나중에..

 

/main/webapp/WEB-INF/classes/props/default.props에는 db선언이 들어 있다.

또한 bootstrap에도 선언되어 있으니 쌍으로 생각하자.

 

 

 

Daemon tools 라는 것이 있는데 데몬이 죽었을 때 자동으로 살려준다.

 

/etc/inittab 을 확인하면 실행하는 프로세스가 있다.

/service 에다가 디렉토리나 ln을 걸어 놓고 그 안에 파일 중에 run 이라는 파일을 찾아서 자동 실행해 준다.

데몬툴수 명령어 중에

Svc –p /service/tokubuy 를 하면 임시 중지

Svc –p /service/tokubuy 를 하면 continue

 



 

 

 


Posted by nkdk
My Programing/Scala&Lift2010/07/03 21:36
지금부터 스칼라에 기초 부터 중급까지 실제 사용하는 함수를 정리 하려 한다. 실제 전체적 구조에 대해서도 다루어 보려 합니다.

일단 이 글을 쓰게 된 이유는 리프트 부터 할려니까 한계가 보이더군요. 그래서 일단은 스칼라 부터 한 후에 lift를 가는 것이 맞다고 생각하게 되었습니다. 내용 상으로는 어렵거나 수학적 개념이 필요한 부분에 대해서는 과감히 빼겠습니다. 일단은 전체적인 부분에 대해 다루도록 하겠습니다.

스칼라라는 것은 무엇인가 일단 JVM에서 돌아가는 훌륭한 언어 입니다.
어느 정도로 훌륭하냐 하면 그루브를 만든 사람이 내가 스칼라라는 것이 있는 줄 알았다면 그루브를 안 만들었다고 이야기 할 정도이니 말입니다.

일단 기본적인 설치 및 설명에 대해서는 스칼라기본설치를 참고 해 주세요.
scala-2.7.7.final.zip (md5) <- 전 일단 이 버전으로 하려 합니다. 현재 최신 버전입니다.

일단 기본적인 경로를 잡으셨고 실행이 가능한 상태라면.. 바로 시작해 봅시다.

가장 간단한 헬로우 월드!

object HelloWorld {
    def main(args : Array[String]) : Unit = {
        System.out.println("Hello, Scala!");
    }
}

컴파일 : scalac HelloWorld.scala
실행 : scala HelloWorld

컴파일 하개 되면 2개의 파일이 생성됩니다 . :) 이 부분에 대해서는 생략 :) 실제 움직이게 하는 건 이 클래스 파일이 되겠죠?

일단 어그레시브한 프로그래밍을 위해서 콘솔에서 간단 간단 하게 확인이 가능한 방법을 보겠습니다.

scala 콘솔에서
object HelloWorld {
    def main(args : Array[String]) : Unit = {
        System.out.println("Hello, Scala!");
    }
}

이렇게 넣으시면
defined module HelloWorld
라고 나오는데 이 상태에서
HelloWorld.main(null) 이라고 치시면 간단히 실행이 가능합니다.

object HelloWorld {
def main(args: Array[String]) {
println("Hello, world! " + args.toList)
}
}
HelloWorld.main(args)

이렇게 하면 인수도 넣을 수 있네요.

-------------------------------------- 간단한 소스 하나 소개 합니다.
class 부터 어떤 식으로 값을 주고 받는지 볼 수 있겠네요.
-------------------------------------------

object Persons {

/** A list of persons. To create a list, we use Predef.List
* which takes a variable number of arguments and constructs
* a list out of them.
*/
val persons = List(
new Person("Bob", 17),
new Person("John", 40),
new Person("Richard", 68)
)

/** A Person class. 'val' constructor parameters become
* public members of the class.
*/
class Person(val name: String, val age: Int)

/** Return an iterator over persons that are older than 20.
*/
def olderThan20(xs: Seq[Person]): Iterator[String] =
olderThan20(xs.elements)

/** Return an iterator over persons older than 20, given
* an iterator over persons.
*/
def olderThan20(xs: Iterator[Person]): Iterator[String] = {

// The first expression is called a 'generator' and makes
// 'p' take values from 'xs'. The second expression is
// called a 'filter' and it is a boolean expression which
// selects only persons older than 20. There can be more than
// one generator and filter. The 'yield' expression is evaluated
// for each 'p' which satisfies the filters and used to assemble
// the resulting iterator
for (p <- xs if p.age > 20) yield p.name
}
}


/** Some functions over lists of numbers which demonstrate
* the use of for comprehensions.
*/
object Numeric {

/** Return the divisors of n. */
def divisors(n: Int): List[Int] =
for (i <- List.range(1, n+1) if n % i == 0) yield i

/** Is 'n' a prime number? */
def isPrime(n: Int) = divisors(n).length == 2

/** Return pairs of numbers whose sum is prime. */
def findNums(n: Int): Iterable[(Int, Int)] = {

// a for comprehension using two generators
for (i <- 1 until n;
j <- 1 until (i-1);
if isPrime(i + j)) yield (i, j)
}

/** Return the sum of the elements of 'xs'. */
def sum(xs: List[Double]): Double =
xs.foldLeft(0.0) { (x, y) => x + y }

/** Return the sum of pairwise product of the two lists. */
def scalProd(xs: List[Double], ys: List[Double]) =
sum(for((x, y) <- xs zip ys) yield x * y);

/** Remove duplicate elements in 'xs'. */
def removeDuplicates[A](xs: List[A]): List[A] =
if (xs.isEmpty)
xs
else
xs.head :: removeDuplicates(for (x <- xs.tail if x != xs.head) yield x)
}


/** The main class, the entry point of this program.
*/
object Fors {

def main(args: Array[String]) {
// import all members of object 'persons' in the current scope
import Persons._

print("Persons over 20:")
olderThan20(persons) foreach { x => print(" " + x) }
println

import Numeric._

println("divisors(34) = " + divisors(34))

print("findNums(15) =")
findNums(15) foreach { x => print(" " + x) }
println

val xs = List(3.5, 5.0, 4.5)
println("average(" + xs + ") = " + sum(xs) / xs.length)

val ys = List(2.0, 1.0, 3.0)
println("scalProd(" + xs + ", " + ys +") = " + scalProd(xs, ys))
}

}
역시 콘솔창에서 실행 가능하고요.
scala> Fors.main(null) 이렇게 실행하면

Persons over 20: John Richard
divisors(34) = List(1, 2, 17, 34)
findNums(15) = (4,1) (5,2) (6,1) (7,4) (8,3) (8,5) (9,2) (9,4) (10,1) (10,3) (10
,7) (11,2) (11,6) (11,8) (12,1) (12,5) (12,7) (13,4) (13,6) (13,10) (14,3) (14,5
) (14,9)
average(List(3.5, 5.0, 4.5)) = 4.333333333333333
scalProd(List(3.5, 5.0, 4.5), List(2.0, 1.0, 3.0)) = 25.5

이런 결과가 나옵니다. 여기서 엿 볼 수 있는 것이 각 3개의 Object가 있고 거기서 메인이 되는 것이 한개가 있어서 각 오브젝트를 불러서 사용 하는 방법들이라던지, 여기서 참 재미있는게 하나 있는데
class Person(val name: String, val age: Int) 이 부분인데요 바로 바로 값이 적용되서 들어 갑니다. 꼭 예전에 bean 썻던것처럼 get, set없이 그냥 쏙쏙 들어가네요 :)

소스를 보면서 분석 해 보시기 바랍니다.

그럼 기초부터 설명 들어갑니다.

일단 간단히 콘솔창에서 놀아 볼까요
scala> 1 + 1
res18: Int = 2

scala> val x = "hellO"
x: java.lang.String = hellO

scala> print(x)
hellO
scala> val xl = x.length
xl: Int = 5

scala> res18 * 10
res21: Int = 20

이렇게 계속 뭔가를 가지고 있네요 :) 재미있습니다.
그리고 저 res라는 걸 보니까 아무래도 뭔가 함수를 날렸을 때의 갯수로 해서 하나씩 증가 하는 것 같습니다. 물론 변수로 보관이 되서 나중에라도 끄집어 낼 수 쓸 수 있네요. :) 이런 좋은 것이 :)

scala> import java.util._
import java.util._

scala> val d = new Date
d: java.util.Date = Sat Jul 03 20:28:05 JST 2010

이런 것도 됩니다. 즉 java.util.Date 라는 클래스를 가져와서 바로 쓸 수 있게끔 하는 것도 있고..

아 그리고 콘솔에서 작업을 할 때 보면,

defined module HelloScala
defined class HelloScala

이렇게 나오는게 있는데 말 그대로 입니다 :) 모듈 혹은 class를 정의 했을 때 나오는 거죠. 아마 그 이외에 더 있지 않을까 생각 되는데 일단 현재 하고 잇는 중에는 이 정도만 나오네요.
뭔가 더 재미있는게 슬슬 나올 것 같지 않나요?

그리고 컴파일러 중에 fsc라는 컴파일러가 있는데 아무래도 뜻이 fast scala compiler가 아닐까 하는 생가깅 든다. 이건 정말 빠른 컴파일러라고 하는데 scalac보다 빠르도가 합니다. 그러나 역시 중 대형 규모가 되기 시작하면 ant혹은 maven으로 컴파일러를 관리해야 하니까 그 부분에 대해서도 공부가 필요하다 생각되네요 :)

넘버 관련 형 을 한번 봐 볼까요?
scala> 1.+(2)
res27: Double = 3.0
그냥 바로 더블형으로 나와 주네요 :) 1. 이게 포인트입니다.

이번에는 시간 관련으로 해서 한번 봐 보죠 :)
object Timer {
  def oncePerSecond(callback: () => Unit) {
    while (true) { callback(); Thread sleep 1000 }
  }
  def timeFlies() {
    println("second 1...")
  }

  def main(args: Array[String]) {
    oncePerSecond(timeFlies)
  }
}

이렇게 해 주면 second 1...이게 1초마다 나옵니다.
여기서 timeFlies 이걸 뺄수도 있는데요 다음과 같습니다 :)

object TimerAnonymous {
  def oncePerSecond(callback: () => Unit) {
    while (true) { callback(); Thread sleep 1000 }
  }
  def main(args: Array[String]) {
    oncePerSecond(() =>
      println("second 1..."))
  }
}

역시나 저는 이게 좀 더 보기 좋네요. 이렇게 쓰는 방식을 가지고 무명 펑션(Anonymous functions) 방식이라고 하는 것 같습니다.

이번에는 복합(complex)클래스를 하나 만들어서 여러개의 값을 가지고 있는 클래스를 하나 만들어 볼까 합니다. 이건 예전에 get, set방식인 bean방식 같네요 :) 물론 더욱 더 편해졌고요 :)

scala> class Complex(str1: String, imaginary: Double) {
     | def st() = str1
     | def im() = imaginary
     | }
defined class Complex

scala> object ComplexNumbers {
     | def main(args: Array[String]) {
     | val c = new Complex("firstData", 3.4)
     | println("String part: " + c.st())
     | println("imaginary part: " + c.im())
     | }
     | }
defined module ComplexNumbers

scala> ComplexNumbers.main(null)
String part: firstData
imaginary part: 3.4

이런 결과가 나오게 됩니다 :) 이해는 바로 되셨을꺼라 생각되네요 :)

그리고 다음으로는 abstract 이건 뭐 :) 설명 없으셔도 알 듯 이전에 자바 하셨던 분이라면
abstract class Term
case class Var(name: String) extends Term
case class Fun(arg: String, body: Term) extends Term
case class App(f: Term, v: Term) extends Term
이런 식으로 사용하시면 됩니다 :) 그리고 이걸 어디에 이용하느냐 바로 case classes :)에 사용하려 합니다.
소스 쭉 나갑니다 메모 메모! :)
scala> val x = Var("x")
x: Var = Var(x)
scala> Console.println(x.name)
x
scala> val x1 = Var("x")
x1: Var = Var(x)
scala> val x2 = Var("x")
x2: Var = Var(x)
scala> val y1 = Var("y")
y1: Var = Var(y)
scala> println("" + x1 + " == " + x2 + " => " + (x1 == x2))
Var(x) == Var(x) => true
scala> println("" + x1 + " == " + y1 + " => " + (x1 == y1))
Var(x) == Var(y) => false

이런식으로 결과 값이 나오게 됩니다. 재미있지 않나요? 특히 저는 x.name 이 부분에 감동을 :)
이걸 응용해서 하나 더 짜보면,
scala> object TermTest extends Application {
     |   def printTerm(term: Term) {
     |     term match {
     |       case Var(n) =>
     |         print(n)
     |       case Fun(x, b) =>
     |         print("^" + x + ".")
     |         printTerm(b)
     |       case App(f, v) =>
     |         Console.print("(")
     |         printTerm(f)
     |         print(" ")
     |         printTerm(v)
     |         print(")")
     |     }
     |   }
     |   def isIdentityFun(term: Term): Boolean = term match {
     |     case Fun(x, Var(y)) if x == y => true
     |     case _ => false
     |   }
     |   val id = Fun("x", Var("x"))
     |   val t = Fun("x", Fun("y", App(Var("x"), Var("y"))))
     |   printTerm(t)
     |   println
     |   println(isIdentityFun(id))
     |   println(isIdentityFun(t))
     | }
defined module TermTest

scala> TermTest
^x.^y.(x y)
true
false
res14: TermTest.type = TermTest$@4b7b1

아주 꼬리에 꼬리를 무는 모듈입니다. :) 너무 너무 좋네요 :)

자 그럼 마지막으로 case classes의 최종본을 볼까요 :)
scala> abstract class Tree
defined class Tree
scala> case class Sum(l: Tree, r: Tree) extends Tree
defined class Sum
scala> case class Var(n: String) extends Tree
defined class Var
scala> case class Const(v: Int) extends Tree
defined class Const

scala> type Environment = String => Int
defined type alias Environment

scala> def eval(t: Tree, env: Environment): Int = t match {
     | case Sum(l, r) => eval(l, env) + eval(r, env)
     | case Var(n) => env(n)
     | case Const(v) => v
     | }
eval: (Tree,(String) => Int)Int
scala> def derive(t: Tree, v: String): Tree = t match {
     | case Sum(l, r) => Sum(derive(l, v), derive(r, v))
     | case Var(n) if (v == n) => Const(1)
     | case _ => Const(0)
     | }
derive: (Tree,String)Tree
scala> def main(args: Array[String]) {
     | val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))
     | val env: Environment = { case "x" => 5 case "y" => 7 }
     | println("Expression: " + exp)
     | println("Evaluation with x=5, y=7: " + eval(exp, env))
     | println("Derivative relative to x:\n " + derive(exp, "x"))
     | println("Derivative relative to y:\n " + derive(exp, "y"))
     | }
main: (Array[String])Unit
scala> main(null)
Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y)))
Evaluation with x=5, y=7: 24
Derivative relative to x:
 Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0)))
Derivative relative to y:
 Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))

이 정도가 되겠습니다 :)

일단 글이 길어 졌네요 다음편에는 if, for, foreach, switch 와 같은 뭔가 흐름을 제어하는 것들에 대해서 한번 알아 볼까 합니다. :)
Posted by nkdk
My Programing/Scala&Lift2010/06/10 23:19
이번 에는 포켓 체인지에 대해서 해 볼까요?

일단 http://wiki.liftweb.net/index.php?title=Lift_View_First 이 사이트를 봐 보시지요.

<html>
...
<lift:snippet type="show:myForm" form="POST">
<tr><td>Name</td><td><f:name><input type="text"/></f:name></td></tr>
<tr><td>Birthyear</td><td><f:year><select><option>2007</option><option>2006</option></select></f:year></td></tr>
<tr><td>&nbsp;</td><td><input type="submit" value="Add"/></td></tr>
</lift:snippet>
...
</html>
이렇게 뷰 부분에 선언이 되어 있는데 이것도 저희 회사 사장님이 자주 이야기 하시는 것 처럼
감각적으로 보게 되면

class Show {
def myForm(xhtml: Group) = {
var name = ""
def handleYear(year: String) {
... the form's been submitted... do something
}
Helpers.bind("f", xhtml, "name" -> SHtml.text(name, name = _),
"year" -> SHtml.select((1900 to 2007).toList.reverse.map(v => (v.toString, v.toString)),
Empty, handleYear _))
}
}

이렇게 하면 show:myForm 라는 타이프가 scala에 코드와 미묘하게 바인딩이 되는게 보이실 겁니다.


두번째 예제를 보면

<table>
<lift:snippet type="show:users">
<tr><td><f:first_name>David</f:first_name></
td><td><f:last_name>Pollak</f:last_name></td></tr>
</lift:snippet>

</table>

그럼 snippet은?

class Show {
def users(xhtml: Group) = Users.findAll.flatMap(user => bind("f",
xhtml, "first_name" --> user.firstName, "last_name" --> user.nameName))
}


정도가 되겠네요.

자 그럼 다음으로 git으로 공개 되 있는 소스좀 받아 볼까 하는데요.

http://git-scm.com/download 로 가서 다운로드를 시도해 봅시다

잘 되네요.

자 그럼
git clone git://github.com/tjweir/pocketchangeapp.git

이 명령어로 소스를 받아 볼까요. 그럼 일단 기본적인 모양이 나오니 참고하시면 좋겠네요.

이제 부터 이 소스를 중점으로 가지고 설명할 것이니.. 꼭 받으세요. 추가로 저는 맥으로 작업 중입니다.
다른 환경에서의 테스트는 해보지 않았기 때문에.. 잘 될지는 모르지만, 지금 모양으로 봐서는 잘 될거 같네요.

다음 화에서는 전체 시스템에 축이 되는 모델에 정의 방법에 대해서 같이 한번 봅시다.


Posted by nkdk
TAG Lift, scala
My Programing/Scala&Lift2010/06/08 23:15

일단 기본 설정 까지는 이렇게 하고 기본적인 구조를 봐 볼까요.

/src/main/webapp 여기에는 HTML소스라던지가 위치하면 되겠네요.. 실제 현재 보고 있는 메인인 index.html이 여기에 있습니다.
그리고 이 폴더에서 한칸 위에 있는
/src/main/webapp/WEB-INF 여길 가 보시면 예전 톰캣 하신분은 아시겠지마, 웹 어플리케이션 설정에 관련된 XML이 들어가 있습니다. 필터 맵핑이라던지, 맵핑이라더지, 해서 url패턴에 따라 접속이 가능하게 한다던지 등등..이 있겠지요.

일단 리프트에서 보게 되는 전체적 구조가 있는데
<prefix:element> 이런식으로 구조를 띄고 있습니다. 이 말은 <lift:surround> 이런식으로 되어 있다는 이야기입니다. 자세한건 조금씩 하면서 보죠.

일단 기본적으로 선언하겠다 싶은게
 <lift:surround with="default" at="content"> 라고 하며 되겠네요. 여기서 디폴트와 그리고 content라는 부분을 잘 봐두세요.
이 부분이 index.html가 있는 폴더에 templates-hidden 폴더로 들어가면
default.html라는 파일이 있는데 여기서 <lift:bind name="content" /> 이 부분에 content입니다.
그리고 혹시 눈치 채신분도 있으시겠지만 파일 이름이 default.html이죠? 아까 그 선언에서 with에 해당하는 이름입니다. 참 특이한 구조군요.

그리고 index.html에 보면 <lift:helloWorld.howdy />  가 있는데 이게 뭔지 좀 봅시다.
일단 이 의미는 helloWorld.scala파일에 howdy라는 펑션이 있을꺼라는 추정이 되네요.
실제로도 그렇고요 src/main/scala/demo/helloworld/snippet 를 보면 HelloWorld.scala라는 파일이 있습니다.
그리고 그 안에 보면 def howdy라는 정의가 있습니다. 뭔가 제대로 가고 있는 것 같네요.

그리고 그 내용을 보면 대충
class HelloWorld {
  def howdy(in: NodeSeq): NodeSeq =
     Helpers.bind("b", in, "time" -> (new _root_.java.util.Date).toString)
}

이런 내용이 써 있는데.. 이 내용을 이야기 하자면, index.html에서
      <lift:helloWorld.howdy>
        <span>Welcome to helloworld at <b:time/></span>
      </lift:helloWorld.howdy>
이 부분이 있는데 이 부분에서 b:time이 부분을 유심히 보면 위에 선언되어 있는 이름이랑 뭔가 딱 들어맞지 않나요? 저도 필이 막 오더라고요.

그리고 이 필은 딱 들어 맞고요. 그걸 나타내는 거 였습니다.

자 다음 화에서는 pocket Change에 대해서 알아 볼까요?

Posted by nkdk
TAG Lift, SOL
My Programing/Scala&Lift2010/06/08 21:50
안녕하세요? 이번에는 스칼라를 이용해 웹 개발을 할 때 거의 절대적으로 필요하다고 할 수 있는.. lift 라는 프레임워크를 같이 한번 보도록 하며 좋겠네요.

일단 기본적인 헬로우 월드까지는 명령어 몇개만 가지고도 끝나버리네요.

기본적인 틀은 다 만들어 주네요. 철저하게 mvc패턴도 지키고 있는 것이 마음에 드네요.

스칼라에 펑션 언어 스타일에 리프트에 편리함이 뒷받침이 정말 환상 조합이네요. 자 시작해 봅시다.


일단.

스칼라 혹은 웹 서버가 되는 jetty에 설치까지 자동으로 해 줍니다.
그런데 jdk까지 설치해주는지는 확인 안했네요. 원래 깔려 있었거든요.
안전하게 깔고 하세요.

일단 lift를 받습니다.

http://www.liftweb.net 입니다.

여기서 다운로드를 하시고, 압축을 풀어주세요.
그리고 해당 커맨드가 어디서도 먹게끔 설정을 해 주세요. path를 잡아 달라는 말씀이지요.

자 그리고 일정 폴더를 만드세요.

mkdir work
cd work 

그리고 커맨드 창에서 다음에 명령어를 치세요.

mvn archetype:generate -U -DarchetypeGroupId=net.liftweb -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=1.0 -DgroupId=demo.helloworld -DartifactId=helloworld -Dversion=1.0-SNAPSHOT

이렇게 치면 뭔가 한창 설치 합니다. 그 내용을 대충 보면 maven이라는 것과 여러가지 필요한 플러그인들과 스칼라를 다운로드 받고요 기본적인 모양을 갖춥니다.

자 그럼 이제 웹서버에 올려야 겠죠?

mkdir helloworld
cd helloworld
mvn jetty:run

이렇게 하면 또 한 10분 정도 혼자 쭉 뭘 합니다.

그리고 끝나면 완성 -_-V

뭐가 완성이냐 하시겠지만, 이게 끝입니다.

http://localhot:8080 으로 들어가 보세요. 이미 웹서버도 떠 있고 헬로우 월드라는 반가운
페이지가 여러분을 반깁니다.

현재 2010년 6월 10일에 한 결과 스칼라가 2.7.7버전이 받아 지네요
현재는 2.8 RC3까지 나온 상태인데.. 이건 좀 더 봐야 할 것 같아요.

다음 편에서는 기본적인 구조를 한번 보죠.
Posted by nkdk
TAG sol lift
My Programing/Scala&Lift2010/06/05 14:28
이번에는 괜찮은 IDE소개 할려고 합니다. 예전에 저 같은 경우는 콘솔 혹은 이클립스에서 플러그인을 설치하여 하는 형태로 했는데.. 그것보다 좀 더 좋은 것 같은 에디터가 있어서 소개 할까 하고요. ^^;

이름하여 외우기도 힘든
IntelliJ IDEA

입니다. 현재 무료 버전으로는 Community Edition 9.0.2 가 있네요.

일단 사이트는 http://www.jetbrains.com/idea/download/index.html#win 여기입니다.

--

시작은 콘솔로 입력해보았지만 개발을 콘솔로 계속 할 것은 아니기 때문에 IDE가 필요합니다. Eclipse에서 Scala플러그인이 존재하고 있기는 하지만 아직 불안정한 면이 있기 때문에 현재로써는 IntelliJ IDEA 가 스칼라를 개발하기에 가장 좋은 환경이라고 합니다. IntelliJ는 거의 처음 사용하는 것과 마찬가지라서 인터페이스 면에서 여러가지로 헤메이고 있는 중입니다. ㅎ

사용자 삽입 
이미지

Setting에 들어가서 Plugins 카테고리에 들어가서 Available탭부분에서 Scala로 검색을 합니다. Scala와 Scala Power Pack 이 나오는데 Scala만 설치해줍니다.(Power Pack은 설치하면 안된다고 합니다.) 오른쪽 마우스클릭으로 Download and Install을 실행하여 설치한 뒤에 IntelliJ를 재시작해줍니다. 재시작뒤에는 Installed 탭에서 Scala가 추가된 것을 확인할 수 있습니다.

사용자 삽입 
이미지 사용자 삽입 
이미지

이제 New Project에서 Create project from scratch를 선택하여 프로젝트 생성을 진행하면서 위의 화면에서 Scala를 선택하고 Finish를 누르면 scala-library를 자동으로 다운로드 받은 뒤에 프로젝트가 생성됩니다.(현재 스칼라는 2.8.0RC3까지 릴리즈 되어 있는데 플러그인에서는  2.8.0RC1까지만 지원하고 있는듯 합니다.)

사용자 삽입 
이미지

프로젝트의 src폴더에서 Scala Class를 선택한 뒤 HelloWorld를 입력하고 kind를 Object로 선택해 줍니다.

사용자 삽입 
이미지

Object안에 위의 Hello World의 코드를 작성해 줍니다. IntelliJ에서는 main입력후 Tab을 누르면 메인메서드가 자동으로 완성됩니다.

사용자 삽입 
이미지

이제 실행(Ctrl + Shift + F10)을 하면 실행된 화면을 볼 수 있습니다. Run\Debug Configulation에서 Scala콘솔을 추가한뒤 선택하고 Run을 하면 IntelliJ내에서 Scala콘솔을 실행할 수 있습니다.

참조 사이트 http://blog.outsider.ne.kr



----

그런데 여기서 주의할 점이 하나 있다. 바로 인코딩이다! UTF-8 어쩌구 저쩌구 에러가 나서 무언가 했더니 글쎄 *.scala파일이 Shift_jis형태이지 않은가 -- UTF-8로 파일 형태를 바꾸니 바로 된다. ^^ 참조하기 바란다.



Posted by nkdk
TAG SCALA IDE
My Programing/Scala&Lift2010/06/03 01:38
이번에는 주요 기능들이라기 하기 모한 샘플 소스들 입니다. 보고 이해 하세요 ^^

Abstract Types

object abstractTypes extends Application {
  abstract class Buffer {
type T; val element: T
}
abstract class SeqBuffer {
type T; val element: Seq[T]; def length = element.length
}
def newIntBuffer(el: Int) = new Buffer {
type T = Int; val element = el
}
def newIntBuffer(el: Int*) = new SeqBuffer {
type T = Int; val element = el
}
println(newIntBuffer(1).element)
println(newIntBuffer(1, 2, 3).length)
}
Result:
1
3

BigInt

/** Bigint's can be used seamlessly */
object bigint extends Application {
def factorial(n: BigInt): BigInt =
if (n == 0) 1 else n * factorial(n-1)

val f50 = factorial(50); val f49 = factorial(49)
println("50! = " + f50)
println("49! = " + f49)
println("50!/49! = " + (f50 / f49))
}

Complex Operations

object complexOps extends Application {
  class Complex(val re: Double, val im: Double) {
    def + (that: Complex) =
      new Complex(re + that.re, im + that.im)
    def - (that: Complex) =
      new Complex(re - that.re, im - that.im)
    def * (that: Complex) =
      new Complex(re * that.re - im * that.im,
                  re * that.im + im * that.re)
    def / (that: Complex) = {
      val denom = that.re * that.re + that.im * that.im
      new Complex((re * that.re + im * that.im) / denom,
                  (im * that.re - re * that.im) / denom)
    }
    override def toString =
      re + (if (im < 0) "-" + (-im) else "+" + im) + "*i"
  }
  val x = new Complex(2, 1); val y = new Complex(1, 3)
  println(x + y)
}

For and Yield

/** Turn command line arguments to uppercase */
object Main {
def main(args: Array[String]) {
val res = for (a <- args) yield a.toUpperCase
println("Arguments: " + res.toString)
}
}

Extend Builtins

/* Adding ! as a method on int's */
object extendBuiltins extends Application {
def fact(n: Int): BigInt =
if (n == 0) 1 else fact(n-1) * n
class Factorizer(n: Int) {
def ! = fact(n)
}
implicit def int2fact(n: Int) = new Factorizer(n)

println("10! = " + (10!))
}

Maps

/** Maps are easy to use in Scala. */
object Maps {
val colors = Map("red" -> 0xFF0000,
"turquoise" -> 0x00FFFF,
"black" -> 0x000000,
"orange" -> 0xFF8040,
"brown" -> 0x804000)
def main(args: Array[String]) {
for (name <- args) println(
colors.get(name) match {
case Some(code) =>
name + " has code: " + code
case None =>
"Unknown color: " + name
}
)
}
}

Implicits

/* Defines a new method 'sort' for array objects */
object implicits extends Application {
implicit def arrayWrapper[A : ClassManifest](x: Array[A]) =
new {
def sort(p: (A, A) => Boolean) = {
util.Sorting.stableSort(x, p); x
}
}
val x = Array(2, 3, 1, 4)
println("x = "+ x.sort((x: Int, y: Int) => x < y))
}

Match Arguments

/** Basic command line parsing. */
object Main {
var verbose = false

def main(args: Array[String]) {
for (a <- args) a match {
case "-h" | "-help" =>
println("Usage: scala Main [-help|-verbose]")
case "-v" | "-verbose" =>
verbose = true
case x =>
println("Unknown option: '" + x + "'")
}
if (verbose)
println("How are you today?")
}
}

Primes

/** Print prime numbers less than 100, very inefficiently */
object primes extends Application {
def isPrime(n: Int) = (2 until n) forall (n % _ != 0)
for (i <- 1 to 100 if isPrime(i)) println(i)

}

Sum Arguments

object Main {
  def main(args: Array[String]) {
try {
val elems = args map Integer.parseInt
println("The sum of my arguments is: " + elems.foldRight(0) (_ + _))
} catch {
case e: NumberFormatException =>
println("Usage: scala Main <n1> <n2> ... ")
}
}
}

Varargs

/** Using Java varargs */
object varargs extends Application {
val msg = java.text.MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet {0}.",
"Hoth", new java.util.Date(), "a disturbance in the Force")
println("Message="+msg)
}

아무래도 윈도우 용이겠죠? :)?

다음과 같이 실행해 보세요 ^^

> mkdir classes
> scalac -d classes %SCALA_HOME%\doc\scala-devel-docs\scala\examples\sort.scala
> scala -cp classes examples.sort
[6,2,8,5,1]

[1,2,5,6,8]

다음화에서 고급용으로 ^^
Posted by nkdk
TAG scala
My Programing/Scala&Lift2010/06/02 21:59
Scala공부를 시작할까 합니다. ^^

오랜만에 시작하는 프로그래밍 언어군요.

일단 이 프로그램 언어는 펑션 프로그래밍이라고 하여 재미있는 점이 꽤 있더라고요.

Getting Started with Scala


자 시작해 봅시다.

일단 왜 스칼라인가 부터 있어야 하지 않을까요? 저도 한지는 얼마 되지 않아서 확실하게 정의하기는 힘들지만.. 일단 이 스칼라라는 언어는 자바를 완벽 지원합니다. 현재 저 같은 경우는 jre1.6.20 에서 작업하는데 완벽 지원되네요 ^^

그리고 또한 그 후에 파생되는 lift라는 프레임워크로 Ruby on Rails(이하 ROR)와 같은 효과를 낼 수 있는 일명 -- 뽑아내기 프로그램이 가능합니다. 그런데 왜! ROR로 하지 스칼라를 먼저 선택해서 해 보는가입니다. 일단.. 현 회사에서 ROR로 만들어져 있고 정말 간단하게 구축되어지는 모습을 보면 ROR을 먼저 파볼까 하고 했지만.. 역시나 속도의 면이나 기동의 면을 봤을 때 스칼라가 더 좋을 거 같더라고요. 일단 펑션 프로그래밍이라는 부분이 있던데 여기에 흥미가 생기더군요. 또한 예전부터 자바 프로그래밍을 했었기 때문에 여러 이슈들에 대해서에 대한 자신감? 하지만 역시 처음 배우는 부분에서는 헤매는건 마찬가지겠지요 :)
하지만.. 헤매는게 어느 정도 시간이 걸리는거는 배워 나가다 보니까 조금씩 익숙해 지는 시간이 줄어 드는 것 같습니다. ^^; 자 그럼 시작해 봅시다.
역시나 제대로된 장점 제대로된 결론적인 것들은 맨 나중에 씁시다. 꼭 목차에 뭐가 좋다 뭐가 좋다 이런거 인터넷에 많이 떠들어져 있지만, 역시 제가 한번 경험해 볼렵니다. 자 고고!

일단 처음 시작이니까 환경 잡아야죠?

일단 윈도우 환경으로 해 볼까요?

1. http://www.scala-lang.org/downloads
여기서 스칼라를 받습니다.
그리고 이게 자바 환경에서 돌아 가기 때문에

2. http://java.sun.com/javase/downloads/widget/jdk6.jsp
자바를 받습니다. ^^

그리고
윈도우 환경 변수를 잡아야 겠죠? 저는 jdk와 scala를 program_lang에다가 깔았어요.

SCALA_HOME : C:\program_lang\scala-2.8.0.RC3
JAVA_HOME : C:\program_lang\Java\jre6
Path : ;%SCALA_HOME%\bin <-이 부분 추가

환경은 이게 끝입니다. ^^;


자 그럼 시작해 볼까요? 역시나 Hello world의 아류작인 Hello Scala!를 만들어 보겠습니다.

window용 CMD
-- Start
C:> scala
Welcome to Scala ----

scala> object HelloWorld {
| def main(args: Array[String]) {
| println("Hello, world!")
| }
| }
defined module HelloWorld

scala> HelloWorld.main(null)
Hello, world!
unnamed0: Unit = ()
scala>:q
--end


이게 다음으로 재미있는게 리눅스나 유닉스에서 쉘 스크립트 프로그래밍으로 쓸 수도 있답니다. ^^

-- 쉘 스크립트 bash start

#!/bin/sh
exec scala "$0" "$@"
!#

object HelloWorld {
def main(args: Array[String]) {
println("Hello, world! " + args.toList)
}
}
HelloWorld.main(args)
-- end

자 다음은 scala파일의 컴파일 방법 인데요.

scalac HelloWorld.scala
scalac -d classes HelloWorld.scala <-기본 디렉토리 설정시

실행시
scala HelloWorld
scala -classpath classes HelloWorld <-classes폴더도 포함 실행

만약 기본적 메인을 쓰고 뭔가 간단한 작업만을 하고 싶다면,

object helloAppli extends Application {
println("Hello, world!")
}

이걸 써도 괜찮네요. Application이라는 클래스를 상속하면 되네요 ^^

그럼 다음 편에서 뵐께요 다음편에서는 스칼라의 주요 기능들이라는 제목으로 할까 생각 중인데.. ^^
주요 기능이라기는 뭐한가? ^^
Posted by nkdk
TAG scala
My Programing/Scala&Lift2010/05/27 20:20
http://cherrykyun.tistory.com/265

일단 이걸 참조하자.

스칼라가 무엇인지를 알 수 있을 것이다 :) 차후 책을 보며 공부 하며 내용을 정리할 것이다.
Posted by nkdk