I was recently working on some test code, building silly view hierarchys and I ran across this little bit of code that made me squint a little extra hard.
var parentView: UIView = UIView() //Warning here
parentView.addSubview(UIImageView())
On the first line is the following warning:
Variable 'parentView' was never mutated; consider changing to 'let' constant
I'm confused as to why this element is not, or why the compiler believes it is not, being mutated. I thought perhaps that Swift was detecting that a collection within the object was being mutated, and not the properties of the object itself. This lead me to attempt the following:
let strings: [String] = []
strings.append("Hi") //This is an error
Given the above code, the only explanation I can come up with is that there is a bug somewhere. Am I missing a keyword somewhere that allows this situation to make sense? Something along the line's of C++'s "mutable" keyword?
If it's not a bug, I'd like to see this scenario re-created in a class that does not inherit from UIObject, so I can understand what causes this.
This is not a bug. For class instances (which are reference types), as e.g. your UIView instance, you may mutate instance properties even if the instance itself is a constant (let). Arrays, on the other hand, are treated as value types in Swift, and members of a constant array (let arr ...) may not be mutated.
Hence, you never actually mutate parentView itself (parentView = UIView() would be a mutation of itself), only its members, and in such a case, it make sense (as the compiler notes) to mark parentView as a constant.
If you create an instance of a structure and assign that instance to a
constant, you cannot modify the instance’s properties, even if they
were declared as variable properties:
...
This behavior is due to structures being value types. When an instance
of a value type is marked as a constant, so are all of its properties.
The same is not true for classes, which are reference types. If you
assign an instance of a reference type to a constant, you can still
change that instance’s variable properties.
From Language Guide - Properties.
...
You’ve actually been using value types extensively throughout the
previous chapters. In fact, all of the basic types in Swift—integers,
floating-point numbers, Booleans, strings, arrays and dictionaries—are
value types, and are implemented as structures behind the scenes.
All structures and enumerations are value types in Swift. This means
that any structure and enumeration instances you create—and any value
types they have as properties—are always copied when they are passed
around in your code.
From Language Guide - Classes and Structures.
Related
I have basic question about allocating memory for the value types.
If any value type is not used in the classes, functions or closures, how memory gets allocated for these value types lie struct or enums?
Also, I want to know, when ARC collects the objects for the value types. If they are not used in any reference types. After setting nil values to these value types, can we be sure that ARC picks up these objects?
Is int type in Dart a value type or reference type?
What is "reference type","value type","canonicalized" in Dart? (concrete definition)
I was looking into the specific definitions of "reference type" and "value type", but in the end, I thought it would be good to understand the code that represents the difference and the behavior (result) of that code.
If possible, I would like Dart code, but if it has the same structure as Dart regarding the above issues, there is no problem in other languages, so I would appreciate it if you could give me sample code.
The meaning of "reference type" and "value type" used here is the distinction made by C#.
A reference type is a traditional object-oriented object. It has identity which it preserves over time. You can have two objects with the same state, but they are different objects.
You don't store reference type values directly into variables. Instead you store a reference to them. When you access members of the object, you do so through the reference (x.foo means "evaluate x to a reference, then access the foo member of the object referenced by that reference).
When you check for identity, identical(a, b), you check whether two different references refer to the same object.
A value type does not have identity. It's defined entirely in terms of its state, its contents. When you assign a value type to a variable, you make a copy of it. It's the "value" in call-by-value.
C# allows you to declare value types with that behavior.
(Reference types do not correspond to call-by-reference, rather to call-by-sharing.)
In Dart, all objects are reference objects. This differs from, say, Java, where an int is a value-type ("primitive type" in their parlance), and they have a separate Integer class which can wrap the int values and is a reference type. That's needed because Integer is a subtype of Object, but int isn't, so you can't store int values in a generic container which expects a subtype of Object.
In Dart, some reference types are still more value-like than others. In particular numbers.
A Dart number, like the integer 1, has precisely one object representing that value. If you write 1 in different places of the program, or even calculate 4 ~/ 4 or 3 - 2, you always get the same object representing the value 1. It's like it's not an object at all, and identical only compares values. And that's precisely what happens, because it allows the compiler to treat integers as primitive values internally, and not worry about sometimes having to give you the same 1 object back that you put in.
This is sometimes expressed as integers being "canonicalized": There is only one canonical instance representing each state.
Dart also canonicalizes other objects.
Constant expressions are canonicalized, so that two different constant expressions generating instances of the same type, with identical states, are made to return the same, canonical, instance representing that value.
Since the value is guaranteed to be immutable, there is no need to have equal objects with different identities. (If they were mutable, it matters very much which one you mutate and which one you don't).
A quick screenshot with the point of interest:
There are 2 questions here.
This happens in a tight loop. The 12.8% code is this:
{
this with Side = side; PositionPrice = position'; StopLossPrice = sl'; TakeProfitPrice = tp'; Volume = this.Volume + this.Quantity * position'
}
This object is passed around a lot and has 23 fields so it's not tiny. It looks like immutability is great for stable code, but it's horrible for performance.
Since this recursive loop is run in parallel, I need to store it's context variables in an object.
I am looking for a general idea of what makes sense, not something specific to that code because I have a few tight loops with a bunch of math which I need to profile as well. I am sure I'll find the same pattern in several places.
The flaw here is that I store both the context for the calculations and its variables in a singe type that gets passed in the loop. As the variable fields get updated, the whole object has to be recreated.
What would make sense here (in general for this type of situations)?
make the fields that can change mutable. In this case, that means keeping the type as is (23 fields) and make some fields mutable (only 5 fields get regularly changed)
move the mutable fields to their own type to have a general context object and one holding all the variables. In this case, that means having a context with (23 - 5 fields) and a separate 5 fields type
make the mutable fields variables and move them out of the type. In this case, these 5 fields would be passed as variables in the recursive loop?
and for the second question:
I have no idea what the 10.0% line with get_Tag is. I have nothing called 'Tag' in the code, so I assume that's a dotnet internal thing.
I have a type called Side and there is a field with the same name used in the loop, but what is the 'Tag' part?
What I would suggest is not to modify your existing immutable type at all. Instead, create a new type with mutable fields that is only used within your tight loop. If the type leaves that loop, convert it back to your immutable type (assuming you don't need a copy to go through the rest of your program with every iteration).
get_Tag in this case is likely the auto-generated get-only property on a discriminated union, it's just how the F# compiler represents this sort of type in CLR. The property can most easily be seen when looking at F# code from C#, here's a great page on F# decompiled:
https://fsharpforfunandprofit.com/posts/fsharp-decompiled/#unions
For the performance issues I can only offer some suggestions:
If you can constrain the context object to your code only, then try making a mutable version and see which effect it has.
You mention that the context object is quite large, is it possible to split it up?
In the code: pbOut is a TPaintBox.
with pbOut.Canvas, Font do
begin
....
end;
The question is, i want to understand what does the comma in with.. do structure do? Is it the same as writing with pbOut.Canvas.Font do or not?
The comma is simply a separator for a list of things to 'scope to' using with.
As to your question, strictly speaking: it depends...
You might make the assumption that pbOut.Canvas always has a Font property (because you know TCanvas has a Font property). But nothing forces a Canvas variable to be of the TCanvas type, so you actually have to consider 2 possibilities.
In your case the first possibility explained below most likely applies, but it's important to be aware of the other.
As to your specific question:
Is it the same as writing with pbOut.Canvas.Font do or not?
It's almost the same, but not quite. That doesn't expose pbOut.Canvas, which the original code does.
Possibility 1
If Font is a member of pbOut.Canvas, then the statement is equivalent to:
with pbOut.Canvas do
begin
with pbOut.Canvas.Font do
begin
{ See notes underneath }
end;
end;
Here you are able to reference members of either pbOut.Canvas or pbOut.Canvas.Font directly; without fully qualifying the reference.
Any members in both pbOut.Canvas and pbOut.Canvas.Font that have have the same identifier would clash. The compiler will favour the inner with item. This means you would still have to fully qualify the pbOut.Canvas member to access it.
Possibility 2
On the other hand, if Font is not an accessible member of pbOut.Canvas, then the statement is equivalent to:
with pbOut.Canvas do
begin
with Font do
begin
{ See notes underneath }
end;
end;
Similar to the previous construct, you can access members of either pbOut.Canvas or Font directly; without fully qualifying the reference.
I must point out that the with statement is not really a useful construct.
It leads to confusing, difficult to read code because you always have to consider what an unqualified identifier really refers to.
There also a risk that adding/removing/renaming members in an existing object or record type might unexpectedly break existing code. Any code using with on instance of the modified type might unexpectedly scope differently.
The with list form in your question is even worse than single with because of the added trickery covered in my answer.
The with statement saves a small amount of code to more explicitly qualify certain identifiers; i.e. minimal "typing" savings, but at a great cost. So it is advised to not use with.
Look into documentation:
A with statement is a shorthand for referencing the fields of a record or the fields, properties, and methods of an object. The syntax of a with statement is:
with obj do statement
or:
with obj1, ..., objn do statement
where obj is an expression yielding a reference to a record, object instance, class instance, interface or class type (metaclass) instance, and statement is any simple or structured statement. Within the statement, you can refer to fields, properties, and methods of obj using their identifiers alone, that is, without qualifiers.
When multiple objects or records appear after with, the entire statement is treated like a series of nested with statements. Thus:
with obj1, obj2, ..., objn do statement
is equivalent to:
with obj1 do
with obj2 do
...
with objn do
// statement
In this case, each variable reference or method name in statement is interpreted, if possible, as a member of objn; otherwise it is interpreted, if possible, as a member of objn1; and so forth. The same rule applies to interpreting the objs themselves, so that, for instance, if objn is a member of both obj1 and obj2, it is interpreted as obj2.objn.
Since a with statement requires a variable or a field to operate upon, using it with properties can be tricky at times. A with statement expects variables it operates on to be available by reference.
Generally using with is a recipe for disaster, since by the look of it, it is difficult to know if a statement refers to one of the with blocks (and which one) or an outer scope.
To answer the question,
Is it the same as writing with pbOut.Canvas.Font do or not?
If you only want to access the Font properties it is the same, but not if you want to access other members of pbOut.Canvas.
For yours and others sake, do not use with statements at all.
Say I have a NSArray, and each item is an NSDictionary with three keys keyA, keyB, and keyC - each referring to objects of unknown type (id).
If I wanted to write a method that found the given element with those three keys i.e.
-(NSDictionary *) itemThatContainsKeys:(id)objectA and:(id)objectB and:(id)objectC
would I run into trouble by simply enumerating through and testing object equality via if([i objectForKey:(keyA) isEqualTo:objectA]) etc? I would be passing in the actual objects that were set in the dictionary initialization - ie not strings with the same value but different locations.
Is this bad practise?
Is there a better way to do this without creating a database?
You can override isEqual to stipulate the notion of equality for your type. The same rules apply as in other languages:
If you provide an implementation of equals you should provide an implementation of 'hash'
Objects that are 'equal' should have the same 'hash'
Equals should be transitive -> if A equals B, and B equals C, then C must equal A.
Equals should be bi-directional -> if A equals B, then B must equal A.
This will ensure predictable behavior in classes like NSSet, that use hash for performance, falling back to equals on when there's a collision.
As Jason Whitehorn notes, Objective-C also has the convention of providing another isEqualToMyType method for convenience.
AppCode, EqualsBuilder, Boiler-plate code
It would be nice if there was something like Apache's 'EqualsBuilder' class, but in the meantime AppCode does a fine job of implementing these methods for you.
The isEqual: method compares object identity unless overwritten by a subclass. Depending on what class the target is, this May or may not be what you want. What I prefer is to use a more class specific comparison like isEqualToNumber: simply because of it's explicitness. But, isEqual should work depending on the target.
Other than that, and not knowing more specifics of what you're doing, it's hard to say if there is a better way to accomplish what you're after. But, here are my thoughts;
An array of a dictionary almost sounds like you might need a custom class to represent some construct in your app. Perhaps the dictionary could be replaced with a custom object on which you implement an isEqualToAnotherThing: method. This should simplify your logic.