I am having trouble understanding the concept between two things being equal and two things being identical. What confuses me is the statement "Two objects can be identical, which means they are equal. But, two object that are equal are not identical." Could someone please help me understand the difference? Thanks.
in objective-c, slightly pseudo code...
NSString * a = #"hello";
NSString * b = #"hello";
a == a //they are identical (the same object)
[a isEqualToString:a]; //they are equal.
a != b //Even though the string contents are the same they are not the same object.
[a isEqualToString:b]; // they aren't identical but they are equal.
For a very long and good blog post on the topic see this
http://www.karlkraft.com/index.php/2008/01/07/equality-vs-identity/
Welcome to the world of boxes... (this works a lot better with pictures, apologies I haven't included any)
Preamble
When you write:
int x;
you are asking for a box which is capable of holding an int and to equate the name of that with x - all boxes have an internal name, what it exactly is is unimportant. So now when you write:
x = 4;
you asking to store the value 4 in the box referenced by the name x. A box is often called a "variable". This use of boxes is why computer programming is different from mathematics, you can write:
x = x + 1;
in computer programming, but not in maths! It means "go to the box referenced by x, copy the value out, add 1 it to, put the value back into the same box".
Now boxes of different types (meaning what can be stored in them) can be "glued" together to form multi-compartment boxes. The whole collection is referred to by a single name, and the individual boxes by two names - the one for the collection and the one for the individual box. Such collections of boxes appear in different programming languages under the terms "record", "structure", "object" etc.
And finally, what can you put in a box? The answer (depending on the rules of the programming language) is anything and this includes the names of other boxes. E.g. you can write:
int *y;
which asks for a box capable of holding the "name of a box which holds an integer" and to call this box y. Such boxes are often called "pointer variables" or "reference variables"
== vs. isEqual
In Objective-C the == operator looks at the contents of two boxes and determines whether they contain the same value - and that value might well be the name of another box.
The isEqual method operates only on boxes (of certain restricted types) which contain the names of other boxes. It looks into the two boxes, uses the names in those boxes to locate two more boxes, and then compares the contents of those boxes. If the boxes it is comparing themselves contain other boxes which contain names of yet further boxes then it traverses to those further boxes to compare them, etc.
Furthermore isEqual does not need to compare for exact equality, but is allowed to compare for "means the same thing". E.g. if you create two dictionaries which contain the same key/value pairs but they are entered in different orders then the arrangement of boxes that make up those two dictionaries may not be identical, but semantically they are the same - the isEqualDictionary: method is defined as:
Two dictionaries have equal contents if they each hold the same number of entries and, for a given key, the corresponding value objects in each dictionary satisfy the isEqual: test.
Conclusion
The == operator is usually only used for "primitive" data types - int, float, NSInteger etc. - and structures of such types - e.g. NSRect. These are the types where the values determine equality.
The isEqual: method is is usually used for Obj-C objects - you usually don't want to know whether to boxes contain the same name (which is what == would determine), but whether what those names refer to are semantically equivalent - which is what isEqual: determines.
Identical generally means they are the same object in memory (occupy the same memory footprint).
Equal usually means their attribute values are the same.
Related
I apologize if this has been asked before (I couldn't find anything).
I'm an extreme noob in Livecode, and I want to know if there is a way of programming a button to create many new, unique variables and assign a value to them. I apologize if this is a dumb question.
Usually you use an array for that. An array is basically a list of things, where each thing is associated with an "index". An index can be any word, so you can use an array like a dictionary, where you'd e.g. have French words as the index, and English words as the value, like:
put "cow" into myDictionary["vache"]
But you can also just use numbers as the keys and make them a numbered list:
put "cow" into allMyAnimals[1]
put "duck" into allMyAnimals[2]
In end effect, you create one variable and put several things in it. For example if you had a loop that calculated something (in this example a number +100) and you wanted to have variables containing all those numbers, but named with 100 less, you'd do something like:
repeat with x = 1 to 250
put x +100 into twoHundredFiftyNumbersFrom101[x]
end repeat
And to read the first one:
answer "the first number is" && twoHundredFiftyNumbersFrom101[1]
Or all of them:
repeat with x = 1 to 250
answer twoHundredFiftyNumbersFrom101[x]
end repeat
Or whatever. You could also use 'do' to build the lines of code as a string, but then you have to make sure your variable names are generated in a fashion that makes them valid identifiers (e.g. have no spaces in them, no special characters). An array key can be any valid string, and the compiler can optimize them, and you can treat them as a whole and pass them between handlers.
Or you can do this "in the clear" with a "do" construction:
on mouseUp
repeat with y = 1 to 10
get random(100)
do "put it into onTheFlyVariable" & y
end repeat
end mouseUp
Step through this handler and watch the variables assemble themselves.
I'm implementing a generic BACnet decoder and came across the following question, of which I can't seem to find the answer within the BACnet standard. The chapter "20.2.1.3.2 Constructed Data" does not answer my question, or I might not fully understand it.
Let's assume I have a List (SEQUENCE OF) with elements of type Record (SEQUENCE).
Said record has 4 fields, identified by context tag, where field 0 and 1 are optional.
I further assume that the order, in which those fields are serialized, can be arbitrary (because they're identified by their context tags).
The data could look like that (number indicates field / column):
[{ "3", "0", 2" }, {"1", "2", "3"}]
Over the wire, the only "structure information" I assume I get are the open / close tags for the list.
That means:
Open Tag List
ctxTagColumn3, valueColumn3,
ctxTagColumn0, valueColumn0,
ctxTagColumn2, valueColumn2,
ctxTagColumn1, valueColumn1,
ctxTagColumn2, valueColumn2,
ctxTagColumn3, valueColumn3
Close Tag List
How do I know, after I've read the last column data ("2") of my first list item, that I must begin decoding the second item, starting with a value for column "1"?
Which of my assumptions is wrong?
Thank you and kind regards
Pascal
The order of elements of a SEQUENCE is always known and shall not be arbitrarily by definition. Further, not all conceivable combinations are possible to encode. Regarding BACnet, all type definitions shall be decodable universally.
Assuming I understand you correctly; the "order" cannot be "arbitrary"; i.e.:
SEQUENCE = *ordered* collection of variables of **different** types
SEQUENCE OF = *ordered* collection of variables of **same** type
The tag-number for the item (SD) context-tag will be different (/possibly an incremented value/maybe +1) from the containing (PD) context-tag; so you could check for that, or better still if the tag-number value is <= 5 (/'length' value) then it's a SD context-tag for one of your items, rather than a (/the closing) PD context tag (/'type' value) delimiting the end of your items.
I have a data set which includes a number of nodes, all of which labeled claim, which can have various properties (names P1, P2, etc., through P2000). Currently, each of the claim nodes can have only one of these properties, and each property has value, which can be of different types (i.e. P1 may be string, P2 may be float, P3 integer, etc.). I also need to be able to look up the nodes by any property (i.e. "find all nodes with P3 which equals to 42").
I have modeled it as nodes having property value and label according to the P property. Then I define schema index on label claim and property value. The lookup then would look something like:
MATCH (n:P569:claim) WHERE n.value = 42 RETURN n
My first question is - is this OK to have such index? Are mixed type indexes allowed?
The second question is that the lookup above works (though I'm not sure whether it uses index or not), but this doesn't - note the label order is switched:
neo4j-sh (?)$ MATCH (n:claim:P569) WHERE n.value>0 RETURN n;
IncomparableValuesException: Don't know how to compare that. Left: "113" (String); Right: 0 (Long)
P569 properties are all numeric, but there are string properties from other P-values one of which is "113". Somehow, even though I said the label should be both claim and P569, the "113" value is still included in the comparison, even though it has no P569 label:
neo4j-sh (?)$ MATCH (n:claim) WHERE n.value ="113" RETURN LABELS(n);
+-------------------+
| LABELS(n) |
+-------------------+
| ["claim","P1036"] |
| ["claim","P902"] |
+-------------------+
What is wrong here - why it works with one label order but not another? Can this data model be improved?
Let me at least try to side-step your question, there's another way you could model this that would resolve at least some of your problems.
You're encoding the property name as a label. Perhaps you want to do that to speed up looking up a subset of nodes where that property applies; still it seems like you're causing a lot of difficulty by shoe-horning incomparable data values all into the same property named "value".
What if, in addition to using these labels, each property was named the same as the value? I.e.:
CREATE (n:P569:claim { P569: 42});
You still get your label lookups, but by segregating the property names, you can guarantee that the query planner will never accidentally compare incomparable values in the way it builds an execution plan. Your query for this node would then be:
MATCH (n:P569:claim) WHERE n.P569 > 5 AND n.P569 < 40 RETURN n;
Note that if you know the right label to use, then you're guaranteed to know the right property name to use. By using properties of different names, if you're logging your data in such a way that P569's are always integers, you can't end up with that incomparable situation you have. (I think that's happening because of the particular way cypher is executing that query)
A possible downside here is that if you have to index all of those properties, it could be a lot of indexes, but still might be something to consider.
I think it makes sense to take a step back and think what you actually want to achieve, and why you have those 2000 properties in the first place and how you could model them differently in a graph?
Also make sure to just leave off properties you don't need and use coalesce() to provide the default.
I want to add a method "average" to array class.
But average doesn't make any sense if input array contains characters/strings/objects.
So I need to check if array contains only integers/floats.
Smalltalk says datatype check [checking if variable belongs to a particular datatype like int string array etc... or not] is a bad way of programming.
So what is best way to implement this?
The specification is somewhat incomplete. You'd need to specify what behavior the collection should show when you use it with non-numeric input.
There are a huge number of possibly desirable behaviors. Smalltalk supports most of them, except for the static typing solution (throw a compile-time error when you add a non-numeric thing to a numeric collection).
If you want to catch non-numeric objects as late as possible, you might just do nothing - objects without arithmetic methods will signal their own exceptions when you try arithmetic on them.
If you want to catch non-numeric elements early, implement a collection class which ensures that only numeric objects can be added (probably by signaling an exception when you add a non-numeric object is added).
You might also want to implement "forgiving" methods for sum or average that treat non-numeric objects as either zero-valued or non-existing (does not make a difference for #sum, but for #average you would only count the numeric objects).
In pharo at least there is
Collection >> average
^ self sum / self size
In Collections-arithmetic category. When you work with with a statically typed languages you are being hit by the language when you add non-number values to the collection. In dynamically typed languages you the same happens when you try to calculate average of inappropriate elements e.i. you try to send +, - or / to an object that does not understand it.
Don't think where you put data, think what are you doing with it.
It's reasonable to check type if you want to do different things, e.g.:
(obj isKindOf: Number) ifTrue: [:num| num doItForNum].
(obj isKindOf: Array ) ifTrue: [:arr| arr doItForArr].
But in this case you want to move the logic of type checking into the object-side.
So in the end it will be just:
obj doIt.
and then you'll have also something like:
Number >> doIt
"do something for number"
Array >> doIt
"do something for array"
(brite example of this is printOn: method)
I would have thought the Smalltalk answer would be to implement it for numbers, then be mindful not to send a collection of pets #sum or #average. Of course, if there later becomes a useful implementation for a pet to add itself to another pet or even an answer to #average, then that would be up to the implementer of Pet or PetCollection.
I did a similar thing when I implemented trivial algebra into my image. It allowed me to mix numbers, strings, and symbols in simple math equations. 2 * #x result in 2x. x + y resulted in x + y. It's a fun way to experiment with currencies by imagining algebra happening in your wallet. Into my walled I deposit (5 x #USD) + (15 * #CAN) for 5USD + 15CAN. Given an object that converts between currencies I can then answer what the total is in either CAN or USD.
We actually used it for supply-chain software for solving simple weights and measures. If a purchase order says it will pay XUSD/1TON of something, but the supplier sends foot-lbs of that same thing, then to verify the shipment value we need a conversion between ton and foot-lbs. Letting the library reduce the equation we're able to produce a result without molesting the input data, or without having to come up with new objects representing tons and foot-pounds or anything else.
I had high ambitions for the library (it was pretty simple) but alas, 2008 erased the whole thing...
"I want to add a method "average" to array class. But average doesn't make any sense if input array contains characters/strings/objects. So I need to check if array contains only integers/floats."
There are many ways to accomplish the averaging of the summation of numbers in an Array while filtering out non-numeric objects.
First I'd make it a more generic method by lifting it up to the Collection class so it can find more cases of reuse. Second I'd have it be generic for numbers rather than just floats and integers, oh it'll work for those but also for fractions. The result will be a float average if there are numbers in the collection array list.
(1) When adding objects to the array test them to ensure they are numbers and only add them if they are numbers. This is my preferred solution.
(2) Use the Collection #select: instance method to filter out the non-numbers leaving only the numbers in a separate collection. This makes life easy at the cost of a new collection (which is fine unless you're concerned with large lists and memory issues). This is highly effective, easy to do and a common solution for filtering collections before performing some operation on them. Open up a Smalltalk and find all the senders of #select: to see other examples.
| list numberList sum average |
list := { 100. 50. 'string'. Object new. 1. 90. 2/3. 88. -74. 'yup' }.
numberList := list select: [ :each | each isNumber ].
sum := numberList sum.
average := sum / (numberList size) asFloat.
Executing the above code with "print it" will produce the following for the example array list:
36.523809523809526
However if the list of numbers is of size zero, empty in other words then you'll get a divide by zero exception with the above code. Also this version isn't on the Collection class as an instance method.
(3) Write an instance method for the Collection class to do your work of averaging for you. This solution doesn't use the select since that creates intermediate collections and if your list is very large that's a lot of extra garbage to collect. This version merely loops over the existing collection tallying the results. Simple, effective. It also addresses the case where there are no numbers to tally in which case it returns the nil object rather than a numeric average.
Collection method: #computeAverage
"Compute the average of all the numbers in the collection. If no numbers are present return the nil object to indicate so, otherwise return the average as a floating point number."
| sum count average |
sum := 0.
count := 0.
self do: [ :each |
each isNumber ifTrue: [
count := count +1.
sum := sum + each.
]
].
count > 0 ifTrue: [
^average := sum / count asFloat
] ifFalse: [
^nil
]
Note the variable "average" is just used to show the math, it's not actually needed.
You then use the above method as follows:
| list averageOrNil |
list := { 100. 50. 'string'. Object new. 1. 90. 2/3. 88. -74. 'yup' }.
averageOrNil := list computeAverage.
averageOrNil ifNotNil: [ "got the average" ] ifNil: [ "there were no numbers in the list"
Or you can use it like so:
{
100. 50. 'string'. Object new. 1. 90. 2/3. 88. -74. 'yup'
} computeAverage
ifNotNil: [:average |
Transcript show: 'Average of list is: ', average printString
]
ifNil: [Transcript show: 'No numbers to average' ].
Of course if you know for sure that there are numbers in the list then you won't ever get the exceptional case of the nil object and you won't need to use an if message to branch accordingly.
Data Type/Class Checking At Runtime
As for the issue you raise, "Smalltalk says datatype check [checking if variable belongs to a particular datatype like int string array etc... or not] is a bad way of programming", there are ways to do things that are better than others.
For example, while one can use #isKindOf: Number to ask each element if it's not the best way to determine the "type" or "class" at runtime since it locks it in via predetermined type or class as a parameter to the #isKindOf: message.
It's way better to use an "is" "class" method such as #isNumber so that any class that is a number replies true and all other objects that are not numeric returns false.
A main point of style in Smalltalk when it comes to ascertaining the types or classes of things is that it's best to use message sending with a message that the various types/classes comprehend but behave differently rather than using explicit type/class checking if at all possible.
The method #isNumber is an instance method on the Number class in Pharo Smalltalk and it returns true while on the Object instance version it returns false.
Using polymorphic message sends in this away enables more flexibility and eliminates code that is often too procedural or too specific. Of course it's best to avoid doing this but reality sets in in various applications and you have to do the best that you can.
This is not the kind of thing you do in Smalltalk. You could take suggestions from the above comments and "make it work" but the idea is misguided (from a Smalltalk point of view).
The "Smalltalk" thing to do would be to make a class that could perform all such operations for you --computing the average, mean, mode, etc. The class could then do the proper checking for numerical inputs, and you could write how it would respond to bad input. The class would use a plain old array, or list or something. The name of the class would make it clear what it's usage would be for. The class could then be part of your deployment and could be exported/imported to different images as needed.
Make a new collection class; perhaps a subclass of Array, or perhaps of OrderedCollection, depending on what collection related behaviour you want.
In the new class' at:put: and/or add: methods test the new item for #isNumber and return an error if it fails.
Now you have a collection you can guarantee will have just numeric objects and nils. Implement your required functions in the knowledge that you won't need to deal with trying to add a Sealion to a Kumquat. Take care with details though; for example if you create a WonderNumericArray of size 10 and insert two values into it, when you average the array do you want to sum the two items and divide by two or by ten?
My tableViewController with a list of items of various types will provide a button to show a modal dialog box. This dialog box (similar to alert view) will provide the user with an exclusive choice from a list of 6 options.
Based on what the user chooses and confirms, the list in the main tableview controller screen will be filtered down to only show items that match the selected type.
At the moment, I have those six types listed in a typedefed enum. So far so good.
However I also need to be able to populate my custom dialog box with six nsstrings whose names will match the types used in the enumeration.
How to reconciliate this enum with my requirement for a source of those strings, but in such a way that I would ensure some level of consistency between the two? I do not want to hardcode anything.
You need a helper method that returns a string for each enum value. This should be written to deal with possible localization. All of your data and event handling should be based on the enum value. The string should be used for display.
The helper method should take an enum value and use a switch statement to return the proper string.
I can think of a few:
Change the enum to a bunch of strings. This makes things a bit tedious if they need to be integers too (-[NSArray indexOfObject:]).
Make a C array of strings. This lets you use C99's handy syntax:
NSString * const names[] = {
[Foo] = #"Foo",
[Bar] = #"Bar",
};
Autogenerated code to do the above.
Caveats:
Both of these will make i18n rather painful. This might not be relevant if it's contract work that will only need to be in one language, but it's Bad Practice.
Using button indexes as keys works until you decide you need to remove buttons in the middle. String keys work much better in the general case (I wrote a UIAlertView/UIActionSheet wrapper that accept (key,title) pairs and returned the key instead of the button index).
I take your remark that you "do not want to hardcode anything" to mean that you don't want any string constants in your code. So:
You could simply assign the strings to your sheet's UI elements (perhaps check boxes, for example) and give those UI elements tag values that match your enumeration (something you could query as your sheet closes). This has the additional benefit that you can easily localize the sheet.
Or:
If you want to keep the strings separate from your sheet, you could create a .strings file (perhaps you could call it Enumeration.strings or some such) formatted something like this:
"001" = "string one";
"002" = "string two";
.
.
"010" = "string ten";
and you could then retrieve the strings using your enumeration values like this:
NSString *myString = NSLocalizedStringFromTable([NSString stringWithFormat:#"%03d", myEnumerationValue], #"Enumeration", #"");
but then you'd have to have a way of plugging the strings into your UI, keeping track of UI elements through IBOutlets. Note that I used three decimal places here; perhaps you could get by with two, or even one. Finally, you get the ability to localize as in the first suggestion.