The paragraph specifically mentions that only function types are by default internal, and contract functions are by default public, even though I agree the wording is a little bit confusing. It says nowhere that they are at the same time both public and internal.
I think that there is some confusion to what a function type is. The same way you specify the type for a 256 int variable with the keyword uint256, you can also specify the type of a variable that will hold a function. The only difference is that this type declaration is a little more complex since functions are more complex and it looks like this:
function (param types) {internal|external} [pure|constant|view|payable] [returns (return types)] varName;
You can then assign to the variable varName a function that has the same type that you defined. This is only possible inside another function.
As a very simple example:
contract Example{
function(uint256) returns (uint256) varName;
function simpleFunction(uint256 parameter) returns (uint256){
return parameter;
}
function test(){
varName = simpleFunction;
}
}
Where varName is the variable of function type, while simpleFunction and test are normal contract functions
Just so you have a simple definition for all those access classifiers:
- public - all can access
- external - Cannot be accessed internally, only externally
- internal - only this contract and contracts deriving from it can access
- private - can be accessed only from this contract
As you can notice private is a subset of internal and external is a subset of public.
Functions can be invoked in two different ways:
- Via a transaction, which is broadcast to the network and changes blockchain state.
- Via a call, which is performed locally on a single Ethereum network and does not change any blockchain state.
It's actually up to the client to decide which to do, but if a function is marked view
, the default behavior of most clients (e.g. Remix, web3.js, etc.) is to use a call. That basically means running the transaction but not recording any state changes.
So in the above case, if you call B()
, it will in effect give you back the value counter + 1
. (During execution, it will increment the counter, but that change will simply be discarded.)
That said, you could invoke B()
via a transaction, in which case the counter
would truly be incremented in a persistent way. In essence, view
is a hint to clients that they should use a call rather than a transaction.
Best Answer
This is discussed here: https://github.com/ethereum/solidity/issues/992 and has been partially implemented in the change you noted.
As I understand it, the point is that
constant
is misleading (constant functions don't necessarily return constant results), and not particularly nuanced. The changes when complete will introduce two replacement keywords:view
andpure
which are intended to be more meaningful and useful.From the GitHub issue,