I come from a Kotlin background and I used to the fact that enums there implements Comparable, which allows me do something like below:
Given a enum
enum class Fruit{
APPLE,
BANANA,
ORANGE,
}
I could use the operators <, >, <= or >=, to compare any occurrence of this enum, like:
APPLE < BANANA -> true
ORANGE < BANANA -> false
I wonder if dart has the same by default or if I have to define custom operators to any enum I might need that.
It's easy to check Enum documentation or try it yourself to see that Enum classes do not provide operator <, operator >, etc.
Dart 2.15 does add an Enum.compareByIndex method, and you also can add extension methods to Enums:
extension EnumComparisonOperators on Enum {
bool operator <(Enum other) {
return index < other.index;
}
bool operator <=(Enum other) {
return index <= other.index;
}
bool operator >(Enum other) {
return index > other.index;
}
bool operator >=(Enum other) {
return index >= other.index;
}
}
As explained in other comments, you can also create your own operator and use it.
Try the code below to see how to handle it without creating an operator.
enum Fruit{
APPLE,
BANANA,
ORANGE,
}
void main() {
print(Fruit.APPLE.index == 0);
print(Fruit.BANANA.index == 1);
print(Fruit.ORANGE.index == 2);
if( Fruit.APPLE.index < Fruit.BANANA.index ){
// Write your code here
print("Example");
}
}
result
true
true
true
Example
Since 2.15, statically:
compareByIndex<T extends Enum>(T value1, T value2) → int
Compares two enum values by their index. [...]
#Since("2.15")
compareByName<T extends Enum>(T value1, T value2) → int
Compares enum values by name. [...]
#Since("2.15")
https://api.dart.dev/stable/2.16.1/dart-core/Enum-class.html
Related
So the Dart API says this about the == operator:
The equality operator.
The default behavior for all Objects is to return true if and only if
this object and other are the same object.
Override this method to specify a different equality relation on a
class. The overriding method must still be an equivalence relation.
That is, it must be:
Total: It must return a boolean for all arguments. It should never
throw.
Reflexive: For all objects o, o == o must be true.
Symmetric: For all objects o1 and o2, o1 == o2 and o2 == o1 must
either both be true, or both be false.
Transitive: For all objects o1, o2, and o3, if o1 == o2 and o2 == o3
are true, then o1 == o3 must be true.
The method should also be consistent over time, so whether two objects
are equal should only change if at least one of the objects was
modified.
If a subclass overrides the equality operator, it should override the
hashCode method as well to maintain consistency.
But how exactly does Dart check, if 2 Objects are the same?
return true if and only if
this object and other are the same object
could be understood as "checks if both objects are references to the same instance" which apparently isn't the case.
So lets say I have 2 instances of
class Car {
int tires = 4;
Color color = Colors.blue;
int doors = 4;
}
Car carA = Car();
Car carB = Car();
From my understanding if I check carA == carB, Dart compares all properties of both instances by looping over them?
If thats the case, does it always drill down to primitives if, for example, some properties are non-primitive classes?
Thanks
I believe that Dart does "checks if both objects are references to the same instance". If you want to compare the properties you can override the == operator, for example:
class Car {
int tires = 4;
int doors = 4;
#override
bool operator ==(Object other) {
return other is Car && this.tires == other.tires && this.doors == other.doors;
}
#override
int get hashCode => this.tires * this.doors;
}
void main() {
Car carA = Car();
Car carB = Car();
print("equal ${carA==carB}");
print("identical ${identical(carA,carB)}");
}
Now the cars are equal. Note that the function identical() does check for the same object.
The Dart Spec specifies that constant objects do check the properties, for example:
class ConstCar {
final int tires = 4;
final int doors = 4;
const ConstCar();
}
void main() {
ConstCar constCarA = const ConstCar();
ConstCar constCarB = const ConstCar();
print("equal ${constCarA==constCarB}");
print("identical ${identical(constCarA,constCarB)}");
}
This returns true for == and identical().
I have a metamodel in which I have a class Range with min a max integer values and I want to define an xText DSL, in which you can define a range like 1..10, but also standard defaults like ? and ! that would stand for 0..1 or 1..1. I looked around the documentation, but couldn't find any way to define this in the xText grammar. So far, I have a rule for the general case
Range: min=INT '..' max=INT;
However, I didn't find any way to define something like
Range: '?' min=0 max=1;
Range: '!' min=1 max=1;
How could I achieve similar behavior for my DSL?
Please note that I am not interested in generating a metamodel from the grammar, as the DSL models should adhere to an existing metamodel.
i dont know an easy solution for that but you might be able to customize Xtexts object creation e.g. like
Model: ranges+=AbstractRange*;
AbstractRange returns Range: ExplicitRange | ZORange | OORange;
ExplicitRange returns Range: min=INT ".." max=INT;
ZORange returns Range: {Range} max=ZEROONE;
ZEROONE returns ecore::EInt: "?";
OORange returns Range: {Range} max=ONEONE;
ONEONE returns ecore::EInt: "!";
And following Customizations
class MyDslEcoreElementFactory extends DefaultEcoreElementFactory {
#Inject extension MyDslGrammarAccess
override set(EObject object, String feature, Object value, String ruleName, INode node) throws ValueConverterException {
if (object instanceof Range) {
if (ruleName == grammar.name+"."+ZEROONERule.name) {
object.max = 1
object.min = 0
return;
} else if (ruleName == grammar.name+"."+ONEONERule.name) {
object.max = 1
object.min = 1
return;
}
}
super.set(object, feature, value, ruleName, node)
}
}
bound like this
class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
override bindIAstFactory() {
MyDslEcoreElementFactory
}
}
unfortunately org.eclipse.xtext.parser.IAstFactory.create(EClassifier)
does not have a second param that specifies the node or rule you are in and you resist to introduce subclasses for the ranges (in a metamodel inherited from your one) which would make this a bit easy (override create only)
How do you 'or' enum entries in IronScheme, ex:
(import
(rnrs)
(ironscheme clr))
(clr-using System.Reflection)
(define public-class-attributes
(bitwise-ior
(clr-static-field-get
TypeAttributes Public)
(clr-static-field-get
TypeAttributes Class)))
(display public-class-attributes)
This causes an error, I haven't found an alternative in the documentation.
I am not sure what your use case is, but as mentioned in the comment, when using clr-call a list of symbols can be used for an OR'd enum. Example here.
Internally, the compiler will wrap the list with a call to Helpers.SymbolToEnum<T>().
Note: The case is ignored.
To illustrate in a small example:
C# code:
[Flags]
enum Foo
{
Bar = 1,
Baz = 2
}
class AType
{
static void Kazaam(Foo foo) { ... }
}
Scheme code:
; same as Bar | Baz
(clr-static-call AType Kazaam '(Bar Baz))
; single value
(clr-static-call AType Kazaam 'Baz)
; same thing
(clr-static-call AType Kazaam '(Baz))
; no value (iow zero)
(clr-static-call AType Kazaam '())
If these are just simple flag, lists should suffice, else you can redefine the enum as an enum-set in Scheme which allows many set operations. Finally, you just use enum-set->list to get the list to pass as an argument as shown above.
I have a Rails application in which I'd like a user to be able to create custom boolean combinations from a list of categories, which is itself dynamically loaded. For example, if I have the categories foo bar and baz, I would like the user to be able to select (foo AND bar) OR baz or foo OR baz or any other logical combination of those categories. The most common use case I anticipate is something like (a OR b OR c) AND (d OR e OR f) AND (g OR h); that is, a conjunction of several disjunctions.
The results would then be stored in some data structure which could be later used as a filter. Ideally this would all be done through a graphical interface, rather than having the user construct the boolean logic in text.
Before I attempt to implement this myself, is there a library that I can pull in that already implements this or something similar? Or something open-source that could get me part of the way there, and that I could fork and modify?
You could implement a Boolean Retrieval with four ways to select a given category:
not selected
positive selected (+ prefix; category is mandatory)
negative selected (- prefix in Google search; category must not occur)
selected (no prefix)
Not in ruby-on-rails but probably easy to translate from c#:
public bool IsMatch(string s)
{
s = s.ToLower();
bool ret = ((negWords.Count == 0) || !hasMatchInSet(s, negWords, true))
&& ((posWords.Count == 0) || hasMatchInSet(s, posWords, false))
&& ((words.Count == 0) || hasMatchInSet(s, words, true));
return ret;
}
private bool hasMatchInSet(string s, HashSet<string> setOfWords, bool breakOnFirstMatch)
{
int matches = 0;
bool ret = false;
foreach (string w in setOfWords)
{
if (s.IndexOf(w, StringComparison.InvariantCultureIgnoreCase) >= 0)
{
matches++;
if (breakOnFirstMatch)
{
break;
}
}
}
ret = (breakOnFirstMatch && (matches > 0)) || (matches == setOfWords.Count);
return ret;
}
Does Dart support == and === ? What is the difference between equality and identity?
Dart supports == for equality and identical(a, b) for identity. Dart no longer supports the === syntax.
Use == for equality when you want to check if two objects are "equal". You can implement the == method in your class to define what equality means. For example:
class Person {
String ssn;
String name;
Person(this.ssn, this.name);
// Define that two persons are equal if their SSNs are equal
bool operator ==(other) {
return (other is Person && other.ssn == ssn);
}
}
main() {
var bob = Person('111', 'Bob');
var robert = Person('111', 'Robert');
print(bob == robert); // true
print(identical(bob, robert)); // false, because these are two different instances
}
Note that the semantics of a == b are:
If either a or b are null, return identical(a, b)
Otherwise, return a.==(b)
Use identical(a, b) to check if two variables reference the same instance. The identical function is a top-level function found in dart:core.
It should be noted that the use of the identical function in dart has some caveats as mentioned by this github issue comment:
The specification has been updated to treat identical between doubles
like this:
The identical() function is the predefined dart function that returns
true iff its two arguments are either:
The same object.
Of type int and have the same numeric value.
Of type double, are not NaNs, and have the same numeric value.
What this entails is that even though everything in dart is an object, and f and g are different objects, the following prints true.
int f = 99;
int g = 99;
print(identical(f, g));
because ints are identical by their value, not reference.
So to answer your question, == is used to identify if two objects have the same value, but the identical is used to test for referential equality except in the case of double and int as identified by the excerpt above.
See: equality-and-relational-operators
As DART is said to be related to javascript, where the === exists, I wish not be downvoted very quickly.
Identity as a concept means that 1 equals 1, but 1.0 doesn't equal 1, nor does false equal 0, nor does "2" equal 2, even though each one evaluates to each other and 1==1.0 returns true.
It should be noted that in Dart, identical works similarly to Javascript, where (5.0 == 5) is true, but identical(5.0, 5) is false.