https://twitter.github.io/scala_school/concurrency.html
http://stackoverflow.com/questions/8344224/how-to-use-spring-autowired-or-manually-wired-in-scala-object
Changing the "val" to "var" is unnecessary (Spring uses reflection, which ignores immutability). I'm pretty sure that that @BeanProperty is also unnecessary (Spring will assign to the underlying field, reflectively).
http://alvinalexander.com/scala/scala-ternary-operator-syntax
in Scala there is no special ternary operator; just use an if/else expression:
val absValue = if (a < 0) -a else a
println(if (i == 0) "a" else "b")
def abs(x: Int) = if (x >= 0) x else -x
def max(a: Int, b: Int) = if (a > b) a else b
val c = if (a > b) a else b
http://blog.tmorris.net/posts/does-scala-have-javas-ternary-operator/
Instead of
http://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html
http://stackoverflow.com/questions/1072784/how-can-i-convert-a-java-iterable-to-a-scala-iterable
http://stackoverflow.com/questions/11637372/why-no-stringbuilder-string-in-scala
http://www.scala-lang.org/docu/files/collections-api/collections_26.html
http://stackoverflow.com/questions/8608664/is-string-concatenation-in-scala-as-costly-as-it-is-in-java
http://docs.scala-lang.org/overviews/core/string-interpolation.html
http://alvinalexander.com/scala/string-interpolation-scala-2.10-embed-variables-in-strings
when you precede your string with the letter s, you’re creating a processed string literal.
println(s"${hannah.name} has a score of ${hannah.score}")
println(f"$name is $age years old, and weighs $weight%.0f pounds.")
The raw interpolator “performs no escaping of literals within the string.”
raw"foo\nbar"
http://stackoverflow.com/questions/20195544/scala-how-to-understand-the-flatmap-method-of-try
http://stackoverflow.com/questions/25583368/why-cant-i-flatmap-a-try
https://blog.knoldus.com/2014/04/11/idiomatic-error-handling-in-scala/
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It’s similar to, but semantically different from the scala.util.Either type. Instances of Try[T], are either an instance of scala.util.Success[T] or scala.util.Failure[T].
val result = letMeSayHello.getOrElse("who cares")
Product
It's a well-known fact that by adding "case" before "class" in Scala, the compiler will generate some scaffolding for you like making all your paremeters "val", creating apply and unapply in a companion object. etc.
http://stackoverflow.com/questions/1301907/how-should-i-think-about-scalas-product-classes
Try
http://danielwestheide.com/blog/2012/12/26/the-neophytes-guide-to-scala-part-6-error-handling-with-try.html
try { buyCigarettes(youngCustomer) "Yo, here are your cancer sticks! Happy smokin'!" } catch { case UnderAgeException(msg) => msg }
in Scala, it’s usually preferred to signify that an error has occurred by returning an appropriate value from your function.
http://alvinalexander.com/source-code/scala/scala-try-success-and-failure-example
http://stackoverflow.com/questions/7219316/println-vs-system-out-println-in-scala
https://scalerablog.wordpress.com/2015/12/21/classtag-class-and-war-stories/
http://stackoverflow.com/questions/7302206/why-doesnt-scala-have-static-members-inside-a-class
http://alvinalexander.com/scala/scala-object-examples-static-methods-companion-objects
http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-3
Integrate with spring
http://stackoverflow.com/questions/17322266/scala-with-spring-constructor-autowiring
http://hub.darcs.net/psnively/spring-scala
https://github.com/spring-projects/spring-scala
http://stackoverflow.com/questions/2294598/how-to-get-an-java-lang-class-of-a-scala-object-for-an-annotation-argument
classOf[MyObject$]
http://www.ibm.com/developerworks/library/j-scala07298/
Scala supports a more flexible code organization in source files.
File names don’t have to match the type names.
The package structure does not have to match the directory structure.
Import statements can appear almost anywhere in the code. [3]
One single file may thus contain several public packages, objects and types.
Visibility rules
Import clauses are relative and support renaming of imported names. [3]
The protected modifier restricts member access to subclasses only
Eclipse Scala:
http://davidb.github.io/scala-maven-plugin/example_java.html
https://vikasrao.wordpress.com/2009/02/19/scala-nature-in-eclipse/
http://stackoverflow.com/questions/8522149/eclipse-not-recognizing-scala-code
Thread sleep 1000
Case Classes and Pattern Matching
http://stackoverflow.com/questions/23298046/is-this-really-the-way-to-pass-void-functions-to-scala-methods-from-java
https://gist.github.com/mkaz/d11f8f08719d6d27bab5
(1 to 10) map { _ * 2 }
http://stackoverflow.com/questions/8344224/how-to-use-spring-autowired-or-manually-wired-in-scala-object
Changing the "val" to "var" is unnecessary (Spring uses reflection, which ignores immutability). I'm pretty sure that that @BeanProperty is also unnecessary (Spring will assign to the underlying field, reflectively).
@Service
object UserRest extends RestHelper {
@Autowired
@BeanProperty
val userRepository: UserRepository = null;
object User {
@Autowired val repo: UserRepository = null
def instance() = this
}
@Configuration
class CompanionsConfig {
@Bean def UserCompanion = User.instance
}
@Component
class Foo {
@Autowired //?
@BeanProperty
val baz:Baz = null
}
in Scala there is no special ternary operator; just use an if/else expression:
val absValue = if (a < 0) -a else a
println(if (i == 0) "a" else "b")
def abs(x: Int) = if (x >= 0) x else -x
def max(a: Int, b: Int) = if (a > b) a else b
val c = if (a > b) a else b
Instead of
c ? p : q
, it is written if(c) p else q
.http://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html
scala> import collection.JavaConverters._
http://stackoverflow.com/questions/1072784/how-can-i-convert-a-java-iterable-to-a-scala-iterable
import scala.collection.JavaConverters._
val myJavaIterable = someExpr()
val myScalaIterable = myJavaIterable.asScala
http://www.scala-lang.org/api/2.12.x/scala/util/Either.htmlsealed abstract classEither[+A, +B] extends Product with Serializable
Either is right-biased, which means that Right is assumed to be the default case to operate on. If it is Left, operations like map, flatMap, ... return the Left value unchanged:
Right(12).map(_ * 2) // Right(24) Left(23).map(_ * 2) // Left(23)http://www.scala-lang.org/api/2.11.x/index.html#scala.util.Either
A common use of Either is as an alternative to scala.Option for dealing with possible missing values. In this usage, scala.None is replaced with a scala.util.Left which can contain useful information. scala.util.Right takes the place of scala.Some. Convention dictates that Left is used for failure and Right is used for success.
For example, you could use
Either[String, Int]
to detect whether a received input is a String or an Int.val in = Console.readLine("Type Either a string or an Int: ") val result: Either[String,Int] = try { Right(in.toInt) } catch { case e: Exception => Left(in) } println( result match { case Right(x) => "You passed me the Int: " + x + ", which I will increment. " + x + " + 1 = " + (x+1) case Left(x) => "You passed me the String: " + x })http://stackoverflow.com/questions/7459174/split-list-into-multiple-lists-with-fixed-number-of-elements
I think you're looking for
grouped
. It returns an iterator, but you can convert the result to a list,scala> List(1,2,3,4,5,6,"seven").grouped(4).toList
res0: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
http://stackoverflow.com/questions/11637372/why-no-stringbuilder-string-in-scala
var b= new StringBuilder
Try b ++= "de"
. A String
is considered a collection of Char
s.http://www.scala-lang.org/docu/files/collections-api/collections_26.html
val buf = new StringBuilder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
scala> buf += 'a' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
scala> buf ++= "bcdef" |
http://stackoverflow.com/questions/8608664/is-string-concatenation-in-scala-as-costly-as-it-is-in-java
Scala uses Java strings (
java.lang.String
), so its string concatenation is the same as Java's: the same thing is taking place in both. (The runtime is the same, after all.) There is a special StringBuilder
class in Scala, that "provides an API compatible with java.lang.StringBuilder
"; see http://www.scala-lang.org/api/2.7.5/scala/StringBuilder.html.
But in terms of "best practices", I think most people would generally consider it better to write simple, clear code than maximally efficient code, except when there's an actual performance problem or a good reason to expect one. The
+
operator doesn't really have "poor performance", it's just that s += "foo"
is equivalent to s = s + "foo"
(i.e. it creates a new String
object), which means that, if you're doing a lot of concatenations to (what looks like) "a single string", you can avoid creating unnecessary objects — and repeatedly recopying earlier portions from one string to another — by using a StringBuilder
instead of a String
. Usually the difference is not important. (Of course, "simple, clear code" is slightly contradictory: using +=
is simpler, using StringBuilder
is clearer. But still, the decision should usually be based on code-writing considerations rather than minor performance considerations.)http://alvinalexander.com/scala/string-interpolation-scala-2.10-embed-variables-in-strings
when you precede your string with the letter s, you’re creating a processed string literal.
println(s"${hannah.name} has a score of ${hannah.score}")
println(f"$name is $age years old, and weighs $weight%.0f pounds.")
The raw interpolator “performs no escaping of literals within the string.”
raw"foo\nbar"
http://stackoverflow.com/questions/20195544/scala-how-to-understand-the-flatmap-method-of-try
http://stackoverflow.com/questions/25583368/why-cant-i-flatmap-a-try
Let's look at the signature of
flatMap
.def flatMap[B](f: (A) => GenTraversableOnce[B]): Set[B]
Your
numberOfCharsDiv2
is seen as String => Try[Int]
. Try
is not a subclass of GenTraversableOnce
and that is why you get the error. You don't strictly need a function that gives a Set
only because you use flatMap
on a Set
. The function basically has to return any kind of collection.
So why does it work with
Option
? Option
is also not a subclass of GenTraversableOnce
, but there exists an implicit conversion inside the Option
companion object, that transforms it into a List
.implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
Then one question remains. Why not have an implicit conversion for
Try
as well? Because you will probably not get what you want.flatMap
can be seen as a map
followed by a flatten
.
Imagine you have a
List[Option[Int]]
like List(Some(1), None, Some(2))
. Then flatten
will give you List(1,2)
of type List[Int]
.
Now look at an example with
Try
. List(Success(1), Failure(exception), Success(2))
of type List[Try[Int]]
.
How will flatten work with the failure now?
- Should it disappear like
None
? Then why not work directly withOption
? - Should it be included in the result? Then it would be
List(1, exception, 2)
. The problem here is that the type isList[Any]
, because you have to find a common super class forInt
andThrowable
. You lose the type.
These should be reasons why there isn't an implicit conversion. Of course you are free to define one yourself, if you accept the above consequences.
def
sayHello(any
:
Any)
=
{
any
match
{
case
x
:
String
=
>
"Hello"
case
_
=
>
throw
new
Exception(
"Huh!"
)
}
}
//> sayHello: (any: Any)String
def
letMeSayHello
=
{
try
{
sayHello(
12
)
}
catch
{
case
e
:
Exception
=
>
"It's Ok if you dont want to say hello"
}
}
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It’s similar to, but semantically different from the scala.util.Either type. Instances of Try[T], are either an instance of scala.util.Success[T] or scala.util.Failure[T].
def
sayHello(any
:
Any)
:
Try[String]
=
{
Try {
any
match
{
case
x
:
String
=
>
"Hello"
case
_
=
>
throw
new
Exception(
"Huh!"
)
}
}
}
if
(result.isSuccess) result.get
else
"who cares"
//> res0: String = who cares
val result = letMeSayHello.getOrElse("who cares")
def
letMeSayHello
=
{
sayHello(
12
)
match
{
case
Success(result)
=
> result
case
Failure(result)
=
>
"who cares"
}
}
def
letMeSayHello
=
{
sayHello(
12
) recover {
case
e
:
Exception
=
>
"who cares"
}
}
Calendar.getInstance.getTime
Product
- The trait
Product
defines access functions for instances of products, in particular case classes.
It's a well-known fact that by adding "case" before "class" in Scala, the compiler will generate some scaffolding for you like making all your paremeters "val", creating apply and unapply in a companion object. etc.
It's not a particular known fact that one of the things it does is extending the class with the trait Product. This trait makes it easy to access the elements of the class
http://stackoverflow.com/questions/1301907/how-should-i-think-about-scalas-product-classes
Try
http://danielwestheide.com/blog/2012/12/26/the-neophytes-guide-to-scala-part-6-error-handling-with-try.html
try { buyCigarettes(youngCustomer) "Yo, here are your cancer sticks! Happy smokin'!" } catch { case UnderAgeException(msg) => msg }
in Scala, it’s usually preferred to signify that an error has occurred by returning an appropriate value from your function.
Where
Option[A]
is a container for a value of type A
that may be present or not, Try[A]
represents a computation that may result in a value of type A
, if it is successful, or in some Throwable
if something has gone wrong. Instances of such a container type for possible errors can easily be passed around between concurrently executing parts of your application.
There are two different types of
Try
: If an instance of Try[A]
represents a successful computation, it is an instance of Success[A]
, simply wrapping a value of type A
. If, on the other hand, it represents a computation in which an error has occurred, it is an instance of Failure[A]
, wrapping a Throwable
, i.e. an exception or other kind of error.
If we know that a computation may result in an error, we can simply use
Try[A]
as the return type of our function. This makes the possibility explicit and forces clients of our function to deal with the possibility of an error in some way.
def parseURL(url: String): Try[URL] = Try(new URL(url))
To achieve this, we are using the
apply
factory method on the Try
companion object. This method expects a by-name parameter of type A
(here, URL
). For our example, this means that the new URL(url)
is executed inside the apply
method of the Try
object. Inside that method, non-fatal exceptions are caught, returning a Failure
containing the respective exception.
val url = parseURL(Console.readLine("URL: ")) getOrElse new URL("http://duckduckgo.com")
Mapping a
Try[A]
that is a Success[A]
to a Try[B]
results in a Success[B]
. If it’s a Failure[A]
, the resulting Try[B]
will be a Failure[B]
, on the other hand, containing the same exception as the Failure[A]
:
If you chain multiple
map
operations, this will result in a nested Try
structure, which is usually not what you want. Consider this method that returns an input stream for a given URL:
Since the anonymous functions passed to the two
map
calls each return a Try
, the return type is a Try[Try[Try[InputStream]]]
.
This is where the fact that you can
flatMap
a Try
comes in handy. The flatMap
method on a Try[A]
expects to be passed a function that receives an A
and returns a Try[B]
. If our Try[A]
instance is already a Failure[A]
, that failure is returned as a Failure[B]
, simply passing along the wrapped exception along the chain. If our Try[A]
is a Success[A]
, flatMap
unpacks the A
value in it and maps it to a Try[B]
by passing this value to the mapping function.
This means that we can basically create a pipeline of operations that require the values carried over in
Success
instances by chaining an arbitrary number of flatMap
calls. Any exceptions that happen along the way are wrapped in a Failure
, which means that the end result of the chain of operations is a Failure
, too.
Let’s rewrite the
inputStreamForURL
method from the previous example, this time resorting to flatMap
:
If you want to establish some kind of default behaviour in the case of a
Failure
, you don’t have to use getOrElse
. An alternative is recover
, which expects a partial function and returns another Try
. If recover
is called on a Success
instance, that instance is returned as is. Otherwise, if the partial function is defined for the given Failure
instance, its result is returned as a Success
.
import java.net.MalformedURLException
import java.io.FileNotFoundException
val content = getURLContent("garbage") recover {
case e: FileNotFoundException => Iterator("Requested page does not exist")
case e: MalformedURLException => Iterator("Please make sure to enter a valid URL")
case _ => Iterator("An unexpected error has occurred. We are so sorry!")
}
http://alvinalexander.com/source-code/scala/scala-try-success-and-failure-example
The
Try
type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala.util.Either type.
For example,
Try
can be used to perform division on a user-defined input, without the need to do explicit exception-handling in all of the places that an exception might occur.
Example:
import scala.util.{Try, Success, Failure} def divide: Try[Int] = { val dividend = Try(Console.readLine("Enter an Int that you'd like to divide:\n").toInt) val divisor = Try(Console.readLine("Enter an Int that you'd like to divide by:\n").toInt) val problem = dividend.flatMap(x => divisor.map(y => x/y)) problem match { case Success(v) => println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v) Success(v) case Failure(e) => println("You must've divided by zero or entered something that's not an Int. Try again!") println("Info from the exception: " + e.getMessage) divide } }
An important property of
Try
shown in the above example is its ability to pipeline, or chain, operations, catching exceptions along the way. The flatMap
and map
combinators in the above example each essentially pass off either their successfully completed value, wrapped in the Success
type for it to be further operated upon by the next combinator in the chain, or the exception wrapped in the Failure
type usually to be simply passed on down the chain. Combinators such as rescue
and recover
are designed to provide some type of default behavior in the case of failure.
Note: only non-fatal exceptions are caught by the combinators on
Try
(see scala.util.control.NonFatal). Serious system errors, on the other hand, will be thrown.
Note:: all Try combinators will catch exceptions and return failure unless otherwise specified in the documentation.
http://alvinalexander.com/scala/try-success-failure-example-reading-filehttp://stackoverflow.com/questions/7219316/println-vs-system-out-println-in-scala
Predef.println
is shortcut for Console.println
and you can use Console.setOut
or Console.withOut
for redirecting.http://stackoverflow.com/questions/7302206/why-doesnt-scala-have-static-members-inside-a-class
http://alvinalexander.com/scala/scala-object-examples-static-methods-companion-objects
In its second meaning, Scala has an
object
keyword, and using that keyword lets you do a variety of things, including a) creating a main
method to launch your application, b) creating the equivalent of Java’s static methods, and also c) creating something called a companion object.
If you’re coming from the Java world and want to use
.class
, you classOf
instead:val info = new DataLine.Info(classOf[TargetDataLine], null)
To create a launching point for your applications, you have two choices. First, you can define an
object
which extends App
:object Foo extends App { // your application begins here }
Or you can define an
object
that contains a main
method:object Bar { def main(args: Array[String]) { // your application starts here } }
Singleton objects
You create Singleton objects in Scala with the
object
keyword. You can’t create static methods in a Scala class, but you can create singleton objects in Scala with the object
keyword, and methods defined in a singleton can be accessed like static methods in Java.// create a singleton object CashRegister { def open { println("opened") } def close { println("closed") } } // call the CashRegister methods just like static methods object Main extends App { CashRegister.open CashRegister.close }
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) } } |
private[mypackage] def myMethod = "test"
Integrate with spring
http://stackoverflow.com/questions/17322266/scala-with-spring-constructor-autowiring
http://hub.darcs.net/psnively/spring-scala
https://github.com/spring-projects/spring-scala
http://stackoverflow.com/questions/2294598/how-to-get-an-java-lang-class-of-a-scala-object-for-an-annotation-argument
classOf[MyObject$]
http://www.ibm.com/developerworks/library/j-scala07298/
package com.tedneward.scala.demonstration
import java.math.BigInteger import BigInteger._
import java.math.BigInteger, BigInteger._
http://www.scala-lang.org/old/node/119Scala supports a more flexible code organization in source files.
File names don’t have to match the type names.
The package structure does not have to match the directory structure.
Import statements can appear almost anywhere in the code. [3]
One single file may thus contain several public packages, objects and types.
Visibility rules
Import clauses are relative and support renaming of imported names. [3]
The protected modifier restricts member access to subclasses only
Eclipse Scala:
http://davidb.github.io/scala-maven-plugin/example_java.html
https://vikasrao.wordpress.com/2009/02/19/scala-nature-in-eclipse/
1. Scala objects are not visible from java classes, only scala classes are, this is apparently a known problem. I dont see why it would a problem allowing the access of the object’s methods like one would access static methods in Java.
2. When I right click -> Scala -> add Scala Nature for a JavaEE project, it does not add the scala libraries to the project classpath. So this does not solve my problem of having Scala code in Java Web apps.
3. So adding Scala nature only works for regular Java Projects for now.
2. When I right click -> Scala -> add Scala Nature for a JavaEE project, it does not add the scala libraries to the project classpath. So this does not solve my problem of having Scala code in Java Web apps.
3. So adding Scala nature only works for regular Java Projects for now.
scala-maven-plugin
http://stackoverflow.com/questions/8522149/eclipse-not-recognizing-scala-code
1) Right-click on project, Configure > Add Scala Nature.
2) In the Scala menu, Run Setup Diagnositics... > Use recommended default settings
Open the Package Explorer, look at your scala source. Does the icon displays a
S
(for Scala), or a J
(for Java)?
If you see a
S
, then you are likely missing the Scala Nature. As Luigi suggested, try to add the Scala Nature and see if that fixes your issue (Right-click on project, Configure > Add Scala Nature.)
Otherwise, if you see a
J
, the odds are that "JDT Weaving" is not enabled. That should not happen and might depend on other plugins you have installed.
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.Thread sleep 1000
Inheritance and overriding
All classes in Scala inherit from a super-class. When no super-class is specified, as in the
Complex
example of previous section, scala.AnyRef
is implicitly used.
It is possible to override methods inherited from a super-class in Scala. It is however mandatory to explicitly specify that a method overrides another one using the
override
modifier, in order to avoid accidental overriding.Methods without arguments
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
}
Maybe the easiest way for a Java programmer to understand what traits are is to view them as interfaces which can also contain code. In Scala, when a class inherits from a trait, it implements that trait’s interface, and inherits all the code contained in the trait.
override def toString(): String = year + "-" + month + "-" + day
override def equals(that: Any): Boolean =
that.isInstanceOf[Date] && {
val o = that.asInstanceOf[Date]
o.day == day && o.month == month && o.year == year
}
This method makes use of the predefined methods
isInstanceOf
and asInstanceOf
. The first one, isInstanceOf
, corresponds to Java’s instanceof
operator, and returns true if and only if the object on which it is applied is an instance of the given type. The second one, asInstanceOf
, corresponds to Java’s cast operator: if the object is an instance of the given type, it is viewed as such, otherwise a ClassCastException
is thrown.
class Reference[T] {
private var contents: T = _
def set(value: T) { contents = value }
def get: T = contents
}
Your function actually has to return
BoxedUnit.UNIT
, which is the unit in question.Unit
is an AnyVal
, not an AnyRef
, so it doesn't include null.
It is so much nicer when functions return interesting values.
https://gist.github.com/mkaz/d11f8f08719d6d27bab5
(1 to 10) map { _ * 2 }
(1 to 1000).reduceLeft( _ + _ )
(1 to 1000).sum
3. Verify if Exists in a String
This example returns a boolean if a word in a list exists in a string. I used this example for checking if a tweet contains a word I'm interested in. I suppose technically it is three lines, but the first two are just setting variables.
val wordList = List("scala", "akka", "play framework", "sbt", "typesafe")
val tweet = "This is an example tweet talking about scala and sbt."
(wordList.foldLeft(false)( _ || tweet.contains(_) ))
wordList.exists(tweet.contains)
val fileText = io.Source.fromFile("data.txt").mkString
val fileLines = io.Source.fromFile("data.txt").getLines.toList
val (passed, failed) = List(49, 58, 76, 82, 88, 90) partition ( _ > 60 )
val results = XML.load("http://search.twitter.com/search.atom?&q=scala")
List(14, 35, -7, 46, 98).reduceLeft ( _ min _ )
List(14, 35, -7, 46, 98).min
List(14, 35, -7, 46, 98).reduceLeft ( _ max _ )
List(14, 35, -7, 46, 98).max
val result = dataList.par.map( line => processItem(line) )
(1 to 4).map { i => "Happy Birthday " + (if (i == 3) "dear NAME" else "to You") }.foreach { println }
https://www.redfin.com/blog/2010/05/how_and_why_twitter_uses_scala.html