?
means Stairs
val conference = "Mobilizejszon"
// conference = "mobilization" // compile error val == "java final"
var age = 90
age = 2
// age = "trolololo!" // compile error String != Int
val name: String = "Mobilization"
val name: String = "Mobilization" ; // yay semicolons, GREAT!!!
public class Person {
private String name;
private String surname;
public Person(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSurname() { return surname; }
public void setSurname(String surname) { this.surname = surname; }
@Override
public String toString() { /*...*/ }
}
class Person(name: String, surname: String)
"You forgot the toString()!"
case class Person(name: String, age: Int)
List<String> girls = FluentIterable
.from(people)
.filter(new Predicate<Person>() {
@Override
public boolean apply(Person person) {
return person != null && person.isWoman();
}
})
.transform(new Function<Person, String>() {
@Override
public String apply(Person input) {
return input.getFirstName() + " " + input.getLastName();
}
})
.toImmutableList();
for(String name : names)
println(String.format("Hello %s!", name);
// PS: DON'T call format on Android!
people.filter(_.isWoman)
people.filter(_.isWoman).map(_.name)
people.filter(_.isWoman).map(_.name).foreach(greet _)
def greet(name: String) = println("Hello " + name + "!")
people filter { _.isWoman } map { _.name } foreach { n => greet _ }
people foreach println
val bothSets: Set[String] = set ++ anotherSet
and others...
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_button_text">
class MyActivity extends Activity {
ListView comments;
Button newComment;
@Override
void onCreate(Bundle bundle) {
super.onCreate(bundle);
comments = (ListView) findViewById(R.id.comments);
newComment = (Button) findViewById(R.id.new_comment);
}
}
What sucks here? class MyScalaActivity extends ScalaActivity {
lazy val Comments = findView(TR.comments)
lazy val NewComment = findView(TR.new_comment)
// with Types!
}
var thing = 0
lazy val incrementInLazyVal = { thing += 1; thing }
thing = 100
incrementInLazyVal
incrementInLazyVal
incrementInLazyVal
assert { thing == 101 && incrementInLazyVal == 101 }
var thing = 0
val incrementInVal = { thing += 1; thing }
thing = 100
incrementInVal
incrementInVal
incrementInVal
assert { thing == 1 && incrementInVal == 1 }
var thing = 0
def incrementDef() = { thing += 1; thing }
incrementDef()
incrementDef
incrementDef
assert { thing == 3 }
def something = 1337
something // OK
something() // compile error
Intuition is: "() means side-effects"
trait SayVerb {
// some magic here... Comes after the next few slides ;-)
def sayAwesome() = "Awesome!".toast() // make a toast!
def sayAmazing() = "Amazing!".toast()
}
trait Logging { /* logging impl */ }
class MyActivity extends Activity
with SayVerb
with Logging
public class ActivityA extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
}
public class ActivityB extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
}
trait GameMenu extends Activity {
override onCreateOptionsMenu(menu: Menu) = {
getMenuInflater.inflate(R.menu.game_menu, menu)
true
}
}
class ActivityA extends Activity
with GameMenu {
/*...*/
}
class ActivityB extends SomethingFromAFrameworkActivity
with GameMenu {
/*...*/
}
trait ContentView extends Activity with TypedActivity {
// force the user to implement this "method? / field?"
def ContentView: TypedLayout
override def onCreate(bundle: Bundle) {
setContentView(ContentView.id)
super.onCreate(bundle)
}
}
class LoginActivity extends ScalaActivity
with ViewListenerConversions
with ContentView {
// we implement the def ContentView with a value!
val ContentView = TR.layout.login
}
object Dictionary extends Logging
with TimedVerb
with RetryVerb
with DoToVerb
with UniquifyVerb
def things() {
import Dictionary._
// use this dictionaty
}
(imagine _ works like * in Java).
"Hello world!".toast
So... where did that method come from?
// Scala "magic" here
val it: java.lang.String = "Hello %s!"
it.format("Łódź") == "Hello Łódź!"
implicit def string2richString(s: String) = new RichString(s)
// String -> RichString
"%s".format("aha!") // compiler starts looking...
// and REWRITES it to:
new RichString("%s").format("aha!")
Back to our Toast example
Java:
Toast.makeText(ctx, msg, Toast.LENGTH_SHORT).show()
Problems?
def add(a: Int): (Int) => Int = addStep2(a, _)
// add returns a function that takes an Int, and returns an Int
def addStep2(a: Int, b: Int) = a + b
// the final step, adding those numbers
// usage:
val part2 = add(2)(2)
We're able to write:
def add(a: Int)(b: Int) = a + b
Tremendously useful!
// IMPLICIT VALUE
implicit val ctx = getApplicationContext()
// IMPLICIT PARAMETER LIST
def example()(implicit ctx: Context) = "I have " + ctx
example()(getApplicationContext)
// or!
implicit val ctx = getApplicationContext
example()
trait Toasts {
implicit def charSeq2toastable(str: java.lang.CharSequence) =
new Toastable(str.toString)
class Toastable(msg: String) {
import android.widget.Toast._
def toast(implicit ctx: Context) {
makeText(ctx, msg, LENGTH_LONG).show()
}
}
}
Usage:
class MyActivity extends Activity with Toasts {
implicit lazy val ctx = getApplicationContext
def sayHello() { "Hello".toast }
}
SomeTextView.setText("Hello World!")
SomeTextView := "Hello World!"
SomeTextView.:=("Hello World!")
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// do things...
}
});
import ListenerConversions._
button onClick { /* do things */ }
// even better:
val sendMessage = { /*...*/ }
button onClick sendMessage
handler.post(new Runnable(){
@Override
void run() {
/* ... */
}
});
inFuture { /* ... */ }
inUiThread { /*...*/ }
inFuture(whenComplete = notifyUser) { /* long task...*/ }
inFutureWithProgressDialog { /* long task...*/ }
SharedPreferences sp = ctx.getSharedPreferences(key, 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", "value");
editor.commit();
AppSharedPreferences.someKey = "value"
def sharedPreferences(implicit ctx: Context) =
ctx.getSharedPreferences(AppName, 0)
def workspaceName(implicit ctx: Context) =
Option { sharedPreferences.getString(KeyWorkspaceName, null) }
def workspaceName_=(name: String)(implicit ctx: Context) {
withSharedPreferencesEditor { _.putString(KeyWorkspaceName, name) }
}
Notice the method name: "something_="
optionalValue map { _.toast }
Which will only be called, if the Option has Some value.
Intent intent = new Intent(this, A.class);
intent.putExtra("user_id", 1234);
intent.putExtra("data", new SomeData());
startActivity(intent);
public class A extends Activity {
@Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
int userId = getIntent().getIntExtra("user_id");
SomeData data = (SomeData) getIntent().getSerializableExtra("data");
}
Intents.Login.show()
Read:
public class A extends Activity {
@Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
LoginData data = Intents.Login.getData(getIntent());
}
interface Intents {
abstract class Login { /*...*/ }
abstract class Messages { /*...*/ }
// etc...
}
if("Bob".equals(person.getName()) {
String name = person.getName();
String surname = person.getSurname();
// do things...
} else {
Log.d("You're not Bob!");
}
person match {
case Person("Bob", surname) =>
("Bob's surname is: " + surname).toast
case _ =>
"You're not Bob!".toast
}
class Data(num: Int)
object Data { // that's called an "companion object"
def apply(num: Int) = new Data(num)
def unapply(i: Intent): Option[Data] =
if (i.hasExtra("num"))
Some(new Data(i.getIntExtra("num")))
else
None
}
val data = Data(1)
// is the same as:
val data2 = Data.apply(2)
Remember Some(12)? Same thing.
data match {
case Data(num) => assert { num == 1 } // matches here! num = 1
case _ => ???
}
data match {
case Data(333) => ???
case Data(1) => // matches here!
}
data match {
case Something(a, b) =>
case other => // matches here
}
> ~test