I have a generic static method that looks like this:
static build<K>() {
return (GenericClass<K> param) => MyClass<K>(param);
}
So far I have tried:
typedef F = MyClass<K> Function(GenericClass<K> param);
but it says that:
The return type '(GenericClass<K>) → MyClass<K>' isn't a '(GenericClass<dynamic>) → MyClass<dynamic>', as defined by the method 'build'.
and
typedef F = SimpleViewModel<K> Function<k>(Store<K> param);
Which says that:
The return type '(GenericClass<K>) → MyClass<K>' isn't a '<K>(GenericClass<K>) → MyClass<K>', as defined by the method 'build'.
MyClass looks like this:
class MyClass<T> {
final GenericClass<T> param;
MyClass(this.param);
static build<K>() {
return (GenericClass<K> param) => MyClass<K>(param);
}
}
So, what is a valid typedef for it?
There are two concepts of "generic" when it comes to a typedef. The typedef can be generic on a type, or the typedef can refer to a generic function (or both):
A typedef which is generic on T:
typedef F<T> = T Function(T);
Then in usage:
F first = (dynamic arg) => arg; // F means F<dynamic>
F<String> second = (String arg) => arg; // F<String> means both T must be String
A typedef which refers to a generic function on M:
typedef F = M Function<M>(M);
Then in usage:
F first = <M>(M arg) => arg; // The anonymous function is defined as generic
// F<String> -> Illegal, F has no generic argument
// F second = (String arg) => arg -> Illegal, the anonymous function is not generic
Or both:
typedef F<T> = M Function<M>(T,M);
And in usage:
F first = <M>(dynamic arg1, M arg2) => arg2; // F means F<dynamic> so the T must be dynamic
F<String second = <M>(String arg1, M arg2) => arg2; // The T must be String, the function must still be generic on the second arg and return type
Related
I've defined an extension:
extension MyIterable<T extends num> on Iterable<T> {
T sum() => reduce((v, e) => v + e); // Error
}
Why is v + e not considered T, why is there an error?
The return type 'num' isn't a 'T', as required by the closure's context.
I'm using it in the main:
void main() {
int a = MyIterable<int>([1, 2]).sum();
double b = MyIterable<double>([1.0, 2]).sum();
num c = MyIterable<num>([1.0, 2]).sum();
}
Although v and e are statically known to be T, which is some subtype of num, the exact subtype isn't known, so v + e is only statically known to conform to num.operator+. Consequently, the result is num (the base type), not necessarily a T (the more specific subtype).
In this case, I think you'll probably need to add an as T explicit cast.
I try to implement pipe-operator overriding |
extension Pipe on Object {
operator |(Function(Object) f) => f(this);
}
typedef Id = A Function<A>(A);
Id id = <A>(A a) => a;
var t1 = id("test"); // String t1
var t2 = "test" | id; // dynamic t2
with the generic Id function above, on id("test") is detected as String, but "test" | id is dynamic which is very problematic.
How can I fix this?
EDIT
Thankfully, #jamesdlin has answered and suggested:
extension Pipe on Object {
Object operator |(Object Function(Object) f) => f(this);
}
the result has improved as
var t2 = "test" | id; // Object t2
I also tried with generic as follows:
extension Pipe<A, B> on A {
B operator |(B Function(A) f) => f(this);
}
I expected it would go better because I thought the generic A B is more specific and better than Object ; however, the result goes as bad as before:
var t2 = "test" | id; // dynamic t2
Why the generic does not work? Is there any way to make the dart compiler infer it as string ?
Your operator | extension does not have a declared return type. Its return type therefore is implicitly dynamic. Also note its callback argument does not specify a return type either, so that also will be assumed to be dynamic.
Declare return types:
extension Pipe on Object {
Object operator |(Object Function(Object) f) => f(this);
}
(Answering your original question about a NoSuchMethodError: when you did
var x = "test" | id;
x | print;
x has type dynamic, but extension methods are static; they are compile-time syntactic sugar and will never work on dynamic types. Consequently, x | print attempts to call operator | on the object that x refers to, but that object doesn't actually have an operator |.)
in System.Activities.WorkflowApplication there is a delegate property:
public Action<WorkflowApplicationCompletedEventArgs> Completed { get; set; }
In my program so far, I have a variable that is an instance of this class
I want to define an F# function to set that:
let f (e: WorkflowApplicationCompletedEventArgs) =
// body
myInst.Completed <- f
but this produces the error:
Error 102 This expression was expected to have type
Action but here has type
'a -> unit
how do I complete function "f" to satisfy the compiler?
If you pass an anonymous function fun a -> ... to a method or a constructor that expects a System.Action<...> or a System.Func<...>, then it is automatically converted; in any other case, you need to convert it explicitly like #Funk indicated.
let f = System.Action<WorkflowApplicationCompletedEventArgs>(fun e ->
// body
)
myInst.Completed <- f
// Another solution:
let f (e: WorkflowApplicationCompletedEventArgs) =
// body
myInst.Completed <- System.Action<_>(f)
I would've thought the following code would work:
use std::num::{Num};
use std::fmt::{Show};
pub type GradFn<T : Num> = for<'a> fn(&'a [T]) -> (T, Vec<T>);
fn minimize<T : Show, F>(f : GradFn<T>, x0 : &[T]) {
// some no-op to test types
print!("{}",f(x0))
}
fn main() {
let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
};
let (fx, grad) = xSquared(vec![2.0f64].as_slice());
print!("{}", fx);
}
But I'm getting a compiler error (see here):
<anon>:12:32: 14:4 error: mismatched types: expected `fn(&'a [f64]) -> (f64, collections::vec::Vec<f64>)`, found `|&[f64]| -> (f64, collections::vec::Vec<f64>)` (expected extern fn, found fn)
<anon>:12 let xSquared : GradFn<f64> = |x : &[f64]| -> (f64, Vec<f64>) {
<anon>:13 return (x[0] * x[0], vec![2.0 * x[0]]);
<anon>:14 };
fn does not define a closure type; it defines bare function pointers (i.e. pointers to functions defined with the fn keyword). That's why you can't assign a closure to a GradFn. Instead, you want to use either Fn, FnMut or FnOnce.
There are a few more changes I needed to make to get this code to compile:
On minimize, the f parameter as you wrote it receives an unsized type by value, which is forbidden. You also put an F type parameter that you don't use. You probably meant to constrain F and to use F as the type of f.
The compiler won't let us use a type alias in a type parameter constraint; we need to spell out the trait fully. This means the type alias is basically useless.
I removed the type annotation on xSquared, which is unnecessary. This let me remove the type alias completely.
Here's the final code:
#![feature(unboxed_closures)]
use std::num::{Num};
use std::fmt::{Show};
fn minimize<T: Show, F: FnMut(&[T]) -> (T, Vec<T>)>(mut f: F, x0: &[T]) {
// some no-op to test types
print!("{}", f(x0))
}
fn main() {
let xSquared = |x: &[f64]| -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
};
let (fx, grad) = xSquared(vec![2.0f64].as_slice());
print!("{}", fx);
}
If your GradFn is actually going to be a bare function pointer (as opposed to a closure) you can keep the type alias, like this:
use std::num::Num;
use std::fmt::Show;
// this type has to point to a bare function, not a closure
pub type GradFn<T> = for<'a> fn(&'a [T]) -> (T, Vec<T>);
fn minimize<T>(f : GradFn<T>, x0 : &[T])
where T: Show + Num {
// some no-op to test types
println!("{}",f(x0))
}
fn main() {
// this is now a bare function
fn x_squared(x : &[f64]) -> (f64, Vec<f64>) {
return (x[0] * x[0], vec![2.0 * x[0]]);
}
// and this is a pointer to it, that uses your type alias
let x_sq : GradFn<f64> = x_squared;
let (fx, grad) = x_sq(&[2f64]);
println!("fx: {} - grad: {}", fx, grad);
minimize(x_sq, &[3f64]);; // works with minimize as well
}
This function should transform each element of the list with the given function transform:
void _doSomething(List<Something> numbers, [transform(Something element)]) {...}
As I don't want to skip this method when the transform should not do anything, I wanted to give a default value to the transform method like this:
void _doSomething(List<Something> numbers,
[transform(Something element) = (v) => v]) {...}
Unfortunately, the editor tells me
Expected constant expected
Is there some workaround or simply not possible (or shouldn't be done like this at all)?
if you want to initialize a Function parameter that is also a field of your class I suggest:
class MyClass{
Function myFunc;
MyClass({this.myFunc = _myDefaultFunc}){...}
static _myDefaultFunc(){...}
}
Or more suitable:
typedef SpecialFunction = ReturnType Function(
FirstParameterType firstParameter,
SecondParameterType secondParameter);
class MyClass{
SpecialFunction myFunc;
MyClass({this.myFunc = _myDefaultFunc}){...}
static ReturnType _myDefaultFunc(FirstParameterType firstParameter,
SecondParameterType secondParameter){...}
}
You can define the default function as private method :
_defaultTransform(Something v) => v;
void _doSomething(List<Something> numbers,
[transform(Something element) = _defaultTransform]) {...}
Or check argument like this :
void _doSomething(List<Something> numbers, [transform(Something element)]) {
if (!?transform) transform = (v) => v;
...
}
Or like Ladicek suggests :
void _doSomething(List<Something> numbers, [transform(Something element)]) {
transform ??= (v) => v;
...
}
Write your default parameters inside a square bracket []
DummyFunctin(String var1, int Var2,[ String var3 = "hello", double var4 = 3.0, List<int> var5 = [2,4,5,6],] ){
// some calculation
// return something
}