SRL Archive - Jr. Member General Help and Discussion

Help with (function?) pointers


Foundry

2013-10-15 16:19:29

I made a script that makes headless arrows and I made two functions to read the amount of feathers and arrow shafts left. I then proceeded to make a variable (LimitingAmount: ^Integer) with the intention of using an if/then statement that makes it point at either the function that returns the current amount of feathers or the one that returns the current amount of shafts. LimitingAmount always reads 0. The feathersLeft() and shaftsLeft() functions work and do return the correct amount, so I did something wrong with either the if/then statement or making the variable point at the function.

Link to thread with entire script

var
LimitingAmount: ^Integer;

function feathersLeft: Integer;
begin
//returns amount of feathers
end;

function shaftsLeft: Integer;
begin
//returns amount of shafts
end;

procedure setup;
begin
if shaftsLeft() > feathersLeft() then
LimitingAmount := @feathersLeft();
else
LimitingAmount := @shaftsLeft();
writeLn(LimitingAmount);
end;

bg5

2013-10-15 16:58:59

It shouldn't even compile because of semicolon before else. Anyway it shouln't be 0 at output, just tested:
var
LimitingAmount: ^Integer;

function feathersLeft: Integer;
begin
writeln('executing...');
Result := 3;
end;

function shaftsLeft: Integer;
begin
writeln('executing2...');
Result := 12;
end;
var s:integer;
begin
if shaftsLeft() > feathersLeft() then
LimitingAmount :=@feathersLeft()
else
LimitingAmount :=@shaftsLeft();
writeLn(LimitingAmount);
end.




Lol, I looked into your script and found solution, you overwrites global LimitingAmount with brave new local var, so it's always 0:
procedure proggy;
var
HAPerHr, LimitingAmount: Integer;
begin
HAPerHr := round((HACounter * 15000) / (GetTimeRunning() / 60000));
WriteLn(LimitingAmount);
WriteLn('-------------------------------------------------------------------------');
WriteLn('Currently making HAs at the rate of ' + IntToStr(HAPerHr) + '/hr (Also the amount of fletch xp/hr).');
WriteLn('Estimated time of completion is ' + FloatToStr(LimitingAmount / HAPerHr) + ' hours.');
WriteLn('Antiban has been used ' + IntToStr(ABCounter) + ' time(s) at an average rate of ' + FloatToStr(round((ABCounter * 1000) / (GetTimeRunning() / 60000))) + '/hr.');
WriteLn('-------------------------------------------------------------------------');
end;

masterBB

2013-10-15 17:32:54

More for the looks instead of actual functionality:

  if shaftsLeft() > feathersLeft() then
LimitingAmount :=@feathersLeft
else
LimitingAmount :=@shaftsLeft;
writeLn(LimitingAmount());

Even though functions and procedures without parameters can be invoked without paranthesises. Try to only use them when you invoke/call a function. Note that in most languages, including lape, @functionName() would actually return the pointer of the result instead of the actual function pointer.

Foundry

2013-10-15 18:56:10

-_- … I didn't notice that local variable, Thanks

From: masterBB
More for the looks instead of actual functionality:

  if shaftsLeft() > feathersLeft() then
LimitingAmount :=@feathersLeft
else
LimitingAmount :=@shaftsLeft;
writeLn(LimitingAmount());

Even though functions and procedures without parameters can be invoked without paranthesises. Try to only use them when you invoke/call a function. Note that in most languages, including lape, @functionName() would actually return the pointer of the result instead of the actual function pointer.



Thanks for the tip :)

Foundry

2013-10-15 19:32:14

I have another question… how do I divide LimitingAmount by HAPerHr? It's giving me this error.

Exception in Script: Operator "Divide" not compatible with types "^Int32" and "Int32" at line 238, column 74

riwu

2013-10-16 02:42:36

From: HardcorBoter
I have another question… how do I divide LimitingAmount by HAPerHr? It's giving me this error.

Exception in Script: Operator "Divide" not compatible with types "^Int32" and "Int32" at line 238, column 74

You must dereference the pointer to get the value before attempting the division.

LimitingAmount^ / HAPerHr

Foundry

2013-10-16 11:06:06

From: riwu
You must dereference the pointer to get the value before attempting the division.

LimitingAmount^ / HAPerHr


Appreciate the response. I'll remember that :D

bonsai

2013-11-06 10:33:12

Hi Hardcore.

I chanced across this today and I don't think the code presented is doing what you intended.

You're looking to set limitingAmount once and call it many times later on. Correct?

In that case you wouldn't use an integer pointer you would use a function pointer. If you set an integer pointer once and reference it over and over, you will get the same answer. Unless someone else changes the integer it is pointing to. If the other functions were going to change an integer, you might as well use a global integer and avoid the pointers completely.

In the other example, you were setting the integer pointer to the results of a function. The question is, what is the address of the results of a function? I would expect them to be somewhat random and unsafe to use. I changed the sample to show what happens when you do this:
program new;

var
LimitingAmount: ^Integer;
featherCount: integer = 3;
shaftCount:integer = 12;
i: integer;

function feathersLeft: Integer;
begin
writeln('executing...');
Result := featherCount;
inc(feathercount);
end;

function shaftsLeft: Integer;
begin
writeln('executing2...');
Result := shaftCount;
dec(shaftCount);
end;

var s:integer;
begin
if shaftsLeft() > feathersLeft() then
LimitingAmount :=@feathersLeft()
else
LimitingAmount :=@shaftsLeft();

for i := 1 to 10 do
writeLn(LimitingAmount^);
end.

Results:
Compiled successfully in 234 ms.
executing2...
executing...
executing...
4
4
4
4
4
4
4
4
4
4
Successfully executed.

So it called feathersLeft once in the if and that changed featherCount to 4. Then we assigned the integer pointer to results of featherCount (which was still 4). The other times we printed it, we got the same result. If other functions called feathersLeft() a few times and we peeked at limitingAmount^ we would see the updated results (I tried it). That's kind of a quirk of lape I would say and I don't know how consistent it would be. But it is not calling featherCount when we reference limitingAmount to get a fresh count.

If we do the same with a function pointer you see it runs the function 10 times. When you use a function pointer shaftsLeft or feathersLeft get called indirectly by referencing limitingAmount():

program new;

var
LimitingAmount: function():integer;
featherCount: integer = 3;
shaftCount:integer = 12;
i: integer;

function feathersLeft: Integer;
begin
writeln('executing...');
Result := featherCount;
inc(feathercount);
end;

function shaftsLeft: Integer;
begin
writeln('executing2...');
Result := shaftCount;
dec(shaftCount);
end;

var s:integer;
begin
if shaftsLeft() > feathersLeft() then
LimitingAmount :=@feathersLeft
else
LimitingAmount :=@shaftsLeft;

for i := 1 to 10 do
writeLn(LimitingAmount());
end.

Results:
Compiled successfully in 234 ms.
executing2...
executing...
executing...
4
executing...
5
executing...
6
executing...
7
executing...
8
executing...
9
executing...
10
executing...
11
executing...
12
executing...
13
Successfully executed.

Let me know if that doesn't make sense.

Foundry

2013-11-06 11:31:48

Yes, I intended to set it once and call it multiple times later.

Makes much more sense with the explanation. I understand now that I was just referencing the result of a function as opposed to an actual function. Thanks for the response :)

EDIT: Was going to rep you but can't do it again, lol.