On Github donatasm / scala-in-practice
* may not be true anymore
public static class Hello
{
  public static void Main(string[] args)
  {
    Console.WriteLine("Hello, world!");
  }
}
          
					
object Hello {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}
          
				
interface I {}
class B<T> {}
class A : B<String>, I
{
  int MyMethod() { return 42; }
}
          
					
trait T
class B[T]
class A extends B[String] with I {
  def myMethod = 42
}
          
				Scala supports two types of variable declarations:
var declares a variable like in C#
var name = "world"
name = name + "!"
          
					val declares a read-only value
val name = "world"
name = name + 1 // ERROR
          
				
lazy val resource = resourceExpensiveToCreate()
          
					
Lazy<Resource> resource =
  new Lazy<Resource>(
    () => ResourceExpensiveToCreate(),
    isThreadSafe = true);
          
				
class Hello {
  def sayTo(name: String): String = {
    return s"Hello, $name"
  }
}
          
					
class Hello {
  def sayTo(name: String) = s"Hello, $name"
}
          
				
val hello = new Hello
hello.sayTo("world")
          
					
val hello = new Hello
hello sayTo "world"
          
				
public sealed class Product
{
  private readonly string _name;
  private readonly string _category;
  private readonly int _price;
  public Product(string name, string category, int price)
  {
    _name = name;
    _category = category;
    _price = price;
  }
  public string Name { get { return _name; }}
  public string Category { get { return _category; }}
  public int Price { get { return _price; }}
  public override bool Equals(object other)
  {
    if (ReferenceEquals(null, other)) return false;
    if (ReferenceEquals(this, other)) return true;
    var o = (Product)other;
    return o._name == _name
      && o._category == _category
      && o._price == _price;
  }
  public override int GetHashCode()
  {
    // magic using number 37, usually generated by tool
  }
}
          
				
case class Product(name: String, category: String, price: Int)
          
					
val p1 = Product("product1", "category1", 99)
val p2 = Product("product1", "category1", 99)
val p3 = Product("product2", "category2", 100)
println(p1)
println(p1 == p2)
println(p2 == p3)
println(p1.price)
          
					
Product(product1, category1, 99)
true
false
99
          
				
public static class ProductJson
{
  public static JsonObject ToJson(this Product product)
  {
    return new JsonObject(
      new JsonProperty("name", product.Name),
      new JsonProperty("category", product.Category),
      new JsonProperty("price", product.Price)
    );
  }
}
          
				
					And then:
var json = new Product("name", "category", 101).ToJson();
          
				
				
object ProductJson
{
  implicit def toJson(product: Product): JsonObject =
    JsonObject(
      JsonProperty("name", product.Name),
      JsonProperty("category", product.Category),
      JsonProperty("price", product.Price)
    )
}
          
				
					And then:
val json: JsonObject = Product("name", "category", 101);
          
				
				
case class User(id: Int)
class UserRepository {
  def getUserById(id: Int): User = {
    // call to database
  }
}
class UserService {
  def getUserById(id: Int, repository: UserRepository): User = {
    repository.getUserById(id)
  }
}
          
				
					And then:
val repository = new UserRepository()
val service = new UserService()
service.getUserById(1, repository)
          
				
				
class UserService {
  def getUserById(id: Int)(implicit repository: UserRepository): User = {
    repository.getUserById(id)
  }
}
          
				
					And then:
implicit val repository = new UserRepository()
val service = new UserService()
service.getUserById(1)
          
				
				
Action a1 = () => {};
Action<int> a2 = (int i) => {};
Func<int> f1 = () => 0;
Func<int, int> f2 = (int i) => 0;
          
					
val a1 = () => {}
val a2 = (i: Int) => {}
val f1 = () => 0
val f2 = (i: Int) => 0
          
				
var n = Enumerable.Range(1, 10);
n.Select(i => i*i);
n.Where(i => i%2 == 0);
n.Take(3);
n.Count();
n.Distinct();
n.Sum();
          
					
val n = 1 to 10
n.map(i => i*i)
n.filter(i => i%2 == 0)
n.take(3)
n.size
n.distinct
n.sum
          
				
test("four bids with the same price, winner is randomized") {
  val adSlot = AdSlot(id = "1", minPrice = Money(1))
  val adSlots = Set(adSlot)
  val bidResponses = List(BidResponse("bidder", bids()))
  val results = (1 to 1000)
    .map(_ => auctioneer.winningBids(adSlots, bidResponses).head)
    .groupBy(_.bid)
    .map { case (_, bids) =>  bids.toSeq.length / 1000.0 }
  all(results) should equal(0.25 +- 0.01)
}
          
				
it should "return 400 when request headers " +
  "too large" in withNginxBidder { bidder =>
  val headers = (1 to 8192)
    .map(i => RawHeader(s"X-Header-$i", i.toString))
  val response = bidder
    .client
    .send(Get(s"http://localhost:$nginxPort/")
    .withHeaders(headers: _*))
  response should equal (HttpResponse(400, HttpEntity.Empty,
    List(`Content-Length`(0), Connection("close"))
  ))
}
          
				
def statsPresentation(stats: Stats) = HttpResponse(
  entity = HttpEntity(`text/html`,
  <html>
    <body>
    <h1>HttpServer Stats</h1>
    <table>
      <tr><td>days:</td><td>{stats.uptime.toDays}</td></tr>
      <tr><td>hours:</td><td>{stats.uptime.toHours}</td></tr>
      <tr><td>minutes:</td><td>{stats.uptime.toMinutes}</td></tr>
      <tr><td>totalRequests:</td><td>{stats.totalRequests}</td></tr>
    </table>
    </body>
  </html>.toString))
          
									
val result = (0 /: |)(_ + _)
          
					
				
										
val | = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
          
					
				
				
										
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val result = list.foldLeft(0)(x, y => x + y)
// result = 45
          
					
				
				
case class Size(width: Int, height: Int)
case class Ad(id: Int, size: Size)
trait AdRepository {
  def get(id: Int): Ad
  def find(size: Size): Ad
}
          
				
trait AdRepositoryComponent {
  def adRepository: AdRepository
  trait AdRepository {
    def get(id: Int): Ad
    def find(size: Size): Ad
  }
}
          
				
// self-type annotation
trait Bidder { this: AdRepositoryComponent =>
  def getAd(id: Int): Ad =
    adRepository.get(id)
  def matchAd(size: Size): Ad =
    adRepository.find(size)
}
          
				
trait MySqlAdRepositoryComponent extends AdRepositoryComponent {
  def adRepository = new MySqlAdRepository
  class MySqlAdRepository extends AdRepository {
    override def get(id: Int): Ad = {
      // TODO: get from database
    }
    override def find(size: Size): Ad = {
      // TODO: get from database
    }
  }
}
          
				
class DefaultBidder extends Bidder with MySqlAdRepositoryComponent
object BidderApplication {
  def main(args: Array[String]): Unit = {
    val bidder = new DefaultBidder
    // ...
  }
}
          
				
class BidderTest extends Bidder with AdRepositoryComponent {
  lazy val adRepository: AdRepository = mock[AdRepository]
  // TODO: write some tests
}
          
				
class DefaultBidder(implicit val repository: AdRepository)
object BidderApplication {
  def main(args: Array[String]): Unit = {
    implicit val repository = new MySqlAdRepository
    val bidder = new DefaultBidder
    // ...
  }
}