Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin: The Good Parts (DevFest 2017)

Kotlin: The Good Parts (DevFest 2017)

Una charla sobre Kotlin para Android, donde recorremos un poco la sintaxis, los "por qué" y algunas de las características que hacen de este lenguaje ideal para ser utilizado en Android.

Esta charla fue parte del DevFest 2017 organizada por el GDGNeuquen el 11/11/2017

Ricardo Markiewicz

November 11, 2017
Tweet

More Decks by Ricardo Markiewicz

Other Decks in Programming

Transcript

  1. TEXT ¿POR QUÉ KOTLIN? ▸ Restricciones y problemas de Java

    ▸ No se pueden extender tipos de la plataforma (Util hell) ▸ NPE Madness ▸ Threading / Mutability ▸ Too verbose ▸ Problemas de diseño de APIs de Android
  2. TEXT ¿POR QUÉ KOTLIN? ▸ Problemas de diseño de APIs

    de Android ▸ Inheritance party ▸ NULL por todos lados ▸ Ceremonias
  3. KOTLIN SINTAXIS val charla = "Kotlin" 
 val asistente: List<String>

    = ArrayList() 
 var tarea: String? = null
  4. KOTLIN SINTAXIS val charla = "Kotlin" 
 val asistente: List<String>

    = ArrayList() 
 var tarea: String? = null
  5. KOTLIN SINTAXIS val charla = "Kotlin" 
 val asistente: List<String>

    = ArrayList() 
 var tarea: String? = null
  6. KOTLIN SINTAXIS val charla = "Kotlin" 
 val asistente: List<String>

    = ArrayList() 
 var tarea: String? = null
  7. KOTLIN SINTAXIS val charla = "Kotlin" 
 val asistente: List<String>

    = ArrayList() 
 var tarea: String? = null
  8. KOTLIN EXTENSION FUNCTIONS // DateUtil.java 
 class DateUtil { 


    public static boolean isWeekend(Date date) { 
 int dayOfWeek = date.getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 } 
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 }}
  9. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 public static boolean isWeekend(Date

    date) { 
 int dayOfWeek = date.getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  10. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun isWeekend(Date date): Boolean

    { 
 int dayOfWeek = date.getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  11. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  12. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  13. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  14. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 }}
  15. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (date.isWeekend()) { 
 
 }}
  16. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {

    
 int dayOfWeek = day; 
 return dayOfWeek == 0 || dayOfWeek == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (date.isWeekend()) { 
 
 }}
  17. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend(): Boolean {


    return day == 0 || day == 6 
 }}
 
 // Somefile.java 
 Date date = new Date() 
 if (date.isWeekend()) { 
 
 }}
  18. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend() = day

    == 0 || day == 6
 
 // Somefile.java 
 Date date = new Date() 
 if (date.isWeekend()) { 
 
 }}
  19. KOTLIN EXTENSION FUNCTIONS // DateUtil.kt 
 fun Date.isWeekend() = day

    == 0 || day == 6
 
 // Somefile.java 
 Date date = new Date() 
 if (date.isWeekend()) { 
 
 }} // DateUtil.java 
 class DateUtil { 
 public static boolean isWeekend(Date date) { 
 int dayOfWeek = date.getDay(); 
 return dayOfWeek == 0 || dayOfWeek == 6 
 } 
 } 
 
 // Somefile.java 
 Date date = new Date() 
 if (DateUtil.isWeekend(date)) { 
 
 } 

  20. KOTLIN FUNCTION EXPRESSIONS ▸ { it.toString() } ▸ { x,

    y -> x + y } ▸ { x: Int, y: Int -> x * y } ▸ val sum: (Int, Int) -> Int = { x, y -> x + y } ▸ val mult = { x: Int, y: Int -> x * y } ▸ sum(2, 4)
  21. KOTLIN FUNCTION EXPRESSIONS ▸ val notEmpty: (String) -> Boolean =

    { !it.isEmpty() } ▸ val fourOrMore: (String) -> Boolean = { it.length() >= 4 } ▸ val someCrazyValidation: (String) -> Boolean = { heavyProcess(it) }
  22. KOTLIN HIGHER-ORDER FUNCTIONS A higher-order function is a function that

    takes functions as parameters, or returns a function
  23. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(...): List<String> { 
 
 } 
 
 val withR = namesThatStartWith(names, ...) 

  24. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, …): List<String> { 
 
 } 
 
 val withR = namesThatStartWith(names, ...) 

  25. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 
 } 
 
 val withR = namesThatStartWith(names, ...) 

  26. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 
 } 
 
 val withR = namesThatStartWith(names, ...) 

  27. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 
 } 
 
 val withR = namesThatStartWith(names, ...) 

  28. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 } 
 
 val withR = namesThatStartWith(names, { it.matches("^R") })

  29. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 } 
 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  30. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String>, matcher: (String) -> Boolean): List<String> { 
 } 
 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  31. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String, matcher: (String) -> Boolean): List<String> { 
 } 
 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  32. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String, matcher: (String) -> Boolean): List<String> { 
 var tmp = ArrayList() 
 list.forEach { 
 if (matches(it)) { 
 tmp.append(it) 
 } 
 } 
 return tmp 
 } 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  33. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String, matcher: (String) -> Boolean): List<String> { 
 var tmp = ArrayList() 
 list.forEach { 
 if (matches(it)) { 
 tmp.append(it) 
 } 
 } 
 return tmp 
 } 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  34. KOTLIN HIGHER-ORDER FUNCTIONS val names = listOf("Ricardo", "Martin", "Roberto", "Carlos")

    
 
 fun namesThatStartWith(list:List<String, matcher: (String) -> Boolean): List<String> { 
 var tmp = ArrayList() 
 list.forEach { 
 if (matches(it)) { 
 tmp.append(it) 
 } 
 } 
 return tmp 
 } 
 val withR = namesThatStartWith(names) { it.matches("^R") }

  35. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  36. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  37. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  38. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  39. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  40. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  41. KOTLIN HIGH-ORDER FUNCTIONS + EXTENSION FUNCTIONS fun <T> List<T>.filter(predicate: (T)

    -> Boolean): List<T> { 
 // ... 
 } 
 
 val names = listOf("Ricardo", "Martin", "Roberto", "Carlos") 
 
 val withR = names.filter { it.matches("/^R/") }
  42. KOTLIN DATA CLASS data class User(val name: String, val age:

    Int) 
 
 val me = User("Ricardo", 38)
  43. KOTLIN DATA CLASS data class User(val name: String, val age:

    Int) 
 
 val me = User("Ricardo", 38) 
 
 val (name, age) = me
  44. KOTLIN DATA CLASS data class User(val name: String, val age:

    Int) 
 
 val me = User("Ricardo", 38) 
 
 val (name, age) = me 
 
 fun Float.toFrac(): Pair { 
 // ... 
 } 
 
 val n = 1.5 
 val (num, den) = n.toFrac() 

  45. KOTLIN DATA CLASS data class User(val name: String, val age:

    Int) 
 
 val me = User("Ricardo", 38) 
 
 val (name, age) = me 
 
 fun Float.toFrac(): Pair { 
 // ... 
 } 
 
 val n = 1.5 
 val (num, den) = n.toFrac() 

  46. KOTLIN DATA CLASS data class User(val name: String, val age:

    Int) 
 
 val me = User("Ricardo", 38) 
 
 val (name, age) = me 
 
 fun Float.toFrac(): Pair { 
 // ... 
 } 
 
 val n = 1.5 
 val (num, den) = n.toFrac() 

  47. KOTLIN REDUCE BOILERPLATE class LoginActivity : AppCompatActivity() { 
 internal

    var emailView: TextView? = null 
 internal var passwordView: TextView? = null 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView = (TextView) findViewById(R.id.email) 
 passwordView = (TextView) findViewById(R.id.password) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}
 }}
  48. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal var emailView: TextView? = null 
 internal var passwordView: TextView? = null 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView = (TextView) findViewById(R.id.email) 
 passwordView = (TextView) findViewById(R.id.password) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }}
 }}

  49. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal var emailView: TextView? = null 
 internal var passwordView: TextView? = null 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView = (TextView) findViewById(R.id.email) 
 passwordView = (TextView) findViewById(R.id.password) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }}
 }}

  50. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal var emailView: TextView? = null 
 internal var passwordView: TextView? = null 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView = (TextView) findViewById(R.id.email) 
 passwordView = (TextView) findViewById(R.id.password) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }}
 }}

  51. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal var emailView: TextView? = null 
 internal var passwordView: TextView? = null 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView = find<TextView>(R.id.email) 
 passwordView = find<TextView>(R.id.password) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}

  52. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal val emailView: TextView = find<TextView>(R.id.email) 
 internal val passwordView: TextView = find<TextView>(R.id.password) 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}
 }}

  53. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal val emailView: TextView = find<TextView>(R.id.email) 
 internal val passwordView: TextView = find<TextView>(R.id.password) 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}
 }}
  54. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal val emailView: TextView = find<TextView>(R.id.email) 
 internal val passwordView: TextView = find<TextView>(R.id.password) 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}
 }}
  55. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal val emailView by lazy { find<TextView>(R.id.email) } 
 internal val passwordView by lazy { find<TextView>(R.id.password) } 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 if (emailView != null) { 
 emailView.setSomeImportantStuff(...) 
 }} 
 }}
 }}
  56. KOTLIN REDUCE BOILERPLATE inline fun <reified T : View> Activity.find(id:

    Int): T = findViewById(id) as T 
 
 class LoginActivity : AppCompatActivity() { 
 internal val emailView by lazy { find<TextView>(R.id.email) } 
 internal val passwordView by lazy { find<TextView>(R.id.password) } 
 
 override fun onCreate(savedInstanceState: Bundle?) { 
 super.onCreate(savedInstanceState) 
 setContentView(R.layout.activity_login) 
 
 emailView.setSomeImportantStuff(...) 
 }}
 }}
  57. KOTLIN REDUCE ERRORS db.beginTransaction() 
 try { 
 db.delete("users", "first_name

    = ?", new String[] { "Ricardo" }); 
 } finally { 
 db.endTransaction(); 
 }
  58. KOTLIN REDUCE ERRORS db.beginTransaction() 
 try { 
 db.delete("users", "first_name

    = ?", new String[] { "Ricardo" }); db.setTransactionSuccess();
 } finally { 
 db.endTransaction(); 
 }
  59. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: () -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 }
  60. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: () -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 }
  61. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: () -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 db.delete("users", "first_name = ?", arrayOf("Ricardo")) 
 }
  62. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: (SQLiteDatabase) -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 db.delete("users", "first_name = ?", arrayOf("Ricardo")) 
 }
  63. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: (SQLiteDatabase) -> Unit) { 


    beginTransaction() 
 try { 
 func(this) 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 db.delete("users", "first_name = ?", arrayOf("Ricardo")) 
 }
  64. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: (SQLiteDatabase) -> Unit) { 


    beginTransaction() 
 try { 
 func(this) 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 it.delete(“users", "first_name = ?", arrayOf("Ricardo")) 
 }
  65. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) { 


    beginTransaction() 
 try { 
 func(this) 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 it.delete(“users", "first_name = ?", arrayOf("Ricardo")) 
 }
  66. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) { 


    beginTransaction() 
 try { 
 this.func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 it.delete(“users", "first_name = ?", arrayOf("Ricardo")) 
 }
  67. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 it.delete(“users", "first_name = ?", arrayOf("Ricardo")) 
 }
  68. KOTLIN REDUCE ERRORS fun SQLiteDatabase.inTransaction(func: SQLiteDatabase.() -> Unit) { 


    beginTransaction() 
 try { 
 func() 
 setTransactionSuccess() 
 } finally { 
 endTransaction(); 
 } 
 } 
 
 db.inTransaction { 
 delete(“users", "first_name = ?", arrayOf("Ricardo")) 
 }
  69. KOTLIN THE GOOD PARTS inline fun notification(context: Context, func: Notification.Builder.()

    -> Unit): Notification { 
 val builder = Notification.Builder(context) 
 builder.func() 
 return builder.build() 
 } 
 
 val n = notification(context) { 
 setContentTitle("Kotlin") 
 setSubText("The Good parts :)") 
 }
  70. KOTLIN THE GOOD PARTS val email:: TextView = // ...

    
 
 email.setVisibility(View.GONE) 
 email.setVisibility(View.VISIBLE)
  71. KOTLIN THE GOOD PARTS val email:: TextView = // ...

    
 
 email.hide() 
 email.show()
  72. KOTLIN THE GOOD PARTS val email:: TextView = // ...

    
 
 email.hide() 
 email.show() 
 
 inline fun TextView.hide() { visibility = View.GONE } 
 inline fun TextView.show() { visibility = View.VISIBLE }