Standard ML export operator from structure as infix - sml

I would like to declare an infix operator within a structure a for use outside the structure. But I cannot seem to get the "infixness" to be recognized outside the structure even when the structure has been opened. Here is an example using Poly/ML:
> structure A = struct infix 6 ++ fun a ++ b = a + b end;
structure A: sig val ++: int * int -> int end
> 1 A.++ 2;
poly: : error: Type error in function application.
Function: 1 : int
Argument: A.++ : int * int -> int
Reason: Value being applied does not have a function type
Found near 1 A.++ 2
Static Errors
> let open A in 1 ++ 2 end;
poly: : error: Type error in function application.
Function: 1 : int
Argument: ++ : int * int -> int
Reason: Value being applied does not have a function type
Found near let open A in 1 ++ 2 end
Static Errors
Is this a limitation of Standard ML?

Yes, this is not supported by Standard ML. You'll have to re-declare the fixity and, optionally, the precedence every time you open that structure. One way to get around it is to declare the fixity globally, i.e., outside any structure, but this isn't well supported with separate compilation and it isn't very modular either. You can read more about it and a possible workaround on the MLton's InfixingOperators page.
For my own projects, I've defined a shortcut in my text editor that will expand into both an open declaration as well as a fixity one.
Also, as a personal style guide, I'm not declaring the precedence. If I need to mix multiple infix operators into the same expression, I'll rather use parentheses explicitly. Eye-parsing an identifier as infix is easy, parsing the precedence is not.

Related

Musing about variable declaration and the typedef specifier in c++

If you want to declare an int you do for instance
int x;
You could after assign a value to x (or "define" x) for instance as follows :
x = 3;
Of course, you could have done directly
int x = 3;
There are types whose variables should be declared and defined at the same time, for instance
const double y = 2.3;
as well as type whose variables you simply can't declare and define at the same time, for instance a pointer to an array of three char's :
typedef char (*pc3)[3];
char c3[3] = "ok";
pc3 apc3 = &c3;
(Am I wrong on the two previous examples ? Is there a one-liner (only one semi-column allowed) for the last one ?)
Consider now the following function pointer definition :
typedef int (*ipfunci)(int);
ipfunci fptr = &f; // where f is some int -> int function
(no one-liner for this as far as I know). Perfectly legal of course, but what about
typedef int (ifunci)(int);
Perfectly legal as well, but you can't define a variable of "type" 'ifunci' after having declared it, and what's it's use ?
This boils down to my real question : looking at
typedef char (*pc3)[3];
typedef int (*ipfunci)(int);
one sees an analogy between the two definitions, if one decides to see a size 3 array of char's as a function
0 -> char
1 -> char
2 -> char
One could also see
typedef int * pi ;
as the definition of the "type" pi as constant function with value equal to an int.
How far does this synthactic and functional analogy go ? What is behind types whose definitions really require a typedef : are they systematically "functional" types ?

ADTs and values

In Rascal, say I have the code:
value x = 2;
data Exp = con(int n);
Is there a way to call con(x), while x is a value (but actually an integer), without knowing on beforehand what the type of con's first argument is supposed to be (thus without explicitly casting it to an int)?
Why is it possible to call a function, say int something(int n) = n, with an integer defined as a value (e.g. value y = 2) passed into its first argument, while it gives me an error when I try to do the same with user-defined ADTs?
When you call a function in Rascal it actually is doing a pattern match on the arguments. So, if you define int something(int n) = n;, and then call something(x), it matches x with int n, sees that x is actually an int (so it can bind the value to n), and calls the function.
If you were to define value x = 2.5 instead and then call something(x) you would get an error since it cannot bind the value 2.5 to int n. You could overload something with a second definition that takes a real instead, like int something(real r) = toInt(r);, and it would then work. Two items to note here, though: something needs to return the same type in both cases, and you need to import util::Math to get access to toInt.
When you are using a constructor, like con(x), it doesn't do a pattern match for you automatically. The type that you give it has to match the type it expects. If you know that x will always be an int, it would be best to just declare it as such. Another option would be to create a function like Exp makeCon(int n) = con(n); which you could then use as you would like, i.e., Exp myExp = makeCon(x);. It would be best in this case to include a default version of the function, just in case you give it something unexpected, like default Exp makeCon(value x) { throw "Unexpected value <x>"; }, this way if you ever try to create a con with something that isn't an int you will get an error that you can handle, with the ability to create your own error message, add additional error handling versus just showing a message, see the value causing the problem, etc, versus just having the interpreter give an error (which may not give you all the info you want).

The equivalent C code of a valid C++ code with a While loop does not compile

The following code containing a while loop compiles in C++.
#include <iostream>
using namespace std;
int main() {
while (int i = 5)
{
break;
}
return 0;
}
However, the following equivalent C code results in an error if compiled in C:
#include <stdio.h>
int main() {
while (int i = 5)
{
break;
}
return 0;
}
Compiler output:
> prog.c: In function 'main': prog.c:5:9: error: expected expression
> before 'int' while (int i = 5)prog.c: In function 'main':
> prog.c:5:9: error: expected expression before 'int' while (int i =
> 5)
Why does this happen? I tried to look up the documentation for the while loop in C, but haven't been able to locate that either.
C and C++ are different languages. <iostream> is not part of C library, and using and namespace are C++ keywords only. Don't mix the languages, as they are not at all the same.
Also, as #sasquatch mentioned, it is illegal in C to declare a variable in the while condition.
You should not expect C++ code to compile in C. You should also not expect the other way around, since C is not a proper subset of C++.
In C++, a condition is tested for before each iteration of a while loop. Verbatim from the C++ reference:
condition - any expression which is contextually convertible to
bool or a declaration of a single variable with a brace-or-equals
initializer. This expression is evaluated before each iteration, and
if it yields false, the loop is exited. If this is a declaration, the
initializer is evaluated before each iteration, and if the value of
the declared variable converts to false, the loop is exited.
Whereas in C, an expression is tested for before each iteration of a while loop. Verbatim from the C reference:
expression - any expression of scalar type. This expression is
evaluated before each iteration, and if it compares equal to zero,
the loop is exited.
In C, the while expects an expression inside the parenthesis. What you have is a declaration of the variable. You would have to declare the variable before the loop and then write the expression as i == 5 to compile in C.
This post covers what C expects compared to C++ in more detail. The same rules that they explain for an if also applies to a while.
There is a difference in the definition of the while statement in C++ and C.
In C++ the while statement is defined the following way
while ( condition ) statement
where in turn the condition is defined like
condition:
expression
attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list
As you can see apart from an expression the condition may be a declaration with some initializer. The value of ibitializer is converted to an expression of type bool and the while statement is executed depending on the boolean value.
So in your C++ program the value of the initializer of the declaration in the condition of the while statement is equal to 5
while (int i = 5)
As it is not equal to zero then it is converted to boolean true.
In C the while statement is defined the following way
while ( expression ) statement
As you can see yourself here is explicitly specified that only expressions may be used. C does not allow to use declarations in the while statement. So this statement
while (int i = 5)
will not be compiled in C.
It is not the only difference between C++ and C. For example this conditional operator below will be compiled in C++ and will not be compiled in C
int x = 10;
int y = 20;
( x < y ? x : y ) = 20;
Or this statement will be compiled in C++ and will not be compiled in C
int x;
int y = 20;
++( x = y );
The code snippet below will yield different results in C++ and C
if ( sizeof( 'A' ) == 1 ) puts( "They are equal" );
else puts( 'They are not equal" );
Or consider the following example
int x = 10;
void *vp = &x;
int *ip;
ip = vp;
This code snippet will be compiled in C and will not be compiled in C++. So you should be caution.
Moreover C and C++ have even different fundamental types. For example in C there is integer type _Bool that is absent in C++. On the other in C++ there is type bool and corresponding boolean literals false and true that is absent in C. In C++ there is pointer literal nullptr that is absent in C. Or in C there are compound literals that are absent in C++. Or in C++ there is the range based for statement that is absent in C and so on.:)
There are multiple issues with the code you have above.
First off you may want to get rid of both the name space and the header. They are not even being used in the code and are not able to be read by the c compiler either.
Second, you cannot define variable types in any looping commands. For example while (int i != 5) and for (int i =0 ...) is invalid in c. You have to define the variable before the loop.
Finally, although I believe the c++ standard allows you to define a variable in a while statement, I highly suggest not doing so. Its semi confusing to have a comparison statement mixed with a variable definition ie: int x, bool y, double z, etc. etc.

Is it possible to use the ternary operator "?" to fill an array list in C/C++?

This is probably a dumb questions. I'm modifying a code developed by someone else. I need to particularize the value of some chars array based on a logic variable ThreeDim. I'm trying to do this without success.
int VarNumber = ThreeDim==1 ? 3 : 2;
const char* VarList [] = ThreeDim==1 ? {"X","Y","Z"} : {"X","Y"};
But the compiler is giving me errors like
error: expected ‘;’ before ‘}’ token
error: initializer fails to determine size of ‘VarList’
VarList needs to be a const char* due to downstream requirements. And its size should be VarNumber. Thanks
You might consider using the preprocessor, #define THREE_DIM, and then use #ifdef to select one or the other code to compile:
#define THREE_DIM
#ifdef THREE_DIM
int VarNumber = 3;
const char* VarList [] = {"X","Y","Z"};
#else
int VarNumber = 2;
const char* VarList [] = {"X","Y"};
#endif
I don't think you can do this with different sized array initializers. However, you can put a conditional expression in the initializer:
const char* VarList [] = {"X", "Y", ThreeDim == 1 ? "Z" : nullptr};
This will always give you a 3 element array with the last element either "Z" or a null pointer.
No, because e.g. {"X","Y","Z"} is not an expression. It's handled specially by the compiler for variable definitions.
And if you're programming C++ you should be using std::vector and std::string instead, then it would be very simple (but verbose):
std::vector<std::string> VarList = ThreeDim==1 ?
std::vector<std::string>{{"X","Y","Z"}} :
std::vector<std::string>{{"X","Y"}};
As per C11 6.7.9, arrays aren't initialized with an expression but with an initializer list; these are two different syntactical elements and can't be mixed. This derives from the fact that arrays aren't assignable, and treating one as a value (as opposed to a value that decays to a pointer) therefore doesn't make sense. Since they aren't values, there's no way to create a legal expression that passes around whole arrays.
The closest direct analogue to what you're asking for would be:
const char** VarList = ThreeDim==1 ? (const char*[]){"X","Y","Z"} : (const char*[]){"X","Y"};
...but this comes at the cost of changing the type of VarList, and is probably not what you want.

Complex C declaration

I was just going through some code on the Internet and found this:
float * (*(*foo())[SIZE][SIZE])()
How do I read this declaration? Is there a specific set of rules for reading such complex declarations?
I haven't done this in a while!
Start with foo and go right.
float * (*(*foo())[SIZE][SIZE])()
foo is a function with no arguments...
Can't go right since there's a closing parenthesis. Go left:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer
Can't go left further, so let's cross the parentheses and go right again
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE ...
Closing parenthesis reached, left again to reach a pointer symbol:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to ...
Left parenthesis again, so we cross it and go right again:
float *( *(* foo())[SIZE][SIZE])()
float *( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments...
And left to the end
float * ( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments returning a pointer to float
And whoever wrote that, please teach him to use typedef:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();
Standard rule: find the leftmost identifier and work your way out, remembering that [] and () bind before *:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
So imagine you have a bunch of functions returning pointers to float:
float *quux();
float *bar();
float *bletch();
float *blurga();
Let's say you want to store them in a 2x2 table:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab is a SIZE x SIZE array of pointers to functions returning pointers to float.
Now let's decide we want a function to return a pointer to that table:
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
Note that you could have several functions that build tables of different functions, or organize the same functions differently:
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
which is the only reason I can think of to do something like this. You shouldn't see types like this in the wild very often (although they do crop up occasionally, and I've been guilty of writing something similarly heinous).
According to cdecl.org
declare foo as function returning pointer to array SIZE of array SIZE
of pointer to function returning pointer to float
Use the spiral rule given by Luchian Grigore if you want to decode it by hand.
The best thing to do here is convert to a series of typedefs.
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();
Generally, you could try cdecl.org but you'd need to substitute for SIZE
Say you swap SIZE for 12, you'd get:
declare foo as function returning pointer to array 12 of array 12 of
pointer to function returning pointer to float
I'm not sure that really helps you!
Two observations here:
I'm guessing that this code didn't have a comment beside it explaining what the purpose of it was (i.e. not the technical explanation of what it is but what it is achieving from a functional / business perspective) If a programmer needs to use something as complex as this, they should be good enough to explain to future maintainers what purpose it serves.
Certainly in C++ there are more obvious and probably safer ways of achieving the same thing.
This document gaves me the best clue about how to easily ready any C declaration :
http://c-faq.com/decl/spiral.anderson.html
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or [] => Array X size of ... or Array undefined size of ...
(type1, type2) => function passing type1 and type2 returning ...
* => pointer(s) to ...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
Example :
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!
Although most of the answers above are good enough, there is a lack of complete set of rules for decoding complex C declarations. I have provided a complete set below to decode any complex C declaration. This set of rules is actually based on the precedence of operators. Rules such as right hand spiral rules can be thought of as a shortcut for these set of rules.
Before anything else we need to know a few things to decode the declaration.
'Basic Type' of a declaration
A C declaration always has only one basic declaration type. This is at the left most position of a declaration.
For example -
int a - basic type is 'int'
float *p - basic type is 'float'
char (*p)[3] - basic type is 'char'
Precedence and associativity
Next we need to know the precedence order of (), [], and * - dereference operator
(), [] - Associativity is left to right
* - Associativity is right to left
Phrase corresponding to each of the operator above
Next we need to know the decoded phrase corresponding to each operator. Examples ahead will make this point clear.
() - function returning
[SIZE] - array of SIZE
* - pointer to
Now follow the rules below to decode the declaration
Always write the variable name first followed by an 'is'.
For example -
int a - a is ...
float *p - p is ...
char (*p)[3] - p is ...
Always end with basic type
For example -
int a - a is ... int
float *p - p is ... float
char (*p)[3] - p is ... char
Now fill the part in between using the following sub-steps
Starting from the name, follow the operator precedence and associativity to choose next highest priority operator and append the phrase corresponding to it to the middle part of the decoded string.
Repeat the sub step above for the remaining declaration until the decoding process is complete
NOTE 1: For simplicity, I have ignored the arguments of the function however it can be included just after the phrase corresponding to ().
NOTE 2: Parenthesis(()) change the priority order of operators, just like in any arithmetic expression.
NOTE 3: You can use parenthesis in the decoded declaration to increase readability( I have done it in some examples below). Think of each set of () as a single unit.
NOTE 4: A n dimensional array is actually an array of array of ... (n-1 times) array. For ex - int A[2][3] - A is array of 2 (array of 3 int) i.e A is an array of 2 elements in which each element is an array containing 3 integers
Examples
int a - a is int
float *p - p is pointer to float
char (*p)[3] - p is pointer to array of 3 char
Some complex declaration examples
int **p[10] - p is array of 10 pointer to pointer to int
int (*p)[10] - p is pointer to array of 10 int
int *p(char *a) - p is function returning pointer to int
int (*p(char*a))[10] - p is function returning (pointer to (array of 10 int))
int *(*p)() - p is pointer to (function returning (pointer to int))
int (*p()[20])[10] - p is function returning (array of 20 (pointer to (array of 10 int)))
This set of rules can be used with const as well - const qualifier modifies the term to the left of it (if present) otherwise it modifies the term to the right of it.
const int *p[10] - p is array of 10 pointer to int const
int const *p[10] - p is array of 10 pointer to const int (this is same as 7th example)
int *const p[10] - p is array of 10 const pointer to int
Now a really complex example which will not find its use anywhere in practice but nevertheless can be used to demonstrate the decoding process
char *(*(**foo[][8])())[] - foo is array of (array of 8 (pointer to (pointer to (function returning (pointer to (array of (pointer to char)))))))
Now at last decoding for the declaration given in the question
float * (*(*foo())[SIZE][SIZE])() - foo is function returning (pointer to (array of SIZE (array of SIZE (pointer to (function returning pointer to float)))))
The following is the link for the article from which I read this decoding process
Example 10 has been taken from this article
http://www.unixwiz.net/techtips/reading-cdecl.html
from http://cdecl.org/
declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float