krakdroid: scala on android

Post on 12-May-2015

2.901 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

A revamped talk about #scala programming on #android. Presentation given at krakdroid 2012. http://krakdroid.pl

TRANSCRIPT

Sunday, December 16, 12

Sunday, December 16, 12

Scala is

Sunday, December 16, 12

Scala is

Sunday, December 16, 12

Scala is

Sunday, December 16, 12

Scala is

Sunday, December 16, 12

Scala is

Simple

Sunday, December 16, 12

Scala is

Simple , but Hard.

Sunday, December 16, 12

Scala is Simple.

Sunday, December 16, 12

Scala is Simple.

Sunday, December 16, 12

Scala is Hard.object  Param  {

   implicit  def  pToT[A[_],  B[_]](f:  (p:  Param[A])  =>  B[p.T]):  A~>B  =  new  (A  ~>  B)  {        def  apply[s](a:  A[s]):  B[s]  =  {            val  v:  Param[A]  {  type  T  =  s}  =  new  Param[A]  {                  type  T  =  s                def  in  =  a            }            f(v)        }    }

}

http://apocalisp.wordpress.com/2010/10/26/type-level-programming

-in-scala-part-7-natural-transformation%C2%A0literals/Sunday, December 16, 12

Scala is

Sunday, December 16, 12

Scala is

A Functional,

Sunday, December 16, 12

Scala is

A Functional,Object Oriented,

Sunday, December 16, 12

Scala is

A Functional,Object Oriented,Statically Typed,

Sunday, December 16, 12

Scala is

A Functional,Object Oriented,Statically Typed,

Scalable,

Sunday, December 16, 12

Scala is

A Functional,Object Oriented,Statically Typed,

Scalable,Language...

Sunday, December 16, 12

Scala is

A Functional,Object Oriented,Statically Typed,

Scalable,Language...

...running on the JVM and DVM!

Sunday, December 16, 12

Android

Sunday, December 16, 12

findViewByIdpublic 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); // ... }}

Sunday, December 16, 12

findViewByIdpublic 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); // ... }}

is null at first...

Sunday, December 16, 12

findViewByIdpublic 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); // ... }}

initialized in method...

Sunday, December 16, 12

findViewByIdpublic 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); // ... }} Explicit casting!

Sunday, December 16, 12

Robo Guicepublic class MakeANoteActivity extends Activity implements View.OnClickListener{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";

@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;

@Inject CalibrationHelper calibrationHelper;

@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;

@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;

// ... }

So many words...

Sunday, December 16, 12

Robo Guicepublic class MakeANoteActivity extends RoboActivity implements View.OnClickListener{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";

@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;

@Inject CalibrationHelper calibrationHelper;

@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;

@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;

// ... }

Type changes in XML, but not here...

ClassCastException!

Sunday, December 16, 12

Robo Guicepublic class MakeANoteActivity extends RoboActivity implements View.OnClickListener{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";

@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;

@Inject CalibrationHelper calibrationHelper;

@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;

@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;

// ... }

Guice is eager. Startup can take a few seconds!

Sunday, December 16, 12

Stairway to Scala

Sunday, December 16, 12

Another look at the Java codepublic class MakeANoteActivity extends RoboActivity implements View.OnClickListener

{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";

@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;

@Inject CalibrationHelper calibrationHelper;

@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;

@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;

// ... }

Sunday, December 16, 12

public class MakeANoteActivity extends RoboActivity implements View.OnClickListener

{ public static final String PHOTO_PATH = "picture_path"; public static final String PHOTO_ATTACHED = "photo_attached";

@Inject SessionManager sessionManager; @Inject LocationHelper locationHelper; @Inject PhotoHelper photoHelper; @Inject Application context;

@Inject CalibrationHelper calibrationHelper;

@InjectView(R.id.attach_photo) Button attachPhoto; @InjectView(R.id.note_text) EditText noteText; @InjectView(R.id.save_button) Button save; @InjectView(R.id.date) TextView dateText; @InjectView(R.id.share) Button share;

@InjectResource(R.string.im_aircasting) String imAircasting; @InjectResource(R.string.share_with) String shareWith;

// ... }

What if... Scala?

Sunday, December 16, 12

class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with)

def toastConferenceName() = "KrakDroid".toast()}

What if... Scala?

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

public is default.

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

ScalaActivity gives us some magic methods

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

ScalaActivity gives us some magic methods

It’s so easy, YOU can implement it!

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

ScalaActivity gives us some magic methods

It’s so easy, YOU can implement it!

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Instead of “...Helper”,use Traits.

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Type Inference

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Who’s missing here?

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

lazy initialization

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Needs Context

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

What’s the type here?!?

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

What’s the type here?!?

Typed Resource - “a better R”

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

What’s the type here?!?

Typed Resource - “a better R”

XML Type changes... Type here changes!

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share: Button = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

What’s the type here?!?

Typed Resource - “a better R”

You can be explicit though!

Sunday, December 16, 12

class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

What if... Scala?

Like @InjectResource, but smarter

Manifests vs. Type Erasure

Sunday, December 16, 12

What if... Scala?class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Does String have a toast() method?

Implicit Conversion

Sunday, December 16, 12

Typed Resource

Sunday, December 16, 12

Typed Resource = Better R

Sunday, December 16, 12

Typed Resource = Better R

Sunday, December 16, 12

class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Typed Resource = Better R

Sunday, December 16, 12

class MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get lazy val locationManager = LocationManager.get

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

val username = findResource[String](R.string.my_username) val friends = findResource[List[String]](R.string.friends)

def toastConferenceName() = "KrakDroid".toast()}

Typed Resource

Typed Resource = Better R

Sunday, December 16, 12

case class TypedResource[T](id: Int)case class TypedLayout(id: Int)

object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)

val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...

}

Typed Resource = Better R

Sunday, December 16, 12

Typed Resource = Better R

case class TypedResource[T](id: Int)case class TypedLayout(id: Int)

object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)

val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...

}

Sunday, December 16, 12

Typed Resource = Better R

case class TypedResource[T](id: Int)case class TypedLayout(id: Int)

object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)

val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...

}

Wrappers

Sunday, December 16, 12

Typed Resource = Better R

case class TypedResource[T](id: Int)case class TypedLayout(id: Int)

object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)

val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...

}

Sunday, December 16, 12

Typed Resource = Better R

case class TypedResource[T](id: Int)case class TypedLayout(id: Int)

object TR { val columns_pager = TypedResource[ViewPager](R.id.columns_pager)

val workspaces = TypedResource[ExpandableListView](R.id.workspaces)

val subtask_txt = TypedResource[TextView](R.id.subtask_txt) // ...

}

Sunday, December 16, 12

TR in Actionclass MakeANoteActivity extends ScalaActivity with View.OnClickListener with PhotoOperations with CalibrationOperations{ val PhotoPath = "picture_path" val PhotoAttached = "photo_attached"

lazy val sessionManager = SessionManager.get // magic here but lazy val locationManager = LocationManager.get // we’ll see this later!

lazy val attachPhoto = findView(TR.attach_photo) lazy val noteText = findView(TR.note_text) lazy val save = findView(TR.save_button) lazy val dateText = findView(TR.date) lazy val share = findView(TR.share)

// magic here too, but we’ll implement this in a few slides! val imAircasting = findResource[String](R.string.im_aircasting) val shareWith = findResource[String](R.string.share_with)

// ...}

Sunday, December 16, 12

Types

Sunday, December 16, 12

Types

You always have the type information at hand.

Sunday, December 16, 12

Types

You always have the type information at hand.

(IntelliJ IDEA, Ensmine/Emacs, Eclipse)⌘ SHIFT I

ALT =

Sunday, December 16, 12

An Implicit Context

Sunday, December 16, 12

An Implicit Context

Implicit != Explicit

Sunday, December 16, 12

An Implicit ContextImplicit != Explicit

def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName(”Siegfried”, getContext)

Sunday, December 16, 12

def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName(”Siegfried”, getContext)

An Implicit ContextImplicit != Explicit

Explicit Parameter

Sunday, December 16, 12

def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName(”Siegfried”, getContext)

An Implicit ContextImplicit != Explicit

Explicit ParameterExplicit Parameter

Sunday, December 16, 12

def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName(”Siegfried”, getContext)

An Implicit ContextImplicit != Explicit

Import inside a method!

Sunday, December 16, 12

def toastMyName(name: String, ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName(”Siegfried”, getContext)

An Implicit ContextImplicit != Explicit

Sunday, December 16, 12

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

An Implicit ContextImplicit != Explicit

Sunday, December 16, 12

Implicit ParametersImplicit != Explicit

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

Implicit Parameter

Sunday, December 16, 12

Implicit ParametersImplicit != Explicit

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

Sunday, December 16, 12

Implicit ParametersImplicit != Explicit

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

toastMyName("Siegfried")

Sunday, December 16, 12

Implicit ParametersImplicit != Explicit

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

implicit val context: Context = getContext

toastMyName("Siegfried")

Sunday, December 16, 12

Implicit ParametersImplicit != Explicit

def toastMyName(name: String)(implicit ctx: Context) { import android.widget.Toast._ makeText(ctx, msg, LENGTH_LONG).show()}

implicit val context: Context = getContext

toastMyName("Siegfried")

toastMyName("Siegfried")(context)

Sunday, December 16, 12

An Implicit Context

class ScalaActivity extends Activity with ImplicitContext

Sunday, December 16, 12

An Implicit Context

trait ImplicitContext { this: Activity => implicit val ctx = getContext}

class ScalaActivity extends Activity with ImplicitContext

Sunday, December 16, 12

An Implicit Context

trait ImplicitContext { this: Activity => implicit val ctx = getContext}

class ScalaActivity extends Activity with ImplicitContext

“I can be only mixed intoan Activity.”

Sunday, December 16, 12

An Implicit Context

trait ImplicitContext { this: Activity => implicit val ctx = getContext}

class ScalaActivity extends Activity with ImplicitContext

“I can be only mixed intoan Activity.”

So I know this method!

Sunday, December 16, 12

Manifests vs. Type Erasure

Sunday, December 16, 12

Manifests vs. Type Erasure

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

Manifests vs. Type Erasure

Java

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

Manifests vs. Type Erasure

Java

Uhm... List<Object>...?

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

List<Thing> t = marshaller.parseList("[]", Thing.class)

Manifests vs. Type Erasure

Java

Uhm... List<Object>...?

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

List<Thing> t = marshaller.parseList("[]", Thing.class)

Manifests vs. Type Erasure

Java

Uhm... List<Object>...?

Oh! List<Thing>, sure!

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

List<Thing> t = marshaller.parseList("[]", Thing.class)

val t: List[Thing] = marshaller.parseList("[]")

Manifests vs. Type Erasure

Java

Scala

Uhm... List<Object>...?

Oh! List<Thing>, sure!

Sunday, December 16, 12

List<Thing> t = marshaller.parseList("[]")

List<Thing> t = marshaller.parseList("[]", Thing.class)

val t: List[Thing] = marshaller.parseList("[]")

Manifests vs. Type Erasure

Java

Scala

Uhm... List<Object>...?

Oh! List<Thing>, sure!

List[Thing]!

Sunday, December 16, 12

val shareWith = findResource[String](R.string.share_with)

Manifests vs. Type Erasure

Sunday, December 16, 12

Manifests vs. Type Erasure

val shareWith = findResource[String](R.string.share_with)

Sunday, December 16, 12

Manifests vs. Type Erasure

val shareWith = findResource[String](R.string.share_with)

def findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

implicit

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

implicit Manifest

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

the type signature

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

see the type... at runtime

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])

case "Int" => ctx.getString(id).toInt.asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

Sunday, December 16, 12

Manifests vs. Type Erasuredef findResource[T](id: Int)(implicit ctx: Context, m: Manifest[T]): T = m.toString match { case "java.lang.String" => ctx.getString(id).asInstanceOf[T] case "java.util.ArrayList[java.lang.String]" => newArrayList(ctx.getString(id).asInstanceOf[T])

case "Int" => ctx.getString(id).toInt.asInstanceOf[T]

case other => throw new UnableToResolveResource(ofType = other, id = id) }

val shareWith = findResource[String](R.string.share_with)

java.lang.String has this...?

Sunday, December 16, 12

Implicit Conversions

Sunday, December 16, 12

Implicit Conversions

Implicit != Explicit

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

toastMyName("Siegfried")

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

toastMyName("Siegfried")

Implicit Context, remember?

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

toastMyName("Siegfried")

What if we could...

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

toastMyName("Siegfried")

"Siegfried".toast()

What if we could...

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

Decorator

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

DecoratorConstructor

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

new Toastable("Hello!").toast()

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

Implicit Conversion: String => Toastable

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

asToastable("Hello!").toast()

Implicit Conversion: String => Toastable

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

Implicit Conversion: String => Toastable

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)}

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

Sunday, December 16, 12

Implicit ConversionsImplicit != Explicit

class Toastable(msg: String) { def toast()(implicit ctx: Context) = ???}

trait ScalaToasts {

implicit def asToastable(str: String) = new Toastable(str)} "Hello!".toast()

class ExampleActivity extends Activity with ImplicitContext with ScalaToasts

asToastable("Hello!").toast()

Sunday, December 16, 12

Implicit Conversions

Sunday, December 16, 12

Collections

Sunday, December 16, 12

POJO

Sunday, December 16, 12

POJOpublic class Person { private final String name; private final String nick;

public Person(String name, String nick) { this.name = name; this.nick = nick; }

public String getName() { return name; }

public String getNick() { return nick; }

@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false;

Person person = (Person) o;

if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false;

return true; }

@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; }}

Sunday, December 16, 12

POJOpublic class Person { private final String name; private final String nick;

public Person(String name, String nick) { this.name = name; this.nick = nick; }

public String getName() { return name; }

public String getNick() { return nick; }

@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false;

Person person = (Person) o;

if (name != null ? !name.equals(person.name) : person.name != null) return false; if (nick != null ? !nick.equals(person.nick) : person.nick != null) return false;

return true; }

@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (surname != null ? surname.hashCode() : 0); return result; }}

Sunday, December 16, 12

POSO**Actually just a Case Class

case class Person(name: String, nick: String)

Sunday, December 16, 12

case class Person(name: String, nick: String)

val name: String

POSO**Actually just a Case Class

Sunday, December 16, 12

case class Person(name: String, nick: String)

Case Classes

Sunday, December 16, 12

case class Person(name: String, nick: String)

Case Classes

Sunday, December 16, 12

case class Person(name: String, nick: String)

val person = Person("Bruce Wayne", "Manbat") // whoops!

Case Classes

Sunday, December 16, 12

case class Person(name: String, nick: String)

val person = Person("Bruce Wayne", "Manbat") // whoops!

Case Classes

val fixed = person.copy(nick = "Batman")

Sunday, December 16, 12

case class Person(name: String, nick: String)

val person = Person("Bruce Wayne", "Manbat") // whoops!

val self = Person(nick = "Ktoso" , name = "Konrad")

Case Classes

val fixed = person.copy(nick = "Batman")

Sunday, December 16, 12

case class Person(name: String, nick: String)

val person = Person("Bruce Wayne", "Manbat") // whoops!

val self = Person(nick = "Ktoso" , name = "Konrad")

val Person(name, hero) = personval hello = ”Hello” + name + ” ” + surname

Case Classes

val fixed = person.copy(nick = "Batman")

Sunday, December 16, 12

case class Person(name: String, nick: String)

val person = Person("Bruce Wayne", "Manbat") // whoops!

val self = Person(nick = "Ktoso" , name = "Konrad")

val Person(name, hero) = personval hello = ”Hello” + name + ” ” + surname

fixed.toString should equal (”Person(Bruce Wayne, Batman)”)

Case Classes

Still thinking assertThat().isEqualTo() is clean?

val fixed = person.copy(nick = "Batman")

Sunday, December 16, 12

Given a list of People,return all the Hero names.

Sunday, December 16, 12

public List<String> heroNames(List<Person> allPersons) { List<String> donePersons = new ArrayList<String>(allPersons.size());

for (Person person : allPersons) { if (person.isHero()) { donePersons.add(person.getName()); } }

return ImmutableList.copyOf(donePersons); }

Given a list of People,return all the Hero names.

Sunday, December 16, 12

Java with Guava at their BestGiven a list of People,

return all the Hero names.

Sunday, December 16, 12

Java with Guava at their Best

return FluentIterable .from(people) .filter(new Predicate<Person>() { @Override public boolean apply(Person person) { return person != null && person.isHero(); } }) .transform(new Function<Person, String>() { @Override public String apply(Person input) { return input.getName(); } }) .toImmutableList();

Given a list of People,return all the Hero names.

Sunday, December 16, 12

Sunday, December 16, 12

Java + Guava at their bestGiven a list of People,

return all the Hero names.

Sunday, December 16, 12

Java + Guava at their best

return FluentIterable .from(people) .filter(isSuperHero) .transform(heroToName) .toImmutableList();

Java, yet pretty slick :-)I <3 Guava.

Given a list of People,return all the Hero names.

Sunday, December 16, 12

Scala Collections at WorkGiven a list of People,

return all the Hero names.

Sunday, December 16, 12

def heroNames(people: List[Person]) = people filter(_.isHero) map { _.name}

Scala Collections at WorkGiven a list of People,

return all the Hero names.

Sunday, December 16, 12

And there’s more!

Sunday, December 16, 12

Simple Threading

Sunday, December 16, 12

Simple Threading

implicit val handler = new Handler

Sunday, December 16, 12

Simple Threading

implicit val handler = new Handler

inUiThread { // ...}

Sunday, December 16, 12

Simple Threading

implicit val handler = new Handler

inFutureWithProgressDialog(timeout = 10.seconds) { // ...}

inUiThread { // ...}

Sunday, December 16, 12

Simple Threading

implicit val handler = new Handler

inFutureWithProgressDialog(timeout = 10.seconds) { // ...}

inUiThread { // ...}

Implicit Conversion on Int

Sunday, December 16, 12

on___

button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... }});

Java

Sunday, December 16, 12

on___

button onClick { view => // ...}

button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // ... }});

Java

Scala

Sunday, December 16, 12

SharedPreferences

Sunday, December 16, 12

SharedPreferences

KanbaneryPreferences.projectId = projectId

Sunday, December 16, 12

SharedPreferences

KanbaneryPreferences.projectId = projectId

val name: Option[Long] = KanbaneryPreferences.projectId

Sunday, December 16, 12

SharedPreferences

KanbaneryPreferences.projectId = projectId

val name: Option[Long] = KanbaneryPreferences.projectId

What? No implicits?! Assume it works! Skip!

Sunday, December 16, 12

SharedPreferencesobject KanbaneryPreferences {

private val KeyLogin = "login"

private def sharedPreferences(implicit ctx: Context) = ???

def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")

Sunday, December 16, 12

SharedPreferencesobject KanbaneryPreferences {

private val KeyLogin = "login"

private def sharedPreferences(implicit ctx: Context) = ???

def login(implicit ctx: Context) = sharedPreferences.getString(KeyLogin, "")

Sunday, December 16, 12

SharedPreferencesobject KanbaneryPreferences {

private val KeyLogin = "login"

private def sharedPreferences(implicit ctx: Context) = ???

def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) }

}

Sunday, December 16, 12

SharedPreferencesobject KanbaneryPreferences {

private val KeyLogin = "login"

private def sharedPreferences(implicit ctx: Context) = ???

def login_=(number: String)(implicit ctx: Context) { withSharedPreferencesEditor { _.putString(KeyLogin, number) }

}

Sunday, December 16, 12

SharedPreferences

def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {

val editor = sharedPreferences.edit()

block(editor)

editor.commit()}

Sunday, December 16, 12

SharedPreferences

def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {

val editor = sharedPreferences.edit()

block(editor)

editor.commit()}

Sunday, December 16, 12

SharedPreferences

def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {

val editor = sharedPreferences.edit()

block(editor)

editor.commit()}

Sunday, December 16, 12

SharedPreferences

def withSharedPreferencesEditor (block: SharedPreferences.Editor => Unit) (implicit ctx: Context) {

val editor = sharedPreferences.edit()

block(editor)

editor.commit()}

withSharedPreferencesEditor { _.putString(KeyLogin, number) }

Sunday, December 16, 12

String interpolation(scala 2.10)

Sunday, December 16, 12

String interpolation(scala 2.10)

Sunday, December 16, 12

String interpolation(scala 2.10)

Sunday, December 16, 12

String interpolation(scala 2.10)

Won’t compile!

Sunday, December 16, 12

Let me warn you...

Sunday, December 16, 12

Let me warn you...

Scala is addictive.

Sunday, December 16, 12

Let me warn you...

Scala is addictive.

Sunday, December 16, 12

Scala is addictive.

Sunday, December 16, 12

Scala is addictive.

Sunday, December 16, 12

Scala is addictive.

Sunday, December 16, 12

Scala is addictive.

Sunday, December 16, 12

def links = • Scala Lang http://www.scala-lang.org/

• Scala Koans http://www.scalakoans.org

• Blog.Project13.pl - http://www.blog.project13.pl

• SBT Android Plugin - https://github.com/jberkel/android-plugin

• Kanbanery for Android - https://github.com/ktoso/kanbanery-tv• Check pl.project13.scala.android.*• Now OpenSource, in Scala, and Lunar Logic is helping to dev :-)• New version soon! Pull and play with it!

• Scaloid https://github.com/pocorall/scaloid• Though I don’t think their impl. is very clean some things are v. nice!

Sunday, December 16, 12

def links = • Scala Lang http://www.scala-lang.org/

• Scala Koans http://www.scalakoans.org

• Blog.Project13.pl - http://www.blog.project13.pl

• SBT Android Plugin - https://github.com/jberkel/android-plugin

• Kanbanery for Android - https://github.com/ktoso/kanbanery-tv• Check pl.project13.scala.android.*• Now OpenSource, in Scala, and Lunar Logic is helping to dev :-)• New version soon! Pull and play with it!

• Scaloid https://github.com/pocorall/scaloid• Though I don’t think their impl. is very clean some things are v. nice!

Mailing lists rock!

Sunday, December 16, 12

Konrad Malawski / @ktosoplGDG / PJUG / KSUG / SCKRK

KrakDroid 14.12.2012Sunday, December 16, 12

Konrad Malawski / @ktosoplGDG / PJUG / KSUG / SCKRK

KrakDroid 14.12.2012

I love feedback! <3

Sunday, December 16, 12

top related