In Julia 1.0, I'm trying to implement a for loop along the lines of:
while t1 < 2*tmax
tcol = rand()
t1 = t0 + tcol
t0 = t1
println(t0)
end
However, I am getting errors that t1 and t0 are undefined. If I put a "global" in front of them, it works again. Is there a better way to handle this than by putting global variables all over my code?
The reason of the problem is that you are running your code in global scope (probably in Julia REPL). In this case you will have to use global as is explained here https://docs.julialang.org/en/latest/manual/variables-and-scoping/.
The simplest thing I can recommend is to wrap your code in let block like this:
let t1=0.0, t0=0.0, tmax=2.0
while t1 < 2*tmax
tcol = rand()
t1 = t0 + tcol
t0 = t1
println(t0)
end
t0, t1
end
This way let creates a local scope and if you run this block in global scope (e.g. in Julia REPL) all works OK. Note that I put t0, t1 at the end to make the let block return a tuple containing values of t0 and t1
You could also wrap your code inside a function:
function myfun(t1, t0, tmax)
while t1 < 2*tmax
tcol = rand()
t1 = t0 + tcol
t0 = t1
println(t0)
end
t0, t1
end
and then call myfun with appropriate parameters to get the same result.
Related
I'm trying to do a solver for equations. When I run the code the X variable appears to be undefined, but it prints out perfectly. What am I missing?
I should give the program some numbers, than operations as Macros and it should create an outer product matrix of the operations applied.
function msu()
print("Insert how many values: ")
quantity = parse(Int64, readline())
values = []
for i in 1:quantity
println("x$i")
num1 = parse(Float64, readline())
push!(values, num1)
end
println(values)
print("How many operations? ")
quantity = parse(Int64, readline())
ops = []
for i in 1:quantity
push!(ops, Meta.parse(readline()))
end
mat = zeros((quantity, quantity))
for i in 1:length(mat)
sum = 0
for j in 1:length(values)
# here begins problems, the following prints are for debugging purpose
print(length(values))
func = Meta.parse("$(ops[convert(Int64, ceil(j / quantity))]) * $(ops[convert(Int64, j % quantity)])")
print(func)
x = values[j]
println(x)
sum += eval(func)
end
mat[i] = sum
end
println(mat)
end
msu()
The original code was in Spanish, if you find any typo it's probably because I skipped a translation.
I have a function within which I would like to evaluate a list of expressions using interpolated literals passed as arguments to the function and assign the result to a new array. Previously I've been able to do this fairly simply:
array_of_expr = Any[:(A * 5), :(B * 6 * T)]
arglist = [:A; :B; :T]
test_input = [1e5, 1e1, 100]
#eval begin
function interpolate_all($(arglist...))
result_array = $(Expr(:vcat, array_of_expr...))
end
end
interpolate_all(test_input...)
which returns the expected result:
2-element Array{Float64,1}:
500000.0
6000.0
(I know the code seems needlessly complicated with the #eval--it's because in the full version of the code, arglist is ~500 items long. This has been causing some compiler errors in the full version of the code, so my attempts here to loop over array_of_expr are part of my testing to find out the exact error, and also help me better understand metaprogramming/variable scope while I'm at it.)
I can index array_of_expr and evaluate an individual elements manually in this MWE:
#eval begin
function interpolate_one($(arglist...))
result_array = similar(array_of_expr)
println("evaluating $(array_of_expr[2])")
result_array = $(array_of_expr[2])
println(result_array)
end
end
interpolate_one(test_input...)
which returns:
evaluating B * 6 * T
6000.0
Which is the expected behavior. But if I try to loop over array_of_expr, I encounter various errors. The following ignores the iterator i and just prints the symbolic expression:
#eval begin
function interpolate_1by1($(arglist...))
result_array = similar(array_of_expr)
# this doesn't work, it just gives the symbolic expression, basically ignoring the $:
for i in range(1, length=length(array_of_expr))
result_array[i] = ($array_of_expr[i])
end
println(result_array)
end
end
interpolate_1by1(test_input...)
The following reports that i is not defined, which I understand is because expressions are evaluated in the global scope, not local:
#eval begin
function interpolate_1by1($(arglist...))
result_array = similar(array_of_expr)
# this doesn't work, i is undefined:
for i in range(1, length=length(array_of_expr))
result_array[i] = $(array_of_expr[i])
end
end
end
interpolate_1by1(test_input...)
Is there any way to make this work? I have tried the tactics in the cited SE answer, but did not have success.
you may unroll the loop at compile time:
#eval begin
function interpolate_1by1($(arglist...))
result_array = similar($array_of_expr)
$((quote
result_array[$i] = $(array_of_expr[i])
end for i in 1:length(array_of_expr))...)
return result_array
end
end
which after expansion is similar to
function interpolate_1by1($(arglist...))
result_array = similar($array_of_expr)
result_array[1] = $(array_of_expr[1])
result_array[2] = $(array_of_expr[2])
...
return result_array
end
I would like to know how to overload a function in scilab. It doesn't seem to be as simple as in C++. For example,
function [A1,B1,np1]=pivota_parcial(A,B,n,k,np)
.......//this is just an example// the code doesn't really matter
endfunction
//has less input/output variables//operates differently
function [A1,np1]=pivota_parcial(A,n,k,np)
.......//this is just an example// the code doesn't really matter
endfunction
thanks
Beginner in scilab ....
You can accomplish something like that by combining varargin, varargout and argn() when you implement your function. Take a look at the following example:
function varargout = pivota_parcial(varargin)
[lhs,rhs] = argn();
//first check number of inputs or outputs
//lhs: left-hand side (number of outputs)
//rhs: right-hand side (number of inputs)
if rhs == 4 then
A = varargin(1); B = 0;
n = varargin(2); k = varargin(3);
np = varargin(4);
elseif rhs == 5 then
A = varargin(1); B = varargin(2);
n = varargin(3); k = varargin(4);
np = varargin(5);
else
error("Input error message");
end
//computation goes on and it may depend on (rhs) and (lhs)
//for the sake of running this code, let's just do:
A1 = A;
B1 = B;
np1 = n;
//output
varargout = list(A1,B1,np1);
endfunction
First, you use argn() to check how many arguments are passed to the function. Then, you rename them the way you need, doing A = varargin(1) and so on. Notice that B, which is not an input in the case of 4 inputs, is now set to a constant. Maybe you actually need a value for it anyways, maybe not.
After everything is said and done, you need to set your output, and here comes the part in which using only varargout may not satisfy your need. If you use the last line the way it is, varargout = list(A1,B1,np1), you can actually call the function with 0 and up to 3 outputs, but they will be provided in the same sequence as they appear in the list(), like this:
pivota_parcial(A,B,n,k,np);: will run and the first output A1 will be delivered, but it won't be stored in any variable.
[x] = pivota_parcial(A,B,n,k,np);: x will be A1.
[x,y] = pivota_parcial(A,B,n,k,np);: x will be A1 and y will be B1.
[x,y,z] = pivota_parcial(A,B,n,k,np);: x will be A1, y will be B1, z will be np1.
If you specifically need to change the order of the output, you'll need to do the same thing you did with your inputs: check the number of outputs and use that to define varargout for each case. Basically, you'll have to change the last line by something like the following:
if lhs == 2 then
varargout = list(A1,np1);
elseif lhs == 3 then
varargout = list(A1,B1,np1);
else
error("Output error message");
end
Note that even by doing this, the ability to call this functions with 0 and up to 2 or 3 outputs is retained.
let countA =0 in
let countC =0 in
let countG =0 in
let countT =0 in
let countChar x =
match x with
'A' -> countA = countA + 1
|'C'-> countC = countC + 1
|'G' -> countG = countG + 1
|'T'-> countT = countT + 1
;;
I am getting a syntax error but I don't understand why, i'm still pretty new to Ocaml.
Your syntax error is caused by the fact that your last let doesn't have an in after it. This, in turn, is caused by the fact that your countChar function isn't defined at the outermost level (of a module). If you want to define a series of top-level names, you should define them all without in:
let countA = 0
let countC = 0
let countChar x = ...
So, that's your syntax problem. However, there are many other problems with this code.
The most obvious two are (A) you're expecting to be able to change the values of countA and so on. But they are immutable values, you can't change them. (B) You are using = as if it's an assignment operator. But in OCaml this is a comparison operator. Your code is just comparing countA against countA + 1. So of course the result is false.
It is definitely worth learning how to compute with immutable values, so I would try to fix this code by learning how to carry the cumulative counts as function parameters and return them at the end. But if you insist on coding imperatively, you will have to use references for your counts.
I also don't see any code that works on a string. Your countChar function (as the name implies) works on just one character.
Update
Here is a function that counts how many even and odd ints appear in an array. It works without mutating anything:
let eoa array =
let rec inner n (evenct, oddct) =
if n >= Array.length array then
(evenct, oddct)
else
let newcounts =
if array.(n) mod 2 = 0 then (evenct + 1, oddct)
else (evenct, oddct + 1)
in
inner (n + 1) newcounts
in
inner 0 (0, 0)
Here's how it looks when you run it:
# eoa [| 3; 1; 4; 1; 5; 9; 2 |];;
- : int * int = (2, 5)
In this code
t1 = os.time()
do_something_slow()
t2 = os.time()
elapsed_diff = os.difftime(t2, t1)
elapsed_sub = t2 - t1
Under what circumstances will elapsed_diff be different to elapsed_sub?
In non-Posix systems, there is no guarantee that the values returned by os.time can be subtracted directly.
In the GNU C Library, you can simply subtract time_t values. But on other systems, the time_t data type might use some other encoding where subtraction doesn't work directly. [1]