I have the following code in some e file:
<'
package my_package;
struct packet {
foo() is {
print "Hello";
};
};
'>
And my top file imports several files, including this one, and at some point it calls the foo() method.
Now, by mistake I added this code:
struct packet {};
in some other file (I just forgot that I already had a struct called “packet”), which is imported by top before the above file.
Strangely, when I tried to load the top file, I got this error:
*** Error: 'p' (of type main::packet) does not have 'foo()' method.
at line 9 in top.e
p.foo();
But why didn’t it fail already on the file that defines foo()?
It has a struct declaration for packet, but packet was already (mistakenly) declared in an earlier file, so why didn’t it give a duplicate type name error? Is it allowed to have two structs with the same name??
Actually, it's not that the main package takes precedence.
But when a type name is used in some file, the same package to which this file belongs, takes precedence.
In this case, the top.e file probably didn't have any "package" statement, so it also belonged to package main.
If top.e had "package my_package", then "packet" in it would resolve to my_package::packet (and not to main::packet), and there would be no error.
You are allowed to have the same name for different structs, but they must be defined in different packages. In your case you first define packet in the my_package package. I'm guessing the other code you added was in some other file that did not have the line package my_package; in it. This means you defined another struct called packet in the main package. This effectively means that you have two different types: my_package::struct and main::struct. In main::packet you didn't define any foo() function (as you can see also from the error message). As Yuti mentions, in your top.e file you probably don't have a package declared, so the main package takes precedence over any other package.
As an exercise, if you change your code in top.e to my_package::packet instead of simply packet it's going to work. You can anyway see something is wrong from the error message. You know you expected my_package::packet, but you were creating a main::packet.
Have a look in the Specman e Language Reference, section 28, Encapsulation Constructs for more info on packages.
Related
I have code that produced a circular build error, and I looked up the error. This page gives a similar but smaller example of what's in my .mli file: https://ocaml.org/learn/tutorials/ocamlbuild/New_kinds_of_build_errors.html
Essentially the problem is that my file is both defining a type and defining functions that use arguments and return values of that same type. However, that's exactly what I want my program to do. My type is not private, it's declared explicitly in the .mli file:
type state = {
current_pos : int*int;
contents : int*int list;
}
val update_state : state -> state
It seems to me reasonable to want to build a module that defines a type and then to share that type with other files, but it seems like the circular build error will always prevent that. Is there some "more proper" way of doing this sharing?
There's nothing at all wrong with the code you posted. It compiles fine. So the problem is in your .ml file.
The page you point to shows code that is incorrect. The only point being made is that you'll get a different error if you use ocamlbuild than you would if you just compile the file directly.
The key point is that you should not use the name of a module inside the definition of the module.
Instead of this (in a.ml):
type t = int
let x : A.t = 14
You should have this:
type t = int
let x: t = 14
If your code is really like this example, you just need to remove the module names inside the .ml file.
As you say, what you want to do is by far the most common use of a module.
I'm unable to access a datatype declared in a separate .swift file.
Scenario:
I have two .swift files: a) envSwift.swift and b) mySwift.swift
'envSwift.swift' has my assorted data types, including an enum (which are defined as themselves, outside of any class):
mySwift.swift:
I'm getting the compiler error: "Use of unresolved identifier 'FKPermission'".
How do I use (refer to) a public datatype defined in a different .swift file?
Hint: when I do a copy/paste of enum FKPermission into the top of mySwift.swift & compile, I get the following compiler error: "Invalid redeclaration of 'FKPermission'"; even though I can't access it. So the original enum is detected, but 'unresolved'.
Although you say that both files are in the same target, maybe one of them is also in another target (e.g. your test target)?
That would be leading to exactly the errors you're describing:
1) the 'unresolved identifier' error (compiling the test target)
2) when copy/pasting the declarations - the 'redeclaration' error (compiling the main target).
So perhaps the solution is: add envSwift.swift to your test target, too.
I'm a bit confused about interfaces vs. signatures in OCaml.
From what I've read, interfaces (the .mli files) are what govern what values can be used/called by the other programs. Signature files look like they're exactly the same, except that they name it, so that you can create different implementations of the interface.
For example, if I want to create a module that is similar to a set in Java:
I'd have something like this:
the set.mli file:
type 'a set
val is_empty : 'a set -> bool
val ....
etc.
The signature file (setType.ml)
module type Set = sig
type 'a set
val is_empty : 'a set -> bool
val ...
etc.
end
and then an implementation would be another .ml file, such as SpecialSet.ml, which includes a struct that defines all the values and what they do.
module SpecialSet : Set
struct
...
I'm a bit confused as to what exactly the "signature" does, and what purpose it serves. Isn't it acting like a sort of interface? Why is both the .mli and .ml needed? The only difference in lines I see is that it names the module.
Am I misunderstanding this, or is there something else going on here?
OCaml's module system is tied into separate compilation (the pairs of .ml and .mli files). So each .ml file implicitly defines a module, each .mli file defines a signature, and if there is a corresponding .ml file that signature is applied to that module.
It is useful to have an explicit syntax to manipulate modules and interfaces to one's liking inside a .ml or .mli file. This allows signature constraints, as in S with type t = M.t.
Not least is the possibility it gives to define functors, modules parameterized by one or several modules: module F (X : S) = struct ... end. All these would be impossible if the only way to define a module or signature was as a file.
I am not sure how that answers your question, but I think the answer to your question is probably "yes, it is as simple as you think, and the system of having .mli files and explicit signatures inside files is redundant on your example. Manipulating modules and signatures inside a file allows more complicated tricks in addition to these simple things".
This question is old but maybe this is useful to someone:
A file named a.ml appears as a module A in the program...
The interface of the module a.ml can be written in file named a.mli
slide link
This is from the OCaml MOOC from Université Paris Diderot.
I'm trying to understand a specific thing about ocaml modules and their compilation:
am I forced to redeclare types already declared in a .mli inside the specific .ml implementations?
Just to give an example:
(* foo.mli *)
type foobar = Bool of bool | Float of float | Int of int
(* foo.ml *)
type baz = foobar option
This, according to my normal way of thinking about interfaces/implementations, should be ok but it says
Error: Unbound type constructor foobar
while trying to compile with
ocamlc -c foo.mli
ocamlc -c foo.ml
Of course the error disappears if I declare foobar inside foo.ml too but it seems a complex way since I have to keep things synched on every change.
Is there a way to avoid this redundancy or I'm forced to redeclare types every time?
Thanks in advance
OCaml tries to force you to separate the interface (.mli) from the implementation (.ml. Most of the time, this is a good thing; for values, you publish the type in the interface, and keep the code in the implementation. You could say that OCaml is enforcing a certain amount of abstraction (interfaces must be published; no code in interfaces).
For types, very often, the implementation is the same as the interface: both state that the type has a particular representation (and perhaps that the type declaration is generative). Here, there can be no abstraction, because the implementer doesn't have any information about the type that he doesn't want to publish. (The exception is basically when you declare an abstract type.)
One way to look at it is that the interface already contains enough information to write the implementation. Given the interface type foobar = Bool of bool | Float of float | Int of int, there is only one possible implementation. So don't write an implementation!
A common idiom is to have a module that is dedicated to type declarations, and make it have only a .mli. Since types don't depend on values, this module typically comes in very early in the dependency chain. Most compilation tools cope well with this; for example ocamldep will do the right thing. (This is one advantage over having only a .ml.)
The limitation of this approach is when you also need a few module definitions here and there. (A typical example is defining a type foo, then an OrderedFoo : Map.OrderedType module with type t = foo, then a further type declaration involving'a Map.Make(OrderedFoo).t.) These can't be put in interface files. Sometimes it's acceptable to break down your definitions into several chunks, first a bunch of types (types1.mli), then a module (mod1.mli and mod1.ml), then more types (types2.mli). Other times (for example if the definitions are recursive) you have to live with either a .ml without a .mli or duplication.
Yes, you are forced to redeclare types. The only ways around it that I know of are
Don't use a .mli file; just expose everything with no interface. Terrible idea.
Use a literate-programming tool or other preprocessor to avoid duplicating the interface declarations in the One True Source. For large projects, we do this in my group.
For small projects, we just duplicate type declarations. And grumble about it.
You can let ocamlc generate the mli file for you from the ml file:
ocamlc -i some.ml > some.mli
In general, yes, you are required to duplicate the types.
You can work around this, however, with Camlp4 and the pa_macro syntax extension (findlib package: camlp4.macro). It defines, among other things, and INCLUDE construct. You can use it to factor the common type definitions out into a separate file and include that file in both the .ml and .mli files. I haven't seen this done in a deployed OCaml project, however, so I don't know that it would qualify as recommended practice, but it is possible.
The literate programming solution, however, is cleaner IMO.
No, in the mli file, just say "type foobar". This will work.
How does function name scoping work across multiple C files?
I'm porting a standard gnu toolchain project to iPhone OS, and using Xcode to do it.
The code builds through make, but not through xcode. when building through xcode, the linker complains that the same symbol (function) is defined in two objects. the code has two distinct source files that #include a common file between them. While... odd (to me at least), it seems to work for the standard toolchain. any ideas if this is something that's somehow handled differently through a standard makefile?
All functions not marked static have global scope (they are dumped in a single namespace). Functions marked static are limited to the translation unit they are defined in.
You have a One Definition Rule violation.
One of your headers probably has a definition for a variable. E.g: in common.h you have
int foo = 42;
change it to:
extern int foo; // a declaration
and then create a common.c file where you put a definition:
int foo = 42;
In C, if I remember correctly, static function names are local to the source file in which they are defined, but all other function names exist in a global namespace. So if you have file1.c with
void fn1() {}
static void fn2() {}
and file2.c with
void fn1() {}
static void fn2() {}
and you tried to compile them with something like
cc file1.c file2.c
then you would get a name conflict between the fn1 in file1.c and the fn1 in file2.c, but not between the two fn2 functions (because they're static). (Of course, you'd get a bunch of other errors too because this program doesn't do anything, but those aren't relevant to scoping.)
If it compiles without errors from the Makefile, but not from your XCode project, it is most likely because the compiler's options are being set differently in the two environments. Check the Makefile to see what options are passed to 'gcc'. In particular, it's possible that the duplicate definitions are conditionally-compiled with #ifdef, and you may need to add some preprocessor definitions to your XCode project's settings.
My guess is that the common header defines an inline function that is resulting in a duplicate symbol. If that is the case, prefix those functions with a static inline, or define them as inline with an extern declaration in another .c file.