CSC/ECE 517 Fall 2014/ch1a 9 aa

From Expertiza_Wiki
Revision as of 21:37, 17 September 2014 by Aashetty (talk | contribs) (Created page with "= Scala : An overview = Scala is an object-functional programming and scripting language generallly used in software applications. Scala has full support for functional programmi...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Scala : An overview

Scala is an object-functional programming and scripting language generallly used in software applications. Scala has full support for functional programming (including currying, pattern matching,algebraic data types,lazy evaluation,tail recursion,immutability, etc.) and a very strong static type system. This allows programs written in Scala to be very concise and thus smaller in size than most general purpose programming languages. Many of Scala's design decisions were inspired by criticism over the shortcomings of Java.

Scala source code is intended to be compiled to Java bytecode, so that the resulting executable code runs on a Java virtual machine. Java libraries can be used directly in Scala code, and vice versa.

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

This program consists of one method called main which takes the command line arguments, an array of strings, as parameter; the body of this method consists of a single call to the predefined method println with the greeting as argument. The main method does not return a value (it is a procedure method). Therefore, it is not necessary to declare a return type. Such a declaration introduces what is commonly known as a singleton object, that is a class with a single instance. The declaration above thus declares both a class called HelloWorld and an instance of that class, also called HelloWorld. This instance is created on demand, the first time it is used. Notice that the main method is not declared as static (like in Java) here. This is because static members (methods or fields) do not exist in Scala. Rather than defining static members, the Scala programmer declares these members in singleton objects.

Features of Scala

Scala is object-oriented

Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Classes are extended by subclassing and a flexible mixin-based composition mechanism as a clean replacement for multiple inheritance.

Scala is functional

Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's classes and its built-in support for pattern matching model algebraic types used in many functional programming languages. Furthermore, Scala's notion of pattern matching naturally extends to the processing of XML data with the help of right-ignoring sequence patterns. In this context, sequence comprehensions are useful for formulating queries. These features make Scala ideal for developing applications like web services.

Scala is statically typed

Scala is equipped with an expressive type system that enforces statically that abstractions are used in a safe and coherent manner. In particular, the type system supports: generic classes, variance annotations, upper and lower type bounds, inner classes and abstract types as object members, compound types, explicitly typed self references, views, and polymorphic methods.

Scala is extensible

In practice, the development of domain-specific applications often requires domain-specific language extensions. Scala provides a unique combination of language mechanisms that make it easy to smoothly add new language constructs in form of libraries: any method may be used as an infix or postfix operator, and closures are constructed automatically depending on the expected type (target typing). A joint use of both features facilitates the definition of new statements without extending the syntax and without using macro-like meta-programming facilities.

Scala interoperates with Java and .NET

Scala is designed to interoperate well with the popular Java 2 Runtime Environment (JRE). In particular, the interaction with the mainstream object-oriented Java programming language is as smooth as possible. Scala has the same compilation model (separate compilation, dynamic class loading) like Java and allows access to thousands of existing high-quality libraries.Support for the .NET Framework (CLR) is also available.

Similarities between Scala and Java

1) Both are JVM based language, Scala produce same byte code as Java and runs on Java Virtual Machine. Similar to Java compiler javac, Scala has a compiler scalac, which compiles Scala code into byte code. At this level, all JVM language like Groovy,JRuby, Scala becomes equals to Java, because they use same memory space, type system and run inside same JVM.

2) You can call Scala from Java and Java from Scala, it offers seems less integration. Moreover, you can reuse existing application code and open source Java libraries in Scala.

3) Major Java programming IDE like Eclipse, Netbeans and InetelliJ supports Scala.

4) One more similarity between Scala and Java is that both are Object Oriented, Scala goes one steps further and also supports functional programming paradigm, which is one of it's core strength.


Scala vs JAVA

Syntactic flexibility

Scala has a very powerful and flexible syntax as it relates to methods, both declaration and invocation. In Java you can create methods with different visibilities, modifiers andreturn types.Scala does allow for different visibilities on not just methods, but any members. For example:

class Person {
  private var name = "Daniel Spiewak"
  val ssn = 1234567890    // public constant field
 
  def firstName() = splitName()(0)   // public method
 
  private def splitName() = name.split(" ")    // private method
 
  protected def guessAge() = {
    import Math._
    round(random * 20)
  }
}

Scala provides he option to import into a specific scope.The import statement within guessAge()is much like a Java static import statement which only provides access to the Math members within theguessAge() method. So we couldn’t just make a call to round() from within the splitName() method. Scala access modifiers are also quite a bit more powerful than Java’s. For example,protected by default limits access to only subclasses, unlike Java which also allows access to other classes in the same package.

Unified type system

Java makes a sharp distinction between primitive types (e.g. int and boolean) and reference types (any class). Only reference types are part of the inheritance scheme, deriving from java.lang.Object. In Scala, however, all types inherit from a top-level class Any, whose immediate children are AnyVal(value types, such as Int and Boolean) andAnyRef (reference types, as in Java). This means that the Java distinction between primitive types and boxed types (e.g. int vs. Integer) is not present in Scala; boxing and unboxing is completely transparent to the user.

For-expressions

Instead of the Java "foreach" loops for looping through an iterator, Scala has a much more powerful concept of for-expressions. These are similar to list comprehensions in languages such as Haskell, or a combination of list comprehensions and generator expressions in Python. For-expressions using the yield keyword allow a new collection to be generated by iterating over an existing one, returning a new collection of the same type. They are translated by the compiler into a series of map,flatMap and filter calls. Where yield is not used, the code approximates to an imperative-style loop, by translating to foreach. A simple example is:

val s = for (x <- 1 to 25 if x*x > 50) yield 2*x
The result of running it is the following vector:
Vector(16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50)

Everything is an expression

Unlike C or Java, Scala makes no distinction between statements and expressions. All statements are in fact expressions that evaluate to some value. Functions that would be declared as returning void in Java, and statements like while that logically do not return a value, are in Scala considered to return the type Unit, which is a singleton type, with only one object of that type.

// Java:
int hexDigit = x >= 10 ? x + 'A' - 10 : x + '0';

//Scala: 
val hexDigit = if (x >= 10) x + 'A' - 10 else x + '0'

Type inference

Due to type inference, the type of variables, function return values, and many other expressions can typically be omitted, as the compiler can deduce it. Examples are val x = "foo" (for an immutable, constant variable or immutable object) or var x = 1.5 (for a variable whose value can later be changed). Type inference in Scala is essentially local.

Anonymous functions

In Scala, functions are objects, and a convenient syntax exists for specifying anonymous functions. An example is the expression x => x < 2, which specifies a function with a single parameter, that compares its argument to see if it is less than 2.

An even shorter form of anonymous function uses placeholder variables: For example:

list map { x => sqrt(x) }

can be written more concisely as

list map { sqrt(_) }

Immutability

Scala enforces a distinction between immutable (unmodifiable, read-only) variables, whose value cannot be changed once assigned, and mutable variables, which can be changed. A similar distinction is made between immutable and mutable objects. The distinction must be made when a variable is declared: Immutable variables are declared with val while mutable variables use var.

Tail recursion

Functional programming languages commonly provide tail call optimization to allow for extensive use of recursion without stack overflow problems. Limitations in Java bytecode complicate tail call optimization on the JVM. In general, a function that calls itself with a tail call can be optimized, but mutually recursive functions cannot. Trampolines have been suggested as a workaround.[24] Trampoline support has been provided by the Scala library with the object scala.util.control.TailCalls since Scala 2.8.0 (released July 14, 2010).[25]

Pattern Matching

pattern matching in Scala is really a lot like Java’s switch/case construct.  So in Java, one might write something like this:

public boolean checkPrime(int number) {
    // checks if a number between 1 and 10 is prime
    switch (number) {
        case 1: return true;
        case 2: return true;
        case 3: return true;
        case 5: return true;
        case 7: return true;
 
        default: return false;
    }
}

One of the major limitations of switch/case in Java is that it can only be used on primitives.  You can’t use switch/case to test a String, for example (a need which arises more often than one would think).  In fact, the most complex type testable within switch/case is the Enum, and even this is just being reduced to its ordinal values under the surface The designers of Scala chose not to include this “feature” in their new language.Instead, they implemented a “new” concept called pattern matching.At a basic level, it allows algorithms which are very similar to the checkPrime(int) example:

def checkPrime(number:Int):Boolean = {
  number match {
    case 1 => return true
    case 2 => return true
    case 3 => return true
    case 5 => return true
    case 7 => return true
 
    case _ => return false
  }
}

The biggest difference which likely jumps out at you is the lack of a default statement.Instead, we see the return of Scala’s ubiquitous wildcard character, the underscore. Literally read, this example means: match the value within number; in the case that it is 1, return true; in the case that it is 2, return true; …; for any previously unmatched value, return false. Scala case statements can’t “overflow” into each-other (causing multiple matches) like Java’s can, so even if we weren’t returning values, the algorithm would still be safe.

Traits

Java’s designers recognized the need for multiple typing (e.g. CollegeStudent is both a Student and a Worker), but they wanted to avoid the issues associated with inheriting conflicting method definitions along multiple paths.  Their solution was to design the interface mechanism, a feature which allows multiple typing without the complications of multiple inheritance.  Scala recognizes that interfaces have their issues.  So rather than blinding creating a reimplementation of the same problems found in either Java or C++, Scala takes a new approach.  Inspired by a combination of Java’s interfaces and Ruby’s mixins, the designers of Scala have created the trait construct.


trait Book 
{
  def title:String
  def title_=(n:String):Unit
 
  def computePrice = title.length * 10
}

Scala’s traits are quite nice in that they can not only define abstract members, but also full method definitions. At the same time, they allow inheriting classes to inherit from more than one trait. They pass on their type information and implementations to their children, as well as enforcing the abstract members. At first glance, this seems like it would be just as bad as straight-up multiple inheritance, but it turns out the problems have been mitigated in some very clever ways. Traits are actually mixins, not true parent classes. Any non-abstract trait members are actually included in the inheriting class, as in physically part of the class.Well, not physically, but you get the picture.It’s as if the compiler performs a cut-and-paste with the non-abstract members and inserts them into the inheriting class.This means that there’s no ambiguity in the inheritance path, meaning no diamond problem. We can rewrite ourCollegeStudent example in Scala without redundancy or fear of paradox:

abstract class Person {
  def schedule:Schedule
}
 
trait Student extends Person {
  private var classSchedule:Schedule = ...
 
  override def schedule = classSchedule
 
  def learn() = {...}
}
 
trait Worker extends Person {
  private var workSchedule:Schedule = ...
 
  override def schedule = workSchedule
 
  def work() = {...}
}
 
class CollegeStudent(school:School, company:Company) extends Student with Worker {
  // ...
}

Now if we make a call to the schedule method on an instance of CollegeStudent, the compiler knows that we’re referring to the implementation of schedule in the Worker trait.  This is because Worker was mixed in after theStudent trait.