I have this question about passing methods and I want to make sure I understand it correctly
What is the value of i and array a if arguments are passed by
a value
b reference
c value/result
asseume we have the following pseudocode
this is my answer
By value
i = 1
a[1]=10
a[2]=11
by reference
i = 3
a[1] = 2
a[2] = 11
by value result
i = 2
a[1] = 10
a[2] = 1
is this correct ? thanks
First of all, when you call a function (or procedure, whatever you name it), a new call stack is created. On that call stack, the parameters are assigned to values (parameters are the ones which is part of your function signature. Usually we call them 'formal parameters', like the x y z in your above procedure f). What they are assigned to is according to the actual arguments by which the function is invoked.
If they are passed by values, the formal parameters are assign to the values of the arguments. That means, the values of the actual arguments are copied to the formal parameters. Any further operations on the formal parameters does not affect the argument at all. In your example, y is assigned to the value of a[1], which is 10. In the function's body, y is reassigned, but nothing happened to a[1] anymore.
If they are passed by reference, on the other hand, the formal parameters are assigned to the memory address of the actual arguments, and in the function's body, the formal parameters are implicitly dereferenced to the values of that memory address. In your example, x will hold the memory address of i, y for a[1] and z for i as well. Operation on x y z are actually operation on i and a[1].
I don't know what you mean by "passed by value result". I have never seen such terms elsewhere.
Another thing I want to mention is, there are two distinct meanings of "reference" in the programming world. There will be no time for me to give a long explanation. You may search for "reference type in Java" and "reference variables in C++" to see the difference.
Related
i see that fix documentation says:
http://www.minizinc.org/doc-lib/doc-builtins-reflect.html#Ifunction-dd-T-cl-fix-po-var-opt-dd-T-cl-x-pc
function array [$U] of $T: fix(array [$U] of var opt $T: x)
Check if the value of every element of the array x is fixedat this point in evaluation. If all are fixed, return an array of their values, otherwise abort.
I am thinking it can be used to coerce a var to a par.
Here is the code.
array [1..num] of var int: value ;
%% generate random numbers from 0..num-1, this should fix the value of the var "value" or so i think
constraint forall(i in index_set(value))(let {int:temp_value=discrete_distribution([1|i in index_set(value)]); } in value[i]=trace(show(temp_value)++"\n", temp_value));
%%% this i was expecting to work, as "value" elements are fixed above
array [1..num] of int:value__ =[ trace(show(fix(value[i])), fix(value[i])) | i in index_set(value)] ;
But i get:
MiniZinc: evaluation error:
with i = 1
in call 'trace'
in call 'fix'
expression is not fixed
My questions are:
1) I think i should expect this error as minizinc is not sequential execution language?
2) Examples of fix in user guide is only where output statement is used. Is it the only place to use fix?
3) How would i coerce a var to a par?
By the way I am trying this var to par conversion because i am having problem with array generator expression. Here is the code
int:num__=200;
int:seed=134;
int: two_m=2097184;
%% prepare weights for generating numbers form 1..(two_m div 64), basically same weight
array [1..(two_m div 64)] of int: value_6_wt= [seed+1 | i in 1..(two_m div 64)] ;
%% generate numbers. this dose not work gives out
%% in variable declaration for 'value6'
%% parameter value out of range
array [1..num__] of int : value6 = [ discrete_distribution(value_6_wt) | j in 1..num__];
In the MiniZinc language the difference between a parameter and a variable is only the fact that a parameter must have a value at compile time. Within the compiler we turn as many variables into parameters as we can. This saves the solver from having to do some work. When we know that a variable has been turned into a parameter, then we can use the fix function to convince the type system that we really can use this variable as a parameter and see its value.
The problem here however is that fix is defined to abort when the variable is not fixed to one value. If no testing is done, this requires some (magic/)knowledge about the compilation process. In your case it seems that the second array is evaluated before the optimisation stage, in which all aliasing is resolved. This is the reason why it does not work. (This is indeed one of the things that is a consequence of a declarative language)
Although fix might only be used in the output statements in the examples (where it's guaranteed to work), it is used in many locations in the MiniZinc libraries. If we for example look at the library that is used for MIP solvers, there are many constraints that can be encoded more efficiently if one of the arguments is a parameter. Therefore, you will often see that the a constraint in this library first tests its arguments with is_fixed, and then use a better encoding if this returns true.
The output statement and when is_fixed returns true will both give the guarantee that a variable is fixed and ensure that the compilation doesn't abort. There is no other way to coerce a variable to a parameter, but unless you are dealing with dependant predicate definitions, you can just trust the MiniZinc compiler to ensure that the resulting FlatZinc will contain a parameter instead of a variable.
In q, a common illustration for the over operator / is the implementation of fibonacci sequence
10 {x,sum -2#x}/ 1 1
This indeed prints the first 10 fibonacci numbers but doesn't make sense in regards of the definition of the over operator in this whitepaper (page 8)
With two arguments, the second one being a list, the function is
called with the left argument as its first parameter and the first
element of the right argument as the second parameter. Next, the
function is called with the result of the previous iteration as the
first parameter and the third element as the second parameter. The
process continues in this way for the remaining elements of the list.
So in the fibonacci example above, at the first iteration the function would be called with [10;1] ("first parameter and first item of second parameter") which would already give an incorrect result.
My implementation is in line with the definition (and works)
1 1 {[l;c] l,sum -2#l}/til 10
but I don't like it because the parameter c is never used.
How can the first example be reconciled with the definition?
Thanks for the help
/ has a number of forms, described here: https://code.kx.com/q/ref/adverbs
The specific form being used here is "repeat" - https://code.kx.com/q/ref/adverbs/#converge-repeat
The fibonacci function here is monadic i.e. takes one parameter (x)
In this form, / will run the function with the supplied parameter (i.e. the list of 1 1), and then with the result of that call, and then again with the result of that call and so, until the number of iterations reaches 10 (the left argument to /)
The definition you provide is true if the function is a dyadic function (i.e. takes two parameters)
Hope this helps
Jonathon
AquaQ Analytics
The left argument is this example is being treated as an iteration integer atom (repeat).
Please see coverge-repeat on code.kx.com may add further clarification.
how to handle subsref at the left of '=' in matlab?
I have a line in my matlab function like this.
s1.type = '{}';
s1.subs = {5};
s2.type = '()';
index = 4 + (day - 1) * 4 + action;
s2.subs = {index};
subsref(subsref(pair(key),s1),s2) = subsref(subsref(pair(key),s1),s2) + 1;
pair is a container.map and key is the key of the map
because of the disgusting syntax, I have to use subsref to put '()' before '{}' of cell.
Here comes the error:
"subsref" previously appeared to be used as a function or command, conflicting with its use here as the name of a variable.
A possible cause of this error is that you forgot to initialize the variable, or you have initialized it implicitly using load or
eval.
How can I put subsref at the left of '=' or how can this expression +1 itself?
subsref is called when you use A(i), A{i} or A.i on the right-hand side (i.e. when you're indexing into an expression).
When you use them on the left-hand side for assignment - in other words, when you use A(i) = B, A{i} = B or A.i = B, MATLAB instead calls subsasgn (pronounced "subs assign") .
I'm not sure exactly what your example code is trying to do, but whatever it is I would think you'll need to call subsasgn, rather than just subsref.
In addition, I note that you're doing this on a variable that is a containers.Map. Note that containers.Map, because of its unusual syntaxes, overloads both subsref and subsasgn, and you are likely to find it very difficult to do what you're trying to do. See my answer here for further information on that topic.
PS: you may like to post a separate question asking how to approach the underlying problem you're trying to solve. Whatever it is, I cannot believe that this level of complexity with subsref and subsasgn is really necessary.
Just having a little difficulty with the syntax of matlab functions;
function f = fact(x)
if x == 1
return
else
f = 1 - x*(fact(x-1))
end
end
When calling this function in the command window with the argument 10 I receive the error
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1))
I've had a look around and solutions for the first revolve around the pathing of the m-file which doesn't seem to be a problem as other files in the same directory run fine,
The second I'm not sure why the error in line 6 occurs, my guess is it has something to do with the variable and function names.
As a side question, are both these end statements necessary?
Thanks!
The most obvious error is your function filename. You have a function called fact defined in your code but you named your file recursion. Make sure that both your function name and the filename are both called fact.
If you were to name your file as recursion, then make the function name defined in your code as fact, this is what would happen if you tried calling your code:
>> f = recursion(10);
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1));
... look familiar?
As such make sure your filename and your function name are named the same. In fact, in the MATLAB editor, it should automatically give you an error saying that both of these are not the same.
There is also another error in your code. The base case is not defined properly. Always remember when you are writing recursive algorithms is that eventually the function is going to return... and that's when you hit the base case. We can see here that it is when x = 1. When x = 1, you're supposed to assign something to f which is the output. You are simply exiting the function, and so when x becomes 1, your code will spit out an error saying that f was not assigned when the function finishes. As such, you need to figure out what your base case is. I'm going to assume that your base case (when x = 1) is going to equal 0. You will obviously need to change this as I don't know what your code is actually computing. Basically, you need to do this:
function f = fact(x)
if x == 1
f = 0; %// Base case needs to change according to your specs
else
f = 1 - x*(fact(x-1))
end
end
When I do this, I get the following output when x = 10
>> f = fact(10);
f =
1334961
I don't get an error when I run this code now. Also, check to see if you have any variables named fact in your workspace. When this happens, you are in fact shadowing over your function with a variable, so it is actually trying to access the variable called fact instead. As such, try clearing your workspace by doing clear all;, then try this code again.
One warning
If you were to specify x to be 0 or negative, this function will never stop. As such, you need to provide some check and perform the proper action when this happens. Also, you need to make sure that you specify what type of inputs are accepted for x. Judging from the context, x are positive integers only. As what #Glen_b has noted, should you provide any number that isn't a positive integer, this function will never stop as x will never equal 1 down the recursion pipeline.
To answer your optional question
The first end statement is required to end the if statement. The second end statement isn't required, but it's good practice anyway. However, if you have multiple functions defined inside your function file, then yes it is most definitely required to properly signify that the end of that function is defined there. However, you don't need it if you're only writing one function per file, but I would recommend keeping it there as it's good practice.
I am trying to implement a polynomial class with fortran 2003, with overloaded arithmetic operations and assignments. The derived type maintains allocatable list of term definitions and coefficients, like this
type polynomial
private
type(monomial),dimension(:),allocatable :: term
double precision,dimension(:),allocatable :: coef
integer :: nterms=0
contains
...
end type polynomial
interface assignment(=)
module procedure :: polynomial_assignment
end interface
...
contains
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(???) :: lhs
type(polynomial),intent(in) :: rhs
...
I had to make it elemental because this is intended to be used as matrices of polynomials. That does work, for the most cases at least. However, I somehow got myself into concerns about self-assignment here. One can simply check the pointers to see if things are the same in C++, but it doesn't seem to be an option in Fortran. However the compiler do detect the self-assignment and gave me a warning. (gfortran 4.9.0)
When I have intent(out) for lhs, the allocatable entries for both lhs and rhs appeared to be deallocated on entry to the subroutine, which made sense since they were both p, and an intent(out) argument would first be finalized.
Then I tried to avoid the deallocation with an intent(inout), and check self-assignment by modifying one field in the lhs output
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(inout) :: lhs
type(polynomial),intent(in) :: rhs
lhs%nterms=rhs%nterms-5
if(lhs%nterms==rhs%nterms)then
lhs%nterms=rhs%nterms+5
return
end if
lhs%nterms=rhs%nterms
Well, now this is what surprised me. When i do
p=p
It didn't make the test and proceeded, giving me a polynomial with 0 terms but no memory violations. Confused, I printed lhs%nterms and rhs%nterms inside the assignment, only to find that they are different!
What is even more confusing is that when I did the same thing with
call polyn_assignment(p,p)
It works perfectly and detected that both arguments are the same. I am puzzled how an interface of a subroutine can run differently from the subroutine itself.
Is there something special about assignment in Fortran 2003 that I've missed?
(First time to ask a question here. Please correct me if i didn't do it right.)
If you have a statement a = b that invokes defined assignment via a subroutine sub, the assignment statement is equivalent to call sub(a, (b)). Note the parentheses - the right hand side argument is the result of evaluating a parenthesised expression and is therefore not conceptually the same object as b. See F2008 12.4.3.4.3 for details.
Consequently, a = a is equivalent to call sub(a, (a)). The two arguments are not aliased. It is different from call sub(a,a), the latter may (depending on the specifics of the internals of sub, including dummy argument attributes) break Fortran's argument aliasing rules (e.g. in your example, a statement such as call polyn_subroutine(a,a) is illegal).