Nested allocatable components [duplicate] - object

Consider the following code:
subroutine tao_show_this ()
implicit none
type b_struct
integer, pointer :: good_user => null()
end type
type a_struct
type (b_struct), allocatable :: value_ptr(:)
end type
type (a_struct) a
a = a_struct()
end subroutine
Compiling with gfortran 5 or 7 gives:
gfortran -c test.f90
test.f90:4:13:
type b_struct
1
Error: The rank of the element in the structure constructor at (1) does not match that of the component (0/1)
This code compiles fine with ifort. Is this a gfortran bug or is there something wrong with my code?

For a default structure constructor, being able to omit the value for an allocatable component is a feature introduced in Fortran 2008.
gfortran does not currently support this feature ("Unimplemented features").
To leave the component not allocated while still giving a value to the constructor one references null:
a = a_struct(NULL())
As DavidS comments, this exists as a reported bug.

Related

What instance of `Num` is used with literals e.g. in `print 1`?

I've just used haskell as calculator expecting to get some cryptic error message about ambiguity of the type instance of the numeric literal. But got none.
For example in ghci
> :t 1
1 :: Num p => p
> print 1
1
It seems crazy that I expect code like print 1 to break xD. But here ghci needs to use some implementation of Show class. Also the 1 is represented in some way in runtime. What representation is used and why doesn't it ask me to specify the type?
Simmilar example:
> 7*15+2
107
The expression has general Num a => a type but is calculated and for that some type needs to be chosen. Is it Integer? This behaviour of course makes sense but how does it work?
Typing e.g. print $ 5 ^ 5 ^ 5 (outside of Int range) prints the correct number so I guess that it is Integer rather than Int.
I haven't found any general Num a => Show a instance, rather the implementations for types like Int are specific to them.
I've tested with ghc in versions 8.8.4, 7.10.3 and 9.0.2. Thanks in advance!
Haskell has a type defaulting mechanism to avoid having to specify the type of every numeric literal you type. The default type for Num is Integer, while for Fractional (literals with a decimal point) it is Double. You can change these defaults using a top level default declaration. This article explains the defaulting rules
The expression has general Num a => a type but is calculated and for that some type needs to be chosen. Is it Integer? This behaviour of course makes sense but how does it work?
Haskell works with type defaulting and the default for a Num a => a type is indeed Integer. Since Integer is also a member of the Show typeclass, it will thus still use Integer and print $ 5 ^ 5 ^ 5 will thus indeed use the Integer instance of Show to print the value.
The default default is (Integer, Double). More info in the Report. You may also want to read about ExtendedDefaultRules; notably this is on by default in ghci.

Binary Search algorithm random array

I don't understand why the recursive function always gives me zero result, even if I put values inside the array.
it seems that size (a) == 0
recursive function binarySearch_R (a, value) result (bsresult)
real, intent(in) :: a(6), value
integer :: bsresult, mid
mid = size(a)/2 + 1
if (size(a) == 0) then
bsresult = 0 ! not found
else if (a(mid) > value) then
bsresult= binarySearch_R(a(:mid-1), value)
else if (a(mid) < value) then
bsresult = binarySearch_R(a(mid+1:), value)
if (bsresult /= 0) then
bsresult = mid + bsresult
end if
else
bsresult = mid ! SUCCESS!!
end if
end function binarySearch_R
program hji
read*, a
read*, value
print*, binarySearch_R
end program hji
Chapter 1: The dangers of implicit typing
The first thing I strongly recommend you do is to include the line
implicit none
after the program line. This will suppress implicit typing, and the resulting errors will give you some useful insight into what is happening.
If you did that, you'd get an error message:
$ gfortran -o binsearch binsearch.f90
binsearch.f90:23:12:
read*, a
1
Error: Symbol ‘a’ at (1) has no IMPLICIT type
binsearch.f90:27:25:
print*,binarySearch_R
1
Error: Symbol ‘binarysearch_r’ at (1) has no IMPLICIT type
binsearch.f90:24:16:
read*, value
1
Error: Symbol ‘value’ at (1) has no IMPLICIT type
It doesn't matter that a, value, and binarySearch_R were defined in the function. As the function is not part of the program block, the program doesn't know what these are.
With implicit typing active, it simply assumed that all three are simple real variables. (The type depends on the first letter of the variable name, i through n are integer, everything else is real)
Because this implicit typing can so easily hide coding errors, it's strongly, strongly suggested to always switch it off.
Which also means that we have to declare the variables a and value in the program:
program hji
implicit none
real :: a(6), value
...
end program hji
Chapter 2: How to introduce a function to the program?
So how does the program get access to the function? There are four ways:
The best way: Use a module
module mod_binsearch
implicit none
contains
recursive function binarySearch_R (a, value) result (bsresult)
...
end function binarySearch_R
end module mod_binsearch
program hji
use mod_binsearch
implicit none
real :: a(6), value
...
end program hji
Note that the use statement has to be before the implicit none.
This method leaves the function separate, but callable.
It automatically checks that the parameters (that's something we'll be coming to in a bit) are correct.
Have the function contained in the program.
Between the final line of code of the program and the end program statement, add the keyword contains, followed by the function code (everything from recursive function ... to end function ...).
This is the quick-and-dirty method. You have to be careful with this method as the function will automatically have access to the program's variables unless there's a new variable with that name declared inside the function.
The convoluted way: Interfaces
Create an interface block in the declaration section of your program's source code,
and repeat the interface information in there.
This still allows the compiler to check whether the function is invoked correctly, but it's up to you to ensure that this interface block is correct and matches the actual implementation.
The really, really ugly way: Declare it like a variable, invoke it like a function.
Please don't do that.
Chapter 3: Calling a function
When you call a function, you have to use the parentheses and give it all the parameters that it expects. In your case, you need to type
print *, binarySearch_r(a, value)
Chapter 4: Dynamic arrays as dummy parameters
In the successive recursive calls to the function, the array gets smaller and smaller.
But the dummy parameter is always the same size (6). Not only will this interfere with your algorithm, but this can also lead to dangerously undefined memory access.
Fortunately, specially for intent(in) dummy parameters, you can use dynamic arrays:
recursive function binarySearch_R(a, value)
real, intent(in) :: a(:), value
The single colon tells the compiler to expect a one-dimensional array, but not the length of it. Since you're already using size(a), it should automatically work.
Too long for a comment, but not an answer (and to any Fortran experts reading this, yes, there are one or two places where I gloss over some details because I think they are unimportant at this stage) ...
The way the code is written does not allow the compiler to help you. As far as the compiler is concerned there is no connection between the function and the program. As far as the program is concerned a is, because you haven't told the compiler otherwise, assumed to be a real scalar value. The a in the program is not the same thing as the a in the function - there is no connection between the function and the program.
The same is true for value.
The same is true for binarysearch_r - and if you don't believe this delete the function definition from the source code and recompile the program.
So, what must you do to fix the code ?
First step: modify your source code so that it looks like this:
program hji
... program code goes here ...
contains
recursive function binarySearch_R (a, value) result (bsresult)
... function code goes here ...
end function binarySearch_R
end program hji
This first step allows the compiler to see the connection between the program and the function.
Second step: insert the line implicit none immediately after the line program hji. This second step allows the compiler to spot any errors you make with the types (real or integer, etc) and ranks (scalar, array, etc) of the variables you declare.
Third step: recompile and start dealing with the errors the compiler identifies. One of them will be that you do not pass the arguments to the function so the line
print*, binarySearch_R
in the program will have to change to
print*, binarySearch_R(a, value)

Fortran: Initialize character string with unknown length in main program

I have a character string I would like to initialize with intent(out) data from a subroutine call. I kind of looks like that:
character(*) :: path
call get_path(path)
The compiler tells me:
Error: Entity with assumed character length at (1) must be a dummy
argument or a PARAMETER
The construct works just fine in a subroutine but fails in the main program. Is it possible to initialize the path variable without knowing its length?
EDIT: Stuff I already tried but failed.
character(99) :: path_temp
character(:), allocatable :: path
call get_path(path_temp)
allocate(path(len(trim(path_temp))))
Error: Shape specification for allocatable scalar at (1)
I don't get why the compiler thinks path is a scalar.
A function that returns a character with assumed length apparently is illegal.
character(*) function get_path ()
get_path = '/path/to/folder/'
end function get_path
Error: Character-valued module procedure 'get_path' at (1) must not be assumed length
What works but gives me a headache because I find it very bad style is to give path an insane length and trim it every time it's used. I think my compiler is having trouble with allocatable character strings because it isn't quite up to date (mpif90). Not sure if it supports them.
Many of the points are covered in other answers linked by comments, such as what "assumed length" requires and how to allocate the scalar deferred length character variable.
I'll point out two things, before coming to an particular answer.
Intrinsic assignment to a deferred length allocatable scalar character variable results in (if required) allocation of that variable to the length of the expression. That is
character(99) :: path_temp
character(:), allocatable :: path
call get_path(path_temp)
allocate(character(len(trim(path_temp))) :: path) ! Note the correct form
path = TRIM(path_temp) ! Or path(:)=path_temp
can be replaced by
character(99) :: path_temp
character(:), allocatable :: path
call get_path(path_temp)
path = TRIM(path_temp)
The other thing to note is quite pedantic, but using the terminology incorrectly may hinder searching. Initialization in Fortran means something specific which isn't applicable here.
You say that a function with an assumed length character result is apparently illegal, based on the compiler error message
Error: Character-valued module procedure 'get_path' at (1) must not be assumed length
That isn't entirely true: character function results can (currently - it's an obsolescent feature of modern Fortran) be of assumed length in some circumstances. They must, though, be external functions. See that the compiler complains about a module procedure (which then isn't external).
That said, having an assumed length character result doesn't help you. The length of the result still has to be assumed from something, and that something isn't in the function body, but a declaration that defines the external function in a scope.
Something like
implicit none
character(99) get_path ! The length of the get_path result is assumed from here
character(:), allocatable :: path
path = TRIM(get_path())
...
As you seem to have complete control over the subroutine get_path, there's the final answer-worthy comment to make. You could directly have the argument allocatable.
subroutine get_path(path)
character(:), allocatable, intent(out) :: path
path = '/path/to/folder/' ! Allocation through intrinsic assignment
path = TRIM(path) ! In general, if it's likely to have trailing blanks
end subroutine

Why does GHC only warn on partial implemented classes, and not error?

I think the title is already self explanatory, but here's an example anyway to show my point:
class Foo a where
someFunction :: a -> a -> Bool
instance Foo Bool
When I compile this the compiler gives a warning:
Warning:
No explicit method or default declaration for `someFunction'
in the instance declaration for `Foo Bool'
Calling the function will now result in a runtime error. Why is this a warning, and not a compile-time error? And is there any way to make this a compile-time error instead?
The GHC documentation provides an example where a warning is sufficient:
-fwarn-missing-methods:
This option is on by default, and warns you whenever an instance declaration is missing one or more methods, and the corresponding class declaration has no default declaration for them.
The warning is suppressed if the method name begins with an underscore.
Here's an example where this is useful:
class C a where
_simpleFn :: a -> String
complexFn :: a -> a -> String
complexFn x y = ... _simpleFn ...
The idea is that: (a) users of the class will only call complexFn; never _simpleFn; and (b) instance declarations can define either complexFn or _simpleFn.
The MINIMAL pragma can be used to change which combination of methods will be required for instances of a particular class. See Section 7.20.5, “MINIMAL pragma”.
That's the reason missing methods don't result in an error, but a warning. If you want to make warnings fatal, use -Werror. Since there is no -ferr-missing-methods, -Werror is the only way to make -fwarn-missing-methods a compiler error.

Unable to get/set a stringArray with the hackage COM package in Haskell

I'm using the IDL compiler Hdirect and the latest com package on hackage.
I'm using GHC 7.4.1.
I want to communicate with Clearcase (version 7).
I'm able to do all kind of operations (getting element, version, label, ...)
BUT if I try to lock a label, I shall give an StringArray variant as argument.
My code looks like this:
ccLab # createLockCCLT "" (0::Int) [""]
ccLab is my label and [""] is my attempt to provide a StringArray.
The code compiles fine but I get a run-time error:
list method not implemented ...
createLockCCLT method is generated by Hdirect:
-- Locks this label type
createLockCCLT :: (Variant a1, Variant a2, Variant a3)`
=> a1
-> a2
-> a3
-> ICCLabelType a0
-> IO ()
createLockCCLT comment obsolete exemptUsersStringArray =
method0 "CreateLock"
[ inDefaultValue (inVariant "") inVariant comment
, inDefaultValue (inInt32 0) inVariant obsolete
, inVariant exemptUsersStringArray
]
I already try to build a safe array myself but without success.
It seems as well a list is not a good candidate because a variant array
is able to contain elements of different types.
Has someone an idea ?

Resources