Liveon Phoenix
Liveon Phoenix

Reputation: 43

In kotlin what is this syntax: "fun ClassName.funcName(): (Type ) -> Type = {fun body}"

Edited: What and how it work? This is a kotlin dsl language.

fun ClassName.funcName(): (Type ) -> Type = {func body}

um this is one of the implementation I found, and also see the concrete syntax to this link: https://dzone.com/articles/the-complete-custom-gradle-plugin-building-tutoria

private fun CodeLinesExtension.buildFileFilter(): 
    (File) -> 
        Boolean = 
            if (fileExtensions.isEmpty()) {
                { true }
            } else {
                { fileExtensions.contains(it.extension) } // filter by extension

            }

if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?

someFiles.filter(CodeLinesExtension.buildFileFilter()).forEach{...}

Upvotes: 0

Views: 449

Answers (1)

Joffrey
Joffrey

Reputation: 37650

There are many things at play here.

fun SomeClass.funcName() is the syntax for declaring extension functions. These are used just like regular methods of the class SomeClass, but can be defined outside of the class, and it's especially useful on classes that you don't control.

The return type of the function you mention is (File) -> Boolean. This expression describes a function type. In this specific case, it is the type of all functions that take a File as single argument, and return a Boolean.

This means that your buildFileFilter() function is an extension function that itself returns a function (File) -> Boolean.

As you can see in the function's body, inside the if statement, there are braces to define the blocks of the if-else ({ ... }), but also braces inside those blocks. This is because Kotlin uses braces for lambda expressions (literals for anonymous functions).

{ true } is a lambda expression that represents a function that may or may not take arguments, but returns true every time.

So this code:

if (fileExtensions.isEmpty()) {
    { true }
} else {
    { fileExtensions.contains(it.extension) } // filter by extension
}

returns either:

  • { true } - a function that takes a File as argument and always returns true, or
  • { fileExtensions.contains(it.extension) } - a function that takes a File as argument and returns whether fileExtensions contains the extension of the File that it receives (it is the implicit name for the File argument)

Note: the fact that these functions take a File as argument is inferred by the compiler based on the return type of buildFileFilter().

if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?

filter() itself actually expects a function as argument. The function you pass to filter() is called a predicate, because it takes one element of the list as argument and returns a Boolean that says whether this element should be included in the resulting list.

So if you apply filter to a List<File>, the predicate expected by filter is exactly of type (File) -> Boolean (it says whether we should put this File item in the resulting collection).

Calling buildFileFilter() returns a function as we have seen, and the function is perfectly of the right type to use it in filter. The File argument of the function returned by buildFileFilter() will be given by the filter function itself when it calls your filter function.

Upvotes: 2

Related Questions