Hello i am writing some values to a stringlist. And would like to delete a value from the string list.
Currently I write to the string list like this.
FGamePlay.Locations.strings[0] := ('NumberOfLocations='+inttostr(NOL+1)); //add one to total
FGameplay.Locations.Add(inttostr(Position.x)+inttostr(Position.Y)+'=pos'); //add the location to list
This will return me a list like so
INDEX VALUE
[0] NumberOfLocations=4
[1] 23=pos
[2] 34=pos
[3] 24=pos
[4] 52=pos
Now i try to delete it like this
FGamePlay.Locations.Delete(FGamePlay.Locations.IndexOf(inttostr(ePosition.x)+inttostr(ePosition.Y)));
were ePosition.x + ePosition.Y will equal 23, 34,24,or 52. Thus it should delete the that line but instead when i add this delete line i get index out of bounds -1. I did stop the code just before this line and looked at Locations() and it had all these numbers in there. Also looked at epostion and the X,Y values were 34, thus correct too. Any idea?
thanks
Glen
When you uses the IndexOf function you must pass the exact string to find, in this case since you are adding the strings in this way
FGameplay.Locations.Add(inttostr(Position.x)+inttostr(Position.Y)+'=pos');
You must add the =pos to the string to search, something like
LIndex:=FGamePlay.Locations.IndexOf(inttostr(ePosition.x)+inttostr(ePosition.Y)+'=pos');
If LIndex>=0 then
FGamePlay.Locations.Delete(LIndex);
As RRUZ says, the string you are looking for to delete is missing the "=pos" suffix.
In order to debug this more effectively, you should break up the code a bit more. If you had this equivalent code:
str := inttostr(ePosition.x)+inttostr(ePosition.Y);
pos := FGamePlay.Locations.IndexOf(str);
FGamePlay.Locations.Delete(pos);
You would get an error on the pos := line, which would allow to to see the source of the error much more easily.
You could also consider making a function like:
function MakePosString(Position : Point);
begin
Result := inttostr(ePosition.x)+inttostr(ePosition.Y)+'=pos';
end;
Then you can call that function instead of reimplementing that code and you are guaranteed that your strings will be consistent.
Whilst I agree with everything everyone else has said about considering using a better data structure for the job at hand, I think for the sake of anyone with a similar problem in the future it is worth mentioning something that nobody else yet identified.
Your expression:
IntToStr(ePosition.x) + IntToStr(ePosition.y)
identifies the NAME of an entry in your string list, when considered as a name/value list. That is, a TStringList where each item is of the form "name=value". Whilst one way to fix your code is to append the rest of the string ('=pos') this of course only works when the "value" part of every named value is always "pos".
If there is the possibility that the "pos" value could be different or unknown for a given named value, then you can still find it by looking up the index of the item using just the name part:
itemName := IntToStr(ePosition.x) + IntToStr(ePosition.y);
itemIndex := fGamePlay.Locations.IndexOfName(itemName);
if itemIndex > -1 then
fGamePlay.Locations.Delete(IndexOfName(itemName));
Related
I try to use
across 1|..|list.count as j
all
list.i_th(z) ~ old list.i_th(z)
end
but it says unknown identifier z. Whats wrong with this syntax??
The syntax is correct. However, no identifier of name z is declared, hence the error. There is a cursor variable j instead. The items at the current cursor position are accessed with j.item.
Another issue is that j is evaluated in the current context (the postcondition), but old expressions are evaluated before the feature body is executed, where j is absent. As a result the code with old list.i_th (j.item) would not compile. In other words, the value should be taken from the old list but with the current index. The expression (old list).i_th (j.item) does the trick.
But this still does not do what is needed. It turns out that old list = list because the reference to the list object remains the same. To get the old elements, the copy of the list is required instead: (old list.twin).
Combining all the above, the expression should look like across 1 |..| list.count as j all list.i_th (j.item) ~ (old list.twin).i_th (j.item) end.
I've been told in Java that I should avoid modifying the original parameters such as
public int doStuff(int begin, int end) {
/* loop or something */
begin++; //bad
end--; //also bad
/* end loop */
return
}
instead, I should do something like
public int doStuff(int begin, int end) {
int myBegin = begin; //something like this
int myEnd = end;
/* stuff */
return
}
So, I've been doing this in lua
function do_stuff(begin, last)
local my_begin = begin
local my_last = last
--stuff
my_begin = my_begin + 1
my_last = my_last - 1
--stuff
end
But, I'm wondering if
function do_stuff(begin, last)
--stuff
begin = begin + 1
last = last - 1
--stuff
end
is also discouraged, or is it nice and concise?
There are no rules. Let taste, clarity, and need decide.
Nevetheless, a common idiom is to provide default values for parameters as in
function log(x,b)
b = b or 10
...
end
If you were told not to modify the parameters of functions, then there was probably a reasoning associated with that. Whatever that reasoning is would apply as much to Lua as to Java, since they have similar function argument semantics. Those reasons could be one or more of (but not limited to):
If you modify a parameter... you don't have it anymore. If you suddenly have a need for the original value you were passed, it's gone now.
Creating confusion, depending on how the parameters are named. The word "begin" suggests the beginning of something. If you change it, it isn't necessarily the beginning anymore, but merely the current element you're operating on.
Creating potential errors, if dealing with reference types (non-basic types in Java, tables and such in Lua). When you modify an object, you're changing it for everyone. Whereas incrementing an integer is just changing your local value. So if you're frequently modifying parameters, you still need to think about which ones you ought to be poking at and which ones you shouldn't be.
To put it another way, if you agreed with the suggestion for doing so in Java, then it applies just as much to Lua. If you didn't agree with the suggestion in Java, then you have no more reason to follow it under Lua.
In Lua functions, threads, tables and userdata types are passed by reference. So unless you have one of those you are working with a local copy anyway.
So in your example:
function do_stuff(begin, last)
--stuff
begin = begin + 1
last = last - 1
--stuff
end
begin and last are local non-reference variables in do_stuff's scope.
The only reason to make a copy of them is that you might want to store there initial value for later use. For that purpose you can either create a backup copy of the initial value or you create a working copy of it. Whatever you prefer.
Only make sure you know what is passed by reference and what by value so you avoid changing things you don't want to change and the other way around.
I'm trying to code something but there is happening something I don't understand.
I get some values from a database and loop over them and change some of them if needed.
This is what I'm trying to do:
if qryGeneral.fieldbyname('B_PRIJS').IsNull or
qryGeneral.fieldbyname('B_PRIJS').Value = 0 then
begin
if (qryGeneral.fieldbyname('V_PRIJS').Value <> 0) or
(qryGeneral.fieldbyname('V_PRIJSEXCL').Value <> 0) then
//make some calculations and save data
end;
B_PRIJS is a float, null type in a SQL Server DB. When I set a breakpoint and I hover .Value it shows 0,11. When I hover IsNull it shows False, so far so good.
Now I would expect it would NOT enter the if-structure, because it is not null and not equal to 0, but it does enter the if-structure.
I don't understand why, I always coded like this.
When I select qryGeneral.fieldbyname('B_PRIJS').Value = 0 while still being in debug mode, I get a message "Expression illegal in evaluator".
I tried replacing Value into AsFloat or changing 0 into 0.0 but it doesn't work.
What am I doing wrong or not understanding here?
Delphi's operator precedence rules mean that your expression is evaluated like this:
if (qryGeneral.fieldbyname('B_PRIJS').IsNull or qryGeneral.fieldbyname('B_PRIJS').Value)
= 0 then
Put parentheses around your = expression just like you have around you <> expressions, and you should get closer to the results you expect. However, the Value property is a Variant. When comparing a Variant to an Integer, the = operator will cause the Variant to be converted to an Integer. Delphi's variant-type-conversion rules show that a Variant holding a real value will be rounded to the nearest integer when the target type is an integer, so your 0.11 value will be rounded to zero. Consider comparing to 0.0 instead.
Could someone please tell me how to write a custom function in Open Office Basic to be used in Open Office Calc and that returns an array of values. An example of one such built-in function is MINVERSE. I need to write a custom function that populates a range of cells in much the same way.
Help would be much appreciated.
Yay, I just figured it out: all you do is return an array from your macro, BUT you also have to press Ctrl+Shift+Enter when typing in the cell formula to call your function (which is also the case when working with other arrays in calc). Here's an example:
Function MakeArray
Dim ret(2,2)
ret(0,0) = 1
ret(1,0) = 2
ret(0,1) = 3
ret(1,1) = 4
MakeArray = ret
End Function
FWIW, damjan's MakeArray function returns a Variant containing an array, I think. (The type returned by MakeArray is unspecified, so it defaults to Variant. A Variant is a container with a descriptive header, apparently cast as needed by the interpreter.)
Almost, but not quite, the same thing as returning an array. According to http://www.cpearson.com/excel/passingandreturningarrays.htm, Microsoft did not introduce the ability to return an array until 2000. His example [ LoadNumbers(Low As Long, High As Long) As Long()] does not compile in OO, flagging a syntax error on the parens following Long. It appears that OO's Basic emulates the pre-2k VBA.
When accessing an element in an array the square brackets are used like so:
{'X is an int and Numbers is an int array'}
X := Numbers[8];
However, While reading others' code I sometimes find the following syntax:
{'PBox , SBox1 , SBox2 are arrays of int , And X,Y are ints'}
Result := Result or PBox(.SBox1[X] or SBox2[Y].);
What does it mean to have parentheses after the array's name, as in PBox(someNumber)? Is this another way to access an array element?
What does the "." before SBox1 and after SBox2 mean? Both SBox1 and SBox2 are arrays. The code compiles without error but I don't know what those dots are for.
Yes, now I see what you do.
In fact, (. and .) are merely alternative ways (but very uncommon!) of writing [ and ] in Delphi.
If PBox is an array, then PBox[a] (or, equivalently, PBox(.a.)) would require a to be an integer, right? And if SBox1[x] and SBox2[Y] are integers, so is the bitwise or of them. (Bitwise or is an operation that takes two integers and returns a new integer.) Hence, PBox(.SBox1[X] or SBox2[Y].) is the (SBox1[X] or SBox2[Y])th element in the array PBox, that is, an integer. So it makes sense to compute the bitwise or between Result and this integer, which is what is done:
Result := Result or PBox(.SBox1[X] or SBox2[Y].);