Will making a variable global solve the issue? - sml

Whenever I define a function say funct(n), then can I assign value of n to a different variable such as m so that I can compare value of n which changes within the function with the initial value of m. Further, since I have nested and sometimes independent other functions, is there a way to make the m variable universal?
What I did is:
fun funct(n)= let val m=n in if (condition) then...
Further, here funct calls funct1 and funct1 calls funct2. The error message reads
Error: unbound variable or constructor: m
for funct2
Error: unbound variable or constructor: funct1
for funct1
Error: unbound variable or constructor: funct1
for funct
I suppose the single correction of m would solve the wholse cascade of errors.

You can access any identifier from scopes which are deeper than the one the identifer has been defined in. E.g.
fun funct(n) =
let fun funct1(x, y, z) = if n < 1 then ...
...
In this example, funct1 has access to n, which has been defined in an outer scope (namely as a parameter of funct).
Be careful though, in functional languages like ML, identifiers have a different meaning from those in imperative languages like C. In your example, n and m are not variables, meaning the values denoted by the identifiers will not change. You can only redefine the identifiers; however, code that uses an identifier before its redefinition will always refer to the original value of that identifier.

Related

Fortran - Variable assignment and Declaration

I am trying to the assign value to a variable at the time of declaration and use that variable to declare the dimensions of some arrays as follows,
type (typ_A), intent (in) :: str_A
integer, parameter ::
x val_4 = (str_A%val_1 + str_A%val_2),
x val_5 = str_A%val_3
integer :: array_1(str_A%val_1, str_A%val_2), array_2(val_4, val_5)
In this code, the array_1 is declared properly with the expected sizes but the array_2 is not declared. Also, I am getting errors like "This symbol must be a defined parameter, an enumerator, or an argument of an inquiry function that evaluates to a compile-time constant."
Note - I can straight away use the expression of val_4 to declare array_2, but sometimes, the expression (str_A%val_1 + str_A%val_2 + ....) is very large and have to use it to define multiple arrays. Hence, for better readability and less number of lines, I want to put it in a variable (val_4 in this case)
A Fortran parameter must be computable at compile time, as the error message hints, and str_A%val_1 etc are not known at compile time.
You can't use a variable directly for this, but you can create a nested argument:
subroutine x (str_A)
type(whatever),intent(in)::str_A
call x_2 (str_A, str_A%val_1 + str_A%val_2)
contains
subroutine x_2 (str_A, mydim)
type(whatever),intent(in)::str_A
integer::mydim
integer:: ary1(mydim), ary2(mydim), ary3(mydim)
...
end subroutine x_2
end subroutine x
or if you can put at least the type and a helper function in a containing module you can do:
module t
type whatever ...
contains
pure function mydim(str_A)
integer::mydim
type(whatever),intent(in)::str_A
mydim = str_A%val_1 + str_A%val_2
end function mydim
subroutine y (str_A)
type(whatever),intent(in)::str_A
integer:: ary1(mydim(str_A)), ary2(mydim(str_A)), ary3(mydim(str_A))
...
end subroutine y
end module t
Added since you may not have considered/realized it:
Alternatively you could simply use ALLOCATABLE arrays instead; those can be allocated (not declared) with bounds computed by any runtime expression, including a local variable.
The answer of #dave_thompson_085 already answers the root for your problem.
A Fortran parameter must be computable at compile time
There are four possibilities to achieve the behaviour you want:
If you use the block statement you create a local, nested scope where you can declare new variables. You can then declare arrays that use runtime variables outside of the block for their shapes.
integer :: n
n = compute_at_runtime()
block
integer :: M(n)
! do something with M
end block
! M does not exist anymore
As #dave_thompson_085 also put it in his answer, you can use contained procedures with a local nested scope, to declare array with runtime variables that exist outside of the procedure.
Or you use allocatable for dynamic memory and automatic destruction/deallocation.
Or you use pointer for dynamic memory, but then you have to manually cleanup.

Expressions depending on integer type parameters in type definitions in Julia are not allowed

I want to define a type around a FixedSizeArrays.Vec{N,T} where N is a function of the type parameter:
using FixedSizeArrays
type MT{N}
x::Vec{N,Int}
y::Vec{N+1,Int}
end
This results in the error message:
ERROR: MethodError: `+` has no method matching +(::TypeVar, ::Int64)
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any...)
+(::Int64, ::Int64)
+(::Complex{Bool}, ::Real)
...
Apparently, simple arithmetic with integer type parameters is not allowed, even if the result can be known at compile time. Does anyone know of a workaround for this limitation?
Apparently, simple arithmetic for with integer type parameters is not allowed
Yes, this is a limitation with type parameters. The standard way around this is with a second type parameter. You can then enforce the parameter invariants with an inner constructor:
type MT{N,Np1}
x::Vec{N,Int}
y::Vec{Np1,Int}
function MT(x,y)
N+1==Np1 || throw(ArgumentError("mismatched lengths; y must be one element longer than x"))
new(x,y)
end
end
# Since we define an inner constructor, we must also provide the
# outer constructor to allow calling MT without parameters
MT{N,M}(x::Vec{N,Int}, y::Vec{M,Int}) = MT{N,M}(x,y)
Example:
julia> MT(Vec(1,2,3),Vec(1,2,3,4))
MT{3,4}(FixedSizeArrays.Vec{3,Int64}((1,2,3)),FixedSizeArrays.Vec{4,Int64}((1,2,3,4)))
julia> MT(Vec(1,2,3),Vec(1,2,3))
ERROR: ArgumentError: mismatched lengths; y must be one element longer than x

Return value from function with alternate entry

When a function has an alternate entry, is it necessary to set the return value for the entry name, or will the primary name always work if the alternate name is not set? For example,
INTEGER FUNCTION MYFUNC( ARG )
INTEGER ARG
INTEGER MYFUNC2
C ... do something here...
GOTO 100
ENTRY MYFUNC2( ARG )
C ... do something else here
100 CONTINUE
MYFUNC = <some value>
C .. is the next line needed, of can it be omitted?
myfunc2 = myfunc
RETURN
END
Citing the Fortran 2008 Standard, Cl. 12.6.2.6 ENTRY statement:
[...]
3 If the ENTRY statement is in a function subprogram, an additional
function is defined by that subprogram. The name of the function is
entry-name and the name of its result variable is result-name or is
entry-name if no result-name is provided.
[...]
If the characteristics of the result of the
function named in the ENTRY statement are the same as the
characteristics of the result of the function named in the FUNCTION
statement, their result variables identify the same variable, although
their names need not be the same. Otherwise, they are storage
associated and shall all be nonpointer, nonallocatable scalars that
are default integer, default real, double precision real, default
complex, or default logical.
The way I read the highlighted passage is that the line
myfunc2 = myfunc
is indeed not required since MYFUNC and MYFUNC2 are both scalar integers of the same kind.
Since no result is specified with either the function statement nor the entry statement, the function name becomes result-name. This is specified in Cl. 12.6.2.2 Function subprogram
[...]
4 If RESULT appears, the name of the result variable of the function
is result-name and all occurrences of the function name in
execution-part statements in its scope refer to the function itself.
If RESULT does not appear, the name of the result variable is
function-name and all occurrences of the function name in
execution-part statements in its scope are references to the result
variable. [...]

What is the purpose of result variables in Fortran?

In Fortran, there are two standard ways to return a result from a function. The first one is by assigning the return value of the function to the function name.
function foo()
integer :: foo
foo = 10
end function foo
The second form, standardized in Fortran 90 is through a "result" variable.
function foo result(res)
integer :: res
res = 10
end function foo
Calling either form of the function returns the value 10. My question is, what was the rationale of the Fortran 90 committee for introducing result variables? Were they standardizing a common practice? Or were they allowing programs to be more modular by not tying the function name to a function result. For example, in the second version of foo(), the name of the function foo() could be changed to bar() and the function would still work as expected when called.
However, I may be wrong. Does anyone know what the actual rationale was for introducing result variables?
Introduced at the same time as the result was recursion. Before we get to how a recursive function comes about, some clarification on what a result variable is.
The function result is always returned through a result variable, whether result is used or not.1 With result the result variable has the name specified, and without it the result variable has the same name as the function. In this latter case use of the name is a reference to the result variable and not the function.
So, if the function foo has result variable foo then we can't do direct recursion:
recursive function foo(n)
foo = foo(n-1) ! Oh dear
end function
result comes about so that we can have
recursive function foo(n) result(res)
res = foo(n-1) ! Yay
end function
[1] Well, this is true up until Fortran 2008, when the definition of variable changed. For modern Fortran use instead the term function result.

No viable overloaded

I have 2 classes CVKinectWrapper.cpp and main.cpp. In the CVKinectWrapper, in the bool CVKinectWrapper::update(){ ... i have a variable XnSkeletonJointPosition righthand; I would like to access this variable in the main.cpp class. therefor i have created a
`void CVKinectWrapper::getRightHand(XnSkeletonJointPosition *righthand){
//*righthand = righthand;
righthand->copyTo(*righthand);
}`
The direct assignment doesn't work, i get this error = 'No match for 'operator=' in*righthand=righthand'.
The copyTo doesnt work because the datatype of righthand hasn't got this method.
For extra info :
This is how i access the wrapper in the main class = CVKinectWrapper *wrapper = CVKinectWrapper::getInstance();
wrapper->getRightHand(XnSkeletonJointPosition *righthand)
My question now is how can i access the righthand variable from the CVKinectWrapper in the main class.
This is probably a very basic question but i'm rather new to c++.
Thanks in advance.
When asking about compiler errors, it is usually a good idea to provide the exact error message, which in this case it probably states what the types of the two arguments are. At any rate, I think I can guess what the problems are.
You mention that you have a variable named righthand, which I assume is actually a member of the class, and you want to copy the value to a different variable passed to the function getRightHand. Now the problem is that the argument of the function has the same name as the member, and it is shadowing it. Inside getRightHand, the identifier righthand refers to the argument, not to the member. You can solve this by either changing the name of the argument or qualifying the access to the member: *righthand = this->righthand;
As of the particular error message, the operation *righthand = righthand; literally means assign the value of the pointer righthand (argument to the function) to the object that it points, which does not make much sense. From a design point of view, the function as it is is quite un-idiomatic in C++, and should probably be replaced by:
const XnSkeletonJointPosition& CVKinectWrapper::getRightHand() const {
return righthand;
}
And the caller would do:
XnSkeletonJointPosition res = wrapper.getRightHand();