What's the difference between String and string in Dart? - dart

I can't understand why in some docs the String method is capitalized, but in some docs the same method is not. string vs String.
What is difference?

The difference is that String is a type and string is not.
For more details it depends on the context.

Related

Better way to assign a value with nullable field in dart

Is there a better way to do this?
Assignment(
dueAt: json['due_at'] == null ?
null :
DateTime.parse(json['due_at']).toLocal()
)
The attribute "dueAt" in Assignment class can be null and i need to parse the string of json['due_at'] to a DateTime, but json['due_at'] can be null too.
Is not really a problem right now but seems noisy and repetitive.
First and foremost, it looks like you're writing JSON serialization code by hand. Your life will be much easier and less bug-prone if you let a library do this instead. json_serializable is very simple and powerful and 100% worth looking into.
However, this pattern is still common outside of json code.
You could also consider writing an extension method for Object? that behaves like the Kotlin standard library's let function (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html)
You can then use Dart's ?. syntax to handle the rest of the logic:
// extension on T rather than Object? to maintain type information
extension Example<T> on T {
R let<R>(R Function(T) function) => function(this);
}
This just applies a given function to this, which isn't incredibly useful on it's own, but allows the use of ?.:
final DateTime? dueAt = json['due_at']?.let(DateTime.parse);
If json['due_at'] evaluates to null, the ?. operator short-circuits, and dueAt is set to null. Otherwise, it evaluates to DateTime.parse(json['due_at']).
Or, you could just use package:kt_dart which ports much of the Kotlin standard library to Dart
In this particular case you may want to use tryParse instead of parse. If dueAt is of type DateTime? you can simply call:
Assignment( dueAt: DateTime.tryParse(json['due_at'])?.toLocal() );
Be aware though that tryParse will return null for any invalid date string (be it null or an improperly formatted string). This may or may not be desired behavior depending on your intended use.

Why does an unitialized typed variable in Dart not implement the type's interface?

I started learning Dart and was reading a critique of some of it's design choices here: https://medium.com/#krossovochkin/dart-language-bad-design-choices-6e35987dc693
The last point that is made is about the poor type system and the author cited this code snippet which prints null:
void main() {
String s = null;
if (s is String) {
print("string");
} else if (s is Null) {
print("null");
} else {
print ("none");
}
}
The is keyword was new to me but "The Dart Programming Language" by Gilad pointed out that is checks the interface implemented by an object's class and not the actual class of an object.
However this didn't help me much because I would think that the variable s is an instance of String and therefore implements String, but the evidence is to the contrary.
I get that the class is not required when defining objects/variables in Dart, and thus I started to wonder if putting the class in the definition just serves as sugar and has little functional purpose. But instead the class of an object/variable is completely determined by its value, and since the default value for all variables in Dart is null, then it would make sense that String is not implemented, but Null is. Is this the case? Am I way of base? Maybe someone could help me wrap my head around this.
The reason is that is checks the interface of the current object itself and not the reference to this object. So yes, s can point to a String object but also allowed to point to null which are a instance of Null: https://api.dart.dev/stable/2.7.2/dart-core/Null-class.html
Since Null does not implement the String interface, this will return false (null is String). This is also mentioned in the article.
The problem the article are trying to focus on are more the fact you are allowed to set the String variable to null value but Null does not implement String.
Well, in the future, this problem are going to be fixed with non-nullable types which are in development right now. When this is implemented you can actually define variables where you can be sure the value will never be null.
So I continued my Dart reading and I came to a better understanding, and that is that Dart is truly optionally typed and that means 2 things:
Type are syntactically optional.
Type has no impact on runtime semantics.
Therefore the actual type annotation of a variable in Dart only serves documentation purposes and it cannot be assumed that a type annotation is true. The actual type of a variable is wholly determined by the value stored at this variable, and in this case it is null.
In truth the variable that I defined in my example is not a String variable or an implementer of the String interface. It is just annotated that it may be/should be/most likely is a string.

Ambiguous match found when calling String.Split()

I'm programming in JScript.NET which is similar to C# . I want to split a string on multiple characters, in this case " - ".
The problem is when I do that like this (which should be the way to do it according to this thread):
var text = "test - test2";
var array = [" - "];
var val = text.Split(array, StringSplitOptions.None);
I get "Ambiguous match found". This is because the String class has both a Split(Char[], StringSplitOptions) and a Split(String[], StringSplitOptions) function, and the compiler doesn't know which one to use.
So my question is then. How do I tell the compiler that I'm using a string array when the arrays in JScript.NET are dynamically typed?
Edit: As far as I know, JScript.NET use the same APIs as C#. So this is the String class I'm using. However, I think the syntax is the same as JavaScript. Maybe someone could confirm this?
Edit2: So if there is a way to enforce a type in JScript.NET so the compiler knows which type is used, I guess that would be the answer for my case as well? JScript.NET does not have the same syntax as C#.
I figured it out once I realized I was coding in JScript.NET and not JScript, which led me to a bunch of useful guides. One of them specifically mentioned how to create typed arrays.
It turns out it was a easy as this:
var array : String[] = [" -"];

Proper key format for objc_setAssociatedObject()

I've been using objc_setAssociatedObject() this way:
objc_setAssociatedObject(myObject, #"myKey1", obj2, OBJC_ASSOCIATION_ASSIGN);
In particular, my key is a character string, so the compiler uses the pointer to that string. I specify the same character string in objc_getAssociatedObject():
objc_getAssociatedObject(myObject, #"myKey1").
I've been using this scheme for a long time without any problem. However, the examples on SO use a pointer to a static variable, so I now realize that my method might be incorrect. The compiler uses the same pointer each time, so it's always worked.
Is my method okay? It seems equivalent to using a pointer to a static string. Under what circumstances might the compiler store two different copies of my key?
Actually two equal string constants have the same address, if they are used in the same translation unit. (A TU is a term from C, basically it means: "The same .m file".) But this behavior is not guaranted and might change in future.
This caveat applies to compile-time string literals as well. Historically, string literals (using the #"..." syntax) have been uniqued across translation units during linking. This is an implementation detail of the compiler and should not be relied upon. If you are using such code, please use global string constants instead (NSString * const MyConst = #"...") or use isEqual:.
http://clang.llvm.org/docs/ObjectiveCLiterals.html
BTW: You should use collision free keys. MyKey does not fulfill this. Better use com.MyComponay.MyTarget.MyKey or a equivalent rDNS notation.
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
There are three ways to set "const void *key" as the globally unique keyword. To sure there is one-to-one match between the const void *key and associated Object.
a static variable :&btnKey
#selector(methodName)
_cmd
1 . A static variable you set
2 . #selector(methodName).
3 . _cmd instead of #selector(methodName)
*_cmd* is the the current method of the selector in OC, the same as *self*
is current method call the object instance.
"It is often recommended that they key be a static char—or better yet, the pointer to one. Basically, an arbitrary value that is guaranteed to be constant, unique, and scoped for use within getters and setters
However, a much simpler solution exists: just use a selector.
objc_getAssociatedObject(self, #selector(associatedObject))
"
Refer to this for complete explanations on Associated Objects: http://nshipster.com/associated-objects/

Global constants in F# - how to

I need to set a version number to be used in the AssemblyVersion attribute by several related projects.
In C# I use the following
public class Constants {
public const string Version = "1.2.3.4";
}
then it can be used as follows:
[assembly:AssemblyVersion(Constants.Version)]
What would be the equivalent construct in F#. All my attempts to come up with a binding which can be accepted as an attribute argument did not work.
Use the attribute Literal:
[<Literal>]
let version = "1.2.3.4"
[<assembly:AssemblyVersion(version)>]
Since I stepped into this trap myself I thought I'd share for anyone following.
A 'Literal' requires that the letter starts with a capital letter. This will hit you when you try to use the literal in a pattern matching construct.
Reference:
Literal attribute not working

Resources