What is the difference between function declarations `f x y` and `f (x, y)` in Standard ML? - ml

In Standard ML, what is the difference between the following declaration (I omitted the definition starting with =):
fun f x y;
and
fun f (x, y);
As far as I understand, the first takes two arguments, while the second takes a tuple. If it so, still, what are the (practical) implications of using one versus another? Can one argument on which is the best style? Assuming, one doesn't actually need to use the tuple as whole, i.e. only x and y, separately, are of relevance.

Yes, as you said, the first takes "two arguments", while the second takes one argument that is a tuple. However, to understand what's really going on, you have to understand currying. In ML, every "function" takes exactly one argument (no more, no less).
In the second case, this is easy to understand, it takes one argument, which is a tuple, and it does something with the things in the tuple, and returns a result. In the first case, you are defining a function that takes one argument, and then returns a function that takes another argument, and then returns the result.
Say, for example, this is a function that takes two ints and returns an int. Looking at the types of these two functions is instructive: the second function's type is (int * int) -> int, i.e. a function from a tuple to int. The first function's type is int -> int -> int, which, since -> is right-associative, can be parsed as int -> (int -> int). So you can see, it takes an int and returns a function. The syntax fun f x y = ... is syntactic sugar for the more verbose val f = fn x => fn y => .... When you apply this function, e.g. f 3 4, function application is left-associative, so that is actually (f 3) 4, so you can see how that works: f takes an int, returns a function that is then applied to another int. This is the gist of currying. ML's syntax simply makes it transparent to do.
The curried version (the first version) allows you to do partial application. This means, although your function conceptually takes two arguments, you don't have to give it that number of arguments. So the f 3 4 we have above (which is (f 3) 4), what if we just took the f 3, and instead of just applying that to 4, just keep it and store it in a variable or something? By "giving the function less arguments than it wants", we automatically get a function that takes the remaining arguments. For example, we can do map (f 3) someList, and it will compute a list of f 3 x for each x in the list, without us having to write some complicated syntax.
In Standard ML, library functions are mostly in the uncurried form; whereas in OCaml and Haskell, they are mostly in the curried form. (See this question.) However, SML library functions that are higher-order functions (like map and fold) tend to take their function arguments in a separate (curried) argument.

Related

What is the purpose of requiring a data type specification of the returned value in a function definition or prototype? Type casting?

Consider the following snippet of code:
#include<stdio.h>
int demo_function(float a);
int main(void)
{
int b;
float fraction_number = 3.15f;
b = demo_function(fraction_number);
printf("The number returned is %d", b);
return 0;
}
int demo_function(float a)
{
float c;
c = a;
printf("The number passed is %.2f \n", c);
return c;
}
The output is:
The number passed is 3.15
The number returned is 3
From this little test code, it seems like actual purpose of writing int as the data type of demo_function's returned value is to type cast.
Firstly, is that the correct interpretation of what is going on?
Secondly, why does the compiler actually need this information? (Or perhaps a better question is, "How does the compiler use this information?"). Specifically, if the compiler sees that variable b is declared as an int, why does it need to explicitly know that the returned value is of type int?
If we end up storing the returned value of variable c into b, what issues would arise if the compiler did NOT require the explicit mention that the returned value is of type int? Would there be information loss as the float c variable tries to get squished into the smaller memory allocated int b variable?
Thanks!
As a practical matter, the compiler needs to know what type a function returns because it needs to know how to interpret the bits a function returns and it needs to know where those bits are.
Suppose that when a function returns, the register used for the return value contains 0x80. If the function is supposed to return an 8-bit unsigned char, then the return value is 128. If the function is supposed to return an 8-bit two’s complement signed char, then the return value is −128. Knowing the type is necessary to know the interpretation of the bits.
In many systems, a function that returns an integer is supposed to put the bits in a certain general register of the processor, but a function that returns a floating-point value is supposed to put the bits in a certain floating-point register. In this case, the caller needs to know the return type of the function in order to know where the bits of the return value are.
At a more abstract level, the compiler needs to know the return type of the function so that it can interpret the expression the function call appears in. Consider that, in C, the expression 5 / 4 performs integer division with truncation and produces 1, but the expression 5. / 4 performs floating-point division and produces 1.25. So, in the expression f(x) / 4, the compiler needs to know what type f returns so that it knows whether to perform integer division of floating-point division.
For another example, suppose f returns a pointer, and the program uses y = *f(x). To execute this code, the compiler has to take the value returned by f and use it as an address to fetch something from memory. But what does it fetch? Does the address point to a one-byte char, an eight-byte double, or a 100-byte structure? The compiler needs to know the type of the pointer returned by f so that it knows what type of object it points to.
From this little test code, it seems like actual purpose of writing int as the data type of demo_function's returned value is to type cast.
The primary purpose is as described above. The fact that the value in a return statement is converted to the return type of the function is a secondary effect; it is merely a convenience of the language, not a necessary effect. (The implicit conversion is not necessary because we could effect the conversion by specifying it explicitly.)
Also note that a cast is an explicit operator. It is not the operation. For example, + and * are operators; they are things that appear in source code that say we want to do certain operations. The actual operations are addition and multiplication. Similarly, a cast is a type name in parentheses; it is some text that appears in source code that specifies we want to perform a conversion.

Why is the output of the folowing code 543 instead of 345? [duplicate]

In C and C++, is there a fixed order for evaluation of parameter to the function? I mean, what do the standards say? Is it left-to-right or right-to-left?
I am getting confusing information from the books.
Is it necessary that function call should be implemented using stack only? What do the C and C++ standards say about this?
C and C++ are two completely different languages; don't assume the same rules always apply to both. In the case of parameter evaluation order, however:
C99:
6.5.2.2 Function calls
...
10 The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.
[Edit]
C11 (draft):
6.5.2.2 Function calls
...
10 There is a sequence point after the evaluations of the function designator and the actual
arguments but before the actual call. Every evaluation in the calling function (including
other function calls) that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately sequenced with respect to
the execution of the called function.94)
...
94) In other words, function executions do not ‘‘interleave’’ with each other.
C++:
5.2.2 Function call
...
8 The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect
before the function is entered. The order of evaluation of the postfix expression and the argument expression list is
unspecified.
Neither standard mandates the use of the hardware stack for passing function parameters; that's an implementation detail. The C++ standard uses the term "unwinding the stack" to describe calling destructors for automatically created objects on the path from a try block to a throw-expression, but that's it. Most popular architectures do pass parameters via a hardware stack, but it's not universal.
[Edit]
I am getting confusing information from the books.
This is not in the least surprising, since easily 90% of books written about C are simply crap.
While the language standard isn't a great resource for learning either C or C++, it's good to have handy for questions like this. The official™ standards documents cost real money, but there are drafts that are freely available online, and should be good enough for most purposes.
The latest C99 draft (with updates since original publication) is available here. The latest pre-publication C11 draft (which was officially ratified last year) is available here. And a publicly availble draft of the C++ language is available here, although it has an explicit disclaimer that some of the information is incomplete or incorrect.
Keeping it safe: the standard leaves it up to the compiler to determine the order in which arguments are evaluated. So you shouldn't rely on a specific order being kept.
In C/C++ is there a fixed order for evaluation of parameter to the function. I mean what does standards says is it left-to-right or right-to-left . I am getting confusing information from the books.
No, the order of evaluation of function parameters (and of two sub-expressions in any expression) is unspecified behaviour in C and C++. In plain English that means that the left-most parameter could be evaluated first, or it could be the right-most one, and you cannot know which order that applies for a particular compiler.
Example:
static int x = 0;
int* func (int val)
{
x = val;
return &x;
}
void print (int val1, int val2)
{
cout << val1 << " " << val2 << endl;
}
print(*func(1), *func(2));
This code is very bad. It relies of order of evaluation of print's parameters. It will print either "1 1" (right-to-left) or "2 2" (left-to-right) and we cannot know which. The only thing guaranteed by the standard is that both calls to func() are completed before the call to print().
The solution to this is to be aware that the order is unspecified, and write programs that don't rely on the order of evaluation. For example:
int val1 = *func(1);
int val2 = *func(2);
print(val1, val2); // Will always print "1 2" on any compiler.
Is it necessary that function call should be implemented using stack only. what does C/C++ standards says about this.
This is known as "calling convention" and nothing that the standard specifies at all. How parameters (and return values) are passed, is entirely up to the implementation. They could be passed in CPU registers or on the stack, or in some other way. The caller could be the one responsible for pushing/popping parameters on the stack, or the function could be responsible.
The order of evaluation of function parameters is only somewhat associated with the calling convention, since the evaluation occurs before the function is called. But on the other hand, certain compilers can choose to put the right-most parameter in a CPU register and the rest of them on the stack, as one example.
Just only to speak for C language, the order of evaluation inside the function parameters depend on compiler. from The C Programming Language of Brian Kernighan and Dennis Ritchie;
Similarly, the order in which function arguments are evaluated is not
specified, so the statement
printf("%d %d\n", ++n, power(2, n)); /*WRONG */
can produce different results with different compilers,
depending on whether n is incremented before power is called. The
solution, of course, is to write
++n;
printf("%d %d\n", n, power(2, n));
As far as I know, the function printf has an exception here.
For an ordinary function foo, the order of evaluation of foo(bar(x++), baz(++x)) is undefined. Correct! However printf, being an ellipsis function has a somewhat more definite order of evaluation.
The printf in the standard library, in fact, has no information about the number of arguments that has been sent to. It just tries to figure out the number of variables from the string placeholders; namely, from the number of percent operators (%) in the string. The C compiler starts pushing arguments from the very right towards left; and the address of the string is passed as a last argument. Having no exact information about the number of arguments, printf evaluates the last address (the string) and starts replacing the %'s (from left to right) with values of the corresponding addresses in the stack. That is, for a printf like below;
{
int x = 0;
printf("%d %d %f\n", foo(x), bar(x++), baz(++x));
}
The order of evaluation is:
x is incremented by 1,
function baz is called with x = 1; return value is pushed to the stack,
function bar is called with x = 1; return value is pushed to the stack,
x is incremented by 1,
function foo is called with x = 2; return value is pushed to the stack,
the string address is pushed to the stack.
Now, printf has no information about the number of arguments that has been sent to. Moreover, if -Wall is not issued in compilation, the compiler will not even complain about the inconsistent number of arguments. That is; the string may contain 3 %'s but the number of arguments in the printf line can be 1, 2, 3, 4, 5 or even can contain just the string itself without any arguments at all.
Say, the string has 3 placeholders and you've send 5 arguments (printf("%d %f %s\n", k1, k2, k3, k4, k5)). If compilation warning is turned off, the compiler will not complain about excessive number of arguments (or insufficient number of placeholders). Knowing the stack address, printf will;
treat the first integer width in the stack and print it as an integer (without knowing whether it is an integer or not),
treat the next double width in the stack and print it as a double (without knowing whether it is a double or not),
treat the next pointer width in the stack as a string address and will try to print the string at that address, until it finds a string terminator (provided, the address pointed to belong to that process; otherwise raises segmentation error).
and ignore the remaining arguments.

Integrating in maple with integer parameter

I'm attempting to integrate
> ans1 := ([int(e^inx/(2*pi), x = -Pi .. Pi, AllSolutions)], assuming [n::integer]);
I was able to get several other similar integrals to evaluate properly. However, for some reason when I evaluate this integral I simply get back e^{inx}. Moreover, if I add '*' between i,n and x I get a different answer.
Is there any reason for this? Am I missing something?
As stated, 'inx' is a single variable in your expression and thus, the answer that you're getting is expected since you do not have an 'x' term in your function. In order to have three separate terms, i, n, and x, you will need to add in the * between each term, 'inx'. If you are entering this in Maple's 2-D math notation, then spaces are interpreted as implicit multiplications and you can leave out the *s.
In addition, you might need to consider changing a few other parts of your syntax to conform to the Maple language (unless of course these are intentional):
The exponential function 'e' is entered as 'exp'
'pi' is the symbolic lowercase Greek letter; 'Pi' is the mathematical constant.
By default, Maple uses 'I' for imaginary numbers. You can change your default to use 'i', but otherwise this is just a symbol 'i'.
Applying these changes to your code, try something like:
int( exp(I*n*x)/(2*Pi), x = -Pi .. Pi, ...)

Array of Integers Changes Content When Passed to a Function [duplicate]

In C and C++, is there a fixed order for evaluation of parameter to the function? I mean, what do the standards say? Is it left-to-right or right-to-left?
I am getting confusing information from the books.
Is it necessary that function call should be implemented using stack only? What do the C and C++ standards say about this?
C and C++ are two completely different languages; don't assume the same rules always apply to both. In the case of parameter evaluation order, however:
C99:
6.5.2.2 Function calls
...
10 The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.
[Edit]
C11 (draft):
6.5.2.2 Function calls
...
10 There is a sequence point after the evaluations of the function designator and the actual
arguments but before the actual call. Every evaluation in the calling function (including
other function calls) that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately sequenced with respect to
the execution of the called function.94)
...
94) In other words, function executions do not ‘‘interleave’’ with each other.
C++:
5.2.2 Function call
...
8 The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect
before the function is entered. The order of evaluation of the postfix expression and the argument expression list is
unspecified.
Neither standard mandates the use of the hardware stack for passing function parameters; that's an implementation detail. The C++ standard uses the term "unwinding the stack" to describe calling destructors for automatically created objects on the path from a try block to a throw-expression, but that's it. Most popular architectures do pass parameters via a hardware stack, but it's not universal.
[Edit]
I am getting confusing information from the books.
This is not in the least surprising, since easily 90% of books written about C are simply crap.
While the language standard isn't a great resource for learning either C or C++, it's good to have handy for questions like this. The official™ standards documents cost real money, but there are drafts that are freely available online, and should be good enough for most purposes.
The latest C99 draft (with updates since original publication) is available here. The latest pre-publication C11 draft (which was officially ratified last year) is available here. And a publicly availble draft of the C++ language is available here, although it has an explicit disclaimer that some of the information is incomplete or incorrect.
Keeping it safe: the standard leaves it up to the compiler to determine the order in which arguments are evaluated. So you shouldn't rely on a specific order being kept.
In C/C++ is there a fixed order for evaluation of parameter to the function. I mean what does standards says is it left-to-right or right-to-left . I am getting confusing information from the books.
No, the order of evaluation of function parameters (and of two sub-expressions in any expression) is unspecified behaviour in C and C++. In plain English that means that the left-most parameter could be evaluated first, or it could be the right-most one, and you cannot know which order that applies for a particular compiler.
Example:
static int x = 0;
int* func (int val)
{
x = val;
return &x;
}
void print (int val1, int val2)
{
cout << val1 << " " << val2 << endl;
}
print(*func(1), *func(2));
This code is very bad. It relies of order of evaluation of print's parameters. It will print either "1 1" (right-to-left) or "2 2" (left-to-right) and we cannot know which. The only thing guaranteed by the standard is that both calls to func() are completed before the call to print().
The solution to this is to be aware that the order is unspecified, and write programs that don't rely on the order of evaluation. For example:
int val1 = *func(1);
int val2 = *func(2);
print(val1, val2); // Will always print "1 2" on any compiler.
Is it necessary that function call should be implemented using stack only. what does C/C++ standards says about this.
This is known as "calling convention" and nothing that the standard specifies at all. How parameters (and return values) are passed, is entirely up to the implementation. They could be passed in CPU registers or on the stack, or in some other way. The caller could be the one responsible for pushing/popping parameters on the stack, or the function could be responsible.
The order of evaluation of function parameters is only somewhat associated with the calling convention, since the evaluation occurs before the function is called. But on the other hand, certain compilers can choose to put the right-most parameter in a CPU register and the rest of them on the stack, as one example.
Just only to speak for C language, the order of evaluation inside the function parameters depend on compiler. from The C Programming Language of Brian Kernighan and Dennis Ritchie;
Similarly, the order in which function arguments are evaluated is not
specified, so the statement
printf("%d %d\n", ++n, power(2, n)); /*WRONG */
can produce different results with different compilers,
depending on whether n is incremented before power is called. The
solution, of course, is to write
++n;
printf("%d %d\n", n, power(2, n));
As far as I know, the function printf has an exception here.
For an ordinary function foo, the order of evaluation of foo(bar(x++), baz(++x)) is undefined. Correct! However printf, being an ellipsis function has a somewhat more definite order of evaluation.
The printf in the standard library, in fact, has no information about the number of arguments that has been sent to. It just tries to figure out the number of variables from the string placeholders; namely, from the number of percent operators (%) in the string. The C compiler starts pushing arguments from the very right towards left; and the address of the string is passed as a last argument. Having no exact information about the number of arguments, printf evaluates the last address (the string) and starts replacing the %'s (from left to right) with values of the corresponding addresses in the stack. That is, for a printf like below;
{
int x = 0;
printf("%d %d %f\n", foo(x), bar(x++), baz(++x));
}
The order of evaluation is:
x is incremented by 1,
function baz is called with x = 1; return value is pushed to the stack,
function bar is called with x = 1; return value is pushed to the stack,
x is incremented by 1,
function foo is called with x = 2; return value is pushed to the stack,
the string address is pushed to the stack.
Now, printf has no information about the number of arguments that has been sent to. Moreover, if -Wall is not issued in compilation, the compiler will not even complain about the inconsistent number of arguments. That is; the string may contain 3 %'s but the number of arguments in the printf line can be 1, 2, 3, 4, 5 or even can contain just the string itself without any arguments at all.
Say, the string has 3 placeholders and you've send 5 arguments (printf("%d %f %s\n", k1, k2, k3, k4, k5)). If compilation warning is turned off, the compiler will not complain about excessive number of arguments (or insufficient number of placeholders). Knowing the stack address, printf will;
treat the first integer width in the stack and print it as an integer (without knowing whether it is an integer or not),
treat the next double width in the stack and print it as a double (without knowing whether it is a double or not),
treat the next pointer width in the stack as a string address and will try to print the string at that address, until it finds a string terminator (provided, the address pointed to belong to that process; otherwise raises segmentation error).
and ignore the remaining arguments.

Difference between division and shift

I was reading this question on SO. After reading the first answer I was unable to understand the reason for -5 >> 1 = -3. I also tweaked a little bit more around it.
You can also see the code and output here.
Here is what I did:
#include<stdio.h>
int main(){
printf("5/2 = %d\n",5/2);
printf("5 >> 1 = %d\n",5 >> 1);
printf("5/2 = %lf\n",5/2);
printf("5 >> 1 = %f\n",5 >> 1);
printf("-5/2 = %d\n",-5/2);
printf("-5 >> 1 = %d\n",-5 >> 1);
printf("-5/2 = %f\n",-5/2);
printf("-5 >> 1 = %f\n",-5 >> 1);
return 0;
}
Output :
5/2 = 2
5 >> 1 = 2
5/2 = 2.168831
5 >> 1 = 2.168831
-5/2 = -2
-5 >> 1 = -3
-5/2 = 2.168833
-5 >> 1 = 2.168833
I am unable to understand 5/2 == 2.168831, 5 >> 2 == 2.168831, 5 >> 1 == -3.
Why this is happening? (It may be possible that the answer is very basic and I am missing some basic things, so pls guide me).
The result of -5 / 2 is an int, not a float or a double. However your format specifier is %f, so your int gets interpreted as a float, which makes no sense, hence the erratic values. What you are doing is called undefined behavior: anything can happen.
The reason you see the results you do is:
When you pass an int argument but use a printf specifier for double (remember that a float is converted to a double in this situation), then most C implementations pass the int argument according to their usual rules for passing a int argument to a variadic function (a function that accepts diverse argument types), but the printf routine interprets the machine state as if it were passed a double argument, as described below. (This is not necessarily what always happens; once you leave the behavior defined by the C standard, a C implementation may do other things. In particular, there can be complex interactions with the optimizer that cause surprising results. However, this is what happens most commonly. You cannot rely on it.)
Each computing platform has some rules for how arguments are passed. One platform might specify that all arguments are pushed onto the stack, from right to left, and that each argument is put onto the stack using only as many bytes as it needs. Another platform might specify that arguments are pushed onto the stack left to right or that arguments are padded up to the next multiple of four bytes, to keep the stack nicely aligned. Many modern platforms specify that integer arguments under a certain size are passed in general registers, floating-point arguments are passed in floating-point registers, and other arguments are passed on the stack.
When printf sees %f and looks for a double argument, but you have passed an int, what does printf find? If this platform pushes both arguments onto the stack, then printf finds the bits for your int, but it interprets those bits as if they were a double. This results in printf printing a value determined by your int, but it bears no obvious relationship to your int because the bits have entirely different meanings in the encodings for int and for double.
If this platform puts an int argument in one place but a double argument in another place, then printf finds some bits that have nothing at all to do with your int argument. They are bits that just happened to be left over in, for example, the floating-point register where the double argument should be. Those bits are just the residue of previous work. The value you get will be essentially random with respect to the int you have passed. You can also get a mix, with printf looking for eight bytes of a double by taking four bytes of the int you passed along with four bytes of whatever else was nearby.
When you run the program multiple times, you will often see the same value printed. This happens for two reasons. First, computers are mechanical. They operate in largely deterministic ways, so they do the same things over and over again, even if those things were not particularly designed to be used the way you are using them. Second, the environment the operating system passes to the program when it starts is largely the same each time you start the program. Most of its memory is either cleared or is initialized from the program file. Some of the memory or other program state is initialized from other environment in the computer. That data can be different from run to run of the program. For example, the current time obviously changes from run to run. So does your command history, plus values the command shell has placed in its environment variables. Sometimes running a program multiple times will produce different results.
When you use code whose behavior is not defined by some specification (which may be the C specification, a compiler specification, a machine and operating system specification, or other documents), then you cannot rely on the behavior of that code. (It is possible to rely on the behavior of code compiled by a particular C compiler that is specified by that C compiler even though it is not fully specified by the C standard.)

Resources