Implement opApply with nogc and inferred parameters - foreach

Note: I initially posted an over-simplified version of my problem. A more
accurate description follows:
I have the following struct:
struct Thing(T) {
T[3] values;
int opApply(scope int delegate(size_t, ref T) dg) {
int res = 0;
foreach(idx, ref val; values) {
res = dg(idx, val);
if (res) break;
}
return res;
}
}
Foreach can be used like so:
unittest {
Thing!(size_t[]) thing;
foreach(i, ref val ; thing) val ~= i;
}
However, it is not #nogc friendly:
#nogc unittest {
Thing!size_t thing;
foreach(i, ref val ; thing) val = i;
}
If I change the signature to
int opApply(scope int delegate(size_t, ref T) #nogc dg) { ... }
It works for the #nogc case, but fails to compile for non-#nogc cases.
The solutions I have tried are:
Cast the delegate
int opApply(scope int delegate(size_t, ref T) dg) {
auto callme = cast(int delegate(size_t, ref T) #nogc) dg;
// use callme instead of dg to support nogc
This seems wrong as I am willfully casting a #nogc attribute even onto
functions that do may not support it.
Use opSlice instead of opApply:
I'm not sure how to return an (index, ref value) tuple from my range. Even if
I could, I think it would have to contain a pointer to my static array, which
could have a shorter lifetime than the returned range.
Use a templated opApply:
All attempts to work with this have failed to automatically determine the
foreach argument types. For example, I needed to specify:
foreach(size_t idx, ref int value ; thing)
Which I see as a significant hindrance to the API.
Sorry for underspecifying my problem before. For total transparency,
Enumap is the "real-world" example. It
currently uses opSlice, which does not support ref access to values. My
attempts to support 'foreach with ref' while maintaining #nogc support is what
prompted this question.

Instead of overloading the opApplyoperator you can implement an input range for your type. Input ranges work automatically as the agregate argument in foreach statements:
struct Thing(K,V) {
import std.typecons;
#nogc bool empty(){return true;}
#nogc auto front(){return tuple(K.init, V.init);}
#nogc void popFront(){}
}
unittest {
Thing!(int, int) w;
foreach(val ; w) {
int[] i = [1,2,3]; // spurious allocation
}
}
#nogc unittest {
Thing!(int, int) w;
foreach(idx, val ; w) { assert(idx == val); }
}
This solves the problem caused by the allocation of the delegate used in foreach.
Note that the example is shitty (the range doesn't work at all, and usually ranges are provided via opSlice, etc) but you should get the idea.

Related

Send multiple arguments to the compute function in Flutter

I was trying to use the compute function in Flutter.
void _blockPressHandler(int row, int col) async {
// Called when user clicks any block on the sudoku board . row and col are the corresponding row and col values ;
setState(() {
widget.selCol = col;
}
});
bool boardSolvable;
boardSolvable = await compute(SudokuAlgorithm.isBoardInSudoku , widget.board , widget.size) ;
}
isBoardInSudoku is a static method of class SudokuAlgorithm. Its present in another file. Writing the above code , tells me that
error: The argument type '(List<List<int>>, int) → bool' can't be assigned to the parameter type '(List<List<int>>) → bool'. (argument_type_not_assignable at [just_sudoku] lib/sudoku/SudokuPage.dart:161)
How do i fix this? Can it be done without bringing the SudokuAlgorithm class's methods out of its file ? How to send multiple arguments to the compute function ?
static bool isBoardInSudoku(List<List<int>>board , int size ){ } is my isBoardInSudoku function.
Just put the arguments in a Map and pass that instead.
There is no way to pass more than one argument to compute because it is a convenience function to start isolates which also don't allow anything but a single argument.
Use a map. Here is an example:
Map map = Map();
map['val1'] = val1;
map['val2'] = val2;
Future future1 = compute(longOp, map);
Future<double> longOp(map) async {
var val1 = map['val1'];
var val2 = map['val2'];
...
}
In OOP and in general, it is more elegant to create a class for that with fields you need, that gives you more flexibility and less hassle with hardcoded strings or constants for key names.
For example:
boardSolvable = await compute(SudokuAlgorithm.isBoardInSudoku , widget.board , widget.size) ;
replace with
class BoardSize{
final int board;
final int size;
BoardSize(this.board, this.size);
}
...
boardSolvable = await compute(SudokuAlgorithm.isBoardInSudoku, BoardSize(widget.board, widget.size)) ;
Use a Tuple
Here is some example code from my app:
#override
Future logChange(
String recordId, AttributeValue newValue, DateTime dateTime) async {
await compute(
logChangeNoCompute, Tuple2<String, AttributeValue>(recordId, newValue));
}
Future<void> logChangeNoCompute(Tuple2<String, AttributeValue> tuple) async {
_recordsById[tuple.item1]!.setAttributeValue(tuple.item2);
await storage.setItem(AssetsFileName, toJson());
}
You can have a function whose only argument is a Map so that you can pass multiple parameters by passing a Map with properties and values. However, the problem that I'm encountering now is that I cannot pass functions. If the value of a Map's property is a function I get an error when I run the compute function.
This example works(keep in mind that I've imported libraries and that's the reason why some functions and classes definitions aren't in this example)
Future<List<int>> getPotentialKeys({
#required int p,
#required int q,
})async{
return await compute(allKeys,{
"p" : p,
"q" : q,
});
}
List<int> allKeys(Map<String,dynamic> parameters){
AdvancedCipherGen key = AdvancedCipherGen();
List<int> possibleE = key.step1(p: parameters["p"], q: parameters["q"]);
return possibleE;
}
This does not work(same thing with a function as the value of a property thows an error)
Future<List<int>> getPotentialKeys({
#required int p,
#required int q,
#required Function(AdvancedCipherGen key) updateKey,
})async{
return await compute(allKeys,{
"p" : p,
"q" : q,
"updateKey" : updateKey,
});
}
List<int> allKeys(Map<String,dynamic> parameters){
AdvancedCipherGen key = AdvancedCipherGen();
List<int> possibleE = key.step1(p: parameters["p"], q: parameters["q"]);
//TODO: Update the key value through callback
parameters["updateKey"](key);
return possibleE;
}
easily use a Class, you can Also Use Map or List But using class is Better and Cleaner
class MyFunctionInput{
final int first;
final int second;
MyFunctionInput({required this.first,required this.second});
}
change your function like this
doSomething(MyFunctionInput input){
}
and use it like below
compute(doSomething,MyFunctionInput(first: 1, second: 4));

How to do lazy evaluation in Dart?

Is there a native (language supported) lazy evaluation syntax? Something like lazy val in Scala.
I've gone through the docs, and could not find anything. There is only a chapter about "lazily loading a library", but it's not what I am asking.
Based on this research I incline to believe (please correct me if I'm wrong) that currently there is no such thing. But maybe you know of any plans or feature requests which will provide the functionality? Or maybe it was considered and rejected by the Dart team?
If indeed there is no native support for this, then what is the best practice (best syntax) for implementing lazy evaluation? An example would be appreciated.
Edit:
The benefits of the feature that I am looking for are mostly the same as in implementation in other languages: Scala's lazy val or C#'s Lazy<T> or Hack's __Memorize attribute:
concise syntax
delayed computation until the value is needed
cache the result (the by-need laziness)
don't break pure functional paradigm (explanation below)
A simple example:
class Fibonacci {
final int n;
int _res = null;
int get result {
if (null == _res) {
_res = _compute(this.n);
}
return _res;
}
Fibonacci(this.n);
int _compute(n) {
// ...
}
}
main(List<String> args) async {
print(new Fibonacci(5).result);
print(new Fibonacci(9).result);
}
The getter is very verbose and has a repetitive code. Moreover I can't make the constructor const because the caching variable _res has to be computed on demand. I imagine that if I had a Scala-like lazy feature then I would also have language support for having a constant constructor. That's thanks to the fact, that the lazy evaluated _res is referentially transparent, and would not be in the way.
class Fibonacci {
final int n;
int lazy result => _compute(this.n);
const Fibonacci(this.n); // notice the `const`
int _compute(n) {
// ...
}
}
main(List<String> args) async {
// now these makes more sense:
print(const Fibonacci(5).result);
print(const Fibonacci(9).result);
}
Update 2021
Lazy initialization is now part of dart from the release 2.12.
Simply add late modifier to the variable declaration
late MyClass obj = MyClass();
And this object will be initialized only when it is first used.
From the docs:
Dart 2.12 added the late modifier, which has two use cases:
Declaring a non-nullable variable that’s initialized after its
declaration.
Lazily initializing a variable.
Checkout the example here:
https://dartpad.dev/?id=50f143391193a2d0b8dc74a5b85e79e3&null_safety=true
class A {
String text = "Hello";
A() {
print("Lazily initialized");
}
sayHello() {
print(text);
}
}
class Runner {
late A a = A();
run() async {
await Future.delayed(Duration(seconds: 3));
print("First message");
a.sayHello();
}
}
Here class A will be initialized only after "First message" has been displayed.
update2
From #lrn s comment - using an Expando for caching makes it work with const:
class Lazy<T> {
static final _cache = new Expando();
final Function _func;
const Lazy(this._func);
T call() {
var result = _cache[this];
if (identical(this, result)) return null;
if (result != null) return result;
result = _func();
_cache[this] = (result == null) ? this : result;
return result;
}
}
defaultFunc() {
print("Default Function Called");
return 42;
}
main([args, function = const Lazy(defaultFunc)]) {
print(function());
print(function());
}
Try it in DartPad
update
A reusable Lazy<T> could look like below in Dart but that also doesn't work with const and can't be used in field initializers if the calculation needs to refer instance members (this.xxx).
void main() {
var sc = new SomeClass();
print('new');
print(sc.v);
}
class SomeClass {
var _v = new Lazy<int>(() {
print('x');
return 10;
});
int get v => _v();
}
class Lazy<T> {
final Function _func;
bool _isEvaluated = false;
Lazy(this._func);
T _value;
T call() {
if(!_isEvaluated) {
if(_func != null) {
_value = _func();
}
_isEvaluated = true;
}
return _value;
}
}
Try it in DartPad
original
Dart version of http://matt.might.net/articles/implementing-laziness/ using a closure to lazy evaluate:
void main() {
var x = () {
print ("foo");
return 10;
}();
print("bar");
print(x);
// will print foo, then bar then 10.
print('===');
// But, the following Scala program:
x = () {
print("foo");
return 10;
};
print ("bar");
print (x());
// will print bar, then foo, then 10, since it delays the computation of x until it’s actually needed.
}
Try it in DartPad
Update
int _val;
int get val => _val ??= 9;
Thanks #Nightscape
Old
I think this little snippet might help you...
int _val;
int get val => _val ?? _val = 9;

Can the D compiler inline constant function pointers

Consider the following code which prints out the even numbers up to 20:
import std.stdio;
class count_to_ten{
static int opApply()(int delegate(ref int) dg) {
int i = 1;
int ret;
while(i <= 10){
ret = dg(i);
if(ret != 0) {
break;
}
i++;
}
return ret;
}
}
void main() {
int y = 2;
foreach(int x; count_to_ten) {
writeln(x * y);
}
}
The syntax of opApply requires that it take a delegate or function as a normal argument. However, even if we relaxed that and allowed opApply to take a function as a template argument, we still would have no recourse for delegates because D doesn't provide any way to separate the stack-frame pointer from the function pointer. However, this seems like it should be possible since the function-pointer part of the delegate is commonly a compile-time constant. And if we could do that and the body of the loop was short, then it could actually be inlined which might speed this code up quite a bit.
Is there any way to do this? Does the D compiler have some trick by which it happens automagically?

How to make Range work with foreach statement

I have the following range:
struct Range {
uint data;
#property{
bool empty() { return false; }
uint front() { return data; }
void popFront() { data = data * 2 + 1; }
}
}
Trying to use it,
foreach(c; Rnage()){ /*...*/ } works, but with foreach(i, c; Range()){ /*...*/ } I get:
Error: cannot infer argument types
I need the i just like in something like foreach(i, v; [1,2,3,4]){ }.
Ranges do not support the syntax
foreach(i, c; range)
While it seems obvious that that should work in the simple case, what that index should even be depends on the type of range and doesn't always make sense. So, no counter for the index is provided automatically by foreach, and a range has no way of providing one.
However, thanks to tuple unpacking with foreach, you can do it by using std.range.sequence std.range.zip with your range:
foreach (i, e; zip(sequence!"n"(), range))
{
}
By the way, you shouldn't mark popFront with #property. It doesn't make any sense. popFront takes no arguments and returns no value. It does not act like a variable at all. And the point of properties is to have functions which act like variables. If/when -property's implementation is fully sorted out and it becomes the normal behavior (it's rather buggy at the moment, which is part of why it's a separate switch for the moment), popFront would not be usable as you defined it.
If you use opApply to implement the range, You can overload one version for the without-index style and for the with-index style:
struct Range {
int opApply(int delegate(int) action){
uint data=0;
while(true){
action(data);
data=data*2+1;
}
return 0;
}
int opApply(int delegate(uint,int) action){
uint i=0;
foreach(element;this){
action(i++,element);
}
return 0;
}
}

Assign function/method to variable in Dart

Does Dart support the concept of variable functions/methods? So to call a method by its name stored in a variable.
For example in PHP this can be done not only for methods:
// With functions...
function foo()
{
echo 'Running foo...';
}
$function = 'foo';
$function();
// With classes...
public static function factory($view)
{
$class = 'View_' . ucfirst($view);
return new $class();
}
I did not found it in the language tour or API. Are others ways to do something like this?
To store the name of a function in variable and call it later you will have to wait until reflection arrives in Dart (or get creative with noSuchMethod). You can however store functions directly in variables like in JavaScript
main() {
var f = (String s) => print(s);
f("hello world");
}
and even inline them, which come in handy if you are doing recusion:
main() {
g(int i) {
if(i > 0) {
print("$i is larger than zero");
g(i-1);
} else {
print("zero or negative");
}
}
g(10);
}
The functions stored can then be passed around to other functions
main() {
var function;
function = (String s) => print(s);
doWork(function);
}
doWork(f(String s)) {
f("hello world");
}
I may not be the best explainer but you may consider this example to have a wider scope of the assigning functions to a variable and also using a closure function as a parameter of a function.
void main() {
// a closure function assigned to a variable.
var fun = (int) => (int * 2);
// a variable which is assigned with the function which is written below
var newFuncResult = newFunc(9, fun);
print(x); // Output: 27
}
//Below is a function with two parameter (1st one as int) (2nd as a closure function)
int newFunc(int a, fun) {
int x = a;
int y = fun(x);
return x + y;
}

Resources