What is the benefit in removing parentheses when using Kotlin lambda expressions? - function

Consider this example given here: https://stackoverflow.com/a/53376287/11819720
fun onClick(action: () -> Unit) { ... }
view.onClick({ toast(it.toString())} )
view.onClick() {toast(it.toString()) }
view.onClick { toast(it.toString()) }
and this code:
fun convert(x: Double, converter: (Double) -> Double): Double{
val result = converter(x)
println("$x is converted to $result")
return result
}
fun convertFive (converter: (Int) -> double): Double{
val result = converter(5)
println(" 5 is converted to $result")
return result
}
fun main (args: Array<String>){
convert(20.0) { it * 1.8 + 32 }
convertFive { it * 1.8 + 32 }
}
It seems the effort is to save on writing a few parentheses at the risk of confusing a reader.
Would it not be better if it was kept standard? The usual way to use the functions in the second example would be:
convert(20, {it * 1.8 + 32})
convertFive({it * 1.8 = 32})
but IntelliJ will complain and suggest moving the lambda out of the parenthesis. Why? Is there a practical benefit? Seems like writing 10 + 2 * 5 / 34 instead of 10 + (2 * 5) / 34.

The real benefit of the trailing-braces lambda is that, like all the best language features, it changes the way you think.
The examples you have provided are just as well written with parentheses, and I agree that the IntelliJ suggestion to use the trailing form all the time is unnecessary...
But when I write something like this:
with(someObject) {
doSomething();
doSomethingElse();
}
It looks like I'm using a cool new feature of the language even though I'm really just calling a function.
The result is that people start thinking like they can write functions that add things to the language, because they kinda can, and that leads them to create new ways of doing things for the people who use their code.
The type-safe builder pattern is a great example of this. A lot of the Kotlin language features work together so that, even though it's just calling functions and passing lambdas, it provides a new experience for the developers that use it.
They get a whole new way to instantiate complex objects that is much more natural than the old ways, and nothing needed to be added to the language just for that -- all the little building-block features can be used for many other things.

There is no practical benefit at all, it is just a convention.
In regards to what you said about "keeping it standard". Where exactly did you get the "usual way" from? There are no global programming conventions that I am aware of, only language-specific ones, so this notation is standard by definition.
Conventions are important as they make reading code a lot less effort for anyone also familiar with the syntax. The conventions also reflect the usage of the language. With Kotlin they promote a very functional style with heavy use of lambdas and inline functions so 'lambdas out of parentheses' is necessary to keep the code clean and explicit.
Also as #Tenfour04 said in the comments, your examples really don't reflect the intended usage of the syntax. Generally you have multiple lines and even if you don't, the pattern is supposed to convey something more. Take the measureTimeMillis function for example:
measureTimeMillis {
askQuestion()
comment()
answerQuestion()
}
By having the lambda outside of the parenthesis it is immediately evident what the function does, even to a non-technical reader which is exactly what conventions are there for.

Closer to your example. Let's say you need to convert an array of numbers and square all the positive ones. Compare what is easier to read:
val result = arrayOf(1.0, 2.0, -3.0).map({ number ->
convert(number, {
if (it > 0) it * it else it
})
})
val result = arrayOf(1.0, 2.0, -3.0).map { number ->
convert(number) {
if (it > 0) it * it else it
}
}

Related

What is a good use case for Kotlin function inlining?

I was recently learning about Kotlin inline functions. I thought the below function, twipsToPixels, seemed like a good use-case for that, but IntelliJ gives me a warning saying there's an "expected performance impact". I would've thought the opposite would be true here? This makes me think I'm missing something deeper. Does anyone have any thoughts?
private inline fun twipsToPixels(value: Int) = (value * SCREEN_RESOLUTION / TWIPS_CONVERSION).roundToInt()
private fun screenBoxInPixels(screenBox: ScreenBox): ScreenBox {
val left = twipsToPixels(screenBox.position.left)
val top = twipsToPixels(screenBox.position.top)
val width = twipsToPixels(screenBox.size.width)
val height = twipsToPixels(screenBox.size.height)
return ScreenBox(Position(left, top), Size(width, height))
}
but IntelliJ gives me a warning saying there's an "expected performance impact"
You misread it; it says this impact is insignificant, that is, probably too small to bother. The second part of the message is
Inlining works best for functions with parameters of functional types
mainly because it allows avoiding creating function objects for these parameters in the first place.

Are there disadvantages to return type inference? If yes, what are they?

A lot of statically typed languages, like C++ and C#, have local variable type inference (with the keywords auto and var respectively, I think).
However, I haven't seen many C-derived languages (apart from those mentioned in the comments) implementing compile-time return type inference. I'll describe what I mean by "return type inference" before I ask the question. (I definitely don't mean overloading by return type.)
Consider this code in a hypothetical C#-like language:
private auto SomeMethod(int x)
{
return 3 * x;
}
It's more than obvious (to humans and to the compiler) that the return type is int (and the compilers can verify it).
The same goes for multiple paths:
private auto SomeOtherMethod(int x)
{
if(x == 0) return 1;
else return 3 * x;
}
It's still not ambiguous at all, because there is already an algorithm in said languages to resolve whether two expressions have compatible types:
private auto YetAnotherMethod(int x)
{
var r = (x == 0) ? 1 : 3 * x;
return r;
}
Since the algorithm exists and it is already implemented in some form, it's probably not a technical problem in this regard. But still, I haven't seen it anywhere in statically typed languages, which got me thinking about whether there's something bad about it.
My question:
Does return type inference, as a concept, have any disadvantage or subtle pitfall that I'm not seeing? (Apart from readability - I already understand that.)
Is there some corner case where it would introduce problems or ambiguity to a statically typed language? (By "introduce", I'm referring to issues that local variable type inference doesn't already have.)
yes, there are disadvantages. one you already mentioned: readability. second - the type has to be calculated so it takes time (in turing-complete type systems it may be infinite). but there is also something different - theory of type systems is much more complicated.
let's write a function that takes a list and return its head. what's its type? or function that takes a function, and a parameter applies that and return the result. in many languages you can't declare it. to support this kind of stuff, java introduced generics and it failed miserably. currently it's one of the most hated features of the language because of consistency problems
another thing: returned type may depend on not only the body of the function but also context of the invocation. let's look at haskell (that has best type system i've ever seen) http://learnyouahaskell.com/types-and-typeclasses
there is a function called read that takes a string, parse it and return... whatever you need, an int, an array.
so each time a type system is designed, the designer has to choose at which level she wants to stop. dynamic languages decided not to infer types at all, scala decided to do some local inference but not, for example, for overloaded or recursive functions and c++ decided not to infer the result

Scala style: how far to nest functions?

One of the advantages of Scala is that it gives you great control over scope. You can nest
functions like this:
def fn1 = {
def fn11 = {
...
}
def fn12 = {
...
def fn121 = {
...
}
}
...
def fn13 = {
...
}
}
The problem here is that fn1 may start to look a bit intimidating. Coming from a Java background, we are advised to keep functions small enough to be viewed on a single "page" in the IDE.
What would you think about taking fn12 out of fn1 based on the reasoning: "It's only used in fn1 right now, but it might come in useful somewhere else in the class later on..."
Also, would you have a preference as to where to place the nested functions - before or after the code that calls them?
In general I don't see that much nesting of functions in real code. It runs against the ethos of keeping methods simple and concise. Such nesting is mainly useful for closures where you'll be using some of the parameters from the outer scope (e.g. the inner loop of a recursive function), so it's cleaner than declaring it outside and having to re-pass those arguments explicitly.
You have to place the nested functions before the code that calls them or it's a forward reference and won't compile. (In objects / classes you can place them after, but not in methods.)
There are a few patterns that take advantage of one layer of nesting.
Recursion, where it is used to hide implementation details (and is cleaner than separating into two separate top-level methods):
def callsRecursive(p: Param): Result = {
def recursive(p: Param, o: OtherParam, pr: PartialResult = default): Result = {
...
}
}
Scope-safe don't-repeat-yourself:
def doesGraphics(p: Point) {
def up(p: Point): Point = // ...
def dn(p: Point): Point = // ...
def lf(p: Point): Point = // ...
def rt(p: Point): Point = // ...
/* Lots of turtle-style drawing */
}
And more esoteric tricks like shadowing implicit conversions for a local block.
If you need both of these, I could envision nesting twice. More than that is likely overkill, mostly because you are probably making one method do too much. You should think about how to subdivide the problem with clean interfaces that can then become their own methods, rather than having a messy hodge-podge of closures around all sorts of variables defined within the method. Big methods are like global variables: everything becomes too dependent on the details of implementation and too hard to keep track of. If you're ready to do the appropriate amount of thinking to make something have a decent interface, even if you only need it once, then consider taking it out to the top level. If you aren't going to think that hard, my inclination is to leave it inside to avoid polluting the interface.
In any case, don't be afraid to create a method anywhere you need it. For example, suppose you find yourself deep within some method with two collections each of which have to have the same operation performed on them at specific points in the logic. Don't worry if you're one or two or three methods deep! Just create the method where it's needed, and call it instead of repeating yourself. (Just keep in mind that creating a list and mapping is an alternative if you simply need to process several things at the same place.)
If you have a top level function like the one you describe it is probably doing to much.
TDD helps as well in the decision if this is the case: Is still everything easily testable.
If I come to the conclusion that this is actually the case I refactor to get the inner functions out as dependencies, with their own tests.
In the end result I make very limited use of functions defined in functions defined ... I also put a much stricter limit on method size: about 10-15 lines in java, even less in scala, since it less verbose.
I put internal functions mostly at the top of the outer method, but it hardly matters since its so short anyway.
I consider it as a best practice to always use the lowest visibility. If a nested function is needed for a different function, it could be moved anyway.
That looks pretty scary indeed! If you want to fine-control the scope of private methods, you can declare them as
private[scope] def fn12 = { ... }
where scope is a package. You can read more in The busy Java developer's guide to Scala.
I personally avoid nesting named methods (def), whereas I don't mind nesting anonymous functions (e.g., closures in continuation-passing style programming).
Nested functions are useful (helpers in recursion for example). But if they get too numerous then there is nothing stopping you extracting them into a new type and delegating to that.

Relevance of recursion

So I'm currently trying to grasp the concept of recursion, and I understand most of the problems that I've encountered, but I feel as though its use wouldn't be applicable to too many computing issues. This is just a novice's assumption though, so I'm asking, are there many practical uses for recursion as a programmer? And also, what typical problems can be solved with it? The only ones that I've seen are heap sort and brain teaser-type problems like "The Towers of Hanoi which just seems very specific and lacking broad use.
Thanks
There are a plethora of uses for recursion in programming - a classic example being navigating a tree structure, where you'd call the navigation function with each child element discovered, etc.
Here are some fields which would be almost impossible without recursion:
XML, HTML or any other tree like document structure
Compilation and parsing
Natural Language Processing
Divide and conquer algorithms
Many mathematical concepts, e.g. factorials
Recursion can lead to brilliantly elegant solutions to otherwise complex problems. If you're at all interested in programming as an art, you really should delve deeper.
Oh and if you're not sure, here's a solid definition of recursion:
Recursion (noun): See "Recursion"
It depends on what you're going to be doing I suppose. I probably write less than one recursive function a year as a C#/ASP.NET developer doing corporate web work. When I'm screwing around with my hobby code (mostly stat research) I find a lot more opportunities to apply recursion. Part of this is subject matter, part of it is that I'm much more reliant on 3rd party libraries that the client has already decided on when doing corporate work (where the algorithms needing recursion are implemented).
It's not something you use every day. But many algorithms about searching and sorting data can make use of it. In general, most recursive algorithms can also be written using iteration; oftentimes the recursive version is simpler.
If you check the questions which are listed as "Related" to this question, you will find a "plethora" of stuff about recursion that will help you to understand it better.
Recursion isn't something new, and it is not just a toy concept. Recursive algorithms have been around since before there were computers.
The classic definition of "factorial" is a prime example:
fact(x) =
if x < 0 then fact(x) is undefined
if x = 0 then fact(0) = 1
if x > 0 then fact(x) = x * fact(x-1)
This isn't something that was created by computer geeks who thought that recursion was a cool toy. This is the standard mathematical definition.
Call recursion, as a program construct, is something that should almost never be used except in extremely high-level languages where you expect the compiler to optimize it to a different construct. Use of call recursion, except when you can establish small bounds on the depth, leads to stack overflow, and not the good kind of Stack Overflow that answers your questions for you. :-)
Recursion as an algorithmic concept, on the other hand, is very useful. It's key to working with any recursively-defined data formats (like HTML or XML, or a hierarchical filesystem) as well as for implementing important algorithms in searching, sorting, and (everyone's favorite) graphics rendering, among countless other fields.
There are are several languages that don't support loops (ie. for and while), and as a result when you need repeating behavior, you need to use recursion(I believe that J does not have loops). In many examples, recursion requires much less code. For example, I wrote an isPrime method, it took only two lines of code.
public static boolean isPrime(int n)
{
return n!=1&&isPrime(n,2);
}
public static boolean isPrime(int n,int c)
{
return c==n||n%c!=0&&isPrime(n,c+1);
}
The iterative solution would take much more code:
public static boolean isPrime(int n)
{
if(n==1) return false;
int c=2;
while(c!=n)
{
if(n%c==0) return false;
}
return true;
}
Another good example is when you are working with ListNodes, for example if you would like to check if all the elements in a ListNode are the same, a recursive solution would be much easier.
public static <E> boolean allSame(ListNode<E> list)
{
return list.getNext()==null||list.getValue().equals(list.getNext().getValue())&&allSame(list.getNext());
}
The iterative solution would look something like this:
public static <E> boolean allSame(ListNode<E> list)
{
while(list.getNext()!=null)
{
if(!list.getValue().equals(list)) return false;
list=list.getNext();
}
return true;
}
As you can see, in most cases recursive solutions are shorter than iterative solutions.

Are hard-coded STRINGS ever acceptable?

Similar to Is hard-coding literals ever acceptable?, but I'm specifically thinking of "magic strings" here.
On a large project, we have a table of configuration options like these:
Name Value
---- -----
FOO_ENABLED Y
BAR_ENABLED N
...
(Hundreds of them).
The common practice is to call a generic function to test an option like this:
if (config_options.value('FOO_ENABLED') == 'Y') ...
(Of course, this same option may need to be checked in many places in the system code.)
When adding a new option, I was considering adding a function to hide the "magic string" like this:
if (config_options.foo_enabled()) ...
However, colleagues thought I'd gone overboard and objected to doing this, preferring the hard-coding because:
That's what we normally do
It makes it easier to see what's going on when debugging the code
The trouble is, I can see their point! Realistically, we are never going to rename the options for any reason, so about the only advantage I can think of for my function is that the compiler would catch any typo like fo_enabled(), but not 'FO_ENABLED'.
What do you think? Have I missed any other advantages/disadvantages?
If I use a string once in the code, I don't generally worry about making it a constant somewhere.
If I use a string twice in the code, I'll consider making it a constant.
If I use a string three times in the code, I'll almost certainly make it a constant.
if (config_options.isTrue('FOO_ENABLED')) {...
}
Restrict your hard coded Y check to one place, even if it means writing a wrapper class for your Map.
if (config_options.isFooEnabled()) {...
}
Might seem okay until you have 100 configuration options and 100 methods (so here you can make a judgement about future application growth and needs before deciding on your implementation). Otherwise it is better to have a class of static strings for parameter names.
if (config_options.isTrue(ConfigKeys.FOO_ENABLED)) {...
}
I realise the question is old, but it came up on my margin.
AFAIC, the issue here has not been identified accurately, either in the question, or the answers. Forget about 'harcoding strings" or not, for a moment.
The database has a Reference table, containing config_options. The PK is a string.
There are two types of PKs:
Meaningful Identifiers, that the users (and developers) see and use. These PKs are supposed to be stable, they can be relied upon.
Meaningless Id columns which the users should never see, that the developers have to be aware of, and code around. These cannot be relied upon.
It is ordinary, normal, to write code using the absolute value of a meaningful PK IF CustomerCode = "IBM" ... or IF CountryCode = "AUS" etc.
referencing the absolute value of a meaningless PK is not acceptable (due to auto-increment; gaps being changed; values being replaced wholesale).
.
Your reference table uses meaningful PKs. Referencing those literal strings in code is unavoidable. Hiding the value will make maintenance more difficult; the code is no longer literal; your colleagues are right. Plus there is the additional redundant function that chews cycles. If there is a typo in the literal, you will soon find that out during Dev testing, long before UAT.
hundreds of functions for hundreds of literals is absurd. If you do implement a function, then Normalise your code, and provide a single function that can be used for any of the hundreds of literals. In which case, we are back to a naked literal, and the function can be dispensed with.
the point is, the attempt to hide the literal has no value.
.
It cannot be construed as "hardcoding", that is something quite different. I think that is where your issue is, identifying these constructs as "hardcoded". It is just referencing a Meaningfull PK literally.
Now from the perspective of any code segment only, if you use the same value a few times, you can improve the code by capturing the literal string in a variable, and then using the variable in the rest of the code block. Certainly not a function. But that is an efficiency and good practice issue. Even that does not change the effect IF CountryCode = #cc_aus
I really should use constants and no hard coded literals.
You can say they won't be changed, but you may never know. And it is best to make it a habit. To use symbolic constants.
In my experience, this kind of issue is masking a deeper problem: failure to do actual OOP and to follow the DRY principle.
In a nutshell, capture the decision at startup time by an appropriate definition for each action inside the if statements, and then throw away both the config_options and the run-time tests.
Details below.
The sample usage was:
if (config_options.value('FOO_ENABLED') == 'Y') ...
which raises the obvious question, "What's going on in the ellipsis?", especially given the following statement:
(Of course, this same option may need to be checked in many places in the system code.)
Let's assume that each of these config_option values really does correspond to a single problem domain (or implementation strategy) concept.
Instead of doing this (repeatedly, in various places throughout the code):
Take a string (tag),
Find its corresponding other string (value),
Test that value as a boolean-equivalent,
Based on that test, decide whether to perform some action.
I suggest encapsulating the concept of a "configurable action".
Let's take as an example (obviously just as hypthetical as FOO_ENABLED ... ;-) that your code has to work in either English units or metric units. If METRIC_ENABLED is "true", convert user-entered data from metric to English for internal computation, and convert back prior to displaying results.
Define an interface:
public interface MetricConverter {
double toInches(double length);
double toCentimeters(double length);
double toPounds(double weight);
double toKilograms(double weight);
}
which identifies in one place all the behavior associated with the concept of METRIC_ENABLED.
Then write concrete implementations of all the ways those behaviors are to be carried out:
public class NullConv implements MetricConverter {
double toInches(double length) {return length;}
double toCentimeters(double length) {return length;}
double toPounds(double weight) {return weight;}
double toKilograms(double weight) {return weight;}
}
and
// lame implementation, just for illustration!!!!
public class MetricConv implements MetricConverter {
public static final double LBS_PER_KG = 2.2D;
public static final double CM_PER_IN = 2.54D
double toInches(double length) {return length * CM_PER_IN;}
double toCentimeters(double length) {return length / CM_PER_IN;}
double toPounds(double weight) {return weight * LBS_PER_KG;}
double toKilograms(double weight) {return weight / LBS_PER_KG;}
}
At startup time, instead of loading a bunch of config_options values, initialize a set of configurable actions, as in:
MetricConverter converter = (metricOption()) ? new MetricConv() : new NullConv();
(where the expression metricOption() above is a stand-in for whatever one-time-only check you need to make, including looking at the value of METRIC_ENABLED ;-)
Then, wherever the code would have said:
double length = getLengthFromGui();
if (config_options.value('METRIC_ENABLED') == 'Y') {
length = length / 2.54D;
}
// do some computation to produce result
// ...
if (config_options.value('METRIC_ENABLED') == 'Y') {
result = result * 2.54D;
}
displayResultingLengthOnGui(result);
rewrite it as:
double length = converter.toInches(getLengthFromGui());
// do some computation to produce result
// ...
displayResultingLengthOnGui(converter.toCentimeters(result));
Because all of the implementation details related to that one concept are now packaged cleanly, all future maintenance related to METRIC_ENABLED can be done in one place. In addition, the run-time trade-off is a win; the "overhead" of invoking a method is trivial compared with the overhead of fetching a String value from a Map and performing String#equals.
I believe that the two reasons you have mentioned, Possible misspelling in string, that cannot be detected until run time and the possibility (although slim) of a name change would justify your idea.
On top of that you can get typed functions, now it seems you only store booleans, what if you need to store an int, a string etc. I would rather use get_foo() with a type, than get_string("FOO") or get_int("FOO").
I think there are two different issues here:
In the current project, the convention of using hard-coded strings is already well established, so all the developers working on the project are familiar with it. It might be a sub-optimal convention for all the reasons that have been listed, but everybody familiar with the code can look at it and instinctively knows what the code is supposed to do. Changing the code so that in certain parts, it uses the "new" functionality will make the code slightly harder to read (because people will have to think and remember what the new convention does) and thus a little harder to maintain. But I would guess that changing over the whole project to the new convention would potentially be prohibitively expensive unless you can quickly script the conversion.
On a new project, symbolic constants are the way IMO, for all the reasons listed. Especially because anything that makes the compiler catch errors at compile time that would otherwise be caught by a human at run time is a very useful convention to establish.
Another thing to consider is intent. If you are on a project that requires localization hard coded strings can be ambiguous. Consider the following:
const string HELLO_WORLD = "Hello world!";
print(HELLO_WORLD);
The programmer's intent is clear. Using a constant implies that this string does not need to be localized. Now look at this example:
print("Hello world!");
Here we aren't so sure. Did the programmer really not want this string to be localized or did the programmer forget about localization while he was writing this code?
I too prefer a strongly-typed configuration class if it is used through-out the code. With properly named methods you don't lose any readability. If you need to do conversions from strings to another data type (decimal/float/int), you don't need to repeat the code that does the conversion in multiple places and can cache the result so the conversion only takes place once. You've already got the basis of this in place already so I don't think it would take much to get used to the new way of doing things.