diff options
| author | Suzane Sant Ana <tetestonaldo@gmail.com> | 2017-12-31 14:27:06 -0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-12-31 14:27:06 -0200 | 
| commit | 42f9329bb3a028d374d6397991ac48b44064741e (patch) | |
| tree | 1e75e2b3e122aeb863e3ffa037f6f64c4027fbf8 /scala.html.markdown | |
| parent | e6b77595f2669d66ac7be43c6e6083cbff80a9a7 (diff) | |
| parent | 70a36c9bd970b928adde06afb2bd69f6ba8e5d5c (diff) | |
Merge pull request #1 from adambard/master
update
Diffstat (limited to 'scala.html.markdown')
| -rw-r--r-- | scala.html.markdown | 277 | 
1 files changed, 192 insertions, 85 deletions
| diff --git a/scala.html.markdown b/scala.html.markdown index 61c735e3..78053b40 100644 --- a/scala.html.markdown +++ b/scala.html.markdown @@ -5,53 +5,98 @@ contributors:      - ["George Petrov", "http://github.com/petrovg"]      - ["Dominic Bou-Samra", "http://dbousamra.github.com"]      - ["Geoff Liu", "http://geoffliu.me"] -filename: learn.scala +    - ["Ha-Duong Nguyen", "http://reference-error.org"]  ---  Scala - the scalable language  ```scala +///////////////////////////////////////////////// +// 0. Basics +/////////////////////////////////////////////////  /* -  Set yourself up: +  Setup Scala:    1) Download Scala - http://www.scala-lang.org/downloads -  2) unzip/untar in your favourite location and put the bin subdir on the path -  3) Start a scala REPL by typing scala. You should see the prompt: +  2) Unzip/untar to your favorite location and put the bin subdir in your `PATH` environment variable +*/ -  scala> +/* +  Try the REPL -  This is the so called REPL (Read-Eval-Print Loop). You may type any valid -  Scala expression into it, and the result will be printed. We will explain what -  Scala files look like further into this tutorial, but for now, let's start -  with some basics. +  Scala has a tool called the REPL (Read-Eval-Print Loop) that is analogous to +  commandline interpreters in many other languages. You may type any Scala +  expression, and the result will be evaluated and printed.   + +  The REPL is a very handy tool to test and verify code.  Use it as you read +  this tutorial to quickly explore concepts on your own.  */ +// Start a Scala REPL by running `scala`. You should see the prompt: +$ scala +scala> + +// By default each expression you type is saved as a new numbered value +scala> 2 + 2 +res0: Int = 4 + +// Default values can be reused.  Note the value type displayed in the result.. +scala> res0 + 2 +res1: Int = 6 + +// Scala is a strongly typed language. You can use the REPL to check the type +// without evaluating an expression. +scala> :type (true, 2.0) +(Boolean, Double) + +// REPL sessions can be saved +scala> :save /sites/repl-test.scala + +// Files can be loaded into the REPL +scala> :load /sites/repl-test.scala +Loading /sites/repl-test.scala... +res2: Int = 4 +res3: Int = 6 + +// You can search your recent history +scala> :h? +1 2 + 2 +2 res0 + 2 +3 :save /sites/repl-test.scala +4 :load /sites/repl-test.scala +5 :h? + +// Now that you know how to play, let's learn a little scala...  /////////////////////////////////////////////////  // 1. Basics  ///////////////////////////////////////////////// -// Single line comments start with two forward slashes +// Single-line comments start with two forward slashes  /* -  Multi line comments, as you can already see from above, look like this. +  Multi-line comments, as you can already see from above, look like this.  */  // Printing, and forcing a new line on the next print  println("Hello world!")  println(10) +// Hello world! +// 10  // Printing, without forcing a new line on next print  print("Hello world") +print(10) +// Hello world10  // Declaring values is done using either var or val. -// val declarations are immutable, whereas var's are mutable. Immutability is +// val declarations are immutable, whereas vars are mutable. Immutability is  // a good thing.  val x = 10 // x is now 10 -x = 20 // error: reassignment to val +x = 20     // error: reassignment to val  var y = 10 -y = 20  // y is now 20 +y = 20     // y is now 20  /*    Scala is a statically typed language, yet note that in the above declarations, @@ -71,18 +116,19 @@ true  false  // Boolean operations -!true // false -!false // true +!true         // false +!false        // true  true == false // false -10 > 5 // true +10 > 5        // true  // Math is as per usual -1 + 1 // 2 -2 - 1 // 1 -5 * 3 // 15 -6 / 2 // 3 -6 / 4 // 1 +1 + 1   // 2 +2 - 1   // 1 +5 * 3   // 15 +6 / 2   // 3 +6 / 4   // 1  6.0 / 4 // 1.5 +6 / 4.0 // 1.5  // Evaluating an expression in the REPL gives you the type and value of the result @@ -120,12 +166,12 @@ s"We have $n apples" // => "We have 45 apples"  // Expressions inside interpolated strings are also possible  val a = Array(11, 9, 6) -s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old." +s"My second daughter is ${a(0) - a(2)} years old."    // => "My second daughter is 5 years old."  s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples." -s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4" +s"Power of 2: ${math.pow(2, 2)}"                      // => "Power of 2: 4"  // Formatting with interpolated strings with the prefix "f" -f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25" +f"Power of 5: ${math.pow(5, 2)}%1.0f"         // "Power of 5: 25"  f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"  // Raw strings, ignoring special characters. @@ -164,6 +210,12 @@ def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y  // Syntax for calling functions is familiar:  sumOfSquares(3, 4)  // => 25 +// You can use parameters names to specify them in different order +def subtract(x: Int, y: Int): Int = x - y + +subtract(10, 3)     // => 7 +subtract(y=10, x=3) // => -7 +  // In most cases (with recursive functions the most notable exception), function  // return type can be omitted, and the same type inference we saw with variables  // will work with function return values: @@ -171,12 +223,12 @@ def sq(x: Int) = x * x  // Compiler can guess return type is Int  // Functions can have default parameters:  def addWithDefault(x: Int, y: Int = 5) = x + y -addWithDefault(1, 2)  // => 3 -addWithDefault(1)  // => 6 +addWithDefault(1, 2) // => 3 +addWithDefault(1)    // => 6  // Anonymous functions look like this: -(x:Int) => x * x +(x: Int) => x * x  // Unlike defs, even the input type of anonymous functions can be omitted if the  // context makes it clear. Notice the type "Int => Int" which means a function @@ -186,15 +238,15 @@ val sq: Int => Int = x => x * x  // Anonymous functions can be called as usual:  sq(10)   // => 100 -// If your anonymous function has one or two arguments, and each argument is +// If each argument in your anonymous function is  // used only once, Scala gives you an even shorter way to define them. These  // anonymous functions turn out to be extremely common, as will be obvious in  // the data structure section.  val addOne: Int => Int = _ + 1  val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3) -addOne(5)  // => 6 -weirdSum(2, 4)  // => 16 +addOne(5)      // => 6 +weirdSum(2, 4) // => 16  // The return keyword exists in Scala, but it only returns from the inner-most @@ -204,9 +256,9 @@ weirdSum(2, 4)  // => 16  def foo(x: Int): Int = {    val anonFunc: Int => Int = { z =>      if (z > 5) -      return z  // This line makes z the return value of foo! +      return z // This line makes z the return value of foo!      else -      z + 2  // This line is the return value of anonFunc +      z + 2    // This line is the return value of anonFunc    }    anonFunc(x)  // This line is the return value of foo  } @@ -218,40 +270,42 @@ def foo(x: Int): Int = {  1 to 5  val r = 1 to 5 -r.foreach( println ) +r.foreach(println)  r foreach println  // NB: Scala is quite lenient when it comes to dots and brackets - study the  // rules separately. This helps write DSLs and APIs that read like English -(5 to 1 by -1) foreach ( println ) +(5 to 1 by -1) foreach (println) -// A while loops +// A while loop  var i = 0 -while (i < 10) {  println("i " + i); i+=1  } +while (i < 10) { println("i " + i); i += 1 } -while (i < 10) {  println("i " + i); i+=1  }   // Yes, again. What happened? Why? +while (i < 10) { println("i " + i); i += 1 }   // Yes, again. What happened? Why?  i    // Show the value of i. Note that while is a loop in the classical sense -       // it executes sequentially while changing the loop variable. while is very -     // fast, faster that Java loops, but using the combinators and -     // comprehensions above is easier to understand and parallelize +     // fast, but using the combinators and comprehensions above is easier +     // to understand and parallelize -// A do while loop +// A do-while loop +i = 0  do { -  println("x is still less than 10"); -  x += 1 -} while (x < 10) +  println("i is still less than 10") +  i += 1 +} while (i < 10) -// Tail recursion is an idiomatic way of doing recurring things in Scala. +// Recursion is the idiomatic way of repeating an action in Scala (as in most +// other functional languages).  // Recursive functions need an explicit return type, the compiler can't infer it.  // Here it's Unit. -def showNumbersInRange(a:Int, b:Int):Unit = { +def showNumbersInRange(a: Int, b: Int): Unit = {    print(a)    if (a < b)      showNumbersInRange(a + 1, b)  } -showNumbersInRange(1,14) +showNumbersInRange(1, 14)  // Conditionals @@ -261,7 +315,7 @@ val x = 10  if (x == 1) println("yeah")  if (x == 10) println("yeah")  if (x == 11) println("yeah") -if (x == 11) println ("yeah") else println("nay") +if (x == 11) println("yeah") else println("nay")  println(if (x == 10) "yeah" else "nope")  val text = if (x == 10) "yeah" else "nope" @@ -272,21 +326,21 @@ val text = if (x == 10) "yeah" else "nope"  /////////////////////////////////////////////////  val a = Array(1, 2, 3, 5, 8, 13) -a(0) -a(3) +a(0)     // Int = 1 +a(3)     // Int = 5  a(21)    // Throws an exception  val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") -m("fork") -m("spoon") +m("fork")         // java.lang.String = tenedor +m("spoon")        // java.lang.String = cuchara  m("bottle")       // Throws an exception  val safeM = m.withDefaultValue("no lo se") -safeM("bottle") +safeM("bottle")   // java.lang.String = no lo se  val s = Set(1, 3, 7) -s(0) -s(1) +s(0)      // Boolean = false +s(1)      // Boolean = true  /* Look up the documentation of map here -   * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map @@ -305,17 +359,24 @@ s(1)  (a, 2, "three")  // Why have this? -val divideInts = (x:Int, y:Int) => (x / y, x % y) +val divideInts = (x: Int, y: Int) => (x / y, x % y) -divideInts(10,3) // The function divideInts gives you the result and the remainder +// The function divideInts gives you the result and the remainder +divideInts(10, 3)    // (Int, Int) = (3,1)  // To access the elements of a tuple, use _._n where n is the 1-based index of  // the element -val d = divideInts(10,3) +val d = divideInts(10, 3)    // (Int, Int) = (3,1) + +d._1    // Int = 3 +d._2    // Int = 1 -d._1 +// Alternatively you can do multiple-variable assignment to tuple, which is more +// convenient and readable in many cases +val (div, mod) = divideInts(10, 3) -d._2 +div     // Int = 3 +mod     // Int = 1  ///////////////////////////////////////////////// @@ -359,7 +420,7 @@ class Dog(br: String) {  val mydog = new Dog("greyhound")  println(mydog.breed) // => "greyhound" -println(mydog.bark) // => "Woof, woof!" +println(mydog.bark)  // => "Woof, woof!"  // The "object" keyword creates a type AND a singleton instance of it. It is @@ -399,8 +460,52 @@ val otherGeorge = george.copy(phoneNumber = "9876")  // And many others. Case classes also get pattern matching for free, see below. +// Traits +// Similar to Java interfaces, traits define an object type and method +// signatures. Scala allows partial implementation of those methods. +// Constructor parameters are not allowed. Traits can inherit from other +// traits or classes without parameters. + +trait Dog { +	def breed: String +	def color: String +	def bark: Boolean = true +	def bite: Boolean +} +class SaintBernard extends Dog { +	val breed = "Saint Bernard" +	val color = "brown" +	def bite = false +}   + +scala> b   +res0: SaintBernard = SaintBernard@3e57cd70   +scala> b.breed   +res1: String = Saint Bernard   +scala> b.bark   +res2: Boolean = true   +scala> b.bite   +res3: Boolean = false   + +// A trait can also be used as Mixin. The class "extends" the first trait, +// but the keyword "with" can add additional traits. + +trait Bark { +	def bark: String = "Woof" +} +trait Dog { +	def breed: String +	def color: String +} +class SaintBernard extends Dog with Bark { +	val breed = "Saint Bernard" +	val color = "brown" +} -// Traits coming soon! +scala> val b = new SaintBernard +b: SaintBernard = SaintBernard@7b69c6ba +scala> b.bark +res0: String = Woof  ///////////////////////////////////////////////// @@ -414,8 +519,8 @@ val otherGeorge = george.copy(phoneNumber = "9876")  def matchPerson(person: Person): String = person match {    // Then you specify the patterns:    case Person("George", number) => "We found George! His number is " + number -  case Person("Kate", number) => "We found Kate! Her number is " + number -  case Person(name, number) => "We matched someone : " + name + ", phone : " + number +  case Person("Kate", number)   => "We found Kate! Her number is " + number +  case Person(name, number)     => "We matched someone : " + name + ", phone : " + number  }  val email = "(.*)@(.*)".r  // Define a regex for the next example. @@ -446,14 +551,17 @@ def matchEverything(obj: Any): String = obj match {    case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"    // You can nest patterns: -  case List(List((1, 2,"YAY"))) => "Got a list of list of tuple" +  case List(List((1, 2, "YAY"))) => "Got a list of list of tuple" + +  // Match any case (default) if all previous haven't matched +  case _ => "Got unknown object"  }  // In fact, you can pattern match any object with an "unapply" method. This  // feature is so powerful that Scala lets you define whole functions as  // patterns:  val patternFunc: Person => String = { -  case Person("George", number") => s"George's number: $number" +  case Person("George", number) => s"George's number: $number"    case Person(name, number) => s"Random person's number: $number"  } @@ -465,6 +573,7 @@ val patternFunc: Person => String = {  // Scala allows methods and functions to return, or take as parameters, other  // functions or methods. +val add10: Int => Int = _ + 10 // A function taking an Int and returning an Int  List(1, 2, 3) map add10 // List(11, 12, 13) - add10 is applied to each element  // Anonymous functions can be used instead of named functions: @@ -492,7 +601,7 @@ sSquared.reduce (_+_)  // The filter function takes a predicate (a function from A -> Boolean) and  // selects all elements which satisfy the predicate  List(1, 2, 3) filter (_ > 2) // List(3) -case class Person(name:String, age:Int) +case class Person(name: String, age: Int)  List(    Person(name = "Dom", age = 23),    Person(name = "Bob", age = 30) @@ -529,7 +638,7 @@ for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared   * best practices around them. We only include this section in the tutorial   * because they are so commonplace in Scala libraries that it is impossible to   * do anything meaningful without using a library that has implicits. This is - * meant for you to understand and work with implicts, not declare your own. + * meant for you to understand and work with implicits, not declare your own.   */  // Any value (vals, functions, objects, etc) can be declared to be implicit by @@ -540,8 +649,8 @@ implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)  // By itself, implicit keyword doesn't change the behavior of the value, so  // above values can be used as usual. -myImplicitInt + 2  // => 102 -myImplicitFunction("Pitbull").breed  // => "Golden Pitbull" +myImplicitInt + 2                   // => 102 +myImplicitFunction("Pitbull").breed // => "Golden Pitbull"  // The difference is that these values are now eligible to be used when another  // piece of code "needs" an implicit value. One such situation is implicit @@ -559,8 +668,8 @@ sendGreetings("Jane")  // => "Hello Jane, 100 blessings to you and yours!"  // Implicit function parameters enable us to simulate type classes in other  // functional languages. It is so often used that it gets its own shorthand. The  // following two lines mean the same thing: -def foo[T](implicit c: C[T]) = ... -def foo[T : C] = ... +// def foo[T](implicit c: C[T]) = ... +// def foo[T : C] = ...  // Another situation in which the compiler looks for an implicit is if you have @@ -569,8 +678,8 @@ def foo[T : C] = ...  // implicit conversion of type A => B, where A is the type of obj, and B has a  // method called "method", that conversion is applied. So having  // myImplicitFunction above in scope, we can say: -"Retriever".breed  // => "Golden Retriever" -"Sheperd".bark  // => "Woof, woof!" +"Retriever".breed // => "Golden Retriever" +"Sheperd".bark    // => "Woof, woof!"  // Here the String is first converted to Dog using our function above, and then  // the appropriate method is called. This is an extremely powerful feature, but @@ -593,11 +702,14 @@ import scala.collection.immutable._  import scala.collection.immutable.{List, Map}  // Rename an import using '=>' -import scala.collection.immutable.{ List => ImmutableList } +import scala.collection.immutable.{List => ImmutableList}  // Import all classes, except some. The following excludes Map and Set:  import scala.collection.immutable.{Map => _, Set => _, _} +// Java classes can also be imported. Scala syntax can be used +import java.swing.{JFrame, JWindow} +  // Your programs entry point is defined in an scala file using an object, with a  // single method, main:  object Application { @@ -628,13 +740,8 @@ writer.close()  ## Further resources -[Scala for the impatient](http://horstmann.com/scala/) - -[Twitter Scala school](http://twitter.github.io/scala_school/) - -[The scala documentation](http://docs.scala-lang.org/) - -[Try Scala in your browser](http://scalatutorials.com/tour/) - -Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) - +* [Scala for the impatient](http://horstmann.com/scala/) +* [Twitter Scala school](http://twitter.github.io/scala_school/) +* [The scala documentation](http://docs.scala-lang.org/) +* [Try Scala in your browser](http://scalatutorials.com/tour/) +* Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user) | 
