Consider the following line of code that doesn't compile in Dart -- lack of comma operator, but comparable things are totally fine in JavaScript or C++:
final foo = (ArgumentError.checkNotNull(value), value) * 2;
The closest I could get with an ugly workaround is
final foo = last(ArgumentError.checkNotNull(value), value) * 2;
with function
T last<T>(void op, T ret) => ret;
Is there a better solution?
Dart does not have a comma operator similar to the one in JavaScript.
There is no obviously better solution than what you already have.
The work-around operation you introduced is how I would solve it. I usually call it seq for "sequence" if I write it.
There is sadly no good way to use an extension operator because you need to be generic on the second operand and operators cannot be generic. You could use an extension method like:
extension Seq on void {
T seq<T>(T next) => next;
}
Then you can write ArgumentError.checkNotNull(value).seq(value).
(For what it's worth, the ArgumentError.checkNotNull function has been changed to return its value, but that change was made after releasing Dart 2.7, so it will only be available in the next release after that).
If the overhead doesn't matter, you can use closures without arguments for a similar effect (and also more complex operations than just a sequence of expressions).
final foo = () {
ArgumentError.checkNotNull(value);
return value;
} ();
This is not great for hot paths due to the overhead incurred by creating and calling a closure, but can work reasonably well outside those.
If you need this kind of test-plus-initialization pattern more than once, the cleanest way would arguably be to put it in a function of its own, anyway.
T ensureNotNull<T>(T value) {
ArgumentError.checkNotNull(value);
return value;
}
final foo = ensureNotNull(value);
Related
I have the following Dart 2 code with null-safety.
extension Foo<T> on List<T> {
List<U> bar<U>({
U Function(T)? transform,
}) {
final t = transform ?? _identityTransform;
return map(t).toList();
}
}
U _identityTransform<T, U>(T t) => t as U; // #1, #2
void main() {
final strings = ['a', 'b', 'c'].bar<String>(); // #3
final ints = ['1', '2', '3'].bar(transform: int.parse);
print(strings);
print(ints);
}
It is an extension method on List<T> with a custom method that is basically a map with the
difference that it can return a new list of the same type if no transform is specified. (My real code is more complex than this, but this example is enough to present my questions.)
I want to be able to call bar() on a List with transform or without; if called without it, _identityTransform should be used.
The code above works, but I have a few reservations as to its quality, and questions, as I haven't really come to terms with Dart generics yet:
In the line marked #1 - the _identityTransform takes two generic parameters as I need access to them, but when the function is used the generic types are not used because I don't think it is possible to write something like _identityTransform<T, U> there. Is there a better way of defining _identityTransform? Am I losing any type safety with my current code?
In the line marked #2 I need a cast as U for the code to compile, I haven't managed to make the code work without it. Is there a way to do it without the cast?
In the line marked #3, when I call the extension method without any transform (i.e. I want the identity transform to kick in) I need to explicitly pass the generic type, otherwise the compiler complains about missing generic type (in strong mode) or infers strings to be List<dynamic> (strong mode turned off). Is some generics magic possible to be able to call .bar() and still have strings be inferred to List<String>?
I would make _identityTransform a nested function of bar so that you can remove its type arguments and instead use the same T and U as bar:
extension Foo<T> on List<T> {
List<U> bar<U>({
U Function(T)? transform,
}) {
U _identityTransform(T t) => t as U;
final t = transform ?? _identityTransform;
return map(t).toList();
}
}
Alternatively if you want to explicitly use _identityTransform<T, U>, then you could use a closure: t = transform ?? (arg) => _identityTransform<T, U>(arg), but that seems like overkill.
You need the cast. T and U are independent/unrelated types. Since you don't know that you want T and U to be the same until bar checks its argument at runtime, you will need the explicit cast to satisfy static type checking.
If the caller passes nothing for the transform argument, there is nothing to infer U from, so it will be dynamic. I can't think of any magical way make U default to T in such a case (again, that would be known only at runtime, but generics must satisfy static analysis).
I'm just beginning to learn Dart and Flutter and I was wondering if there is any difference in the following declarations?
final List<WordPair> _suggestions = <WordPair>[];
and
final _suggestions = <WordPair>[];
They both seem to exhibit the same behaviour but I'm wondering if there is some underlying difference?
I prefer the first declaration as I'm coming from a C/C++ back ground
There's no difference between them at all.
The second syntax is here only to avoid pointless repetition.
Usually you should prefer the shorthand in Dart. According to the DO/DON'T of dart, there are some conditions in which you'll want to use the full syntax though.
final List<Foo> globalVariable = <Foo>[];
void func() {
final localVariable = <Foo>[]
}
I am having difficulty referring to parameterless functions in Fable.
With this example:
let f1 () =
1
let someRefTof1 = f1
I'd expect the generated js to look something like this:
function f1() {
return 1;
}
var someRefTof1 = f1;
but what I actually get is:
function f1() {
return 1;
}
var someRefTof1 = exports.someRefTof1 = function someRefTof1(arg00_) {
return f1(arg00_);
};
I'm unclear on the purpose of arg00_ or how to avoid it being generated?
(As a bit of background, I am struggling to call a function in an external js library which expects a function to be passed as a parameter)
Edit:
Background
The above is what i believe to be a minimal, verifiable, reproduction of my question but, after comments, I thought it may be useful to provide a touch more context on why this is causing issues. What I am actually trying to do is use angularjs from Fable.
So my example looks more like this:
let app = AngularFable.NgFable.angular.``module``("app",[||])
type TestCtrl() =
member this.Val1() = "boom";
app?controller("test", TestCtrl)
which gets compiled to:
var app = exports.app = angular.module("app", []);
var TestCtrl = exports.TestCtrl = function () {
function TestCtrl() {
_classCallCheck(this, TestCtrl);
}
TestCtrl.prototype.Val1 = function Val1() {
return "boom";
};
return TestCtrl;
}();
_fableCore.Util.setInterfaces(TestCtrl.prototype, [], "App.TestCtrl");
app.controller("test", function (unitVar) {
return new TestCtrl();
});
with unitVar being the problematic parameter introduced in this example. When I use this in my html with something like:
<div ng-app="app">
<div ng-controller="test as vm">
{{vm.Val1()}}
</div>
</div>
I run into an unknown provider error whereas if I simply change the compiled javascript to remove the unitVar parameter from the last line like this:
app.controller("test", function () {
return new TestCtrl();
});
then my example works as expected.
I'd really like to know if there is a way to avoid having the Fable compiler generate this parameter. I'm 99% sure this reduces to the same problem as in my original question but I've included this additional context to better explain why this is an issue
Thank you very much for your question and detailed explanations. There're two things here that are a bit tricky and are caused by optimisations both of the F# compiler and Fable.
In the AST provided by the F# compiler, methods (functions that are members of a type or module) are compiled as usual methods as in C#. This is for optimization.
However, when you create an anonymous lambda or make a reference to a method, the F# compiler will keep F# semantics, that is, all functions have a single argument (as John Palmer says, unit is an argument too) and can be curried.
Ok, this info is just to make clear why the F# compiler/Fable represent methods and lambdas differently. Let's go with the issue of argumentless functions: the obvious solution would be of course to remove the F# compiler generated argument for functions accepting unit (as it's already done for methods). In fact, I also had problems with libraries like Mocha because of this.
I did try to remove the unit argument at the beginning but I got fails in some scenarios because of this. TBH, I don't remember now exactly which tests were failing but because of the expectation that there'll be always an argument, in some cases function composition or inlining was failing when the unit argument was removed.
Other attempts to modify the semantics of F# functions in the JS runtime have always failed because they don't cover all scenarios. However, we can be more lenient with delegates (System.Func<>) as it's usually safe to assume these ones should behave more like functions in languages like C# or F#. I can try to remove the unit argument just for delegates and see what happens :)
For more info about sending F# functions to JS code you can check the documentation.
UPDATE: Scratch all that, please try fable-compiler#0.6.12 and fable-core#0.6.8. This version eliminates unit arguments, the solution was actually simpler than I thought and (hopefully) shouldn't create issues with existing projects. (The explanation about methods and lambdas compiled differently still applies.)
How can I described a method body like this with expression-bodied way?
void SomeMethod() =>
foreach(int value in ListOfInt)
collect += count;
As its name suggested, it's an expression at first. An expression is evaluated to a value, while your SomeMethod doesn't. You can argue that it does return a void and it's valid in C#. The point is do expression-bodies methods make your code more readable. If not, don't use it.
Instead of converting to expression bodies method directly, it makes more sense to simplify current code. Given only piece of code in question, it can be written
collect += ListOfInt.Count() * count;
If count is calculated from value, then it can be
collect += ListOfInt.Select( value => ...calculate count ...).Sum();
or leverage Enumerable.Aggregate for complex logic.
The trick is to convert foreach statement to expression. Then converting whole method to expression is easier.
The simplest solution is to not use an expression bodied function e.g.
void SomeMethod()
{
foreach(int value in ListOfInt)
collect += count;
}
You can use ForEach method as expression-body instead. Now your expression would look like this:
void SomeMethod() => ListOfInt.ForEach(value => {collect+=count;});
I want users of my C++ application to be able to provide anonymous functions to perform small chunks of work.
Small fragments like this would be ideal.
function(arg) return arg*5 end
Now I'd like to be able to write something as simple as this for my C code,
// Push the function onto the lua stack
lua_xxx(L, "function(arg) return arg*5 end" )
// Store it away for later
int reg_index = luaL_ref(L, LUA_REGISTRY_INDEX);
However I dont think lua_loadstring will do "the right thing".
Am I left with what feels to me like a horrible hack?
void push_lua_function_from_string( lua_State * L, std::string code )
{
// Wrap our string so that we can get something useful for luaL_loadstring
std::string wrapped_code = "return "+code;
luaL_loadstring(L, wrapped_code.c_str());
lua_pcall( L, 0, 1, 0 );
}
push_lua_function_from_string(L, "function(arg) return arg*5 end" );
int reg_index = luaL_ref(L, LUA_REGISTRY_INDEX);
Is there a better solution?
If you need access to parameters, the way you have written is correct. lua_loadstring returns a function that represents the chunk/code you are compiling. If you want to actually get a function back from the code, you have to return it. I also do this (in Lua) for little "expression evaluators", and I don't consider it a "horrible hack" :)
If you only need some callbacks, without any parameters, you can directly write the code and use the function returned by lua_tostring. You can even pass parameters to this chunk, it will be accessible as the ... expression. Then you can get the parameters as:
local arg1, arg2 = ...
-- rest of code
You decide what is better for you - "ugly code" inside your library codebase, or "ugly code" in your Lua functions.
Have a look at my ae. It caches functions from expressions so you can simply say ae_eval("a*x^2+b*x+c") and it'll only compile it once.