From 464189ff4ee5d8b3ce701003b135eb6fbe335020 Mon Sep 17 00:00:00 2001 From: chandra Date: Wed, 24 Oct 2018 16:43:09 -0400 Subject: [PATCH] Introduction to Scala Updated examples --- .gitignore | 4 +- core-scala/pom.xml | 2 +- .../scala/ControlStructuresDemo.scala | 44 ++++++++++ .../scala/com/baeldung/scala/Employee.scala | 29 +++++-- .../scala/com/baeldung/scala/HelloWorld.scala | 4 +- .../baeldung/scala/HigherOrderFunctions.scala | 29 +++++-- .../scala/com/baeldung/scala/IntSet.scala | 34 ++++++++ .../main/scala/com/baeldung/scala/Utils.scala | 85 ++++++------------- .../scala/ControlStructuresDemoUnitTest.scala | 33 +++++++ .../com/baeldung/scala/EmployeeUnitTest.scala | 32 ++++--- .../scala/HigherOrderFunctionsUnitTest.scala | 63 +++++++------- .../com/baeldung/scala/IntSetUnitTest.scala | 23 +++++ .../com/baeldung/scala/UtilsUnitTest.scala | 67 ++++++--------- 13 files changed, 291 insertions(+), 158 deletions(-) create mode 100644 core-scala/src/main/scala/com/baeldung/scala/ControlStructuresDemo.scala create mode 100644 core-scala/src/main/scala/com/baeldung/scala/IntSet.scala create mode 100644 core-scala/src/test/scala/com/baeldung/scala/ControlStructuresDemoUnitTest.scala create mode 100644 core-scala/src/test/scala/com/baeldung/scala/IntSetUnitTest.scala diff --git a/.gitignore b/.gitignore index 7fe2778755..0e71421ee7 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,6 @@ jmeter/src/main/resources/*-JMeter.csv **/tmp **/out-tsc **/nbproject/ -**/nb-configuration.xml \ No newline at end of file +**/nb-configuration.xml +core-scala/.cache-main +core-scala/.cache-tests diff --git a/core-scala/pom.xml b/core-scala/pom.xml index a5d6ac6e07..eb7c1c3330 100644 --- a/core-scala/pom.xml +++ b/core-scala/pom.xml @@ -47,7 +47,7 @@ - 2.11.8 + 2.12.7 diff --git a/core-scala/src/main/scala/com/baeldung/scala/ControlStructuresDemo.scala b/core-scala/src/main/scala/com/baeldung/scala/ControlStructuresDemo.scala new file mode 100644 index 0000000000..7c1281e573 --- /dev/null +++ b/core-scala/src/main/scala/com/baeldung/scala/ControlStructuresDemo.scala @@ -0,0 +1,44 @@ +package com.baeldung.scala + +/** + * Sample code demonstrating the various control structured. + * + * @author Chandra Prakash + * + */ +object ControlStructuresDemo { + def gcd(x : Int, y : Int) : Int = { + if (y == 0) x else gcd(y, x % y) + } + + def gcdIter(x : Int, y : Int) : Int = { + var a = x + var b = y + while (b > 0) { + a = a % b + val t = a + a = b + b = t + } + a + } + + def rangeSum(a : Int, b : Int) = { + var sum = 0; + for (i <- a to b) { + sum += i + } + sum + } + + def factorial(a : Int) : Int = { + var result = 1; + var i = 1; + do { + result *= i + i = i + 1 + } while (i <= a) + result + } + +} \ No newline at end of file diff --git a/core-scala/src/main/scala/com/baeldung/scala/Employee.scala b/core-scala/src/main/scala/com/baeldung/scala/Employee.scala index 3266b9a557..397f166aa7 100644 --- a/core-scala/src/main/scala/com/baeldung/scala/Employee.scala +++ b/core-scala/src/main/scala/com/baeldung/scala/Employee.scala @@ -1,10 +1,27 @@ package com.baeldung.scala -class Employee(val name: String, var salary: Int, annualIncrement: Int = 20) extends AnyRef { +/** + * Sample Code demonstrating a class. + * + * @author Chandra Prakash + * + */ +class Employee(val name : String, + var salary : Int, + annualIncrement : Int = 20) { - def incrementSalary(): Unit = { - salary += annualIncrement - } + def incrementSalary() : Unit = { + salary += annualIncrement + } + + override def toString = + s"Employee(name=$name, salary=$salary)" +} + +/** + * A Trait which will make the toString return upper case value. + */ +trait UpperCasePrinter { + override def toString = super.toString toUpperCase +} - override def toString = s"Employee(name=$name, salary=$salary)" -} \ No newline at end of file diff --git a/core-scala/src/main/scala/com/baeldung/scala/HelloWorld.scala b/core-scala/src/main/scala/com/baeldung/scala/HelloWorld.scala index fde03f2cb4..b3f0ce09a5 100644 --- a/core-scala/src/main/scala/com/baeldung/scala/HelloWorld.scala +++ b/core-scala/src/main/scala/com/baeldung/scala/HelloWorld.scala @@ -1,6 +1,6 @@ package com.baeldung.scala object HelloWorld extends App { - println("Hello World!") - args foreach println + println("Hello World!") + args foreach println } diff --git a/core-scala/src/main/scala/com/baeldung/scala/HigherOrderFunctions.scala b/core-scala/src/main/scala/com/baeldung/scala/HigherOrderFunctions.scala index bab28d4f86..df97013206 100644 --- a/core-scala/src/main/scala/com/baeldung/scala/HigherOrderFunctions.scala +++ b/core-scala/src/main/scala/com/baeldung/scala/HigherOrderFunctions.scala @@ -1,14 +1,27 @@ - - package com.baeldung.scala +/** + * Sample higher order functions. + * + * @author Chandra Prakash + * + */ object HigherOrderFunctions { - def mapReduce(r: (Int, Int) => Int, i: Int, m: Int => Int, a: Int, b: Int) = { - def iter(a: Int, result: Int): Int = { - if (a > b) result - else iter(a + 1, r(m(a), result)) - } - iter(a, i) + def mapReduce(r : (Int, Int) => Int, + i : Int, + m : Int => Int, + a : Int, b : Int) = { + def iter(a : Int, result : Int) : Int = { + if (a > b) result + else iter(a + 1, r(m(a), result)) + } + iter(a, i) + } + + def whileLoop(condition : => Boolean)(body : => Unit) : Unit = + if (condition) { + body + whileLoop(condition)(body) } } \ No newline at end of file diff --git a/core-scala/src/main/scala/com/baeldung/scala/IntSet.scala b/core-scala/src/main/scala/com/baeldung/scala/IntSet.scala new file mode 100644 index 0000000000..f1a5722a4e --- /dev/null +++ b/core-scala/src/main/scala/com/baeldung/scala/IntSet.scala @@ -0,0 +1,34 @@ +package com.baeldung.scala + +/** + * An abstract class for set of integers and its implementation. + * + * @author Chandra Prakash + * + */ +abstract class IntSet { + // add an element to the set + def incl(x : Int) : IntSet + + // whether an element belongs to the set + def contains(x : Int) : Boolean +} + +class EmptyIntSet extends IntSet { + + def contains(x : Int) : Boolean = false + + def incl(x : Int) = + new NonEmptyIntSet(x, this) +} + +class NonEmptyIntSet(val head : Int, val tail : IntSet) + extends IntSet { + + def contains(x : Int) : Boolean = + head == x || (tail contains x) + + def incl(x : Int) : IntSet = + if (this contains x) this + else new NonEmptyIntSet(x, this) +} \ No newline at end of file diff --git a/core-scala/src/main/scala/com/baeldung/scala/Utils.scala b/core-scala/src/main/scala/com/baeldung/scala/Utils.scala index af41685be9..93cd3e697e 100644 --- a/core-scala/src/main/scala/com/baeldung/scala/Utils.scala +++ b/core-scala/src/main/scala/com/baeldung/scala/Utils.scala @@ -1,66 +1,33 @@ package com.baeldung.scala +/** + * Some utility methods. + * + * @author Chandra Prakash + * + */ object Utils { - def average(x: Double, y: Double) = (x + y) / 2 + def average(x : Double, y : Double) = (x + y) / 2 - def gcd(x: Int, y: Int): Int = { - if (y == 0) x else gcd(y, x % y) + def randomLessThan(d : Double) = { + var random = 0d + do { + random = Math.random() + } while (random >= d) + random + } + + def power(x : Int, y : Int) : Int = { + def powNested(i : Int, accumulator : Int) : Int = { + if (i <= 0) accumulator + else powNested(i - 1, x * accumulator) } + powNested(y, 1) + } - def gcdIter(x: Int, y: Int): Int = { - var a = x - var b = y - while (b > 0) { - a = a % b - val t = a - a = b - b = t - } - return a - } - - def rangeSum(a: Int, b: Int) = { - var sum = 0; - for (i <- a to b) { - sum += i - } - sum - } - - def factorial(a: Int): Int = { - var result = 1; - var i = a; - do { - result *= i - i = i - 1 - } while (i > 0) - result - } - - def randomLessThan(d: Double) = { - var random = 0d - do { - random = Math.random() - } while (random >= d) - random - } - - def whileLoop(condition: => Boolean)(body: => Unit): Unit = - if (condition) { - body - whileLoop(condition)(body) - } - - def power(x: Int, y: Int): Int = { - def powNested(i: Int, accumulator: Int): Int = { - if (i <= 0) accumulator - else powNested(i - 1, x * accumulator) - } - powNested(y, 1) - } - - def fibonacci(n: Int): Int = n match { - case 0 | 1 => 1 - case x if x > 1 => fibonacci(x - 1) + fibonacci(x - 2) - } + def fibonacci(n : Int) : Int = n match { + case 0 | 1 => 1 + case x if x > 1 => + fibonacci(x - 1) + fibonacci(x - 2) + } } \ No newline at end of file diff --git a/core-scala/src/test/scala/com/baeldung/scala/ControlStructuresDemoUnitTest.scala b/core-scala/src/test/scala/com/baeldung/scala/ControlStructuresDemoUnitTest.scala new file mode 100644 index 0000000000..71422a8b4f --- /dev/null +++ b/core-scala/src/test/scala/com/baeldung/scala/ControlStructuresDemoUnitTest.scala @@ -0,0 +1,33 @@ +package com.baeldung.scala + +import com.baeldung.scala.ControlStructuresDemo._ +import org.junit.Test +import org.junit.Assert.assertEquals + +class ControlStructuresDemoUnitTest { + @Test + def givenTwoIntegers_whenGcdCalled_thenCorrectValueReturned = { + assertEquals(3, gcd(15, 27)) + } + + @Test + def givenTwoIntegers_whenGcdIterCalled_thenCorrectValueReturned = { + assertEquals(3, gcdIter(15, 27)) + } + + @Test + def givenTwoIntegers_whenRangeSumcalled_thenCorrectValueReturned = { + assertEquals(55, rangeSum(1, 10)) + } + + @Test + def givenPositiveInteger_whenFactorialInvoked_thenCorrectValueReturned = { + assertEquals(720, factorial(6)) + } + + @Test + def whenFactorialOf0Invoked_then1Returned = { + assertEquals(1, factorial(0)) + } + +} \ No newline at end of file diff --git a/core-scala/src/test/scala/com/baeldung/scala/EmployeeUnitTest.scala b/core-scala/src/test/scala/com/baeldung/scala/EmployeeUnitTest.scala index 997a11a518..c51631dd2c 100644 --- a/core-scala/src/test/scala/com/baeldung/scala/EmployeeUnitTest.scala +++ b/core-scala/src/test/scala/com/baeldung/scala/EmployeeUnitTest.scala @@ -1,22 +1,30 @@ package com.baeldung.scala +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert._ class EmployeeUnitTest { - @Test - def whenEmployeeSalaryIncremented_thenCorrectSalary() = { - val employee = new Employee("John Doe", 1000); - employee.incrementSalary(); - assertEquals(1020, employee.salary); - } + @Test + def whenEmployeeSalaryIncremented_thenCorrectSalary = { + val employee = new Employee("John Doe", 1000) + employee.incrementSalary() + assertEquals(1020, employee.salary) + } + + @Test + def givenEmployee_whenToStringCalled_thenCorrectStringReturned = { + val employee = new Employee("John Doe", 1000) + assertEquals("Employee(name=John Doe, salary=1000)", employee.toString) + } + + @Test + def givenEmployeeWithTrait_whenToStringCalled_thenCorrectStringReturned = { + val employee = + new Employee("John Doe", 1000) with UpperCasePrinter + assertEquals("EMPLOYEE(NAME=JOHN DOE, SALARY=1000)", employee.toString) + } - @Test - def givenEmployee_whenToStringCalled_thenCorrectStringReturned() = { - val employee = new Employee("John Doe", 1000); - assertEquals("Employee(name=John Doe, salary=1000)", employee.toString); - } } diff --git a/core-scala/src/test/scala/com/baeldung/scala/HigherOrderFunctionsUnitTest.scala b/core-scala/src/test/scala/com/baeldung/scala/HigherOrderFunctionsUnitTest.scala index a939e38c25..63530ecaf4 100644 --- a/core-scala/src/test/scala/com/baeldung/scala/HigherOrderFunctionsUnitTest.scala +++ b/core-scala/src/test/scala/com/baeldung/scala/HigherOrderFunctionsUnitTest.scala @@ -1,44 +1,49 @@ package com.baeldung.scala +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert._ -import HigherOrderFunctions._ + +import HigherOrderFunctions.mapReduce class HigherOrderFunctionsUnitTest { - @Test - def whenCalledWithSumAndSquareFunctions_thenCorrectValueReturned = { - def square(x: Int) = x * x + @Test + def whenCalledWithSumAndSquareFunctions_thenCorrectValueReturned = { + def square(x : Int) = x * x - def sum(x: Int, y: Int) = x + y + def sum(x : Int, y : Int) = x + y - def sumSquares(a: Int, b: Int) = - mapReduce(sum, 0, square, a, b) + def sumSquares(a : Int, b : Int) = + mapReduce(sum, 0, square, a, b) - val n = 10 - val expected = n * (n + 1) * (2 * n + 1) / 6 - assertEquals(expected, sumSquares(1, n)); - } + assertEquals(385, sumSquares(1, 10)) + } - @Test - def whenComputingSumOfSquaresWithAnonymousFunctions_thenCorrectValueReturned = { - def sumSquares(a: Int, b: Int) = - mapReduce((x, y) => x + y, 0, x => x * x, a, b) + @Test + def whenComputingSumOfSquaresWithAnonymousFunctions_thenCorrectValueReturned = { + def sumSquares(a : Int, b : Int) = + mapReduce((x, y) => x + y, 0, x => x * x, a, b) - val n = 10 - val expected = n * (n + 1) * (2 * n + 1) / 6 - assertEquals(expected, sumSquares(1, n)); - } + assertEquals(385, sumSquares(1, 10)) + } - @Test - def givenCurriedFunctions_whenInvoked_thenCorrectValueReturned = { - def sum(f: Int => Int)(a: Int, b: Int): Int = - if (a > b) 0 else f(a) + sum(f)(a + 1, b) + @Test + def givenCurriedFunctions_whenInvoked_thenCorrectValueReturned = { + // a curried function + def sum(f : Int => Int)(a : Int, + b : Int) : Int = + if (a > b) 0 else f(a) + sum(f)(a + 1, b) - def mod(n: Int)(x: Int) = x % n + // another curried function + def mod(n : Int)(x : Int) = x % n - def sumMod5 = sum(mod(5)) _ - - assertEquals(10, sumMod5(6,10)); - } + // application of a curried function + assertEquals(1, mod(5)(6)) + + // partial application of curried function + // trailing underscore is required to make function type explicit + val sumMod5 = sum(mod(5)) _ + + assertEquals(10, sumMod5(6, 10)) + } } \ No newline at end of file diff --git a/core-scala/src/test/scala/com/baeldung/scala/IntSetUnitTest.scala b/core-scala/src/test/scala/com/baeldung/scala/IntSetUnitTest.scala new file mode 100644 index 0000000000..5cc19e9215 --- /dev/null +++ b/core-scala/src/test/scala/com/baeldung/scala/IntSetUnitTest.scala @@ -0,0 +1,23 @@ +package com.baeldung.scala + +import scala.Range + +import org.junit.Assert.assertFalse +import org.junit.Test + +class IntSetUnitTest { + + @Test + def givenSetof1To10_whenContains11Called_thenFalse = { + + // Set up a set containing integers 1 to 10. + val set1To10 = + Range(1, 10) + .foldLeft(new EmptyIntSet() : IntSet) { + (x, y) => x incl y + } + + assertFalse(set1To10 contains 11) + } + +} \ No newline at end of file diff --git a/core-scala/src/test/scala/com/baeldung/scala/UtilsUnitTest.scala b/core-scala/src/test/scala/com/baeldung/scala/UtilsUnitTest.scala index f4799ed552..47f9873aad 100644 --- a/core-scala/src/test/scala/com/baeldung/scala/UtilsUnitTest.scala +++ b/core-scala/src/test/scala/com/baeldung/scala/UtilsUnitTest.scala @@ -1,50 +1,37 @@ package com.baeldung.scala +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue import org.junit.Test -import Utils._ -import org.junit.Assert._ + +import Utils.average +import Utils.fibonacci +import Utils.power +import Utils.randomLessThan class UtilsUnitTest { - @Test - def whenAverageCalled_thenCorrectValueReturned() = { - val average = Utils.average(10, 20) - assertEquals(15.0, average, 1e-5) - } + @Test + def whenAverageCalled_thenCorrectValueReturned() = { + assertEquals(15.0, average(10, 20), 1e-5) + } - @Test - def givenTwoIntegers_whenGcdCalled_thenCorrectValueReturned = { - assertEquals(3, Utils.gcd(15, 27)) - } + @Test + def whenRandomLessThanInvokedWithANumber_thenARandomLessThanItReturned = { + val d = 0.1 + assertTrue(randomLessThan(d) < d) + } - @Test - def givenTwoIntegers_whenGcdIterCalled_thenCorrectValueReturned = { - assertEquals(3, Utils.gcdIter(15, 27)) - } + @Test + def whenPowerInvokedWith2And3_then8Returned = { + assertEquals(8, power(2, 3)) + } - @Test - def givenTwoIntegers_whenRangeSumcalled_thenCorrectValueReturned = { - assertEquals(55, Utils.rangeSum(1, 10)) - } - - @Test - def givenPositiveInteger_whenFactorialInvoked_thenCorrectValueReturned = { - assertEquals(720, Utils.factorial(6)) - } - - @Test - def whenRandomLessThanInvokedWithANumber_thenARandomLessThanItReturned = { - val d = 0.1 - assertTrue(Utils.randomLessThan(d) < d) - } - - @Test - def whenPowerInvokedWith2And3_then8Returned = { - assertEquals(8, power(2, 3)) - } - - @Test - def whenFibonacciCalled_thenCorrectValueReturned = { - assertEquals(34, fibonacci(8)) - } + @Test + def whenFibonacciCalled_thenCorrectValueReturned = { + assertEquals(1, fibonacci(0)) + assertEquals(1, fibonacci(1)) + assertEquals(fibonacci(6), + fibonacci(4) + fibonacci(5)) + } } \ No newline at end of file