Showing posts with label function. Show all posts
Showing posts with label function. Show all posts

Thursday, 22 July 2021

Python crash course part 7: more on defining functions

 In the part 2 we've shown most basic ways of definining functions in Python.

Let's elaborate on that a bit more, using some examples.

First, a simple function just doing something, for instance printing text to screen (something tradinionally called a procedure rather than a function), is defined like this:

def just_do_it():
    print("Just do it")

... and called like this:

    just_do_it()

So execution of the program below:

# !/usr/bin/python3

def just_do_it():
    print("Just do it")

def main():

    just_do_it()

...results in the following output:

Just do it

What if we want to return value from function, so we can use it in the moment it's called? Well, let's simply use return keyword:

def please_return_something():
    return 3.14

The type doesn't have to be defined.

As an example we'll assign the value returned by the function above to pi variable, and then print it to the screen.

def main():

    pi = please_return_something()
    print(pi)

Result:

3.14

What if we want our function to take some parameters?

This is when the things became interesting, as Python allows us to defined both named and unnamed (positional) paramaters. By default, both. So we can define our function as:

def divide(nominator, denominator):
    return nominator/denominator

...and call it in two ways:

    print(divide(6,2))

Or:

    print(divide(nominator=6,denominator=2))

...both resulting in:

3.0

Please note that if we call our function with named parameters, their order doesn't matter. So call:

    print(divide(denominator=2,nominator=6))

...also results in:

3.0

The last thing for today will be default parameter value, which is defined using the = sign.

An example looks like this...

def power(a, b = 2):
    return a**b

( ** is power operator, a**b means a to the power of b).

The above function has two parameters, but the second one (exponent) has default value. This means that if we skip the second param, our function becomes simply square function.

So the "full-param" call looks like this:

    print(power(2,3))

...and results in:

8

And the call using default parameter value can look like this:

print(power(3))

..resulting in:

9

There are more details about defining and calling functions in Python, which we can elaborate further on in future, but I think for now we've covered the most important features.


Saturday, 17 July 2021

Android Java to Kotlin migration by example part 10: higher-order functions

 A higher-order function is a function, which returns another function, or takes another function as parameter.

Today we'll begin with Kotlin code. Kotlin, being much more functional-oriented than Java (although Java is getting more functional since version 8), makes use of higher-order function much more elegant and readable.

Let's consider a mathematical function A, mapping some value to other value, for instance y=x*x (square). We can construct another function B (or functionAMultipliedBy2) which would map any x to functionA(x)*2.

In functional programming we can use a higher-order function in that case: create a function functionB, taking functionA as param. Such function can then be stored like a variable, and called. I guess it's more understandable in the code form. So let us take a look at a program defining our functionMultipliedBy2, getting a Float->Float function (getting float as param and returning a float) as parameter and returning Float->Float function (the function passed as a parameter multiplied by 2). 

Kotlin:

package com.mypackage

fun functionMultipliedBy2(
functionArg: (arg: Float) -> Float): (Float) -> Float
{
val funcToReturn = {a: Float ->functionArg(a)*2}
return funcToReturn
}

fun squareA(arg: Float): Float{
return arg*arg
}

fun main() {
println(squareA(2.0f)) // "4.0"

// we can pass squareA as parameter to functionMultiplied by 2
val squareDoubled = functionMultipliedBy2(::squareA)
// :: because it's class member

// squareDoubled is now a FUNCTION, taking Float
// as param and returning 2* square(param)

// we can simply call it:
println(squareDoubled(2.0f)) // "8.0"
}

The same code in Java would look like this:

import java.util.function.Function;

import static java.lang.System.out;

public class MainClass {

static Function<Float, Float> functionMultipliedBy2(
Function<Float, Float> functionArg)
{
Function<Float, Float> funcToReturn =
input -> functionArg.apply(input) * 2;
return funcToReturn;
}

static float squareA(float arg){
return arg*arg;
}

public static void main(String[] args){
out.println(squareA(2.0f)); // "4.0"

Function<Float, Float> squareDoubled =
functionMultipliedBy2(MainClass::squareA);
// -> ugly

// squareDoubled is an object of type Function
// getting Float as param and returning 2*square (param)

// call looks like this:
out.println(squareDoubled.apply(2.0f)); // "8.0"

}
}

The code execution result is the same in both cases and it's:

4.0
8.0

Please note how the Java code makes use of class Function objects to deal with functions. In Kotlin, we define returned value (or acccepted as argument) as function simply by (Float) -> Float notation.

What's more, in Kotlin we can simply call passed function. A Java Function object has to be used by calling .apply method to it (because it's an object, not a "real" function). I think Kotlin, as more functional-oriented languages, deals with this in much more "natural" way.

The higher-order function can also be used with lambda expressions. In Java:

import java.util.function.Function;

import static java.lang.System.out;

public class MainClass {

static Function<Float, Float> functionMultipliedBy2(
Function<Float, Float> functionArg)
{
Function<Float, Float> funcToReturn =
input -> functionArg.apply(input) * 2;
return funcToReturn;
}

public static void main(String[] args){
Function<Float, Float> squareRoot =
input -> (float)Math.sqrt((double)input);
Function<Float, Float> squareRootDoubled =
functionMultipliedBy2(squareRoot);
out.println(squareRootDoubled.apply(4.0f));
}
}

... as well as in Kotlin:

package com.mypackage

import kotlin.math.sqrt

fun functionMultipliedBy2(
functionArg: (arg: Float) -> Float): (Float) -> Float
{
val funcToReturn = {a: Float ->functionArg(a)*2}
return funcToReturn
}

fun main() {
val squareRoot = {arg:Float -> sqrt(arg.toDouble()).toFloat()}
val squareRootDoubled = functionMultipliedBy2(squareRoot)
println(squareRootDoubled(4.0f))
}

Again, Kotlin is much more concise - and allows us to simply call the function, without using any special .apply() methods.

Saturday, 19 June 2021

Python crash course (part 2) - functions and lambdas

The script in the previous part included very limited and basic use of functions. They were not returning anything, and they were quite simple. I also wasn't using any lambdas (which in Python mean simple, anonymous functions defined in a specific way). So let's take a look at a little illustrative program, showing how to define and call a function in Python, how to pass a parameter to it and return a value, how to pass a function as a parameter and how to define and use a lambda (in our case, passed as a parameter). 

Once again, some programming experience may be needed to understand what's going on - the code below is just some simple examples of basic language constructions. This time: functions and lambdas. Some details in the comments. In the further part (below), one more notion regarging lambdas. For now, it's much less practical than the code in the first part, but I wanted to simply show (and note for myself) some basic syntax and use cases. Still not object-oriented.

Listing 1:
# a function doing something (printing text), 
# not returning anything ("procedure")
def simply_print_some_text():
    print("To be or not to be")

# a function taking a numeric parameter and returing its squared value
def get_value_squared(x):
    return x*x

# a function taking a function as parameter and printing
# its first 10 non-negative values
def show_first_10_values(some_function):
    for a in range(0,10): #from 0 to 9
        print(some_function(a),end=', ')

def main():
    # call the first function:
    simply_print_some_text()

    # print the value returned by the squaring function with param "3":
    print(get_value_squared(3))

    # call the values-printing method with squaring function as param
    show_first_10_values(get_value_squared)
    print() # print a new line character

    # call the third function with a lambda (also returning squared value)
    show_first_10_values(lambda x: x*x)
    print()


if __name__ == "__main__":
    main()

The result of this running this code looks as follows:

Listing 2:
To be or not to be
9
0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
0, 1, 4, 9, 16, 25, 36, 49, 64, 81,

Note on lambdas in Python

The code in Listing 1 shows use of lambda in Python. The last call in the main: 

show_first_10_values(lambda arg: arg*arg))

is the call to a function, which takes another function as a param and calls it 10 times, with arguments from 1 to 10. I think that, although not very practical itself, it shows more-or-less how to use lambdas.

Meanwhile, there is a common example of using such lambdas in Python, which, although technically correct, doesn't make much sense:

Listing 3 (wrong practice?):
doubled = lambda x: x * 2
print(doubled(3))

First of all - this code works. It prints a number 6 in that case. But the problem is:

What's the point of using lambda here, if it's basically a function? The same code could look like this:

Listing 4:
def doubled(x):
   return x * 2
print(doubled(x))

... or even like this (please note it's the same code, just one code indentation is ommited):

Listing 5:
def doubled(x): return x * 2
print doubled(x)

... and well, that's what functions are for, right?

Such practice, although quite common in various articles on lambdas in Python, seems to be criticized in the official Python style guide.

In the first example (Listing 1, show_first_10_values(lambda arg: arg*arg)), there is at least some reason of using a lambda: we need to pass some function as a parameter, and we want to define it ad hoc . Please note this:

show_first_10_values(lambda x: x*x)

is simply much shorter (and elegant) than this:

def get_value_squared(x):
    return x*x
(...)
show_first_10_values(get_value_squared)


The next part: collections and data structures.

Python crash course part 10: inheritance and polymorphism

In the last part we've shown how to create and use a class in Python. Today we're going to talk about inheritance: wchich means cre...