Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

How to Make the Compiler Smarter

Add effects to your functions with Kotlin Contracts

 

 
Denis Craciunescu
I write about things I’m learning — Android Developer @Nagarro
Published: November 25, 2020
Tweet
Share
 

Developer and Compiler working together

 

Introduction

The Kotlin compiler is smart. By performing static analysis on your code, the compiler identifies mistakes in your code as you type it.

One of the most notable features of the Kotlin compiler is smart casting. The compiler has the ability to perform a cast based on the type checks done by the developer.

The compiler tracks the is-checks, null-checks, and explicit casts for immutable values. Using the acquired information, the compiler casts variables when needed.

 

 

Smart cast :)

 

However, the smart cast mechanism is limited. The compiler does not cast variables when the variable can change between the check and the usage.

Moreover, the compiler tracks the type checks only in the same block or in the same condition in which the check was performed.

 

 

No smart cast :(

 

The compiler is not THAT smart…

In your codebase, you have a better understanding of what can happen and what cannot.

Wouldn’t it be nice if you could somehow transfer this knowledge to the compiler?

 

Kotlin Contracts

Image for post

You transfer your knowledge to the compiler

 

With Kotlin Contracts, you can “sign an agreement” between you and the compiler — if something goes wrong, the compiler will “sue” you (by crashing the application).

However, Contracts are deterministic and describe the natural effect of your code, hence it is highly unlikely for a contract to cause a crash if carefully declared.

The effect of the contract helps the compiler in the static analysis process. 
For example, if you create a function that returns true if the argument is not null, then the compiler can use this information to smart cast the argument to a non-nullable type outside the function.

 

How do Contracts work?

Image for post

Functions produce effects

 

A contract adds an effect to a function.
If a function f has an effect e, we say that the invocation of f produces the effect e.

The compiler tracks all the effects produced and uses them to enhance the static analysis step.

You can declare a contract only at the beginning of a function using the Contract DSL.

 

 

Contracts syntax

 

Contract Effects

You can use the following functions to declare a contract:

  • returns(value)
  • returnsNotNull()
  • implies(booleanExpression)
  • callsInPlace(lambda, kind)

 

‘Returns’ Effect

The returns(value) function describes a situation when a function returns normally with the specified value.

The returnsNotNull() functions describe a situation when a functionreturns a non-null value.

Both these functions can be composed together with the implies function to form an effect.

The implies(booleanExpression) specifies that this effect, when observed, guarantees booleanExpression to be true.

 

 

Returns effect example

 

In the code snippet from above, if the function isNotNull returns true, the expression this@isNotNull != null (line 13) is guaranteed to be true.

Hence, if our function returns true, then the compiler understands that the receiver String is not null and smart casts it to a non-nullable String, outside the extension function.

 

‘CallsInPlace’ Effect

Let’s take the following example:

 

 

Error (line 3): “Captured member values initialization is forbidden due to possible reassignment”

 

This code snippet does not compile because the compiler is not able to determine that the lambda from lines 2–4 gets executed only once.

From the compiler’s perspective, this lambda could be executed many times, initiating the a variable more than once.

For the code from above to run successfully, the compiler should somehow know that the block gets executed only once.

Let’s take the same example, this time using a mutable variable (var):

 

 

Error (line 5): “Variable ‘a’ must be initialized”

 

Similarly, if a is a mutable variable (var), the code still does not compile.

From the compiler’s perspective, this lambda is not guaranteed to be executed at least once, hence, it might happen that the a variable is left uninitialized.

 

This is where the callsInPlace effect comes into play.

 

The callsInPlace(lambda, kind) function allows you to specify how often the given lambda will be run.

The kind parameter is of type InvocationKind and can take the following values:

  • UNKNOWN
  • EXACTLY_ONCE
  • AT_LEAST_ONCE
  • AT_MOST_ONCE

 

 

CallsInPlace effect example

 

In the above code snippet, we assure the compiler that the initializefunction will be called AT_LEAST_ONCE.

The compiler then observes that in the passed lambda (lines 3–5), we are initializing a, and since the initialization block will run AT_LEAST_ONCE, the compiler understands that a will always be initialized on line 6.

The following InvocationKinds can be used to initialize a variable in a lambda:

  • Immutable variables (val): EXACTLY_ONCE
  • Mutable variables (var): AT_LEAST_ONCE, EXACTLY_ONCE

 

Contracts are already part of the Kotlin Standard Library:

 

Image for post

Usage of `callsInPlace` effect in Kotlin standard library

 

For example, scope functions define a callsInPlace effect that specifies that the given lambda will be executed EXACTLY_ONCE.

With this knowledge, the compiler lets us initialize variables in the block executed by the scope function.

 

 

‘Apply’ scope function

 

Summary

The Kotlin compiler is smart. But sometimes you understand your code better than the compiler.

With the use of Contracts, you can transfer your knowledge to the compiler. Contracts specify the effect that the invocation of a function produces.

The compiler tracks all the effects and uses the acquired information to smart cast variables or permit the initialization of variables in a lambda.

Sadly, for the moment this is all that contracts can do. 
However, the possibilities are endless and we are yet to see how this mechanism will evolve in the future.

 

If you found the information useful, don’t forget to 👏!

Until next time! 😀

 

Headline of Android Weekly #439
Featured in Kotlin Weekly #223

 

Denis Crăciunescu - Android Developer - Nagarro | LinkedIn

View Denis Crăciunescu's profile on LinkedIn, the world's largest professional community. Denis has 1 job listed on…

www.linkedin.com

 

*illustrations generated using icons8 vector creator

 

Tags: Android, Kotlin, Programming, Android App Development, AndroidDev

 

View original article at: 


 

Originally published: November 06, 2020

Android News
Compose CameraX on Android
Compose CameraX on Android

By Peng Jiang

Android new UI toolkit Jetpack compose is in beta now, which has all the features you need to build production-ready apps. CameraX is another Jetpack support library, which let you control the camera easier. As compose is still under development, lots of the views are still not available the compose way.

By ProAndroidDev -
Android News
Getting… your BottomSheetScaffold working on Jetpack Compose Beta 03
Getting… your BottomSheetScaffold working on Jetpack Compose Beta 03

By Carlos Mota

It’s Monday, no releases this week, and… there’s a new version of Jetpack Compose — beta 03—available. What a perfect time to just increment 02 to 03 and see what’s new. The API is (almost) final so after updating from alpha to beta there weren’t any big changes to do. However, and remember that’s still in development, there’s always something that I need to update. 

By ProAndroidDev -
Android News
Noisy Code With Kotlin Scopes
Noisy Code With Kotlin Scopes

By Chetan Gupta

Scopes make your code more readable? think again... You are going to encounter these scope functions namely let, run, apply, also, within every Kotlin codebase, along with all the mischievous ways developers exploit their usage from the way they were intended for. Let see how popular opinion on those ends up just as a code noise.

By ProAndroidDev -
Android News
Improving Android DataBinding with Bindables library
Improving Android DataBinding with Bindables library

By Jaewoong Eum

DataBinding is one of the most important factors for MVVM architecture. The basic concept of DataBinding is to link the view and view model via observer patterns, properties, event callbacks, etc. Linking and automating communication between the view via the bound properties or something in the view model has a lot of benefits in the MVVM architecture concept.

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One