How to initialise an array of objects in Eiffel? - eiffel

I am trying to implement a solution to the Producer-Consumer problem using Eiffel. I have an array p of class PRODUCER and an array c of class CONSUMER declared and initialized as following:
local
p : attached ARRAY[PRODUCER]
c : attached ARRAY[CONSUMER]
do
!!p.make(1, 5)
!!c.make(1, 5)
But when I try to access a feature in one of the components of the array (like p.at(i).somefeature()), it gives a runtime exception saying Feature call on void target.
Any ideas on how to solve this? Is it because I am not calling a creation procedure for individual components of the array? Or is there a basic flaw in the approach to create the arrays? Thanks.
I figured the problem occurs because the individual components of the arrays (in this case, a producer or a consumer), being a reference type is initialized to void. The solution suggested is to use make_filled(default_value:T;low,high:INTEGER;), where T is the complex type. An example is given for string arrays as
string_list : ARRAY[STRING]
string_list.make_filled(" ", low, high)
causing each element of string_list to be initialized to a string that is a blank space. Any help on how to give a default value for the class PRODUCER? Thanks
I think I figured out the solution to the problem. I just had to create an instance of PRODUCER and CONSUMER and use those in the default value in make_filled. Then I can manipulate p[i] and c[i].
This is not a super efficient way, so if there is a better solution, please do share it. Thanks.

{ARRAY}.make_filled is normally used when all the elements of the array should be the same. If the elements are different, the array can be filled one by one:
create p.make_empty
p.force (create {PRODUCER}.make ("producer 1"), 1) -- Use appropriate code to
p.force (create {PRODUCER}.make ("producer 2"), 2) -- create PRODUCER objects.
...
There is also a somewhat obsolete syntax to create arrays, so it has to be used with care:
p := <<
create {PRODUCER}.make ("producer 1"), -- Or some other code
create {PRODUCER}.make ("producer 2") -- to create producers.
>>

Related

Eiffel: How to wipe_out an ARRAY object without recreating it

Trying to do something like
a: ARRAY[STRING]
create a.make_empty
a.put("foo foo fool")
a.wipe_out
Do I have to? or is there another way as STRING doesn't seem to have a .has_default
create a.make_empty
a.put("foo foo fool")
create a.make_empty
The most straightforward way is to use keep_head (n). It keeps only first n items, therefore, when n = 0, all items are removed altogether:
a.keep_head (0)
Another way is to use a creation procedure, for example, make_empty as a regular one. It is going to set an array to the state of a newly created one:
a.make_empty
However, this approach looks a bit odd. And it can change lower index of the array. So, keep_head is preferable.
Note. ARRAYED_LIST is a good alternative to ARRAY: it has almost all features of ARRAY, is more flexible, has other features, and wipe_out among them.

Ruby - Error accessing instance variables

I'm learning Ruby, and I'm having a problem while making a program.
I have a class "LineAnalyzer" that has 4 parameters (2 provided and 2 calculated). Both calculated params are: #high_wf_count (integer) and #high_wf_words (array).
Then, I have this one:
class Solution < LineAnalyzer
attr_reader :analyzers,
:highest_count_across_lines,
:highest_count_words_across_lines
def initialize
#analyzers = []
end
def analyze_file
File.foreach('test.txt') do |line|
#analyzers << LineAnalyzer.new(line.chomp,#analyzers.length+1)
end
end
def calculate_line_with_highest_frequency
#highest_count_words_across_lines = []
#highest_count_across_lines = #analyzers.max_by do
|a| a.instance_variable_get(:#highest_wf_count)
end .instance_variable_get(:#highest_wf_count)
#highest_count_words_across_lines << #analyzers.each do
|a| a.instance_variable_get(:#highest_wf_count) == #highest_count_across_lines
end .instance_variable_get(:#highest_wf_words)
end
end
The problem is that I cannot append the array #highest_wf_count to #highest_count_words_across_lines in the way I've done (it returns nil). But, I've previously taken the integer #highest_wf_count in the same way perfectly.
Can anyone tell me where's the problem?
Thanks in advance!
It seems that your problem is in this bit of code:
#highest_count_words_across_lines << #analyzers.each do
|a| a.instance_variable_get(:#highest_wf_count) == #highest_count_across_lines
end .instance_variable_get(:#highest_wf_words)
Preferably formatted as:
#highest_count_words_across_lines << #analyzers.each do |analyzer|
analyzer.instance_variable_get(:#highest_wf_count) == #highest_count_across_lines
end.instance_variable_get(:#highest_wf_words)
The problem here is that you are calling .instance_variable_get(:#highest_wf_words) on the result of the :each method.
A few lines above, you are doing something similar, where you call .instance_variable_get(:#highest_wf_count) on the result of the :max_by method, and it is working.
The difference between :max_by and :each is that :max_by returns a single analyzer, whereas :each returns the array of #analyzers over which it is iterating.
When you call :instance_variable_get(:#highest_wf_words) on that array, it's returning nil because an array will not have an instance variable named :#highest_wf_words
That is where your problem exists.
Sidenote:
It is generally not good practice to ever use :instance_variable_get. I would recommend adding to your analyzer class attr_reader :highest_wf_words, :highest_wf_count
Then, instead of calling analyzer.instance_variable_get(:#highest_wf_words), you can just call analyzer.highest_wf_words
There's a lot going on here and most of the code results from going against the grain when writing Ruby. Using instance_variable_get should be an absolute last resort. It's considered highly rude to just reach into an object and pull out a variable. It creates ugly and undesirable inter-dependencies. If that other object wanted to give you that value it would have a method to access it.
The way I see it what you're trying to do boils down to something like this:
def highest_frequency
#analyzers.map do |a|
a.highest_wf_count
end.sort.last
end
Let Analyzer implement highest_wf_count as a method, even if it's just an attr_reader. This gives you the flexibility to change how and when that value is computed. Maybe you don't need to do it when the object is initialized. Maybe it's done in another thread, or it's evaluated lazily.
Whenever possible try and structure your code as a series of straight-forward transformations. Try not to create convoluted, branching, ugly comparisons. Lean on Enumerable whenever possible, it's usually got a method that does exactly what you want, or two that in conjunction do the job perfectly.
This is way more complex than it needs to be (or should be).
Why does Solution subclass LineAnalyzer? And why are you using instance_variable_get? You should define getter methods using attr_reader on the LineAnalyzer class so you can call methods instead of using instance_variable_get, which is a brute force approach that should only be used as a last resort.
I think you should fix this before proceeding.
When you have instance methods created with attr_reader, calculating the max becomes very simple:
highest_count_across_lines = #analyzers.map(&:highest_wf_count).max
I think your error probably is caused by these lines:
#highest_count_words_across_lines << #analyzers.each do
|a| a.instance_variable_get(:#highest_wf_count) == #highest_count_across_lines
end .instance_variable_get(:#highest_wf_words)
I suggest simplifying this code, and the error will probably present itself to you. Did you really mean to append the value returned by each to #highest_count_words_across_lines? This will be an Array of analyzers. The Array class, of course, does not have a variable named :#highest_wf_words.
Again, I think you really need to simplify this code.

How to add and remove objects from an array in Eiffel

I am trying to make a CONTAINER class that maintains an array of CRITTER objects (that I have already created and tested. Note, there are various CRITTER subspecies, that are inheriting from the CRITTER super class). The aim is to add and remove CRITTER objects from this array. This is what the CONTAINER class looks like:
class
CONTAINER
create
make
feature
num: detachable INTEGER
list: ARRAY[CRITTER]
make
local
do
create list.make_empty
num := 0
end
addCritter(critter: CRITTER)
do
list.put(animal, num)
num := num + 1
end
removeCritter(critter: CRITTER)
do
list.put (list.at (num), ???) -- put last element in position of element to be removed
list.remove_tail (num) -- remove tail
num := num - 1
end
end
Two issues:
Firstly, I can instantiate the CONTAINER class inside APPLICATION, but when I call
create container.make
container.addCritter(myCritter)
I get a precondition, invalid index violation error on the second line. This may be because I have not set the upper and lower bounds of the array. However, when I try to do so, I get syntax errors. Which is the way to solve this issue?
Secondly, in order to remove an object from the array, it would help if I could get hold of the index value, but I can't see any function that does this, unless I am missing something.
ARRAYs are usually used for fixed-length containers. In your case, with lots of dynamic changes, it's better to use more dynamic structures, for example, ARRAYED_LIST. Similar to ARRAY it provides features to access items by their index, but there are also more convenient ones. New elements can be added by using feature extend. Old elements can be removed by using feature prune if only one element matching a given one needs to be removed, or prune_all, if all matching elements need to be removed. The word "matching" denotes either reference or object equality, depending on which comparison criteria is required: = or ~. The comparison criteria is changed using feature compare_objects.
Some general observations:
There is no need to track number of elements yourself, usually there is a feature count that provides this number.
Indexes in Eiffel usually start with 1, not 0.
The declaration detachable INTEGER is equivalent to INTEGER because INTEGER is expanded and all expanded types are attached regardless of any attachment marks.
The following discussion might also be useful:
How to initialise an array of objects in Eiffel?

matlab initialize array of objects

I am playing around with OOP in MATLAB, and I have the following constructor:
function obj = Squadron(num_fighters, num_targets, time_steps)
if nargin == 0
num_targets = 100;
time_steps = 100;
num_fighters = 10;
end
obj.num_shooters = num_fighters;
for iShooter = 1:obj.num_shooters
a(iShooter) = Shooter(num_targets, time_steps);
end
obj.ShooterArray = a;
obj.current_detections = zeros(num_fighters, num_targets);
end
That temporary variable 'a' smells terrible. Is there a better way to initialize an array of objects, I wish there was a push/pop method. I am sure there is a better way to do this.
Looks like you are trying to create an array of handle objects (Shooters) and store it inside the property of another handle object (a Squardron). I have had a very similar problem discussion that might help you.
In short: What you are doing might not be pretty - but might be pretty good already.
When creating an array in Matlab it is usually a good Idea to do some pre-allocation to reserve memory which speeds up performance significantly.
In a normal case something like this:
a=zeros(1,1000);
for n=1:1000
a(n)=n;
end
(here a=1:1000; would be even better)
For objects the pre-allocation works by assigning one of the objects to the very last field in the array. Matlab then fills the other fields before that with objects (handles) that it creates by calling the constructor of that object with no arguments (see Matlab help). Hence a pre-allocation for objects could look like this:
a(1,1000)=ObjectConstructor();
for n=1:1000
a(n)=ObjectConstructor();
end
or simply
for n=1000:-1:1
a(n)=ObjectConstructor();
end
Making sure Shooter can be called with no arguments you should be able to do something like:
for iShooter = obj.num_shooters:-1:1
obj.ShooterArray(iShooter) = Shooter(num_targets, time_steps);
end
However, it turns out that for some reason this direct storing of an array of objects in another object's property creates very bad performance. (Probably the array pre-allocation does not work well in this case). Hence using an auxiliary variable and allocating the full array at once to the property is in this case is a good idea to increase performance.
I would try:
for iShooter = obj.num_shooters:-1:1
a(iShooter) = Shooter(num_targets, time_steps);
end
obj.ShooterArray = a;
Again - for more detail see this discussion
There are a couple of ways to handle this situation...
Building object arrays in the constructor:
You could modify your Shooter class such that when you pass arrays of values it creates an array of objects. Then you could initialize ShooterArray like so:
obj.ShooterArray = Shooter(repmat(num_targets,1,num_fighters),...
repmat(time_steps,1,num_fighters));
Replicating instances of a value class:
If Shooter is a value class, and each object is going to be exactly the same (i.e. you don't initialize any of its default properties to random values), then you can create just one object and replicate it using REPMAT:
obj.ShooterArray = repmat(Shooter(num_targets,time_steps),1,num_fighters);
Unfortunately, if Shooter is a subclass of the handle class, you can't just replicate it as you can with a value class. You would actually be replicating references to just one object, when you really need a number of separate objects each with their own unique reference. In such a case, your current code is likely the best solution.

Sort ArrayBuffer[A] in scala?

I have an array in Scala with the class ArrayBuffer[Actor], where Actor is a class that implements the Ordered[Actor] trait. How do I sort this array without coding it manually?
I know there is an object called Sorting, but it doesnt seem to work since ArrayBuffer doesn't implement/extend the right classes.
How do I sort ArrayBuffer[A] type arrays?
If you are using Scala 2.8, you could use the sortWith method of the ArrayBuffer[T] class, which is inherited from the SeqLike trait.
The following code snippet sorts an ArrayBuffer[T] object in ascending order:
def ascendingSort[T <% Ordered[T]](xs: ArrayBuffer[T]) = xs.sortWith(_ < _)
Note that this does not mutate the actual ArrayBuffer, but creates a new one with the elements in the right order.
If you are using Scala 2.7, you could use the stableSort method of the Sorting object. This takes the elements of the ArrayBuffer and produces an array of elements sorted in the right order (given by a closure as an argument, ascending as a default).
For example:
val a = new scala.collection.mutable.ArrayBuffer[Int]()
a += 5
a += 2
a += 3
scala.util.Sorting.stableSort(a)
The important question is what do you want to do with the ArrayBuffer. Usually, a Buffer is used internally in different algorithms in order to increase the performance of intermediate results. If you are using it for that, have a look at the ways of sorting the collection you want to return at the end of your algorithm. The Sorting object already provides a way of transforming an ArrayBuffer into a sorted Array.
From the scaladoc of the Buffer class:
Buffers are used to create sequences of elements incrementally
As you are using it with Actors, it might be used for some kind of actor queue - in which case, you might want to have a look at the Queue collection.
Hope it helps,
-- Flaviu Cipcigan
Btw, the Actor class here is my own class used for "Actors" in a world created using my new game engine for scala ("Awesome Game Engine for Scala ~ AGES"), so it has nothing to do with the concurrency actor class. Also, implementations of lists in scala are a jungle, everything is either deprecated or implemented in a lot of different ways...ArrayBuffer works for my need (my need being a variable size array for containing actors).
Hope this clarifies :)

Resources