How do I do things in a constructor in F#? I cant quite figure it out...
I would check out Constructors (F#):
Objects of class types have
constructors. There are two kinds of
constructors. One is the primary
constructor, whose parameters appear
in parentheses just after the type
name. You specify other, optional
additional constructors by using the
new keyword. Any such additional
constructors must call the primary
constructor.
Related
I'm new to dart and came across code like below:
class Foo {
Foo._internal();
static final Foo instance = Foo._internal();
// other stuff
}
I was confused by that the function _internal is called twice(in line2 and line3 respectively).
Later I realized the first one is actually not an invocation but a definition of a constructor.
It's just that the body of the definition is omited(allowing this is really bad a syntax rule of Dart IMHO).
So my question become that in what cases a function of dart can omit body?
Dart provides a lot of syntactic sugar for constructors, including the ability to use a semicolon in place of an empty constructor body. Since initialization lists should be preferred when possible, it's not uncommon for constructors to have empty bodies, so the shorthand is useful. Additionally, redirecting constructors and const constructors aren't allowed to have bodies at all.
Constructors aren't functions, so that shorthand does not apply to functions and methods in general. (As another example of a distinction between constructors and functions, only constructors can be used with new and const.) For methods, distinguishing between no body and an empty body is important:
abstract class AbstractInterface {
void mustBeOverridden();
void optionallyOverridden() {}
}
I agree that a constructor like Foo._internal(); looks weird, but I think it's not a common situation since it requires the intersection of a number of cases to make it look like a method call:
The class uses a named constructor.
That constructor takes no arguments.
That constructor does not use an initializer list.
That constructor does not use a constructor body.
So the following code snippet
Set mySet = {1,2,3};
is an instance of type Set which is permissible, however what would the class of the set literal be. I have tried to search for this, however I have found no answer in the dart documentation.
A literal exists only in your source code. Asking for its "class" doesn't make a lot of sense.
Using a Set, Map, or List literal is just syntactic sugar for invoking a corresponding constructor. The Set factory constructor constructs a LinkedHashSet.
However, you'll see that LinkedHashSet is also abstract. Its factory constructor returns an instance of a private, internal class. You can see its typename via print(Set().runtimeType); the actual type might be different for different platforms and is unlikely to be useful to you.
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 following declaration:
type
TRec = record
constructor Create;
end;
produces this compilation error:
E2394 Parameterless constructors not allowed on record types
The documentation rather unhelpfully states:
No further information is available for this error or warning.
My question is why the language was designed this way. Was it done this way purely to echo the analogous restriction for C# structs?
The language guide says this:
Records are constructed automatically, using a default no-argument constructor, but classes must be explicitly constructed. Because records have a default no-argument constructor, any user-defined record constructor must have one or more parameters.
But that doesn't make much sense. If there is a default constructor for a record, it can't be found through RTTI. And even if there was, why would that imply that it was impossible to add another one? You can do so for classes.
Perhaps the rationale is that if we were allowed to define our own parameterless constructors, we'd expect the compiler to call them automatically.
Note: I understand that you can use a parameterless static class function as a workaround. Indeed, I personally always prefer to use static class function instead of record constructors. But that's not the point of the question. What I really want to know is why parameterless constructors are not allowed on record types.
I can't give you a definitive answer (only the compiler builders can), but I suspect it is not related to Delphi's .NET past, but rather to Delphi's relation with C++Builder.
As cppreference says:
A default constructor is a constructor which can be called with no arguments (either defined with an empty parameter list, or with default arguments provided for every parameter).
C++ allows for parameterless constructors, and these parameterless constructors would become the default constructor, in C++. A default constructor is called in many situations, e.g. if you simply declare:
Foo myFoo;
The default constructor is called. This does not happen in Delphi, but a C++ programmer might expect it. Similarly, if you do:
Foo elements[1000];
The default constructor is called on each element (I checked that). This also doesn't happen in Delphi, although a C++ programmer might expect it.
Other hints that this is C++-related:
Constructors with different names (e.g. Init) are not allowed either. This seems to point to conflicts with C++ or with C#, as in both, constructors have the name of the class or struct, so any parameterless constructor would be mapped to Foo() (in a struct or class called Foo.)
Constructors with only default parameters are not allowed either. This matches the cppreference description for default constructors with only default arguments.
All in all, there are hints that parameterless constructors (or ones with only default parameters) conflict with C++ (i.e. C++Builder) and that that is why they are not allowed.
Note that this is not the only restriction caused by differences with C++: e.g. in Delphi you can't cast integers to and from floating point types either, because in C and C++, that would cause a conversion, while in Delphi, it would merely cause a reinterpretation of the bits. In order not to confuse people who were coming to Delphi from C or C++, the casting restriction was placed on floating point types. There may be more.
If I have a class declaration like this one:
MyCollection<T: TBaseCopyable, constructor> = class
What does the keyword constructor do?
Doesn't every class have a constructor already, what is it up doing there?
It is a generic constraint.
Constraints can be associated with a type parameter of a generic. Constraints declare items that must be supported by any particular type passed to that parameter in a construction of the generic type.
This particular constraint is the constructor constraint:
A type parameter may be constrained by zero or one instance of the reserved word "constructor". This means that the actual argument type must be a class that defines a default constructor (a public parameterless constructor), so that methods within the generic type may construct instances of the argument type using the argument type's default constructor, without knowing anything about the argument type itself (no minimum base type requirements).
In a constraint declaration, you can mix "constructor" in any order with interface or class type constraints.
In my opinion it's a largely useless feature. Every time I've written a generic container class that wishes to instantiate members, I've found that I needed to be able to pass parameters to the constructor. I have absolutely no idea why the feature exists in this crippled form.
There is a well-known technique that allows generic containers to instantiate members, discussed here: Generics constructor with parameter constraint?