Why I can't define a function in the `lib` scope? - crystal-lang

For example, this code won't compile
def double
x * x
end
lib LibC
# Error
def double
x * x
end
end
I know that we can use module, but we can't have the same LibC name as both module and lib
lib LibC
end
module LibC
def double
x * x
end
end
Is there any solution for this problem?

Why is this a problem for you? :)
lib defines a binding to an external library. Technically it does so by defining function signatures of external symbols that the linker will resolve. Additionally it allows the definition of structs with C ABI semantics, enums for mapping a series of constants used in an external library interface into a useful grouping and aliases to make it easier to map Crystal types to C types in a binding definition.
When binding a library, this lowlevel lib definition should never be the end result for the user of your binding! Instead you should define at least a thin wrapper transforming the external API into a more idiomatic Crystal version.
So say we're writing a binding to the fictional libsaucepan you would start out with a lib definition, maybe like this:
#[Link("saucepan")]
lib LibSaucepan
alias Pan = Void*
fun aquire : Pan
fun add_water(pan : Pan, ml : LibC::Int)
fun cook(pan : Pan)
fun is_done(pan : Pan) : LibC::Int
end
You wouldn't stop here, but maybe create a class that wraps the API:
class Saucepan
def initialize
#pan = LibSaucepan.aquire
end
def add_water(ml : Int)
LibSaucepan.add_water(#pan, LibC::Int.new(ml))
end
def done?
LibSaucepan.is_done(#pan) == 1
end
def cook
LibSaucepan.cook(#pan)
until done?
sleep 1
end
end
def heat_water(ml : Int)
add_water(ml)
cook
end
end
This wrapper is where you would put any helper methods :)

Related

Are interface blocks ever required to compile Fortran?

I'm trying to teach myself Fortran, and have been messing around with linking multiple files together. Following examples, I have been writing programs in one file, functions in another, and using interface blocks in my main program to refer to the external function.
I was testing how much information was needed in the interface block and realised that I can remove it entirely.
My program:
program test
implicit none
real :: x, y, func
x = 3
y = func(x)
print *, y
end program test
And the function file:
function func(x)
implicit none
real :: x, func
func = x**3
end function func
I then compile it using gfortran -o test test.f90 func.f90 and the code works as expected. My question is, why do I not need to include an interface block in my program file? Is it simply a matter of good practice, or does defining func as a real variable serve as shorthand? I am on Windows, having installed gfortran through minGW.
As an aside/related question, if I instead use a subroutine:
subroutine func(x,y)
implicit none
real :: x,y
y = x**3
end subroutine func
And change the line y = func(x) to call func(x,y) then the code will work fine without any interface block or declaration. Why is this?
The declaration real :: func in the main program here declares func to be a function with (default) real result. This function has an interface in the main program as a result, so it is legitimate to reference that function with y = func(x).
The interface in this case is implicit. In this way, the main program knows exactly three things about func:
it is a function (with that name);
it has the external attribute;
it has real result.
The reference to the function is compatible with that knowledge. Further, how you reference the function matches precisely the properties of the function itself.
Equally, in the case of the subroutine, a call func(x,y) tells the main program exactly three things, again with the implicit interface:
it is a subroutine (with that name);
it has the external attribute;
it takes two real arguments.
Those three things again match the subroutine's definition, so things are fine.
Loosely, then, you don't need an interface block in these cases because the implicit interfaces are good enough.
There are times when an explicit interface is required and in most (nearly all) cases an explicit interface is better. As you can see in other questions and answers, there are usually better ways to provide an explicit interface than using an interface block.
Why do I not need to include an interface block in my program file?
Since Fortran 90, the recommended way to define reusable functions and subroutines is to use modules.
module func_m
contains
function func(x)
implicit none
real :: x, func
func = x**3
end function func
end module func_m
Then write use func_m in the main program, before implicit none: gfortran -c func_m.f90, gfortran -c test.f90 and gfortran -o test test.o func_m.o.
When you use modules, the compiler will check the type of the arguments of the functions. You also do not need to declare real :: func as the declarations are taken from the module.
When you compile as a "simple" object file, the compiler will simply call whatever function is named func without verification, as long as such a function is given in an object file.
The interface block is a kind of "in between". In your case, you could add one in the program file. This would force you to follow that declaration in the program. But it will not prevent linking to wrong functions at link time: there is no guarantee that the interface is right. It is mostly useful if you need to call C or FORTRAN 77 code from someone else, for which you couldn't use modules.
And change the line y = func(x) to call func(x,y) then the code will
work fine without any interface block or declaration. Why is this?
The interface issue is orthogonal to the function vs subroutine issue.
There are some cases where interface blocks are needed. For example if the called subroutine uses a pointer, allocatable or assumed shape arrays (this list is not complete, see the standard for more):
integer, pointer :: x(:,:) ! pointer attribute
integer, allocatable :: x(:,:) ! pointer attribute
integer :: a(:,:) ! assumed shape array
The pointer/allocatable have the advantage that the called subroutine can allocate it for the calling function. Assumed shape arrays automatically transfer the dimensions to the called subroutine.
If you use any of this your program will crash without explicit interface. Easiest solution is like said in the other answer: use modules to have the interface automtically correct. We use a perl script automatically extracting interfaces to have interface check without rewriting the code to modules (and avoid long compile times until all compilers reliably support Fortran 2008 submodules...)

Module dependency cycle

I have:
Module 1:
provides type Module1.type1, its constructor, and some functions that accept and return type1
Module 2:
open Module1
open Module3
provides type Module2.type2, also has functions that accept type1 and type3 as params
Module 3:
open Module1
open Module2
provides type Module3.type3, and its constructor that depends on type1
provides functions that accept and return types type1, type2 and type3
question
as a result I obviously get dependency cycle: src/Module3.cmj -> src/Module2.cmj -> src/Module3.cmj error by compiler. Something that is trivially achievable in TypeScript/JS with individual import, is not possible in Reason. How to get around this?
I don't really want to change the architecture of my program, just to facilitate shortcomings of compiler/module system.
The simplest way to handle your problem is indeed recursive modules. I don't advise you to use them, as recursive modules can make your code harder to read, compile and can in the most complex cases break your code at run time. Not to mention if you use side-effects in your module definitions (please don't).
I will use the OCaml syntax, you should be able to easily translate to Reason.
If you want to go with that anyway, here is the quick and dirty solution, using recursive module and functors.
The quick and dirty solution
1) Create a module myModTypes that will indicate the expected types of module2 and module3. It should look like:
module type Module2type = sig ... end
module type Module3type = sig ... end
with ... being the expected signatures of your modules (if you already have interface files written, just copy/paste them here, if you don't write those, they are important)
2) Put module2 and module3 within functors expecting the other module
For example, the code of module2 should now look like
module MakeModule2(Module3 : MyModTypes.Module3type) = struct
(* the code of module2 *)
end
The code of module3 will be in the same way, just swap 2 and 3 in the added lines.
3) Create a module makemodules2and3 with that code (translated to Reason):
module rec Module2 : MyModTypes.Module2type = Module2.MakeModule2(Module3)
and Module3 : MyModTypes.Module3type = Module3.MakeModule3(Module2)
Note that recursive module definitions always expect a module type.
4) Subsequent uses of Module2 and Module3 should now open Makemodules2and3 before being able to use them.
The right solution
You have to change the architecture of your program. Slightly.
As the OP said, there are no cycle of dependency in the functions, and that's a relief. Just split module2 and module3 into two new modules each. One with the functions that only depend on module1 and their own module, one with the "next step" functions.
This is a better way to approach how you declare your modules: they should be one with the types they define. Ideally, you have a module for each type, plus one additional module for each interaction between types.
Looks like Module1 doesn't depend on the other two modules. You can keep it as is. But since the other two are mutually recursive, you can express that using the recursive module syntax. This does have a requirement though that you declare the module signatures at the point of definition, since Reason needs to know what to expect. For example:
/* Impl.re */
module rec Module2: {
type type2;
let make: (Module1.type1, Module3.type3) => type2;
} = {
... actual implementation of Module2 ...
} and Module3: {
type type3;
let make: Module1.type1 => type3;
let foo: Module1.type1;
let bar: Module2.type2 => type3;
} = {
... actual implementation of Module3 ...
};
This is the general shape you'd use, you can adapt it to your needs.
If you don't want your users to have to do Impl.Module2.... to access the recursive modules, you can even expose them as file modules using include:
/* Module2.re */
include Impl.Module2;
And you can even annotate the implementation modules (Impl.Module2 and 3) with a compile-time warning to let users know not to use those ones:
/* Impl.re */
[#deprecated "Please use Module2 instead of Impl.Module2"]
module Module2: {...} = {...};

Resolve library conflict in SML/NJ Compilation Manager

I'm using SML/NJ 110.79, which includes support for new structures defined by the Successor ML project. Among others, the Fn structure.
As it happens, I already had an identically named structure in one of my personal project with utilities, which worked fine before 110.79.
With 110.79, for this .cm file:
group is
$/basis.cm
$SMACKAGE/sml-extras/v0.1.0/sources.sml.cm
I get the following error, though:
sources.cm:3.3-3.45 Error: structure Fn imported from
$SMLNJ-BASIS/(basis.cm):basis-common.cm#155252(fn.sml) and also from
$SMACKAGE/sml-extras/v0.1.0/(sources.sml.cm):src/fn.sml
Does anyone know how to resolve this conflict through the Compilation Manager. Ideally, my Fn structure will be able to "extend" the standard Fn by just open-ing it, but projects using the sml-extras library, will not see the standard Fn structure, only my extended version.
Is this possible? Do I need to wrap/re-export the whole basis.cm library in my sml-extras.cm project?
I managed to solve this by using what I believe is called an administrative library in the CM manual, §2.9.
What that means precisely is to create an auxiliary .cm file that wraps the basis library and re-exports only the symbols we're interested in.
sources.cm
This is the main project file.
library
structure Main
is
(* Let's say this library redefines the Fn and Ref structures *)
(* and the REF signature. *)
$SMACKAGE/sml-extras/v0.1.0/sources.sml.cm
(* This excludes out Fn, Ref and REF from the Basis library, but *)
(* imports anything else. *)
amended-basis.cm
main.sml
amended-basis.cm
This file imports $/basis.cm and then re-exports all of it except Fn, Ref and REF.
group
library($/basis.cm) - (
structure Fn
structure Ref
signature REF
)
is
$/basis.cm
main.sml
structure Main =
struct
open Fn (* sml-extras's Fn *)
end
The solution is based on the set calculus described in the CM manual, §4 and on the EBNF grammar from Appendix A.
Another solution would have been to change sml-extras to re-export the whole $/basis.cm, while shadowing the conflicting symbols. However, in the interest of modularity I decided to go with the solution detailed above.

Functors in OCaml: triple code duplication necessary?

I'd like to clarify one point: currently it seems to me that triple signature duplication is necessary while declaring a functor, provided we export it in the .mli file. Here is an example:
Suppose we have a functor Make, which produces a module A parametrized by SigA (simplest example I could think of). Consequently, in the .mli file we have:
module type A = sig
type a
val identity : a -> a
end
module type SigA = sig
type a
end
module Make (MA:SigA) :
A with type a := MA.a
Now I understand that we have to write an implementation in the .ml file:
module Make (MA:SigA) = struct
type a = MA.a
let identity obj = obj
end
So far so good, right? No! Turns out we have to copy the declaration of A and SigA verbatim into the .ml file:
module type A = sig
type a
val identity : a -> a
end
module type SigA = sig
type a
end
module Make (MA:SigA) = struct
type a = MA.a
let identity obj = obj
end
While I (vaguely) understand the rationale behind copying SigA (after all, it is mentioned in the source code), copying A definition seems like a completely pointless exercise to me.
I've had a brief look through the Core codebase, and they just seem to either duplicate it for small modules and for larger once they export it to the separate .mli, which is used both from .ml and .mli.
So is it just a state of affairs? Is everyone fine with copying the module signature THREE times (once in the .mli file, two times in the .ml file: declaration and the definition!!)
Currently I'm considering just ditching .mli files altogether and restricting the modules export using signatures in the .ml files.
EDIT: yes I know that I can avoid this problem by declaring the interface for A inline inside Make in the .mli file. However this doesn't help me if I want to use that interface from outside of that module.
That's because a pair of ML and MLI file acts like a structure and a corresponding signature it is matched against.
The usual way to avoid writing out the module type twice is to define it in a separate ML file. For example,
(* sig.ml *)
module type A = sig
type a
end
module type B = sig
type b
val identity : b -> b
end
(* make.mli *)
module Make (A : Sig.A) : Sig.B with type b = A.a
(* make.ml *)
module Make (A : Sig.A) =
struct
type b = A.a
let identity x = x
end
It is fine to leave out an MLI file in the case where it does not hide anything, like for the Sig module above.
In other cases, writing out the signature separately from the implementation is a feature, and not really duplication -- it defines the export of a module, and usually, that is a small subset of what's in the implementation.

Making multiple modules from multiple common blocks fortran 77

Currently in my program I have several common blocks spread across several subprograms and functions. I sometimes forget to change all instances of a common block as I add variables to it. I want to make these common blocks into modules so I can add and remove variables to the module in one place without worrying about updating all instances of the module across my subprograms.
Do I need to include 'use' statements in the program that initializes the variables in the module or do I include the program in the module? I normally would use common blocks for this but am trying to implement modules because I think they will help my code remain readable as complexity increases.
NOTE: Some values of the variables in the modules need to be able to change as they are passed from one program to another.
I tried to write a simplified test program to become acquainted with modules but could not get it to work. I am familiar with fortran 77 but have never used modules before. I appreciate any help or advice.
I am using gfortran 4.6.1
Main.f
program main
use Words
use Vals
double precision x,y,z
character*5 Greet
integer i
Greet = 'Hello'
x = 4.1
y = 5.2
z = 10.0
i = 3
call foo ()
end program main
subroutine foo ()
use Words
use Vals
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
module Words
character*5 Greet
save
end module
module Vals
double precision x,y
integer int
save
end module
You only need one instance of a module. You make it known to any main program or procedure (subroutine or function) that uses it with a use statement. If you have a subroutine that sets values then, like any other, it has to have a use statement. If are are setting initial values you can do so in the declaration. If the module is used by the main program then it will always be in scope and the values of the variables will persist throughout the run of the program. If the module is only used by procedure, in principle the module will go out of scope when none of those procedures are in the call chain and the compiler is allowed to forget the values of the module variables. (It is doubtful that any Fortran compiler actually does this.) This can be prevented by declaring each variable with SAVE. SAVE is implicit if you declare the variable with an initial value.
Normally you have to compile the modules first before they are used so that the compiler "knows" about them when it encounters the use statement. This is done either by putting them first in the file or compiling their files first. Here is your example reordered:
module Words
character*5 Greet
save
end module
module Vals
double precision x,y
integer i
save
end module
module my_subs
contains
subroutine foo ()
use Words
use Vals
double precision :: z
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
end module my_subs
program main
use Words
use Vals
use my_subs
Greet = 'Hello'
x = 4.1
y = 5.2
i = 3
call foo ()
end program main
There are a couple of reasons why your code will not compile:
You have your modules positioned after your main program, which means they will not have been compiled by the time you use them there. Either put these in separate files and compile them before the main program, or put them before the main program.
You re-declare variables from your module in the main program, which the compiler will interpret as a name conflict. All module variables with the public attribute (which is the default) will become available in the scope where you use the module; this is called "use association". In other words, use vals is enough to make x, y and int available.
Additionally, modules are more like singleton objects rather than just data containers. They can also contain procedures, listed after a contains statement, which aids grouping variables and related procedures together. An example would be grouping your two modules into one, along with subroutine foo:
module vals
implicit none
double precision :: x = 4.1, y = 5.2
integer :: i = 3
character(5) :: greet = 'Hello'
contains
subroutine foo()
double precision :: z ! New local variable
print *, Greet
z = x + y
print *, z
print *, i
end subroutine
end module
Above, I have used the "new" :: double colon operator, which allows declaring and initialising multiple variables at once. Since module variables are already save'd implicitly, this is just fine.
Alternatively, if these modules are intended to be separate, you can also have contains sections in your main program (or any subprogram) and place the subroutine there. The advantage is that procedures declared in such a way always have explicit interfaces, which greatly benefits error diagnosis by the compiler and is even required in certain newer cases. This is one of the main improvements of F90, since F77 only dealt with external subprograms and implicit interfaces.
The simplest way to do common blocks is to have one include file per common block and make all your declarations within the include file. That way, the common block is only ever declared in one place. The problem of having to convert the code to use modules then just magically disappears.
Also, if you are starting new code, prefixing the name of the common block variables with the same name as the named common block will make coding a lot easier. It is a pain initially and the prima donnas who have been coding for years will refuse to conform. The people who maintain the code will just find it so easy: no greps or groks. Just by looking at the name, you know which common block it comes from.
Keeping the same convention with modules also helps. If all routine names and variable names begin with the module name, then just by looking at the name, you know which module it comes from.