I'm looking for a way to call Precursor on another feature. The context is that I redefine a routine calling another heir's feature that calls mine, and I'd like to call it explicitly. Is there a way to do something such as in java Precursor.feature_a.
If not, the only alternative I find is to write a feature_a_implementation and call it from redefined feature. Is there a particular reason not to have this mechanism? The consequences of doing that would be to define 2 times the contract of feature_a into feature_a and feature_a_implementation
Feature replication can be used for that:
class A feature
f do print ("A") end
end
class B inherit
A redefine f select f end
A rename f as g end
feature
f do print ("B") end
h do g end
end
Feature f of class A appears in class B twice: under name f (the redefined and selected version) and under name g (the original version). The feature h calls g and prints A as expected.
Related
Repeatedly inheriting from 2 classes having the same parent, I fall into the classic case of inheriting 2 times of the same attribute. I'd like to merge the 2 attributes into one and tried to do it with an undefine, but it gets me a compile error.
The other solution I see is renaming the attribute from one of both parents, but as I understand each instance of my D class would have an useless attribute which is not what I want...
Error: Undefine subclause lists name of frozen feature or attribute or
C external.
What to do: unless you can change the status of the feature in the parent,
remove its name from Undefine subclause since it cannot be undefined.
How to merge 2 attributes from repeatedly inherited classes
class A
serial: STRING
end -- class A
class B
inherit
A
end -- class B
class C
inherit
A
end -- class C
class D
inherit
B
undefine
serial -- error seems to appear here in that case
end
C
end -- class D
In case it's two unrelated attributes (not coming from the same parent) that you want to merge, you should redefine both of them:
class A
feature
serial: STRING
end
class B
feature
serial: STRING
end
class C
inherit
A
redefine
serial
end
B
redefine
serial
end
feature
serial: STRING
end
As you already saw, the compiler will not let you undefine an attribute, even when the goal is to merge it with another attribute.
There is no reason to undefine a feature that is going to be merged with the same version coming from a different inheritance path. In the example, the attribute serial is not changed in B, C, and D. Therefore, inheriting from B and C without any adaptation is OK:
class D inherit
B
C
end
Is there a way (I'm sure there is out of runtime check...) to specify that a parameter or a variable in general conforms to multiple types? to avoid doing something such as
work (a_printer: PRINTER; a_scanner: SCANNER)
do
a_printer.print
a_scanner.scan
-- OR without second parameter
if attached {SCANNER} a_printer as l_scanner then
l_scanner.scan
else
throw RuntimeError
end
end
If feature work belongs to a class that may have formal generic parameters, it could be defined as taking one argument of the corresponding formal generic type:
class X [D -> {PRINTER, SCANNER}] feature
work (device: D)
do
device.scan
device.print
end
end
Then, at the caller site, one could make the call
x.work (multi_function_device)
where x has an appropriate type, e.g. X [MULTI_FUNCTION_PRINTER].
If work could also be declared and implemented as a class feature, the temporary variable could be avoided:
{X [like multi_function_device]}.work (multi_function_device)
If the auxiliary class X is not an option, the current version of the language provides no means to declare an argument as conforming to more than 1 type (e.g., work (d: {PRINTER, SCANNER})), so you would have to resort to preconditions like
work (p: PRINTER)
require
attached {SCANNER} p
do
check
from_precondition: attached {SCANNER} p as s
then
s.scan
end
p.print
end
I think that, if possible, you should use a common ancestor to your multiple types. If you cannot (if you are using library types), you can create descendant classes (MY_PRINTER inherit from PRINTER and DEVICE and MY_SCANNER inherit from SCANNER and DEVICE). Another way is to use ANY as the type, but it is not the best solution.
I don't know if this feature exists or if symbolic is the right name for it.
I want to be able to have a variable, say f, for a (math) function with certain properties. I want to be able to use this variable in expressions. But I don't actually want to define what the function f does.
For example, I might want to say "define f to be a function in one variable that is differentiable on the real numbers". Then I want to be able to use f(x) in expressions. I might want to define another function g(x) in terms of f(x) and be able to differentiate g(x) and get an expression from sage. So I want to issue the following commands
f is defined as before
define g(x)=(f(x))^2
differentiate g
output: g'(x)=2f(x)f'(x)
Does this feature exist?
How about this:
sage: f = function('f')
sage: g(x) = f(x)**2
sage: g.derivative()
x |--> 2*f(x)*diff(f(x), x)
class
MAP[G]
create
make
feature --attributes
g_array: ARRAY[G]
size:INTEGER
feature{NONE}
make
do
g_array.make_empty
size:=0
end
class
MAP_TESTING
m: MAP[INTEGER]
create m.make
print(m.size)
The first class consist of an array and its size. When I tried to create an m object of ARRAY, nothing seems to be printing out when I put print(m.size). Am I instantiating the array correctly? Am I using the correct make function for ARRAY? Why isn't it printing anything?
---------------------------
class
MAP[G]
create
make
feature --attributes
g_array: ARRAY[G]
size:INTEGER
feature{NONE}
make
--I left this blank
end
class
MAP_TESTING
m: MAP[INTEGER]
create m.make
print(m.size)
This actually works when I left the make blank. It prints out 0. But this is no good because obviously if I call other functions using the array in MAP, it won't work. I actually tried using other functions from the class ARRAY, but I got a compile error.
The line to create the array in MAP should be:
create g_array.make_empty
And MAP_TESTING should be:
class
MAP_TESTING
creation
make
feature
m: MAP[INTEGER]
make
do
create m.make
print(m.size)
end
end
(Note that the print does not output a newline so the zero may easily be lost in the terminal.)
I have two things that I would like to do with my matlab function. I have a function that will get data from a series of files. Say i have this file structure:
Number 1:
I would like to be able to have some selected variables in a function become globally accessible and persist after the function has completed. That is say i have the following function:
[] = function(directory)
b = read(directory)
struct c = (do some stuff with b)
somehow globalise c
end
I understand that you can have c = function(directory) and then pass a variable however i would not like to o this, i would rather that the variable c just persists in the global scope. Can this be done?
Number 2:
Is it possible for a matlab function to have default arguments. Lets take the function from above. What I want to do is to have the directory default as the current directory. For example if the following data structure exists:
MatlabMainFolder
-> MatlabFunctions
-> Data
The user should be able to run function in Data and it will use the Data directory.But should also be able to do function('../Data') from the MatlabFunctions directy for the same effect. Is this possible?
First:
I think the following should make a variable globally accessible from within the function:
[] = function(directory)
b = read(directory)
global c; <------
struct tmp = (do some stuff with b)
c = tmp; <------
end
Then, add global c in all other files where you want c to be available, before using it. I would recommend just using c = function... if at all possible, though.
As suggested by #Ben, assignin can also be used to assign a variable into a different workspace. That way, from a function, any variable can be assigned in the 'base' workspace, which is the workspace accessible by all other files too. In this case:
assignin('base','c',c)
will create a variable c in the base workspace, with the same value as c in the function file. (Add this line at the end of the function).
Second:
You could do something like this:
function(path)
if nargin<1
path = '../Data';
end
% do things with path
end
This way, if function is called without inputs, the default path ../Data will be used, otherwise, the path given as input will be used. nargin will be equal to the number of arguments that were given as input.
To 1) globals as well as asignin are often frowned upon. You could also use persistent
Pseudocode snippet:
function out=fun((directory)
persistent out
if isempty(out)
fill out
return out;
Or even handle objects in case you feel like going modern ;)
To 2): Read about doc InputParser - it's more work than in many other languages - but it's possible.