1

Function types Internal and external functions

A function type is a type that represents functions. You can assign a function to a variable of another function type, pass a function as an argument, and return a function type variable in a function call. There are two types of functions: – Internal functions and external functions:

  • Internal functions can only be called within the current contract (more specifically, within the current code block, including internal library functions and inherited functions), because they cannot be executed outside the current contract context. Calling an inner function is done by jumping to its entry tag, just as calling a function inside the current contract.

  • An external function consists of an address and a function signature that can be passed or returned by an external function call.

Function types are expressed as follows

function () {internal|external} [pure|constant|view|payable] [returns ()]

In contrast to parameter types, return types cannot be null — if the function type does not need to return, the entire RETURNS () section needs to be removed.

Function types are internal by default, so you do not need to declare the internal keyword. In contrast, the function itself in the contract is public by default, and is an internal function only if it is treated as a type name.

There are two ways to access functions in the current contract:

  • One is to just use its name, F;

  • The other is to use this.f.

The former applies to internal functions and the latter to external functions.

An exception is thrown if a function type variable is called when it has not been initialized. The same happens if a function is called after it has been deleted.

If external function types are used outside of the Solidity context, they are treated as function types. This type encodes the function address, followed by its function identifier, as a Bytes24 type.

Note that the public function of the current contract can be used as an internal or external function. If you want to use a function as an internal function, use f. If you want to use it as an external function, use this.f.

In addition, public (or external) functions also have a special member variable called selector, which returns an ABI function selector:

Pragma solidity ^ 0.4.16; contract Selector {function f() public view returns (bytes4) {    returnthis.f.selector; }}Copy the code

If an example of an internal function type is used:

Pragma solidity ^ 0.4.16; Library ArrayUtils {// Inner functions can be used in inner library functions, // because they become part of the same code contextfunction map(uint[] memory self, function (uint) pure returns (uint) f)

    internal

    pure

    returns (uint[] memory r)

  {

    r = new uint[](self.length);

    for(uint i = 0; i < self.length; i++) { r[i] = f(self[i]); }}function reduce(

    uint[] memory self,

    function (uint, uint) pure returns (uint) f 

 )

    internal

    pure

    returns (uint r) 

 {

    r = self[0]; 

   for(uint i = 1; i < self.length; i++) { r = f(r, self[i]); }}function range(uint length) internal pure returns (uint[] memory r) {

    r = new uint[](length);

    for (uint i = 0; i < r.length; i++) {

      r[i] = i; 

   }

  }

}

contract Pyramid {

  using ArrayUtils for *;

  function pyramid(uint l) public pure returns (uint) {

    return ArrayUtils.range(l).map(square).reduce(sum);

  }

  function square(uint x) internal pure returns (uint) {

    return x * x; 

 }

  function sum(uint x, uint y) internal pure returns (uint) {

    returnx + y; }}Copy the code

Another example of using an external function type:

Pragma solidity ^ 0.4.11; contract Oracle { struct Request { bytes data;function(bytes memory) external callback;

  }

  Request[] requests;

  event NewRequest(uint);

  function query(bytes data, function(bytes memory) external callback) public {

    requests.push(Request(data, callback));

    NewRequest(requests.length - 1);

  }

  functionReply (uint requestID, bytes response) public {// Verify that reply came from trusted source requests[requestID].callback(response); } } contract OracleUser { Oracle constant oracle = Oracle(0x1234567); // Known contractsfunction buySomething() { 

   oracle.query("USD", this.oracleResponse);

  }

  functionoracleResponse(bytes response) public { require(msg.sender == address(oracle)); // Use data}}Copy the code

Annotation Lambda expressions or inline functions are planned, but not currently supported.

2

Function visibility specifiers public, private, external, internal

Public: visible internally and externally (see creating getters for store/state variables)

Private: visible only in the current contract

External: Only visible externally (only modifiable functions) — that is, only available for message calls (even if called within the contract, only through this.func)

Internal: only visible internally (i.e. visible in the current Solidity source file, not just in the current contract)

Function visibility specifier format:

function myFunction() <visibility specifier> returns (bool) {

    return true;
}
Copy the code

3

Function modifier

When modifying a pure function: State is not allowed to be modified or accessed — but it is not currently mandatory. View decorates a function: State modification is not allowed — but is not currently mandatory. When decorating the function ‘payable’ : allows to receive Ether from the call. Constant: Does not allow assignment (except for initialization) and does not occupy the storage slot. Constant is equivalent to view. When anonymous decorates events: do not store event signatures as topics. Indexed Modifies events: Stores parameters as topics.

Author: HiBlock blockchain community technology evangelist Hui Ge

Originally published in Jane’s book

The following is our community introduction, welcome all kinds of cooperation, exchange, learning 🙂