I have a list of numbers and I want to add them and then multiply them by a constant.
addList := proc(a::list,b::integer)::integer;
local x,i,s;
description "add a list of numbers and multiply by a constant";
x:=b;
s:=0;
for i in a do
s:=s+a[i];
end do;
s:=s*x;
end proc;
sumList := addList([2, 2, 3], 2) works fine but at the same time sumList := addList([20, 20, 30], 2) gives an error.
Can somebody point out the error ?
In the for loop you do s:=s+a[i] but i is set to one of the values in a already - not the index of a value. A first pass fix would be to just change the statement above to s:=s+i.
You could also write the function as
proc(a::list,b::integer)::integer;
convert(a,`+`)*b;
end;
Even shorter, there is
addList:= (a,b)-> `+`(a[])*b;
Related
I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);
I want to do something like..
position := [100, 200]
Click, position[1], position[2]
but the above doesn't work, no error, but doesn't do click
Click, %position[1]%, %position[2]%
above gives error, variable name contains an invalid character
position := [100, 200]
p1 := position[1]
p2 := position[2]
Click, %p1%, %p2%
above works, but I don't want to assign dummy variables each time I need to click..
any help?
thanks!
This will do what you want:
click % position[1] . "," . position[2]
The % must be followed by a space or tab. It causes the command to use expression mode.
More information on "expression mode" can be found under Help > Variables and Expressions > Variables > Retrieving the contents of variables.
ERROR at line 8: PL/SQL: Statement ignored
CREATE OR REPLACE PROCEDURE POS(A IN NUMBER,M IN NUMBER,TOTAL OUT NUMBER)
AS
BEGIN
TOTAL:=0;
WHILE A>0 LOOP
M:=MOD(A,10);
TOTAL:=TOTAL+M;
A:=(A/10);//statement ignored error
END LOOP;
DBMS_OUTPUT.PUT_LINE(TOTAL);
END;
DECLARE
X NUMBER;
Y NUMBER:=5;
Z NUMBER;
BEGIN
POA(X,Y,Z);
END;
OK, I've had a look at your procedure and tried to resolve the issues you are having with it.
You haven't explained much (or indeed anything) about what you are trying to achieve which makes it really difficult to get you an answer.
People on here really want to help but you have to at least give us the tools with witch to provide that help.
Anyhow, with a host of assumptions, here is my version of your procedure with the following assumptions:
Your procedure is names POS (you name it POS in the procedure definition but then try to execute it as POA).
Your main issue was trying to assign a new value to input parameter "a" within the loop. As it is an input parameter it is immutable and you cannot assign new values to it. I have got round this by declaring a local variable "v_iter" and assigning that the value of "a" and then using it to control the loop.
I have added an "exception" section to handle any unexpected errors and output that error via DBMS_OUTPUT. You might want to make this more robust.
You do not test to check if the input parameter "a" is null or a valid number (i.e. not negative), you might want to do this to make your procedure more robust.
Here is the changed code:
CREATE OR REPLACE
PROCEDURE POS (
a IN NUMBER,
m IN NUMBER,
total OUT NUMBER
)
AS
— Declare variables
v_iter NUMBER := a;
BEGIN
— Initialise total
total := 0;
— Loop through “v_iter”
WHILE v_iter > 0
LOOP
m := MOD(v_iter,10);
total := total + m;
v_iter := (v_iter/10);
END LOOP;
DBMS_OUTPUT.put_line(total);
EXCEPTION
WHEN others
THEN
— Output and raise an error;
DBMS_OUTPUT.put_line(sqlerrm);
RAISE;
END POS;
/
To call it:
DECLARE
X NUMBER;
Y NUMBER:=5;
Z NUMBER;
BEGIN
POS(X,Y,Z);
END;
/
Hope it helps.
I would like to have a for loop with 1:25 range but I do not want the for loop to go through number 23 in that range
in another format; I want it like this 1:22 24:25
is it doable this way?
please help
Yes. You can write:
for num = [1:22 24:25]
% do something with num
end
Another solution:
for idx=1:25
if idx==23, continue, end
disp(num2str(idx));
end
Just to add an alternative:
skip = [23];
for idx = 1:25
if ~any(idx == skip)
%// Your code here
end
end
I think it's more readable than using [1:22 24:25] as your loop variable as you can see clearly and quickly which numbers are being skipped (unless [1:22 24:25] is a variable getting generated elsewhere in which case I would go with that method), it avoids continue which is controversial and it's easy to add other numbers to skip (i.e. skip = [7, 18, 23] etc...)
I want to write a code for postgis in pgAdmin that is based on postgresql. It defines a 3-dimensional array of geometry.
I used this code for it:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN 1..9 LOOP
for j IN 1..9 LOOP
for k IN 1..9 LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
But it returned this error:
"array subscript out of range"
I used this instead:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN array_lower(G, 1)..array_upper(G, 1) LOOP
for j IN array_lower(G, 1)..array_upper(G, 1) LOOP
for k IN array_lower(G, 1)..array_upper(G, 1) LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
I have a different error this time:
"lower bound of FOR loop cannot be null"
I used this in BEGIN Part and solved all the errors:
G[1][1][1] := '01010000200400000000000000000000000000000000000000';
But I think this is not true and doesn't calculate all of the iterations for loops. I think this takes in account only the G[1][1][1]. What should I do now?
In PostgreSQL, simply declaring the array dimensions does not initialize or pre-allocate anything. The array is dynamic in all its dimensions. That differs significantly from the multi-dimensional array implementations found in general programming language like C.
To mimic the logic of these languages, you may first initialize the 9x9x9 array with a statement like this:
G:=array_fill('point(0 0)'::geometry, array[9,9,9]);
Then the rest of the code will just work when refering to G[i][j][k] either as source or destination of assignments.