I trying make the following overloading inside my class:
class Array extends ListBase<double> {
List<double> l = [];
List<double> operator +=(List<double> b) {
var c = Array.length(l.length);
for(int i = 0; i < l.length; i++) {
c[i] = this[i] * b[i];
}
return c;
}
}
but the Dart compiler show the error message: the string '+=' ins't a user-definable operator. Is there some way to make the overloading of the operator += for others classes types?
Overload only operator +. Dart reuse operators that have a well known semantic meaning such as +=.
Add #override annotation if operator already defined in base class.
Related
I'm working on some generic list utility functions and there seems to be an issue with the type inference for a generic function when the primary variables are lists. This is demonstrated with the following code:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
When I use this code as-is, the type inference within the lambda sets a and b to be Object?, which results in the following error message:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'.
Try adding a null check to the target ('!').
Doing what the error message says changes the message to the following:
The operator '+' isn't defined for the type 'Object'.
Try defining the operator '+'.
The issue obviously is that type inference is assigning the parameters to Object? instead of the expected int. This can be worked around by either typing the parameters or explicitly passing the generic type to the function:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
However, that's an added level of verbosity that I don't want to have to force the users of these utility functions to have to do (not to mention it will be a support issue when I have to explain to them to do this). Is there a way to change the function signature to make it so type inference works as expected?
This is basically Dart List.fold vs List.reduce type inference, but in your case you could sidestep the problem by making your function an extension method so that T is deduced from the receiver instead of from the arguments:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
class X extends Y {
X(int a, int b) : super(a,b);
}
Can someone give me an explanation about the syntax meaning of the colon :?
This feature in Dart is called "initializer list".
It allows you to initialize fields of your class, make assertions and call the super constructor.
This means that it is not the same as the constructor body. As I said, you can only initialize variables and only access static members. You cannot call any (non-static) methods.
The benefit is that you can also initialize final variables, which you cannot do in the constructor body. You also have access to all parameters that are passed to the constructor, which you do not have when initializing the parameters directly in the parentheses.
Additionally, you can use class fields on the left-hand of an assignment with the same name as a parameter on the right-hand side that refers to a parameter. Dart will automatically use the class field on the left-hand side.
Here is an example:
class X {
final int number;
X(number) : number = number ?? 0;
}
The code above assigns the parameter named number to the final field this.number if it is non-null and otherwise it assigns 0. This means that the left-hand number of the assignment actually refers to this.number. Now, you can even make an assertion that will never fail (and is redundant because of that, but I want to explain how everything works together):
class X {
final int number;
X(number): number = number ?? 0, assert(number != null);
}
Learn more.
It's ok to access non static member in initializer list.
class Point {
num x, y;
Point(this.x, this.y);
Point.origin(): this.x = 10, this.y = 10;
}
main() {
Point p = Point.origin();
print(p.x); // 10
}
I need clarity on how objects are declared and assigned a definition in F#.
What's happening in this code?
let service = {
new IService with
member this.Translate(_) = raise error }
My guess is we're creating an object that will implement some interface on the fly even though there is no actual class that's backing this object. Hence, we're removing the ceremony involved with creating an object by not having to declare a separate class to use it. In this case, we're minimizing the ceremony involved for implementing a mock object that could be used within a unit test.
Is my understanding accurate?
I tried to research my question and found the specification for F# 3.0 (Section - 6.3.8 Object Expressions)
6.3.8 Object Expressions An expression of the following form is an object expression: { new ty0 args-expropt object-members interface
ty1 object-members1 … interface tyn object-membersn } In the case
of the interface declarations, the object-members are optional and are
considered empty if absent. Each set of object-members has the form:
with member-defns endopt Lexical filtering inserts simulated $end
tokens when lightweight syntax is used. Each member of an object
expression members can use the keyword member, override, or default.
The keyword member can be used even when overriding a member or
implementing an interface.
For example:
let obj1 =
{ new System.Collections.Generic.IComparer<int> with
member x.Compare(a,b) = compare (a % 7) (b % 7) }
You can get a pretty good picture of what is happening behind the scenes if you look at the generated IL using a decompiler like ILSpy. For the example involving IComparer, it generates a hidden class, which implements the interface:
internal sealed class obj1#2 : IComparer<int> {
public obj1#2() : this() { }
int IComparer<int>.System-Collections-Generic-IComparer(int x, int y) {
int num = x % 7;
int num2 = y % 7;
if (num < num2) { return -1; }
return (num > num2) ? 1 : 0;
}
}
Inside the body of the method, it then creates a new instance:
IComparer<int> obj1 = new obj1#2();
Having a simple class as follows is considered a static warning, why?
operator 'negate' should return numeric type
class Vector {
final int x,y;
const Vector(this.x, this.y);
Vector operator +(Vector v) { // Overrides + (a + b).
return new Vector(x + v.x, y + v.y);
}
Vector operator -(Vector v) { // Overrides - (a - b).
return new Vector(x - v.x, y - v.y);
}
Vector operator negate() { // Overrides unary negation (-a).
return new Vector(-x,-y);
}
String toString() => '($x,$y)';
}
main() {
final v = new Vector(2,3);
final w = new Vector(2,2);
assert((-v).x == -2 && (-v).y == -3); // -v == (-2,-3)
}
As of 8/21/2012 the Dart Specification Section 7.1.2 Operators, considers defining negate with a possible nullary type as bad style and should report to the user a static warning.
Defining a nullary method named negate or a binary method named equals
will have the same effect as dening an operator but is considered bad
style, and will cause a static warning.
[...]
It is a static warning if the return type of the user-declared
operator []= is explicitly declared and not void. It is a static
warning if the return type of the user-declared operator equals is
explicitly declared and is not bool. It is a static warning if the
return type of the user-declared operator negate is explicitly
declared and not a numerical type.
We have an open bug for this: http://code.google.com/p/dart/issues/detail?id=3416
this is example code in C# :
class exampleClass
{
struct exampleStruct
{
public int number;
}
private exampleStruct[,] e;
private enum exampleMove { Up, Down, Right, Left, Enter, Escape };
Stack<int> returnPath;
bool returntoBeg;
int numRandomMoves;
public exampleClass()
{
e = new exampleStruct[5, 5];
exampleStruct ex;
returntoBeg = false;
returnPath = new Stack<int>();
numRandomMoves = 0;
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
ex = new exampleStruct();
ex.number = 0
e[x, y] = ex;
}
}
}
}
I have an example code like above, i want to translate it into F#. But the problem is, when i make a class using F# and define struct in it, it shows errors and pointing that i can't declare type inside class type. Any help?
I think the following is a good workaround for nested types.
namespace MyNamespace
module private PrivateTypes =
[<Struct>]
type ExampleStruct(number: int) =
member __.Number = number
open PrivateTypes
type ExampleClass() =
let e = Array2D.init 5 5 (fun y x -> ExampleStruct(0))
//other members
ExampleStruct is nested under PrivateTypes, which is only visible in the same file.
While you cannot nest types, you can use intrinsic complex types that F# provides. Tuples are often a good data structure for data that has not very wide, observable scope, such as it is in your case.
In practice, I usually define implementation types in a module called e. g. Internal, and do not allow them to escape from the library. You may also define separate module per logical group of classes or even per complex class implementation.