In lambda programming, a definition of a function not determined by any object is called the lambda expression or the anonymous function. Based on the mathematical basics of lambda calculus, lambda functional programming introduces several fundamental principles:
In this C# and Python lambda tutorial, we will clarify each of these concepts separately.
In functional languages, the function is the basic building block of your code. As in object-oriented languages, we can create and use objects, so in functional languages, we can create and use functions in the same way.
Simply put, we can create a function, assign it to a variable, or pass it to another function as an argument. Terms Java, C# functional programming determine functional programming in Java and C#, respectively.
A higher-order function is a function that can accept some other function as its argument. This is a very powerful concept that allows simple and natural implementation of control inversion, which is one of the most important principles in software development.
Small anonymous functions can be created with the keyword lambda. This expression gives the sum of its two parameters: lambda a,b:a+b. Lambda functions can be used wherever required a function object type. They are syntactically restricted to a single expression. Semantically, they are only syntactic sugar for normal function definitions. As nested functions, lambda functions can refer to variables from the field that contains:
>>> def incrementator(N):
... return lambda x: x + n
...
>>> F = incrementator (42)
>>> F(0)
42
>>> F(one)
43
Next, we provide conventions about the content and formatting of documentation strings.
The initial remark should at all times be a diminutive, brief abstract of the usage of the object. To be brief, it should not openly mention the designation or type of the object, because these are obtainable by other means (except if the name is a verb that describes the operation of the function). This line should begin with a capital letter and end with a point.
In case there are multiple sentences in the documentation string, the second line should be
empty, visually separating the abstract from the rest of the description. The subsequent sentences should be additional paragraphs unfolding the conventions to call the object, its side effects, etc.
Python parser does not remove the bleeding string literals multi-line, then the tools that process documentation have to remove it if they wish. This is done using the following convention. The first line which is the next blank to the first line of the chain determines the amount of indentation for the entire documentation string. (We cannot use the first line since it is generally adjacent to the opening quote chain and bleeding is not noticeable in the text string). Whitespace “equivalent” to this bleeding is then stripped from the start of each line in the chain. There should be no lines with less bleeding, but if there are all the blanks should be stripped.
This is an example of a multi-line docstring:
>>> def my_function():
... "" "It does more than document the function.
...
... Actually no. Does nothing.
... "" "
... pass
...
>>> print(my_function.__Doc__)
Does more than document the function.
Actually no. Does nothing.
Function annotations are arbitrary and completely optional information in user-defined functions. Neither Java nor Python standard library itself or use annotations functions in any way; This section shows the syntax only. Third-party projects are free to use annotations functions for documentation, control types, and other cases.
The annotations are stored in the attribute__ annotations__ function as a dictionary and have no effect on any other part of the function. Annotations parameters are defined after a colon after the parameter name followed by an expression that evaluates the value of the annotation. Return annotations are defined by the literal->Followed by an expression, including the list of parameters and the two points that mark the end of the statement def. The following example has a positional argument, one appointed, and the return value meaningless noted:
>>> def F(Ham: 42, eggs: int = 'meat') -> "nothing nothing":
... print("Annotations", F._annotations__)
... print("Arguments", ham, eggs)
...
>>> F('wonderful')
Annotations { 'eggs: <class' int'>, 'return' 'none none', 'ham': 42}
Arguments: wonderful meat
The list data type has some more methods. Here are all methods of list objects:
list.append(X)
Adds an item to the end of the list. Equals a [len (a)]=[X].
list.extend(L)
Extends the list adding all the items in the given list. Equals a [len (a)]=L.
list.insert(I, x)
Inserts an item in a given position. The first argument is the index of the item before which it is inserted, therefore a.insert (0,x)inserted at the beginning of the list, a.insert (len (a),x) equals a.append (x).
list.remove(X)
Removes the first item from the list whose value isx. It is an error if there is no such item.
list.pop([I])
Removes the item at the given position in the list, and returns it. If an index is not specified,a.pop ()removes and returns the last item in the list. (The brackets enclosing in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Reference Library Python.)
list.clear()
Remove all items from the list. Equivalent to of theto[:].
list.index(X)
Returns the index in the list of the first item whose value isx. It is an error if there is no such item.
list.count(X)
Returns the number of times x It listed.
list.sort()
Sorts items in situ list.
list.reverse()
Inverts the elements listed in situ.
list.copy()
Returns a shallow copy of the list. Equivalent to to[:].
Maybe one will observe that procedures like insert or remove which just alter the list of values returns None value. This represents a design strategy for each changeable data construction in Python.
The list procedures make it easier to use a list as a stack, where the final item appended is the first item removed (LIFO – Last In First Out). To add an element to the top of the stack, apply Append () method. To remove an element from the stack top, use pop () method without an exact argument.
List conceptions provide a precise approach to generate lists. Mutual practices are to create new lists where every item is the result of specific operations utilized on every member of another sequence or to generate a subarray of such items that satisfy a specific condition.
For example, let’s assume we want to create a list of squares, such as:
>>> list1 = []
>>> for n in range(5):
... list1.append (n**2)
...
>>> list1
[0, 1, 4, 9, 16]
We can get the same result:
list1 = [n ** 2 for n in range(5)]
This is equivalent also list1=list (map (lambda x:x ** 2 range (10))) but it is more concise and readable.
A list appreciation comprises of rectangle brackets encompassing an articulation pursued by the for the announcement and after that at least one proclamations for or if. The outcome will be another rundown out to assess the articulation with regards to for or if that pursues. For instance, this rundown perception consolidates the components of two records in the event that they are not equivalent:
>>> [(n, m) for n in range(3) for m in [2,1,5] if x ! = Y]
[(1, 2), (1, 5), (2, 1), (2, 5), (3, 2), (3, 1), (3, 5)]
and it is the same as:
>>> list2 = []
>>> for n in range(3):
... for m in [2,1,5]:
... if n ! = m:
... list2.append ((n, m))
...
>>> list2
[(1, 2), (1, 5), (2, 1), (2, 5), (3, 2), (3, 1), (3, 5)]
Notice how the order of the for or if It is the same in both pieces of code.
If the expression is a tuple (such as(X, Y)in the above example) must be in parentheses.
All examples of adding a method to a delegate you’ve seen so far use the method name. For example, if you return to the previously described scenario of an automated factory, you added the StopFolding method object to the stopMachinery delegate as follows:
this.stopM + = folder.StopF;
This approach is very useful if there is a suitable method that matches the signature of the delegates, but what if this is not the case? Assume that the StopFolding method has the following signature:
void StopF (int shutDownTime); // turns off in a certain number of seconds
This signature is now different from the FinishW and PaintOff method signature, and therefore you cannot use the same delegate to handle all three methods. What do you need to do now?
One way to solve this problem is to create another method that calls the StopF method but does not receive the parameters independently as here:
void FinishF ()
{
folder.StopF (0); // off immediately
}
You can then add the FinishF
method to the stopM
delegate to the StopF method using the same syntax as before:
this.stopM + = folder.FinishF;
When a stopM delegate is called, he calls the FinishF method that calls the StopF method by passing the parameter 0.
Note The FinishF method is a classic example of an adapter: a method that converts (or adjusts) a method to give it a different signature. This form is more common than usual and is one of the sets of forms documented.
In most cases, adapter methods such as these are small, and it is easy to get them into the sea method, especially within the large class. Additionally, except that the adapter method is used to adjust the StopF method for use by delegates, it is unlikely that the adapter method will be invoked elsewhere. The C # language provides lambda expressions for situations like this. In Chapter 18, you first encounter lambda expressions, and you’ve seen more examples earlier in this chapter. In the factory scenario, you can use the following lambda expression:
this.stopM + = (() => folder.StopF (0));
When you call the StopM delegate, he will run a code that defined a lambda term, which will call StopF method with the appropriate parameter.
Lambda expressions may have several different forms in Java and C#. C# lambda expressions originate from a mathematical notation called a lambda account, which provides a function-description notation (you can consider the function as a return method). Although the C# language has extended the syntax and semantics of the lambda calculus in its implementation of the lambda expression, many of the original principles still apply. Here are some examples that show different forms of lambda expressions that are available in C #:
x => x * x // simple expression that returns the square of its parameter
// The parameter type x is derived from the context.
x => {return x * x; } // semantically the same as the previous one
// expression, but uses the C # block statement as
// body instead of a simple expression
(int x) => x / 2 // a simple expression that returns a value
// parameter divided by 2
// the parameter type x is explicitly assigned.
() => folder.StopF (0) // call method
// Term does not receive parameters.
// The term will or will not
// restore value.
(x, y) => {x ++; return x / y; } // Multiple parameters; compiler
// perform parameter types.
// Parameter x is passed to value, so
// that the effect of the ++ operation
// local to expression.
(ref int x, int y) => {x ++; return x / y; } // Multiple parameters
// with explicit types
// Parameter x is forwarded using
// reference is an effect
// ++ operations are permanent.
To summarize, here are some of the features of lambda expressions that you should be careful of:
If the lambda expression receives parameters, specify them in brackets to the left of the => operator. You can omit the parameter types and the Java and C # compiler will execute their types from the lambda expression. You can pass the parameters over the reference (using the ref keyword) if you want to enable the lambda expression to change their values other than locally, but this is not recommended.
Lambda expressions can return values, but the return type must match the type of delegates to which lambda expressions are added.
The lambda expression body can contain a simple expression or block C # code that makes multiple statements, method calls, the definition of variables, and other code elements.
Variables defined in the lambda expression of the method go out of the validity area when the method finishes work.
A lambda term can access and change all non-lambda-variable variables that are in the field of validity when the lambda term is defined. Be careful when it comes to this feature!
Lambda expressions and anonymous methods are a new addition to C # in version 3.0.