Surprised that Default in class ANY is frozen and without implementation???, what is the semantic for this function??
Class ANY
frozen default: detachable like Current
-- Default value of object's type
do
end
My intention was to define a default: like Current or maybe detachable which returns the default value for current Class, so redefine it...
This is a default value of a detachable version of a type. For reference types, this is Void. For expanded types, this is the corresponding default value, i.e. the one initialized with default_create. E.g., for BOOLEAN, it is False.
If an expanded class provides a specific implementation of default_create, it is used to initialize Result even without a body in default. For example, consider a class
expanded class X inherit ANY redefine default_create end feature
item: INTEGER_32
default_create do item := 42 end
end
For a variable x of type X, an expression x.default.item would give 42. When default is called, the value of Result is initialized by calling X.default_create that sets item. So, no instructions in the body of default are required.
To summarize, default returns
Void for reference types;
a default value for expanded types that do not redefine default_create, including basic types: False, 0, 0.0, etc. If an expanded type has nested attributes, they are initialized recursively using the same rule.
a value obtained by calling default_create otherwise.
Related
I want to use intersection so I dont have to explicitly write every type of my defaultProps but rather take it's type from my declared variable, is that possible? As you can see in my code example even thought myProp is set as nullable, it isn't accepting null value
An intersection combines existing types meaning all the types on both object are present. You cannot use the type of the declared variable to define testProps if its a union of multiple types, as when you set the default value you bind it to a particular type.
How do you declare a variable to be the same type as a type parameter used to instantiate a generic class? The following code does not compile:
class
TEST [G, H -> INTEGER]
feature
f (i: INDEXABLE [G, H])
local
y: H
do
y := i.lower -- Type error here.
end
end
The compiler says that the source of the assignment is not compatible with target.
In the current implementation, INDEXABLE [G, H] inherits from TABLE [G, INTEGER]. As a result, lower is of type INTEGER, not H. And INTEGER does not conform to the formal generic type H of the class TEST. This explains the error.
To me, it looks like a mistake in the declaration of class INDEXABLE. It should inherit from TABLE [G, H] instead. Then, the example code would compile.
Type anchoring can be used in those cases:
feature
f (i: INDEXABLE [G, H])
local
y: like i.lower
do
y := i.lower
end
Sometimes a generic type is not used as return type of any accessible feature on a class, so in those cases I like to declare a fake feature specifically to allow anchoring:
class SOME_CLASS [G]
feature
generic_type_anchor: G
do
check
for_anchoring_only: False
-- This method should never actually be called, only used as an anchor in type declarations
end
end
This is particularly useful with complex inheritance trees or when descendant classes close the generics, in which case the correct type is not apparent from the declared type. Personally I tend to use type anchoring whenever values are semantically related as this helps expressing intent, simplifies refactoring (as there are fewer repetitions of types which by definition must match) and facilitates covariance.
Also as a side-note, expanded types (like INTEGER) cannot be used polymorphically (you need a reference for that; if class A is expanded and class B [expanded or reference] inherits A, you could not assign a value of type B to a variable of type A; inheritance from expanded types is implicitly non-conforming), and moreover the compiler disallows inheriting from basic expanded types (INTEGER, BOOLEAN, REAL_64, etc.), therefore the generic constraint in your example makes no sense because H could never be anything but INTEGER.
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.
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).
Scala.Array includes a function toArray, as an implicit import from ArrayOps.
Are there any use cases for Array.toArray or will it always return a copy of the object?
ArrayOps inherits toArray from GenTraversableOnce (and a default implementation is provided in TraversableOnce)
In case of an Array it's pointless, but the method is there for all the other subclasses of GenTraversableOnce, like Map, List, Set and many others.
Analogously, Map inherits a pointless toMap method, List a toList, Set a toSet and so on.
In the specific case of toArray, the default implemention provided in the TraversableOnce trait is overridden by ArrayOps.
Calling toArray on an Array will return a new one only if the runtime class of the destination type is different, otherwise it will just cast the Array to the appropriate type and return the same instance.
So, generally speaking, calling toArray on an instance of Array is useless, although not significantly expensive.