How To Make A Better Sandwich

How To Make A Better Sandwich

This was a lightning talk I gave at Chicago Kotlin User Group on July 17th. It attempts to explain higher order functions through the analogy of sandwiches (borrowed from Ruby Koans). This will hopefully give new ideas for what is possible in Kotlin when it comes to DRYing up various parts of your codebase.

Ce0de7299bfbc54dd950689e04a4f053?s=128

Cody Engel

July 17, 2018
Tweet

Transcript

  1. How To Make A Better Sandwich Cody Engel @POTUS404 Senior

    Engineer
  2. @POTUS404 Slice Of Bread

  3. @POTUS404 Add Lettuce

  4. @POTUS404 Tomato

  5. @POTUS404 Cold Cuts

  6. @POTUS404 Fancy Mustard

  7. @POTUS404 Slice Of Bread

  8. @POTUS404 Slices Of Bread (Boring) (Boring)

  9. @POTUS404 Dijon = Interesting (Boring) (Boring) (Interesting)

  10. val startTime = System.currentTimeMillis() for (i in 0..100000) { println("Person:

    ${Person()}") } val endTime = System.currentTimeMillis() val runTime = endTime - startTime @POTUS404 Sandwich Code
  11. val startTime = System.currentTimeMillis() for (i in 0..100000) { println("Person:

    ${Person()}") } val endTime = System.currentTimeMillis() val runTime = endTime - startTime @POTUS404 Sandwich Code
  12. val startTime = System.currentTimeMillis() for (i in 0..100000) { println("Person:

    ${Person()}") } val endTime = System.currentTimeMillis() val runTime = endTime - startTime @POTUS404 Sandwich Code
  13. val startTime = System.currentTimeMillis() for (i in 0..100000) { println("Person:

    ${Person()}") } val endTime = System.currentTimeMillis() val runTime = endTime - startTime @POTUS404 Sandwich Code
  14. Higher Order Functions • Takes one or more functions as

    arguments. • Returns a function as a result.
  15. class Benchmark { fun benchmark(block: () -> Unit): Long {

    // assemble sandwich here } } @POTUS404 Higher Order Functions
  16. fun benchmark(block: () -> Unit): Long { val startTime =

    System.currentTimeMillis() block.invoke() return System.currentTimeMillis() - startTime } @POTUS404 Higher Order Functions
  17. fun benchmark(block: () -> Unit): Long { val startTime =

    System.currentTimeMillis() block.invoke() return System.currentTimeMillis() - startTime } @POTUS404 Higher Order Functions
  18. fun benchmark(block: () -> Unit): Long { val startTime =

    System.currentTimeMillis() block.invoke() return System.currentTimeMillis() - startTime } @POTUS404 Higher Order Functions
  19. val runtime = Benchmark().benchmark { for (i in 0..100000) {

    println("Person: ${Person()}") } } println("Executed in ${runtime}ms") @POTUS404 Higher Order Functions
  20. A Word About Keywords

  21. class Benchmark { fun benchmark(block: () -> Unit): Long {

    // assemble sandwich here } } @POTUS404 A Word About Keywords
  22. public final class Benchmark { public final long benchmark(@NotNull Function0

    block) { Intrinsics.checkParameterIsNotNull(block, "block"); long startTime = System.currentTimeMillis(); block.invoke(); return System.currentTimeMillis() - startTime; } } @POTUS404 A Word About Keywords
  23. val runtime = Benchmark().benchmark { for (i in 0..100000) {

    println("Person: ${Person()}") } } println("Executed in ${runtime}ms") @POTUS404 A Word About Keywords
  24. long runtime = (new Benchmark()).benchmark((Function0)null.INSTANCE); String var2 = "Executed in

    " + runtime + "ms"; System.out.println(var2); @POTUS404 A Word About Keywords
  25. class Benchmark { inline fun benchmark(block: () -> Unit): Long

    { // assemble sandwich here } } @POTUS404 A Word About Keywords
  26. public final class Benchmark { public final long benchmark(@NotNull Function0

    block) { Intrinsics.checkParameterIsNotNull(block, "block"); long startTime = System.currentTimeMillis(); block.invoke(); return System.currentTimeMillis() - startTime; } } @POTUS404 A Word About Keywords
  27. val runtime = Benchmark().benchmark { for (i in 0..100000) {

    println("Person: ${Person()}") } } println("Executed in ${runtime}ms") @POTUS404 A Word About Keywords
  28. new Benchmark(); long startTime$iv = System.currentTimeMillis(); int var5 = 0;

    for(int var6 = 100001; var5 < var6; ++var5) { String var7 = "Person: " + new Person((String)null, (String)null, 0, 7, (DefaultConstructorMarker)null); System.out.println(var7); } long runtime = System.currentTimeMillis() - startTime$iv; String var2 = "Executed in " + runtime + "ms"; System.out.println(var2); @POTUS404 A Word About Keywords
  29. new Benchmark(); long startTime$iv = System.currentTimeMillis(); int var5 = 0;

    for(int var6 = 100001; var5 < var6; ++var5) { String var7 = "Person: " + new Person((String)null, (String)null, 0, 7, (DefaultConstructorMarker)null); System.out.println(var7); } long runtime = System.currentTimeMillis() - startTime$iv; String var2 = "Executed in " + runtime + "ms"; System.out.println(var2); @POTUS404 long runtime = (new Benchmark()).benchmark((Function0 )null.INSTANCE); String var2 = "Executed in " + runtime + "ms"; System.out.println(var2); (Without Inline) (With Inline) A Word About Keywords
  30. Examples From IRL

  31. // Timing.kt public inline fun measureTimeMillis(block: () -> Unit) :

    Long { val start = System.currentTimeMillis() block() return System.currentTimeMillis() - start } @POTUS404 Examples From IRL
  32. @Test fun `when download contact list info completes loading contacts

    should be false`() { expectDownloadContactInfoResponse(Response()) initViewModel() assertViewState { currentState -> assertThat(currentState.loadingContacts).isFalse() } } private fun assertViewState(state: (currentState: ContactsViewState) -> Unit) { assertThat(viewModel.viewState.value).isNotNull state.invoke(viewModel.viewState.value!!) } @POTUS404 Examples From IRL
  33. fun waitFor(precondition: () -> Boolean) { var waitingFor = 0L

    while (precondition.invoke() && waitingFor < 1000) { Thread.sleep(25) waitingFor += 25 } } @POTUS404 Examples From IRL
  34. class KeyboardObserver(private val rootLayout: View) { var onKeyboardDisplayed: () ->

    Unit = {} var onKeyboardHidden: () -> Unit = {} init { rootLayout.viewTreeObserver.addOnGlobalLayoutListener({ if (keyboardHeight > screenHeight * 0.15) { if (!keyboardDisplayed) { onKeyboardDisplayed.invoke() } } else { if (!keyboardHidden) { onKeyboardHidden.invoke() } } }) } } @POTUS404 Examples From IRL
  35. Cody Engel @POTUS404 Senior Engineer (We’re Hiring) Thanks!