void foo(bool b, int i, double d, String s, Object o) {
if (someCondition) {
return foo(b, i, d, s, o);
}
}
I thought there exist something like
return foo(this);
How can I call foo from within foo without passing the parameters? Is there any shorthand?
There is not.
There is nothing special about a recursive call, you have to pass all the arguments, just like any other call.
What you can do, and what I usually do for recursive algorithms, is to have a local helper function:
void foo(bool b, int i, double d, String s, Object o) {
void rec() {
...
if (someCondition) {
return rec();
}
}
rec();
// ...
}
That function will usually have at least one argument, the thing I'm really recursing on, but the remaining variables do not need to be passed on every recursive call.
Another option, since this looks like tail-recursion, would be rewriting into a while loop:
void foo(bool b, int i, double d, String s, Object o) {
while (someCondition) {
// the fix.
}
// the actual code.
}
Related
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));
On Dart 1.0.0, I just tried:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b = true]) {
if(?b) {
// ...
}
}
}
And am getting a compiler error on the ?b part:
The argument definition test ('?' operator) has been deprecated
So what's the "new" way of testing for whether or not an argument was supplied?
There is no way to test if an argument was provided or not. The main-reason for its removal was, that it was very complex to forward calls this way.
The generally preferred way is to use null as "not given". This doesn't always work (for example if null is a valid value), and won't catch bad arguments. If null is used, then the parameter must not have a default-value. Otherwise the parameter is not null but takes the default-value:
foo([x = true, y]) => print("$x, $y");
foo(); // prints "true, null"
So in your case you should probably do:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if(b == null) { // treat as if not given.
// ...
}
}
}
This makes new MyClass(5, null) and new MyClass(5) identical. If you really need to catch the first case, you have to work around the type-system:
class _Sentinel { const _Sentinel(); }
...
MyClass(int x, [b = const _Sentinel()]) {
if (b == const _Sentinel()) b = true;
...
}
This way you can check if an argument has been provided. In return you lose the type on b.
The argument definition test operator was deprecated because it was redundant with checking for null; an optional parameter that was omitted would get the value null, and the caller could've passed null explicitly anyway. So instead use == null:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if (b == null) {
// throw exception or assign default value for b
}
}
}
This might be a really stupid question but what happens to data that is returned from a method? For example, if I have a method that adds two numbers and I tell it to return the sum, how would I access that information from the place where the method was called?
Assuming your question is related with java.
You could assign the whole method to a new variable.
public class Test {
public static void main(String args[]){
int value1=2;
int value2=5;
int sum=sum(value1,value2);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
return value1+value2;
}
}
What is actually happening, is that the method signature sum(value1,value2) holds the result of the 2 numbers summation. There is also another way of writing the code inside the method but the result will be the same.
For example:
public class Test {
public static void main(String args[]){
int sum=sum(2,5);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
int sum=value1+value2;
return sum;
}
}
P.S. You could try to use the above samples directly. They will compile and run.
In most languages, you access the result of a function by putting the function call on the right hand side of an assignment expression.
For example, in Python, you can assign the result of calling the built-in len function on a list to a variable called x by doing the following:
x = len([1, 2, 3])
If I have a class with a setter defined, how do I reference then generated method as a function from an instance of that class. The spec sort of suggests it would be the id of the variable + '=" (seems daft), but this doesn't parse.
So for example:
class Bar {
set foo(int value) {
//whatever
}
}
typedef F(int value);
void main() {
F f = new Bar().foo=; //Fails, but what should this be??
f(5);
}
The setter is named foo= but this is not something you can reference in the way you want. Even looking at dart:mirrors the MethodMirror (the mirror for object methods including setters) has no way of invoking it. You could easily rewrite this as:
class Bar {
set foo(int value) {
//whatever
}
}
typedef F(int value);
void main() {
Bar b = new Bar();
F f = (int value) => b.foo = value;
f(5);
}
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;
}