Comparing object/value instead of reference in Eiffel - comparison

I have been trying to figure out how to make the postcondition work for the following code.
There are 3 classes, Bank is the client of Customer, and Customer is the client of Account
Here is the Bank Class, I just cant pass the postcondition other_customer_unchanged
new (name1: STRING)
-- Add a new customer named 'name1'
-- to the end of list `customers'
require
customer_not_already_present:customer_exists(name1)=false
do
customers.force (create {CUSTOMER}.make (name1))
count := customers.count
ensure
total_balance_unchanged:
sum_of_all_balances = old sum_of_all_balances
num_customers_increased:count /= old count and old count+1=count
total_unchanged:total = old total
customer_added_to_list:
customer_exists (name1)
and then customers[customer_id (name1)].name ~ name1
and then customers[customer_id (name1)].balance ~ zero
other_customers_unchanged:
customers_unchanged_other_than(name1, old customers.deep_twin)
end
Here is the feature of customers_unchanged_other_than
customers_unchanged_other_than (a_name: STRING;old_customers:like customers): BOOLEAN
-- Are customers other than `a_name' unchanged?
local
c_name: STRING
do
from
Result := true
customers.start
until
customers.after or not Result
loop
c_name := customers.item.name
if c_name /~ a_name then
Result := Result and then
old_customers.has (customers.item)
end
customers.forth
end
ensure
Result =
across
customers as c
all
c.item.name /~ a_name IMPLIES
old_customers.has (c.item)
end
end
and I have redefined the is_equal feature in customer class
is_equal (other: like Current): BOOLEAN
do
Result := name ~ other.name and balance = other.balance
ensure then
Result = (name ~ other.name and balance = other.balance)
end
I have looked into what is in the old customer.deep_twin, it does contain the item of the customer, but somehow when it uses .has feature, it just makes the Result false.
Any help is greatly appreciated :)

I presume from your code that customers and old_customers are of type descendant of CONTAINER (ARRAY, LIST, STACK, QUEUE, etc.) You can then use customers.compare_objects (or old_customers.compare_objects) to ask the CONTAINER to use is_equal instead of "=" when searching.

Related

Lua : copying a table efficiently (deep copy)

I try to make efficiently a copy of a lua table. I have written the following function copyTable() that works well (see below). But I imagined I could have something more efficient using the "passing by value" mechanism of the functions. I made a few tests to explore this mechanism :
function nop(x)
return x
end
function noop(x)
x={}
return x
end
function nooop(x)
x[#x+1]=4
return x
end
function copyTable(datatable)
local tblRes={}
if type(datatable)=="table" then
for k,v in pairs(datatable) do tblRes[k]=copyTable(v) end
else
tblRes=datatable
end
return tblRes
end
tab={1,2,3}
print(tab) -->table: 0x1d387e0 tab={1,2,3}
print(nop(tab)) -->table: 0x1d387e0 tab={1,2,3}
print(noop(tab)) -->table: 0x1e76f90 tab={1,2,3}
print(nooop(tab)) -->table: 0x1d387e0 tab={1,2,3,4}
print(tab) -->table: 0x1d387e0 tab={1,2,3,4}
print(copyTable(tab)) -->table: 0x1d388d0
We can see that the reference to the table is transferred unchanged through the functions (when I just read it or add things) except within noop() where I try a radical modification of the existing.
I read Bas Bossink and the answer made by Michael Anderson in this Q/A. Regarding the passing or tables as arguments, they emphasized the difference between "arguments passed by ref" and "arguments passed by values and tables are references" with examples where this difference appears.
But what does that mean precisely ? Do we have a copy of the reference, but what difference does that make with a passing through ref since the data pointed and therefore manipulated is still the same, not copied ? Is the mechanism in noop() specific when we try to affect nil to the table, specific to avoid the deletion of the table or in which cases does it trigger (we can see with nooop() that it is not always the case when the table is modified) ?
My question : how the mechanism of passing tables really works ? Is there a way to make a more efficient way to copy the data of a table without the burden of my copyTable ?
The rules of argument passing in Lua is similarly to C: everything is pass by value, but tables and userdata are passed around as pointers. Passing a copy of a reference does not appear so different in usage, but it is completely different than passing by reference.
For example, you brought this part up specifically.
function noop(x)
x={}
return x
end
print(noop(tab)) -->table: 0x1e76f90 tab={1, 2, 3}
You are assigning the value for the new table[1] into variable x (x now holds a new pointer value). You didn't mutate the original table, the tab variable still holds the pointer value to the original table. When you return from noop you are passing back the value of the new table, which is empty. Variables hold values, and a pointer is a value, not a reference.
Edit:
Missed your other question. No, if you want to deep-copy a table, a function similar to what you wrote is the only way. Deep copies are very slow when tables get large. To avoid performance issues, you might use a mechanism like "rewind tables", which keep track of changes made to them so they can be undone at later points in time (very useful in recursive with backtrack contexts). Or if you just need to keep users from screwing with table internals, write a "freezable" trait.
[1] Imagine the {} syntax is a function that constructs a new table and returns a pointer to the new table.
If you are sure that those 3 assumptions (A) are valid for "tab" (the table being copied):
There are no table keys
t1 = {}
tab = {}
tab[t1] = value
There are no repeated table values
t1 = {}
tab = {}
tab.a = t1
tab.b = t1
-- or
-- tab.a.b...x = t1
There are no recursive tables:
tab = {}
tab.a = tab
-- or
-- tab.a.b...x = tab
Then the code you provided is the smallest and almost as efficient as possible.
If A1 doesn't hold (i.e. you have table keys), then you must change your code to:
function copyTable(datatable)
local tblRes={}
if type(datatable)=="table" then
for k,v in pairs(datatable) do
tblRes[copyTable(k)] = copyTable(v)
end
else
tblRes=datatable
end
return tblRes
end
If A2 doesn't hold (i.e. you have repeated table values), then you could change your code to:
function copyTable(datatable, cache)
cache = cache or {}
local tblRes={}
if type(datatable)=="table" then
if cache[datatable] then return cache[datatable]
for k,v in pairs(datatable) do
tblRes[copyTable(k, cache)] = copyTable(v, cache)
end
cache[datatable] = tblRes
else
tblRes=datatable
end
return tblRes
end
This approach only pays off, though, if you have lots of repeated large tables. So, it is a matter of evaluating which version is faster for your actual production scenario.
If A3 doesn't hold (i.e. you have recursive tables), then your code (and both adjustments above) will enter an infinite recursive loop and eventually throw a stack overflow.
The simplest way to handle that is keeping a backtrack and throwing an error if table recursion happens:
function copyTable(datatable, cache, parents)
cache = cache or {}
parents = parents or {}
local tblRes={}
if type(datatable)=="table" then
if cache[datatable] then return cache[datatable]
assert(not parents[datatable])
parents[datatable] = true
for k,v in pairs(datatable) do
tblRes[copyTable(k, cache, parents)]
= copyTable(v, cache, parents)
end
parents[datatable] = false
cache[datatable] = tblRes
else
tblRes=datatable
end
return tblRes
end
My solution for a deepcopy function which handles recursive tables, preserving the original structure may be found here: https://gist.github.com/cpeosphoros/0aa286c6b39c1e452d9aa15d7537ac95

Should parameters be used as variables in Lua?

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.

Elder Scroll Online Addon

This is my first time working with Lua, but not with programming. I have experience in Java, Action Script, and HTML. I am trying to create an addon for Elder Scroll Online. I managed to find the ESO API at the following link:
http://wiki.esoui.com/API#Player_Escorting
I am trying to make a function that returns a count of how many items each guild member has deposited in the bank. The code I have so far is as follows
function members()
for i=0, GetNumGuildEvents(3, GUILD_EVENT_BANKITEM_ADDED)
do
GetGuildEventInfo(3, GUILD_EVENT_BANKITEM_ADDED, i)
end
I am having trouble referencing the character making the specific deposit. Once I am able to do that I foresee making a linked list storing character names and an integer/double counter for the number of items deposited. If anyone has an idea of how to reference the character for a given deposit it would be much appreciated.
I don't have the game to test and the API documentation is sparse, so what follows are educated guesses/tips/hints (I know Lua well and programmed WoW for years).
Lua supports multiple assignment and functions can return multiple values:
function foo()
return 1, "two", print
end
local a, b, c = foo()
c(a,b) -- output: 1, "two"
GetGuildEventInfo says it returns the following:
eventType, secsSinceEvent, param1, param2, param3, param4, param5
Given that this function applies to multiple guild event types, I would expect param1 through param5 are specific to the particular event you're querying. Just print them out and see what you get. If you have a print function available that works something like Lua's standard print function (i.e. accepts multiple arguments and prints them all), you can simple write:
print(GetGuildEventInfo(3,GUILD_EVENT_BANKITEM_ADDED,i))
To print all its return values.
If you don't have a print, you should write one. I see the function LogChatText which looks suspiciously like something that would write text to your chat window. If so, you can write a Lua-esque print function like this:
function print(...)
LogChatText(table.concat({...}, ' '))
end
If you find from your experimentation that, say, param1 is the name of the player making the deposit, you can write:
local eventType, secsSinceEvent, playerName = GetGuildEventInfo(3,GUILD_EVENT_BANKITEM_ADDED, i)
I foresee making a linked list storing character names and an integer/double counter for the number of items deposited.
You wouldn't want to do that with a linked list (not in Lua, Java nor ActionScript). Lua is practically built on hashtables (aka 'tables'), which in Lua are very powerful and generalized, capable of using any type as either key or value.
local playerEvents = {} -- this creates a table
playerEvents["The Dude"] = 0 -- this associates the string "The Dude" with the value 0
print(playerEvents["The Dude"]) -- retrieve the value associated with the string "The Dude"
playerEvents["The Dude"] = playerEvents["The Dude"] + 1 -- this adds 1 to whatever was previous associated with The Dude
If you index a table with a key which hasn't been written to, you'll get back nil. You can use this to determine if you've created an entry for a player yet.
We're going to pretend that param1 contains the player name. Fix this when you find out where it's actually located:
local itemsAdded = {}
function members()
for i=0, GetNumGuildEvents(3, GUILD_EVENT_BANKITEM_ADDED ) do
local eventType, secsSinceEvent, playerName = GetGuildEventInfo(3, GUILD_EVENT_BANKITEM_ADDED, i)
itemsAdded[playerName] = (itemsAdded[playerName] or 0) + 1
end
end
itemsAdded now contains the number of items added by each player. To print them out:
for name, count in pairs(itemsAdded) do
print(string.format("Player %s has added %d items to the bank.", name, count))
end

Delete line in TSTringlist

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));

How to call plpgsql functions from Ruby on rails?

How to call plpgsql functions from Ruby on Rails application?
This is the function definition:
CREATE OR REPLACE FUNCTION add_org_pincode(i_user_id integer, i_org_id integer, i_amount numeric, i_pincode_id integer)
RETURNS integer AS
$BODY$
Declare
v_org_balance numeric;
Begin
Select o.balance
Into Strict v_org_balance
From organizations o
Left Join organizations d On o.parent_organization_id = d.id
Where o.id = i_org_id
For Update Of o;
--
Insert Into org_balance_transactions(organization_id, balance, amount_added, reason, action_user_id, transaction_id)
Values (i_org_id, v_org_balance, i_amount, 10, i_user_id, i_pincode_id);
--
Update organizations
Set balance = balance + i_amount
Where id = i_org_id;
-- Other error
Return 0;
End;$BODY$
LANGUAGE 'plpgsql' VOLATILE;
So, how do I call add_org_pincode?
Like the others have said, something akin to:
result = connection.execute ("SELECT add_org_pincode(#{user_id}, #{org_id}, #{amount}, #{pincode_id};")
This is an example that I have proven, it might help you...
CREATE LANGUAGE plpgsql;
/**PROMEDIOS**/
CREATE OR REPLACE FUNCTION average(valores NUMERIC[],OUT prom NUMERIC) AS $$
DECLARE
element_count INT4;
sum numeric := 0.0;
BEGIN
element_count := array_upper(valores, 1) - array_lower(valores, 1) +1;
FOR i IN array_lower(valores, 1) .. array_upper(valores, 1)
LOOP
sum := sum + valores[i];
END LOOP;
prom := trunc(sum/element_count,1);
END;
$$ LANGUAGE plpgsql;
Obviously you have to execute this SQL in your database, just add it in your SQL Editor (pointing your database) in PGAdmin, after executing that, this function must be available like this select average(ARRAY[4.5,3.2,7.0]);.
In Rails Console I tried the example like this:
_calificaciones = Calificacion.all(:conditions => ["promedio_parciales != average(array[parcial1,parcial2,parcial3])"])
and it worked fine for me... Good luck...
You can go straight to the ActiveRecord::Base.connection to execute SQL which is what I did for some prototype code...
result = ActiveRecord::Base.connection.execute("SELECT * FROM stock_hourly_performance(#{stock_id})")
I don't know if its the best solution to the problem but it got me up and running.
You can execute raw SQL with:
ActiveRecord::Base.connection.execute('SQL goes here')
Be sure that it is absolutely necessary to bypass ActiveRecord (Rail's ORM).

Resources