Should I give type when creating variable?
Any downside for just declaring the keyword "var"?
Any difference between these two?
var a = 0;
int a = 0;
Pros/Cons
ONGOING WORK
Best Practices
It's recommended to use var or final keyword, without specifying type annotation, and implicitly infer type for known local variables. Otherwise it's recommended to specify type annotations. As for dynamic keyword, it should be used very sparingly in specific use-cases, when you're doing manual type checking. For example print(myVariable is SomeType).
omit_local_variable_types Dart linter rule encourages omitting type annotation for known local variables. always_specify_types encourages specifying type annotations for cases that don't fall into the scope of the former linter rule.
1. Style guide for Flutter repo
1.1 avoid using var
All variables and arguments are typed; avoid "dynamic" or "Object" in
any case where you could figure out the actual type. Always specialize
generic types where possible. Explicitly type all list and map
literals.
This achieves two purposes: it verifies that the type that the
compiler would infer matches the type you expect, and it makes the
code self-documenting in the case where the type is not obvious (e.g.
when calling anything other than a constructor).
Always avoid "var". Use "dynamic" if you are being explicit that the
type is unknown, but prefer "Object" and casting, as using dynamic
disables all static checking.
2. Dart Lint Rules
2.1 omit_local_variable_types
CONSIDER omitting type annotations for local variables.
Usually, the types of local variables can be easily inferred, so it
isn't necessary to annotate them.
2.2 always_specify_types
DO specify type annotations.
Avoid var when specifying that a type is unknown and short-hands that
elide type annotations. Use dynamic if you are being explicit that the
type is unknown. Use Object if you are being explicit that you want an
object that implements == and hashCode.
References
You can refer to Style guide for Flutter repo, full list of Dart's Linter Supported Lint Rules, and Effective Dart's Style Guide.
Note, Style guide for Flutter repo is used among flutter community and takes precedence over LinterRules and Effective Dart's Style Guide especially within repo contributions. From what I've seen, Style guide for Flutter repo is more of a superset Style Guide that should honor Dart Linter rules.
There isn't any difference between the two statements you gave.
And I don't see any downside to only declare the keyword "var", unless that your code might become a bit more difficult to read. On the other side, specifying the type might become a bit redundant sometimes.
But this is really just a question of taste 😄
I advise you to pick between those two, and be consistent in your code.
If you choose to always specify the type, you can use always_specify_types in your file analysis_options.yaml :
https://dart-lang.github.io/linter/lints/always_specify_types.html
Related
I see this recommended in the dart style guide, and copied in tons of tutorials and flutter source.
final foo = config.foo;
I don't understand it, how is this considered best practice when the readability is so poor? I have no clue what foo is here, surely final String foo = config.foo is preferable if we really want to use final?
This seems the equivalent to using var, which many consider a bad practice because it prevents the compiler from spotting errors and is less readable.
Where am I wrong?
In a lot of cases is does not really matter what type you are using as long the specific type can be statically determined by the compiler. When you are using var/final in Dart it is not that Dart does not know the type, it will just figure it out automatically based on the context. But the type must still be defined when the program are compiled so the types will never be dynamic based on runtime behavior. If you want truly dynamic types, you can use the dynamic keyword where you tell Dart "trust me, I know what I am doing with this types".
So types should still be defined where it matter most. This is e.g. for return and argument types for methods and class variables. The common factor for this types is that they are used to define the interface for using the method or class.
But when you are writing code inside a method, you are often not that interested in the specific types of variables used inside the method. Instead the focus should be the logic itself and you can often make it even more clear by using good describing variable names. As long the Dart analyzer can figure out the type, you will get autocomplete from your IDE and you can even still see the specific type from your IDE by e.g. Ctrl+Q in IntelliJ on the variable if you ends up in a situation where you want to know the type.
This is in particular the case when we are talking about the use of generics where it can be really tiresome to write the full specific type. Especially if you are using multiple generics inside each other like e.g. Map<String, List<String>>.
In my experience, Dart is really good to figure out very specific types and will complain loudly if your code cannot be determined statically. In the coming future, Dart will introduce non-null by default, which will make the Dart compiler and analyzer even more powerful since it will make sure your variable cannot be null unless this is something you specifically want and will make sure you are going to test for null when using methods which are specified to not expecting null.
About "Where am I wrong?". Well, a lot of languages have similar feature of var/final like Dart with the same design principle about the type should still be statically determined by a compiler or runtime. And even Java has introducing this feature. As a experienced Java and Dart programmer I have come to the conclusion for myself that typing inside methods are really not that important in a lot of cases as long I can still easily figure out the specific type by using an IDE when it really matters.
But it does make it more important to name your variables so they are clearly defining the purpose. But I am hoping you already are doing that. :)
I tried to use method overloading in some dart code and quickly learned that overloading is not offered in dart.
My questions are: why is it not offered, and what is the recommended alternative? Is there a standard naming convention since methods that do the same thing but with different inputs must have different names?
Is it standard to use named parameters and then check that the caller has supplied enough information to complete the calculation?
Say I have a method that returns how much money someone makes in a year, called yearlyIncome.
In Java, I would create a method like this
double yearlyIncome(double hourlyRate, double hoursWorkedPerYear)
And maybe another method like this
double yearlyIncome(double monthlyRate, int monthsWorkedPerYear)
and so on. They're all used to calculate the same thing, but with different inputs. What's the best, standardized way to do this in dart?
Thanks so much in advance.
Function overloading is not supported in Dart at all.
Function overloading requires static types. Dart at its core is a dynamically typed language.
You can either use different names for the methods or optional named or unnamed parameters
// optional unnamed
void foo(int a, [String b]);
foo(5);
foo(5, 'bar');
// optional named
void foo(int a, {String b});
foo(5);
foo(5, b :'bar');
Optional parameters can also have default values. Optional named and unnamed parameters can not be used together (only one or the other for a single function)
In the case of a constructor you can use named constructors as an alternative
Dart did not support overloading originally because it was a much more dynamic language where the declared types did not have any semantic effect. That made it impossible to use static type based overload resolution.
Dart has since changed to be more statically type, and there is nothing fundamentally preventing Dart from adding overloading today, except that it would be a huge work and a huge change to the language. Or so I'd assume, because there isn't any obvious design that isn't either highly complicated or hugely breaking.
What you do instead in Dart is to use optional parameters. A method like:
String toString([int radix]);
effectively have two signatures: String Function() and String Function(int). It can act at both signatures.
There are definite limits to how far you can go with just optional parameters, because they still need to have exactly one type each, but that is the alternative that Dart currently provides. (Or use different names, but that's not overloading, you can do that in languages with overloading too).
Optional parameters is also one of the complications if we wanted to add overloading to the Dart language - would existing functions with optional parameters would count as multiple overloadings? If you declare a class like:
abstract class WithOverloading {
String toString();
String toString(int radix);
}
is that then the same signature as:
abstract class WithoutOverloading {
String toString([int radix]);
}
Probably not because you can tear off the latter and get one function with an optional parameter, and you might not be able to tear off both functions from the former and combine them into one function. Or maybe you can, that's why it's not a trivial design question how to include overloading into the existing Dart language.
See for example Data.Maybe.Base in the stdlib — all Maybe, Any, and All have a just constructor.
Agda allows these definitions. How can one specify which one to use?
Each data type comes with its own module. So Maybe, All and Any are all type constructors and modules simultaneously. Thus you can write Maybe.just, All.just or Any.just to disambiguate the constructor. Or it can be disambiguated by type inference (unification is a more appropriate term) or an explicit type signature like Thilo said in their comment. (It's not true however that you'll get an error if there some ambiguity -- you'll get an unsolved meta).
The terms "declaration" and "definition" are being used synonymously in Apple's Swift documentation and it's getting me confused.
Under the "Initialization" section (which talks about class initializers), Apple states:
You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition.
Further in a subsection they state:
You can set the initial value of a stored property from within an initializer, as shown above. Alternatively, specify a default property value as part of the property’s declaration.
I thought a variable declaration was different than a variable definition.
You are right that those two mean different thing, THOUGH I think most of the people just use both of them in the same meaning and I think that is also the case of those AppleDocs. Here is great article on subject:
Summary
A declaration provides basic attributes of a symbol: its type and its
name. A definition provides all of the details of that symbol--if it's
a function, what it does; if it's a class, what fields and methods it
has; if it's a variable, where that variable is stored. Often, the
compiler only needs to have a declaration for something in order to
compile a file into an object file, expecting that the linker can find
the definition from another file. If no source file ever defines a
symbol, but it is declared, you will get errors at link time
complaining about undefined symbols.
After doing much searching across the web for legitimate explanations, I have seemed to have found an answer:
The problem is that the two terms overlap to some extent. Definitions also serve as declarations, because they inject an identifier of a certain type to a scope. However, a declaration isn't a definition because it doesn't entail storage allocation for the declared object. To add to the confusion, the semantics of definitions and declarations is slightly different when applied to types and functions, as I will show momentarily. So let's look at a more detailed analysis of these two terms.
Here is the article: Declarations and Definitions.
The article gives further explanation and examples.
Declaration of variable mean to tell compiler their is a var\funct\struct of particular data type. Definition of variable mean asking compiler to allocate memory to variable or define storage for that variable. you can define a variable only one time but you can declare it as many time you want.
I think Apple's Swift 4 Language Reference can be construed as the authoritative answer. From the Declarations section (emphasis mine):
A declaration introduces a new name or construct into your program.
For example, you use declarations to introduce functions and methods,
variables and constants, and to define new, named enumeration,
structure, class, and protocol types. You can also use a declaration
to extend the behavior of an existing named type and to import symbols
into your program that are declared elsewhere.
In Swift, most declarations are also definitions in the sense that
they are implemented or initialized at the same time they are
declared. That said, because protocols don’t implement their members,
most protocol members are declarations only. For convenience and
because the distinction isn’t that important in Swift, the term
declaration covers both declarations and definitions.
What exactly is the difference between F#'s type augmentation and type extension, and do we really need both?
Are there situations where one is better than the other, and vice-versa?
I'm asking because I recently had a lecture in F# where the lecturer talked about both, and afterwards commented that he couldn't see the reason why both were included in the F# language.
Update:
Ok, so Vladislav Zorov links to a page with examples of using type augmentation both when defining your own types, and extending (or augmenting?) an external type.
pad links to an MSDN page where they call it intrinsic and optional type extension.
Both seem to illustrate the same thing. Can someone come with a concrete example of type extension and another concrete example of type augmentation perhaps, in order to explicitly clarify what the two things are exactly?
The following bits from MSDN's Type Extensions page are relevant (emphasis mine):
There are two forms of type extensions that have slightly different
syntax and behavior. An intrinsic extension is an extension that
appears in the same namespace or module, in the same source file, and
in the same assembly (DLL or executable file) as the type being
extended. An optional extension is an extension that appears outside
the original module, namespace, or assembly of the type being
extended. Intrinsic extensions appear on the type when the type is
examined by reflection, but optional extensions do not. Optional
extensions must be in modules, and they are only in scope when the
module that contains the extension is open.
The purpose of optional extension is clear. It helps you inject new functionalities to types not belonging to your assemblies. For examples, FSharpx uses it to create various helpers for parsing primitive types:
open System
type Boolean with
static member parse x =
match bool.TryParse(x) with
| true,v -> Some v
| _ -> None
Why do you need intrinsic extension then? The answer is its convenience. I find it useful to break down type definitions to multiple sections with clear purposes.
In many F# libraries, I saw the use of the following pattern: type definition -> utility functions -> intrinsic extension. In this way, you can define sophisticated utility functions on your types, make them available in modules and still can use them directly in your member definitions. You can look at Complex type in F# PowerPack to see the pattern.
EDIT:
To be honest, I often use type extension and type augmentation interchangeably. The thing that matters is whether they are intrinsic or optional.
They are different things. Type augmentations, when defined in the same namespace, module and source file, actually become part of the type when compiled. Type extensions (a.k.a. type augmentations for types outside of the module and source file) are implemented with .NET extension methods.
They both use the same syntax, the only difference is whether the type you mention is in the same namespace and assembly, i.e. you're augmenting your own code and the additional methods can be added to your type before compilation.
Source: http://tomasp.net/blog/fsharp-iii-oop.aspx
Edit:
This is a terminology mix-up, they are both referring to the same thing - intrinsic extensions are type augmentations of the first kind (i.e. same namespace and assembly), optional extensions are type augmentations of the second kind (i.e. 3rd party assembly, in the blog post this is the List<T> augmentation example).
I assume when your lecturer is talking about type augmentations, he's referring to intrinsic extensions, i.e. first kind type augmentations, and when he's talking about type extensions, he's talking about optional extensions, or second kind type augmentations.