Functions: Calling A Function

A function is called using the function-call operator, (), which optionally contains a comma-separated list of arguments. For example:

$dx = 3.5;$dy = 2.7;
$hypot = \sqrt($dx*$dx +$dy*$dy);  Here, we use Pythagoras' Theorem to find the hypotenuse of a right-triangle. The call to the library function sqrt contains one argument, of type float, and it returns a value of the same type. Hack supports recursion; that is, a function can call itself directly or indirectly. For example: function factorial(int$i): int {
return ($i > 1) ?$i * factorial($i - 1) :$i;
}

<<__EntryPoint>>
function main(): void {
for ($i = 0;$i <= 10; ++$i) { \printf("%2d! = %d\n",$i, factorial($i)); } }  Output 0! = 0 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800  By default, arguments are passed by value; however, if a parameter contains the inout modifier, the corresponding argument must also contain that modifier. See the swap function in defining a function for an example. Function calls in the presence of FormatString The typechecker is "aware" of certain functions whose arguments are inter-related, so it can check they are called correctly. One such function is \printf (and its sibling, \sprint). Consider the following: \printf("Hello, World!\n"); \printf("Value is %d\n", 6 + 4); \printf("Decimal: %d, HEX: %X, Unsigned: %u\nBinary: %b\n", -1, -1, -1, -1);  from which this output is produced: Hello, World! Value is 10 Decimal: -1, HEX: FFFFFFFFFFFFFFFF, Unsigned: 18446744073709551615 Binary: 1111111111111111111111111111111111111111111111111111111111111111  The contents of the first argument string are used to determined whether more arguments follow, and, if so, how they are to be handled. The expectation of further arguments and their handling are determined by the presence of conversion specifiers, which begin with %. In the first case, there are none, so the text Hello, World!\n is simply written out to standard output. In the second case, %d is seen, so another argument is expected, and it is output as a signed decimal integer. In the third case, %d, %X, %u, and %b are seen, so another four arguments are expected, with their values being output as a signed decimal integer, uppercase hexadecimal integer, unsigned decimal integer, and binary integer, respectively. The typechecker also makes sure that the number of arguments actually provided matches the number expected. For example: \printf("Value is %d\n"); // Error: too few arguments \printf("Values are %d and %d\n", 10, 20, 30); // Error: too many arguments  It is important to note that the first argument must be a string literal: $format = "Value is %d\n";
\printf($format, 6 + 4); // Error: format string must be a string literal  In the examples above, the type of the argument passed exactly matches that expected; however, what if that was not the case? Consider the following: \printf("Value is %d\n", 6.0 + 4.0); // Value is 10 \printf("Value is %d\n", 6.901 + 4.123); // Value is 11  The expression 6.0 + 4.0 has type float, yet %d says to format the result as a signed integer. Yes, but the runtime can then convert float to int first. And as there are no fractional parts, no precision is lost, and 10 is output. In the case having fractional parts, the two values are added resulting in the float 11.024, which is then truncated to the int 11. Here are some more examples: \printf("Value is %d\n", false); // Value is 0 \printf("Value is %d\n", vec[]); // Value is 0 \printf("Value is %f\n", true); // Value is 1.000000 \printf("Value is %f\n", vec[10,20]); // Value is 1.000000  According to Hack's conversion rules, when converted to int (or float), false is 0 (or 0.0) and true is 1 (or 1.0). And an empty vec is converted to 0 (or 0.0), while a non-empty one is converted to 1 (or 1.0). But what if the argument cannot be converted to the expected form? That is flagged as an error: \printf("Value is %d\n", new C()); // Error: class C could not be converted to int  In the earlier example in which a string variable rather than a literal was given as the first argument, the actual error message produced by the typechecker is something like the following: This argument must be a literal string The function expects an object of type HH\FormatString, which is incompatible with string  Function \printf is declared, as follows: function printf(\HH\FormatString<PlainSprintf>$fmt, ...\$fmt_args): int;


FormatString is a generic library type, and while we don't need to understand it to use \printf, clearly, the string literals—which have type string---we've been passing as the first argument are permitted when this type is expected, but a variable of type string is rejected.

Examples of other functions that take an argument of this type are invariant and queryf.