Core classes and methods used by default by Nit programs and libraries.
This module is the root of the module hierarchy. It provides a very minimal set of classes and services used as a foundation to define other classes and methods.
Each other class implicitly specializes Object,
therefore the services of Object are inherited by every other class and are usable
on each value, including primitive types like integers (Int
), strings (String
) and arrays (Array
).
Note that Object
, not Object
, is the root of the type hierarchy
since the special value null
is not considered as an instance of Object.
self
and other
the same value?assert 1 + 1 == 2
assert not 1 == "1"
assert 1.to_s == "1"
The exact meaning of same value is left to the subclasses.
Implicitly, the default implementation, is is_same_instance
.
The laws of ==
are the following:
a.is_same_instance(b) implies a == b
(a == b) == (b == a)
(a == b) and (b == c) implies (a == c)
==
might not be constant on some objects overtime because of their evolution.
var a = [1]
var b = [1]
var c = [1,2]
assert a == b and not a == c
a.add 2
assert not a == b and a == c
Lastly, ==
is highly linked with hash
and a specific redefinition of ==
should
usually be associated with a specific redefinition of hash
.
ENSURE result implies self.hash == other.hash
self
and other
different values?!=
is equivalent with not ==
.
The hash code is used in many data-structures and algorithms to identify objects that might be equal.
Therefore, the precise semantic of hash
is highly linked with the semantic of ==
and the only law of hash
is that a == b implies a.hash == b.hash
.
assert (1+1).hash == 2.hash
assert 1.to_s.hash == "1".hash
hash
(like ==
) might not be constant on some objects over time because of their evolution.
var a = [1]
var b = [1]
var c = [1,2]
assert a.hash == b.hash
a.add 2
assert a.hash == c.hash
A specific redefinition of ==
should usually be associated with a specific redefinition of hash
.
Note that, unfortunately, a correct definition of hash
that is lawful with ==
is sometime tricky
and a cause of bugs.
Without redefinition, hash
is based on the object_id
of the instance.
self
and other
are the same instance (i.e. same identity).var a = new Buffer
var b = a
var c = new Buffer
assert a.is_same_instance(b)
assert not a.is_same_instance(c)
assert a == c
Obviously, the identity of an object is preserved even if the object is mutated.
var x = [1]
var y = x
x.add 2
assert x.is_same_instance(y)
Unless specific code, you should use ==
instead of is_same_instance
because
most of the time is it the semantic (and user-defined) comparison that make sense.
Moreover, relying on is_same_instance
on objects you do not control
might have unexpected effects when libraries reuse objects or intern them.
Unless specific code, you should not use this method but
use hash
instead.
As its name hints it, the internal hash code, is used internally
to provide a hash value.
It is also used by the inspect
method to loosely identify objects
and helps debugging.
var a = "Hello"
var b = a
assert a.object_id == b.object_id
The specific details of the internal hash code it let to the specific engine. The rules are the following:
object_id
MUST be invariant for the whole life of the object.object_id
.object_id
.object_id
of a garbage-collected instance MIGHT be reused by new instances.object_id
of an object MIGHT be non constant across different executions.For instance, the nitc
compiler uses the address of the object in memory
as its object_id
.
TODO rename in something like internal_hash_code
This method MUST not be used by programs, it is here for debugging only and can be removed without any notice.
TODO: rename to avoid blocking a good identifier like output
.
This method MUST not be used by programs, it is here for debugging only and can be removed without any notice.
TODO: rename to avoid blocking a good identifier like output
.
self
and other
have the same dynamic type.assert 1.is_same_type(2)
assert "Hello".is_same_type("World")
assert not "Hello".is_same_type(2)
The method returns false if the dynamic type of other
is a subtype of the dynamic type of self
(or the other way around).
Unless specific code, you should not use this method because it is inconsistent with the fact that a subclass can be used in lieu of a superclass.
Sys
is a singleton class, its only instance is accessible from everywhere with sys
.
Because of this, methods that should be accessible from everywhere, like print
or exit
,
are defined in Sys
.
Moreover, unless there is an ambiguity with self
, the receiver of a call to these methods is implicitly sys
.
Basically it means that the two following instructions are equivalent.
print "Hello World"
sys.print "Hello World"
Sys
is the class where are defined top-level methods,
i.e. those defined outside of any class like in a procedural language.
Basically it means that
redef class Sys
fun foo do print "hello"
end
is equivalent with
fun foo print "hello"
As a corollary, in a top-level method, self
(the current receiver) is always sys
.
In a module, the instructions defined outside any classes or methods
(usually called the main of the module) is
an implicit definition of this main
method.
Basically it means that the following program
print "Hello World"
is equivalent with
redef class Sys
redef fun main do
print "Hello World"
end
end
When a program starts, the following implicit sequence of instructions is executed
sys = new Sys
sys.run
Whereas the job of the run
method is just to execute main
.
The only reason of the existence of run
is to allow modules to refine it
and inject specific work before or after the main part.
main
method to be implemented by subclassesactors > examples > agent_simulation
a "Framework" to make Multi-Agent Simulations in Nitactors > examples > fannkuchredux
Example implemented from "The computer Language Benchmarks Game" - Fannkuch-Reduxactors > examples > mandelbrot
Example implemented from "The computer Language Benchmarks Game" - Mandelbrot