Why do Iterable classes in Dart have both the isEmpty and isNotEmpty fields? Is it purely for readability? (According to the documentation, it suggests so).
Would there be any circumstances where list.isEmpty == list.isNotEmpty is true?
It depends on the way they're implemented.
According to IterableBase/Mixin and Base/Mixin:
bool get isNotEmpty => !isEmpty;
As long as they use the Mixin, .isEmpty == .isNotEmpty cant be true then... i guess..?
Related
Consider the following line of code that doesn't compile in Dart -- lack of comma operator, but comparable things are totally fine in JavaScript or C++:
final foo = (ArgumentError.checkNotNull(value), value) * 2;
The closest I could get with an ugly workaround is
final foo = last(ArgumentError.checkNotNull(value), value) * 2;
with function
T last<T>(void op, T ret) => ret;
Is there a better solution?
Dart does not have a comma operator similar to the one in JavaScript.
There is no obviously better solution than what you already have.
The work-around operation you introduced is how I would solve it. I usually call it seq for "sequence" if I write it.
There is sadly no good way to use an extension operator because you need to be generic on the second operand and operators cannot be generic. You could use an extension method like:
extension Seq on void {
T seq<T>(T next) => next;
}
Then you can write ArgumentError.checkNotNull(value).seq(value).
(For what it's worth, the ArgumentError.checkNotNull function has been changed to return its value, but that change was made after releasing Dart 2.7, so it will only be available in the next release after that).
If the overhead doesn't matter, you can use closures without arguments for a similar effect (and also more complex operations than just a sequence of expressions).
final foo = () {
ArgumentError.checkNotNull(value);
return value;
} ();
This is not great for hot paths due to the overhead incurred by creating and calling a closure, but can work reasonably well outside those.
If you need this kind of test-plus-initialization pattern more than once, the cleanest way would arguably be to put it in a function of its own, anyway.
T ensureNotNull<T>(T value) {
ArgumentError.checkNotNull(value);
return value;
}
final foo = ensureNotNull(value);
For enums with associated values, Swift doesn't provide the equality operator. So I implemented one to be able to compare two enums:
enum ExampleEnum{
case Case1
case Case2(Int)
case Case3(String)
...
}
func ==(lhs: ExampleEnum, rhs: ExampleEnum) -> Bool {
switch(lhs, rhs){
case (.Case1, .Case1): return true
case let (.Case2(l), .Case2(r)): return l == r
case let (.Case3(l), .Case3(r)): return l == r
...
default: return false
}
}
My problem is that I have a lot of such enums with a lot of cases so I need to write a lot of this comparison code (for every enum, for every case).
As you can see, this code always follows the same scheme, so there seems to be a more abstract way to implement the comparison behavior. Is there a way to solve this problem? For example with generics?
As of Swift 4.2 just add Equatable protocol conformance.
It will be implemented automatically.
enum ExampleEquatableEnum: Equatable {
case case1
case case2(Int)
case case3(String)
}
print("ExampleEquatableEnum.case2(2) == ExampleEquatableEnum.case2(2) is \(ExampleEquatableEnum.case2(2) == ExampleEquatableEnum.case2(2))")
print("ExampleEquatableEnum.case2(1) == ExampleEquatableEnum.case2(2) is \(ExampleEquatableEnum.case2(1) == ExampleEquatableEnum.case2(2))")
I.e. default comparison takes associated values in account.
Currently there is no way of achieving this without writing out all the cases, we can hope that it'll be possible in a later version.
If you really have a lot of cases and you don't want to write them all out, you can write a small function that generates the code automatically for you (I've been doing this just recently for something that wasn't possible to refactor)
I'm almost certainly doing something wrong or misunderstanding List.retainAll().
I have two lists that are equal (size() ==1), yet when I call list1.retainAll(list2), list 1 becomes empty.
Code:
List<DomainObject> list1 = someService.getData()
List<DomainObject> list2 = someService.getOtherData()
log.info("Equal: ${list1.equals(list2)}")
boolean changed = list1.retainAll(list2)
log.info("Changed: ${changed}")
log.info("list1 empty: ${list1.isEmpty()}")
Log shows:
Equal: true
Changed: true
list1 empty: true
I... don't know what I'm doing wrong. I've run tests with more generic objects (the actual domain object is fairly complex, but implements equals/hashcode correctly) and retainAll worked as expected.
I'm not even sure what specific question I should be asking... Are there conditions I'm missing where equals() can return true but retainAll() fails?
Hopefully to help someone else down the line, and this is something I should have known and had run into before.
list1.equals(list2) //true, one element per list
list1.get(0).id == list2.get(0).id //true, same DB object
list1.get(0).equals(list2.get(0)) //false... ?!
The reason was equals() was implemented starting with:
equals() {
if(getClass() != o.class) return false
}
getClass() was returning DomainObject but o.class (or o.getClass()) was returning javaassist__blahblah.
I replaced the check with
if(!(o instanceof DomainObject)) return false
Not sure if that's the cleanest way to do class checking in equals, for some reason I was of the impression that instanceof was slow.
It appears that in iOS I have a number of options that seem to fit for boolean values:
YES
NO
TRUE
FALSE
true
false
Which ones should I use? In this particular case I'm hiding a label, so should I set the hidden property to YES, TRUE, or true?
Short answer: you should prefer YES and NO for setting foundation properties of type BOOL.
For the long answer, let's first see where are these constants defined:
true and false are from stdbool.h; they are #define-d as 1 and 0
TRUE and FALSE are from CFBase.h; they are #define-d as 1 and 0
YES and NO are from NSObjCRuntime.h. This is where signed char is typedef-ed as BOOL, and its two values are #define-d as ((BOOL)1) and ((BOOL)0) or __objc_yes/__objc_no if objc_bool is supported.
The foundation classes consistently use BOOL, which is a typedef for signed char, to represent its boolean properties. Since the first two pairs get converted to int constants, using them may result in warnings, though it would probably work correctly anyway. The YES and NO constants, however, are defined in the most compatible way for your compiler, regardless of its version. Therefore, I would recommend using YES and NO consistently throughout your code.
Actually there is no difference between YES, TRUE and true those all represent a true state represented by 1.
And NO, false, FALSE is represents a false state represented by 0.
You can also use:
BOOL aBool = 1;
which is equivalent to BOOL aBool = true; and BOOL aBool = TRUE; and BOOL aBool = YES;
But:
BOOL bBool = 7;
if (bBool)
{
NSLog(#"bBool is YES!\n");
}
if (bBool != YES) {
NSLog("bBool is not YES!\n");
}
Will output like:
b is YES!
b is not YES!
This is because direct comparison with YES will fail when the value of a BOOL type is a non-zero value other than 1.
Here is a nice article for you.
I think all of them are okay. But personally, I'd like to use YES/NO.
I found a doc called Objective-C Runtime Reference:
Boolean Values
These macros define convenient constants to represent Boolean values.
#define YES (BOOL)1
#define NO (BOOL)0
Constants
YES
Defines YES as 1.
Available in iOS 2.0 and later.
Declared in NSObjCRuntime.h.
NO
Defines NO as 0.
Available in iOS 2.0 and later.
Declared in NSObjCRuntime.h.
Declared In
objc.h
I share your view on this, whilst they are currently all defined the same, porting the code is a pain when you may find TRUE != true. (Precisely why we should never test X == 1 for TRUE as some languages use -1 and some use 1)
I think it might be personal preference and mainly about future ports.
I follow the TRUE and FALSE options so that porting to C/C++ is easier.
You may find that true and false is better if you're regularly converting code to Java so there's less search/replaces but I found consistency with Cocoa easier.
Use YES and NO is the same to use TRUE and FALSE or 1 and 0 respectively.
And use NSLog to view result like this little example:
BOOL result;
result = YES;
NSLog(#"my boolean result is %#",result ? #"Yes" : #"No");
I want to do this in Actionscript:
typeof(control1) != typeof(control2)
to test if two objects are of the same type. This would work just fine in C#, but in Actionscript it doesnt. In fact it returns 'object' for both typeof() expressions because thats the way Actionscript works.
I couldn't seem to find an alternative by looking in the debugger, or on pages that describe typeof() in Actionscript.
Is there a way to get the actual runtime type?
The best way is to use flash.utils.getQualifiedClassName(). Additionally, you can use flash.utils.describeType() to get an XML document the describes more about the class.
Actionscript 3 has an is operator which can be used to compare objects. Consider the following code:
var mySprite:Sprite = new Sprite();
var myMovie:MovieClip = new MovieClip();
trace(mySprite is Sprite);
trace(myMovie is MovieClip);
trace(mySprite is MovieClip);
trace(myMovie is Sprite);
Which will produce the following output:
true
true
false
false
This will work for built-in classes, and classes you create yourself. The actionscript 2 equivalent of the is operator is instanceof.
You'll want to use the Object.prototype.constructor.
From the documentation:
dynamic class A {}
trace(A.prototype.constructor); // [class A]
trace(A.prototype.constructor == A); // true
var myA:A = new A();
trace(myA.constructor == A); // true
(Conveniently, this is also how to check types in javascript, which is what originally led me to this in the docs)
So, to test this out before I posted here, I tried it in an app I have, in a class called Player. Since the prototype property is static, you can't call it using "this" but you can just skip the scope identifier and it works:
public function checkType():void {
trace(prototype.constructor, prototype.constructor == Player);
// shows [class Player] true
}
Is there a way to get the actual runtime type?
Yes.
var actualRuntimeType:Class = Object(yourInstance).constructor;
Some other answers already refer to .constructor, but you can't always directly access .constructor in ActionScript 3. It is only accessible on dynamic classes, which most classes are not. Attempting to use it on a regular class will cause a compile-time error under the default settings.
However, because every class inherits from Object, which is dynamic, we can look up their .constructor property just by casting an instance to Object.
Therefore if we are not interested in subclasses, we can confirm that two instances are of exactly the same class by simply evaluating this:
Object(instanceA).constructor === Object(instanceB).constructor;
I learned of this from the post "Get the class used to create an object instance in AS3" by Josh Tynjala.
A even simpler alternative that also works for me is just:
var actualRuntimeType:Class = yourInstance["constructor"];
The runtime is entirely capable of giving you the .constructor, it's just that the compiler complains if you use that syntax. Using ["constructor"] should produce the same bytecode, but the compiler isn't clever enough to stop you.
I included this second because it hasn't been tested anywhere except my current Flash environment, whereas several users have said that the method described above works for them.
If you want to account for inheritance, then you might want to try something like this:
if (objectA is objectB.constructor || objectB is objectA.constructor)
{
// ObjectA inherits from ObjectB or vice versa
}
More generally, if you want to test whether objectA is a subtype of objectB
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
...
if (objectA is getDefinitionByName(getQualifiedClassName(objectB)))
{
...
}
Object obj = new Object();
Object o = new Object();
if(o.getClass().getName().endsWith(obj.getClass().getName())){
return true;
}else{
return false;
}