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 // ... } }