Eiffel: setting a constant with reference to other class constant - eiffel

How to set a constant refering to another class constant in Eiffel?
Something like that doesn't compile unfortunately
Default_log_level: like {MY_LOGGER}.log_level = {MY_LOGGER}.Log_level_info

Constant attributes cannot be defined using other constant attributes in the current version of Eiffel.

Constant attributes can only be made of a manifest constant, but a possible workaround could be to use frozen once functions:
frozen Default_log_level: INTEGER
once
Result := {MY_LOGGER}.Log_level_info
ensure
definition: Result = {MY_LOGGER}.Log_level_info
end
frozen means that it cannot be redefined in descendant classes (like constant attributes).
Unfortunately, the type of once functions cannot rely on anchored types, hence the use of INTEGER instead of like {MY_LOGGER}.log_level.
And finally, the drawback with this solution is that it cannot be used where constant attributes are expected (e.g. in inspect instructions).

Related

FloatArray vs Array<Float>: why are they different

Apologies if the answer is obvious, but I don't get it. I have a function that accepts a FloatArray so I passed a Array<Float> to it but it rejects it! I thought FloatArray was just another way of creating Array<Float>. What's the difference?
Short answer: one is an array of primitives, the other an array of references to Float objects.
The difference is mostly hidden from you in Kotlin, so to explain it's probably best to go back to Java…
Java has nine basic types (if I've counted correctly). Eight of them hold a value directly: boolean, byte, short, char, int, long, float, and double — those are called ‘primitives’. The other type is a reference, which can point to an instance of an object or array.
Because there are cases when you need to pass one of those primitive values around as an object, Java also provides some objects which simply wrap a primitive value: java.lang.Boolean, java.lang.Byte, and so on. There's one for each primitive type.
Most code uses primitives directly, but sometimes it's handy to be able to pass an object reference. (For one thing, primitives are not nullable, so if you need to support a null, then you'll need an object reference. For another, generic code such as List and the other classes in the collections framework can handle only object references.)
However, object wrappers are less efficient, because each instance is a full object and takes a certain amount of memory (e.g. 16–32 bytes, depending on the Java runtime) — and that's in addition to the size of references to it (perhaps 8 bytes). The JVM caches commonly-used wrappers (e.g. true and false for booleans, and some small numbers), but for anything else you'll be creating new objects on the heap.
The wrappers are clearly distinguished from the primitive types — they're capitalised (and, in the case of Integer, spelled differently). In early versions of Java, they were not interchangeable; you needed to explicitly wrap (e.g. Int(someValue) and unwrap (e.g. someReference.intValue()) when needed. Java 5 added ‘autoboxing’, where in many cases the compiler would do that for you. This blurs the distinction a bit, but most of the time you still need to be aware of it.
One of the benefits of Kotlin is that it removes some of Java's unnecessary complexity. One of the ways it does this is by hiding that distinction almost completely. The Kotlin language has no primitives: everything looks like an object. However, for reasons of efficiency, compiled Kotlin uses primitives ‘under the hood’ where possible. For example:
var i: Int
That declares an Int value — which will be stored as a primitive field. However:
var i: Int?
That declares a reference to an integer wrapper. (That's because primitives are not nullable, and so a primitive can't store a null value.)
This is an implementation detail: most of the time, when you're writing Kotlin, you don't need to be aware of this. But the distinction is still there at runtime, and arrays are one of the rare times it becomes visible:
FloatArray is an array of primitives. It uses the minimum of memory, and interoperates with Java code that uses a float[] type.
Array<Float> is an array of references to Float objects. It's more flexible, and interoperates with Java code that uses a Float[] type.
So you can see that these are two different types, even though they do similar things.
If you're interoperating with existing code, that will control which one you should use. If you're writing new code, then you have the choice: FloatArray is likely to be more efficient and use less memory — but Array<Float> tends to be better supported in other code (which may be able to process all the relevant types just by accepting a generic Array, instead of having to support FloatArray and IntArray and LongArray and all the others).
Some information about arrays in Kotlin is available here: https://kotlinlang.org/docs/basic-types.html#primitive-type-arrays
Kotlin also has classes that represent arrays of primitive types without boxing overhead: ByteArray, ShortArray, IntArray, and so on. These classes have no inheritance relation to the Array class, but they have the same set of methods and properties.
So FloatArray and Array<Float> are not the same, the difference is that the first has no boxing overhead.
Look at how FloatArray is declared in the documentation. It is just another class, not related to the Array<T> class at all. Sure, they represent very similar things, with the difference being that one of them would box Float values, and the other doesn't, as explained by the other answer. But from the perspective of the type system, they are totally unrelated. It's as if I declared:
class A
class B
and tried to pass an instance of A to a parameter expecting a B.
There are builtin methods to convert between these types though:
floatArrayOf(1f,2f,3f).toTypedArray() // FloatArray to Array<Float>
arrayOf(1f,2f,3f).toFloatArray() // Array<Float> to FloatArray
It's just that there is no implicit conversion between them, because these are unrelated types, unlike if you have subclasses and superclasses for example.

Eiffel, multiple types conformance: a way to specify that a parameter is a descendent from A and B?

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.

D: Creating an array of templated objects

I'm trying to create an array of Regex objects, like so: Regex[] regexes;.
The compilation fails with main.d(46): Error: template std.regex.Regex(Char) is used as a type.
I find the documentation cryptic. All I understand is that templates generate code on compilation, but I don't see what's preventing me from creating an array of Regex.
There's an existing question on StackOverflow with the same problem, but it deals with C++, not D.
You cannot create a regex object without first instantiating the template with a type. this is because the actual type is generated at compile time based on the instantiation type you give. Regex itself is not an actual type, it is just a template function allowing you to generate a type when instantiated.
In this case you probably want to change:
Regex[] regexes;
into:
Regex!char[] regexes;
to tell the compiler that your regex contains chars as opposed to some derived type. This means specifically you are instantiating the Regex template with the type char.

Recursive visibility of symbols in Ada packages

Let's say I have a generic vector library. To make it easier to use, I want to instantiate various common forms of the vector library and make them visible in a single package.
I'm trying this:
with GenericVector;
package Vectors is
package Vectors3 is new GenericVector(3);
use all type Vectors3.Vector;
subtype Vector3 is Vectors3.Vector;
package Vectors4 is new GenericVector(4);
use all type Vectors4.Vector;
subtype Vector4 is Vectors4.Vector;
end;
The end goal is that I want to be able to do with Vectors; use Vectors; and end up with Vector3 and Vector4 types directly available which Just Work.
Naturally, the code above doesn't work. It looks like the use all type statements import the definitions attached to the specified type into the package specification but then those definitions aren't exported to the user of Vectors. I have to do with Vectors; use Vectors; use all type Vectors.Vectors3; instead. This is kind of sucky.
How can I do this?
You could simply make Vector3 and Vector4 new types, and not just subtypes. That would implicitly declare all the inherited, primitive operations from GenericVector in Vectors.
use Vectors gives you direct visibility to those identifiers that are declared in Vectors, including those that are declared implicitly. (Implicit declarations are things like "+", "-", operators when you declare a new integer type, and inherited operations when you declare a derived type.) But it doesn't give you direct visibility to anything else. In particular, use is not transitive, because use all type Vectors3.Vector does not declare any new identifiers in Vectors.
You could accomplish this by declaring renaming identifiers for everything that you want a use Vectors user to see. (For types, you'd have to use subtype since there's no type renaming in Ada.) E.g. in Vectors:
function Dot_Product (V1, V2 : Vectors3.Vector) return Float
renames Vectors3.Dot_Product;
(I'm just guessing at what the operations in GenericVectors might look like.) Now, anywhere that says use Vectors will be able to use Dot_Product directly. You'd have to do something like this for every identifier, though. If there are a lot of them, this probably isn't a viable solution. (The renaming declaration doesn't have to use the same name Dot_Product.)
Although it may seem annoying that you can't get this kind of transitive visibility, the alternative probably would turn out to be more annoying, because you can't look at Vectors and see what identifiers would be made visible by use Vectors; the result would probably be either unexpected name conflicts or other surprises.

Objective-C / C giving enums default values

I read somewhere about giving enums default values like so:
typedef enum {
MarketNavigationTypeNone = 0,
MarketNavigationTypeHeirachy = 1,
MarketNavigationTypeMarket = 2
} MarketNavigationLevelType;
.. but i can't remember the value of doing this. If i don't give them default values - and then someone later on reorders the enum - what are the risks?
If i always use the enum name and don't even refer to them by their integer value, is there any risks?
The only possible problem i can think of is if i'm initialising an enum from an int value from a DB - and the enum is reordered - then the app would break.
That are not default values, you are giving them the values they will always have.
If you wouldn't initialize them explicitly, the first enumerators value is zero. For all others, if there is no initializer, their value is the value of the previous enumerator increased by one.
There are two reasons for giving them explicit values:
you don't want them to have the values they'd have otherwise
you want to make it clear what value they have (for you or other developers)
If you always refer to them by their name and never explicitly use an integral value for comparison or assignment, explicitly giving them a value is not needed.
In general this only matters if the enum is exposed to some kind of external API or it is going to be used to exchange data via data files or other means. If the enum is only every used within your app and nowhere else then the actual values don't matter.

Resources