I'm playing with the difference between - as a unary operator and a binary operator in caml-light.
let a b =
print_int b;
print_newline();
;;
let c d e =
print_int d;
print_newline();
print_int e;
print_newline();
;;
a (3 - 4 ) ;
c (9 - 4 )
;;
I expect the code to either throw an error (because it gets confused about how many arguments a or c have) or to print:
-1
5
However, it compiles with no problems (compiler version below) and prints
-1
Can anyone tell me what happens with the last call?
Cobrakai$camlc -v
The Caml Light system, version 0.80
(standard library from /usr/local/lib/caml-light)
The Caml Light runtime system, version 0.80
The Caml Light compiler, version 0.80
The Caml Light linker, version 0.80
Cobrakai$
In ML, all functions take exactly one argument. A seemingly multi-parameter function is actually a function that takes one argument, and returns another function which takes the remaining arguments.
So let c d e = ... is actually syntactic sugar for let c = function d -> function e -> ...
And the type of c is int -> int -> unit, and -> is right-associative, so it is int -> (int -> unit). So you can see clearly that is a function which takes int and returns a function.
When you apply it to multiple arguments like c 1 2, function application is left-associative so it is actually (c 1) 2, so you can see that c 1 evaluates to a function which then is applied to 2.
So, when you give a function "too few arguments", the result is a function. This is a useful and common technique in ML called "partial application", which allows you a convenient way to "fix" the first few arguments of a function.
I am not sure how the Caml Light interpreter handles it when the expression you type evaluates to a function. But from what you're saying, it seems to not print anything.
Related
I'm an OCaml beginner using OCaml 4.12.0 on MacOS. This let expression:
let gg x y = (x -. y) < 5.0
at the toplevel results in:
Error: This expression has type float but an expression was expected of type
int
Explicitly adding type information, etc., did not fix the problem. In frustration, I visited the online REPL TryOCaml, and the expression was accepted without error, returning the type signature of:
val f : float -> float -> bool = <fun>
as expected. But I'd like utop to work on the Mac - what am I missing?
Very possibly you're using a library that overrides the built-in meaning of < in OCaml. Some people (not me) think the polymorphic comparison operators are a problem.
One problem with this (IMHO) is that it causes confusing results like this.
For example, the Jane Street Base library is documented as overriding the polymorphic comparison operators: https://ocaml.janestreet.com/ocaml-core/latest/doc/base/index.html
When you use Base (or Core, or Core_kernel and other Janestreet standard libraries) the comparison operator and its friends (like various equality operators) work only on values of type int. For all other values you have to use specialized comparison operators provided by the module that implements that type, e.g., to compare two floats,
Float.(3.14 < 4.14)
to compare strings,
String.("hello" <> "world")
And, using your example,
let gg x y = Float.(x -. y < 5.0)
or even
let gg x y = Float.(x - y < 5.0)
Notice that we don't need to use the ugly -. operators anymore and can use - (and other arithmetic operators) as they are all defined specifically for float in module Float.
Besides, the notation Foo.(<expr>) is a short-hand for let open Foo in <expr> and is called local open.
Background
I'm a relative newcomer to Reason, and have been pleasantly suprised by how easy it is to compare variants that take parameters:
type t = Header | Int(int) | String(string) | Ints(list(int)) | Strings(list(string)) | Footer;
Comparing different variants is nice and predictable:
/* not equal */
Header == Footer
Int(1) == Footer
Int(1) == Int(2)
/* equal */
Int(1) == Int(1)
This even works for complex types:
/* equal */
Strings(["Hello", "World"]) == Strings(["Hello", "World"])
/* not equal */
Strings(["Hello", "World"]) == Strings(["a", "b"])
Question
Is it possible to compare the Type Constructor only, either through an existing built-in operator/function I've not been able to find, or some other language construct?
let a = String("a");
let b = String("b");
/* not equal */
a == b
/* for sake of argument, I want to consider all `String(_)` equal, but how? */
It is possible by inspecting the internal representation of the values, but I wouldn't recommend doing so as it's rather fragile and I'm not sure what guarantees are made across compiler versions and various back-ends for internals such as these. Instead I'd suggest either writing hand-built functions, or using some ppx to generate the same kind of code you'd write by hand.
But that's no fun, so all that being said, this should do what you want, using the scarcely documented Obj module:
let equal_tag = (a: 'a, b: 'a) => {
let a = Obj.repr(a);
let b = Obj.repr(b);
switch (Obj.is_block(a), Obj.is_block(b)) {
| (true, true) => Obj.tag(a) == Obj.tag(b)
| (false, false) => a == b
| _ => false
};
};
where
equal_tag(Header, Footer) == false;
equal_tag(Header, Int(1)) == false;
equal_tag(String("a"), String("b")) == true;
equal_tag(Int(0), Int(0)) == true;
To understand how this function works you need to understand how OCaml represents values internally. This is described in the section on Representation of OCaml data types in the OCaml manual's chapter on Interfacing C with OCaml (and already here we see indications that this might not hold for the various JavaScript back-ends, for example, although I believe it does for now at least. I've tested this with BuckleScript/rescript, and js_of_ocaml tends to follow internals closer.)
Specifically, this section says the following about the representation of variants:
type t =
| A (* First constant constructor -> integer "Val_int(0)" *)
| B of string (* First non-constant constructor -> block with tag 0 *)
| C (* Second constant constructor -> integer "Val_int(1)" *)
| D of bool (* Second non-constant constructor -> block with tag 1 *)
| E of t * t (* Third non-constant constructor -> block with tag 2 *)
That is, constructors without a payload are represented directly as integers, while those with payloads are represented as "block"s with tags. Also note that block and non-block tags are independent, so we can't first extract some "universal" tag value from the values that we then compare. Instead we have to check whether they're both blocks or not, and then compare their tags.
Finally, note that while this function will accept values of any type, it is written only with variants in mind. Comparing values of other types is likely to yield unexpected results. That's another good reason to not use this.
Why does let f ~x ?(y = 1) = x - y;; make the label for argument x become necessary? In other words, when I tried to evaluate f 3 ~y:2;;, I received this error:
Error: The function applied to this argument has type x:int -> int
This argument cannot be applied without label
What's the reason behind such design?
It is not necessary to label the argument x:
let g = f 0
works and returns a function g of type ?y:int -> int.
To understand this behaviour, it is best to remember that the generic rule is that
labels are mandatory when applying a function.
However, there is a specific rule for total application: if a function is applied to as many non-optional arguments as possible, then labels can be omitted.
A typical example would be
let f ~a ~b c d ~e f ~g = a + b + c + d + e + f + g
let x = f 1 2 3 4 5 6 7
Going back to your case, your function f takes at most one non-optional argument. It is thus considered as totally applied when applied to exactly one argument.
Another important point is that optional arguments are only send to the function once a subsequent positional argument has been sent. This explains why the variable g is still a function: no positional arguments were provided to f thus the optional argument ?y was never sent to f.
Applied to more complex example
let f ~a ?(b=0) c ~d e ~f ~g ?(h=0) = a + b + c + d +e + f + g + h
(* there are 8 arguments, 2 optional *)
(* g is applied to the full 6 non-optional arguments, thus total *)
let g = f 1 3 4 5 6 7
the type of g is ?h:int -> 0. Indeed, the application is total, thus all non-optional arguments have been provided. Then, the first optional argument ?b was followed by a positional argument. It was then provided to the function. However, the last optional argument ?h has not been yet triggered and is still here.
This behavior implies that optional argument are only useful if there is at least one positional argument after them, as advised by the compiler itself:
let f ~x ?(y=0) = x + y;;
Line 1, characters 11-14:
Warning 16: this optional argument cannot be erased.
If I define a function in OCaml, for example let f x = x + 1;; and then I try to call it passing a negative number
f -1;; it gives to me the following error
Error: This expression has type int -> int
but an expression was expected of type int
Why this error occurs?
Basically, it comes from the precedence of the parser. The compiler believes that f -1 means you want to subtract f by 1. It has been complained about for ages now.
Typing in f (-1) or f ~-1 will solve your problem (the later using the "explicitly unary minus").
UPDATE:
As stated in the OCaml manual:
Unary negation. You can also write - e instead of ~- e.
Basically, - can be used both as a binary operator 4 - 1 and a unary operator -1. But, as in your case, there can be confusion: f - 1 is "f minus one" and not "f applied to minus one". So the ~- operator was added to have a non-confusing unary minus as well.
Note that the spaces are not significant here, and that won't change because a lot of already existing code may contain operations without space.
So I've been avoiding Fortran like the plague, but finally my time has come... I need to take part of someone else's Fortran code (let's call it program A) and do two things with it:
(1) Merge it with a third person's Fortran code (let's call it program B) so that B can call A
(2) Merge it with my C++ code (program C) so that C can call A
B and C are optimization algorithms, and A is a collection of benchmark functions... But before all that awesomeness can happen, I must first compile the portion of A that I need. All the subroutines of A that I need are contained in one file. I've been getting it into shape based on information I got online (e.g. adding "IMPLICIT NONE" to the code and making it suitable for gfortran). But I've got two stubborn bugs and a warning (I'll leave the warning for another post).
Here's how I am currently compiling it (via a Makefile):
all:
gfortran progA.FOR
g++ -c progC.cpp
g++ -o Program.out progA.o progC.o
rm *.o
But the first line fails to complete with the following errors,
FIRST ERROR:
SUBROUTINE TP1(MODE)
1
Error: Unclassifiable statement at (1)
RELEVANT CODE (starting from the top of the file):
IMPLICIT NONE
INTEGER NMAX,MMAX,LMAX,MNNMAX,LWA,LIWA,LACTIV,N,NILI,NINL,
/ NELI,NENL,NEX, MODE
PARAMETER (NMAX = 101,
/ MMAX = 50,
/ LMAX = 50,
/ MNNMAX = NMAX + NMAX + MMAX + 2,
/ LWA = 2*NMAX*NMAX + 33*NMAX + 10*MMAX + 200,
/ LIWA = MMAX + NMAX + 150,
/ LACTIV = 2*MMAX + 15)
LOGICAL INDEX1,INDEX2
SUBROUTINE TP1(MODE)
COMMON/L1/N,NILI,NINL,NELI,NENL
COMMON/L2/X(2)
COMMON/L4/GF(2)
COMMON/L6/FX
COMMON/L9/INDEX1
COMMON/L10/INDEX2
COMMON/L11/LXL
COMMON/L12/LXU
COMMON/L13/XL(2)
COMMON/L20/LEX,NEX,FEX,XEX(2)
REAL*8 X,G,GF,GG,FX,XL,XU,FEX,XEX
LOGICAL LXL(2),LXU(2),LEX
GOTO (1,2,3,4,4),MODE
1 N=2
NILI=0
NINL=0
NELI=0
NENL=0
X(1)=-2.D0
X(2)=1.D0
LXL(1)=.FALSE.
LXL(2)=.TRUE.
LXU(1)=.FALSE.
LXU(2)=.FALSE.
XL(2)=-1.5D0
LEX=.TRUE.
NEX=1
XEX(1)=1.D0
XEX(2)=1.D0
FEX=0.D0
RETURN
2 FX=100.D0*(X(2)-X(1)**2)**2+(1.D0-X(1))**2
RETURN
3 GF(2)=200.D0*(X(2)-X(1)**2)
GF(1)=-2.D0*(X(1)*(GF(2)-1.D0)+1.D0)
4 RETURN
END
I do not understand why this error appears since there are over 300 other subroutines declared exactly the same way (e.g. SUBROUTINE TP2(MODE), ..., SUBROUTINE TP300(MODE) ).
SECOND ERROR:
HX=TP273A(X)
1
Error: Return type mismatch of function 'tp273a' at (1) (REAL(4)/REAL(8))
RELEVANT CODE:
SUBROUTINE TP273(MODE)
COMMON/L1/N,NILI,NIML,NELI,NENL
COMMON/L2/X
COMMON/L4/GF
COMMON/L6/FX
COMMON/L11/LXL
COMMON/L12/LXU
COMMON/L20/LEX,NEX,FEX,XEX
LOGICAL LEX,LXL(6),LXU(6)
REAL*8 X(6),FX,GF(6),FEX,XEX(6),HX,DFLOAT
GOTO (1,2,3,4,4)MODE
1 N=6
NILI=0
NINL=0
NELI=0
NENL=0
DO 6 I=1,6
X(I)=0.D+0
XEX(I)=0.1D+1
LXL(I)=.FALSE.
6 LXU(I)=.FALSE.
LEX=.TRUE.
NEX=1
FEX=0.D+0
RETURN
2 HX=TP273A(X)
FX=0.1D+2*HX*(0.1D+1+HX)
RETURN
3 HX=TP273A(X)
DO 7 I=1,6
7 GF(I)=0.2D+2*(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1)
1 *(0.1D+1+0.2D+1*HX)
4 RETURN
END
REAL*8 FUNCTION TP273A (X)
REAL*8 X(6),DFLOAT
TP273A=0
DO 10 I=1,6
10 TP273A=TP273A+(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1)**2
RETURN
END
After reading Physics Forums I tried renaming the variable "TP273A" to "TP273Avar" so that it would not have the same name as the function. This did not resolve the error. Also, I replaced the "1" with "F" just below "7 GF(I) = ..." and recompiled. Nothing changed. I'm pretty sure the changes I just mentioned are necessary anyway, but there must be something else going on.
I have also read Data type mismatch in fortran and Function return type mismatch, so I naively tried adding "module mycode" to the top and "end module mycode" to the bottom of the file to no avail.
After this is all said and done, my goal is to call these subroutines from C++ using a code similar to:
#include <kitchensink>
extern"C"
{
void TP1_(int *mode);
}
int main()
{
TP1_(2);
return 0;
}
Once the Fortran Code compiles, I want to modify the subroutines so that C++ can pass std::vector X to TP#_(2,*X,*Y) and get back the computed value for Y. My std::vector X will replace COMMON/L2 X in each of the subroutines, and Y will be the value of FX computed in the subroutines. I used Mixing Fortran and C as guidance for the above C++ code.
As for the B calls A part, I hope that it will be as simple as compiling A along with B, and adding "CALL TP1(MODE)" lines wherever I need them.
Any and all guidance will be greatly appreciated!!!
You cannot have statements just in a file outside of a compilation unit. These can be subroutines, functions, modules or programs. In your case you have some statements( first of them being implicit none) and only after them there is the beginning of the subroutine TP1.
Either organize the procedures in a module and leave the common part before the contains section (more work with the C++ interoperability will follow if you are a Fortran newbie) or you must include the implicit none and others in every subroutine separately. Are you sure you even need this if the code worked before?