Skip to content

Instantly share code, notes, and snippets.

@kayvank
Last active August 30, 2019 05:56
Show Gist options
  • Save kayvank/6c824a64d4f7e6e0fb780d0a9d4444c2 to your computer and use it in GitHub Desktop.
Save kayvank/6c824a64d4f7e6e0fb780d0a9d4444c2 to your computer and use it in GitHub Desktop.

Questions

1. Explain the performance of the following programs

def findElement(e: String, dict: Map[String, Any]): Option[Any] =
dict.get(e) 

Regardless of Map implementation, maps are key value. dict.get is a key look up that returns Some(value) or None. The performance characteristic is eC, Effectively Constant. Depending on Map implementation the performance characteristic is O(1) for hash map, O(log n) for tree implementations like.

def findElement(e: String, dict: Map[String, Any]): Option[Any] =
 dict.find { case (k, v) => k == e } map (_._2)

find, returns the 1st match satisfying the find predicate. This is a complete scan of the collection until the predicate is satisfied or collection is exhausted. not a key look up, therefore is complete scan of the collection. The map function is also another instruction hit should the find return an element.

2. How are List and Array different in Scala? Describe use cases suitable for each data structure.

List

List is an immutable sequence of elements, implemented as a linked list. Lists support efficient addition of new elements at the front. They are ideal for sequentially processing of collections and dynamically adding new elements to the front of the list

Array

Used for random access lookup, and mutating element at and index, processing elements by index most efficient with constant size, adding new elements to full array is expensive

3. What's the output of these two examples?

val future1 = Future { Thread.sleep(3000); println("a") } // step 1 execution starts eagerly
val future2 = Future { Thread.sleep(2000); println("b") } // step 2 execution starts eagerly
val future3 = Future { Thread.sleep(1000); println("c") } // step 3 execution starts eagerly
val future = for {
  _ <- future1
  _ <- future2
   _ <- future3
} yield {}

step 1 thru 3 are eagerly started asynchronously. the val future is a monadic structure that will sequences the result of steps 1 thru 3. The likely output will be

c
b
a
val future = for {
 _ <- Future { Thread.sleep(3000); println("a") } //step 1
 _ <- Future { Thread.sleep(2000); println("b") } //step 2
 _ <- Future { Thread.sleep(1000); println("c") } //step 3
} yield {}

The val future wraps a mondaic structure where the execution order is: execute step 1, chain, flatMap, step 2, chain, flatMap step3 where chain <=> flatMap

a
b
c

4.What's the benefit of using immutable data structures over mutable ones?

  • Immutable data structure allows to reason about computations on that data thru Referential Transparency, Expression/computations may be replaced by their result without changing the meaning of the program.
  • State and mutable values are hard to follow
  • Immutable data may be shared freely among components without having to worry that a change in component will inadvertently be visible to the other
  • It allows to use pure functions, where there are no side-effects, only effects, which are just immutable data structures, together with functions for composing them. Immutable objects are inherently thread safe and have no synchronization concern
  • It allows for potential compiler optimizations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment