Is there a way to return several values in a function return statement (other than returning an object) like we can do in Go (or some other languages)?
For example, in Go we can do:
func vals() (int, int) {
return 3, 7
}
Can this be done in Dart? Something like this:
int, String foo() {
return 42, "foobar";
}
Dart doesn't support multiple return values.
You can return an array,
List foo() {
return [42, "foobar"];
}
or if you want the values be typed use a Tuple class like the package https://pub.dartlang.org/packages/tuple provides.
See also either for a way to return a value or an error.
I'd like to add that one of the main use-cases for multiple return values in Go is error handling which Dart handle's in its own way with Exceptions and failed promises.
Of course this leaves a few other use-cases, so let's see how code looks when using explicit tuples:
import 'package:tuple/tuple.dart';
Tuple2<int, String> demo() {
return new Tuple2(42, "life is good");
}
void main() {
final result = demo();
if (result.item1 > 20) {
print(result.item2);
}
}
Not quite as concise, but it's clean and expressive code. What I like most about it is that it doesn't need to change much once your quick experimental project really takes off and you start adding features and need to add more structure to keep on top of things.
class FormatResult {
bool changed;
String result;
FormatResult(this.changed, this.result);
}
FormatResult powerFormatter(String text) {
bool changed = false;
String result = text;
// secret implementation magic
// ...
return new FormatResult(changed, result);
}
void main() {
String draftCode = "print('Hello World.');";
final reformatted = powerFormatter(draftCode);
if (reformatted.changed) {
// some expensive operation involving servers in the cloud.
}
}
So, yes, it's not much of an improvement over Java, but it works, it is clear, and reasonably efficient for building UIs. And I really like how I can quickly hack things together (sometimes starting on DartPad in a break at work) and then add structure later when I know that the project will live on and grow.
Create a class:
import 'dart:core';
class Tuple<T1, T2> {
final T1 item1;
final T2 item2;
Tuple({
this.item1,
this.item2,
});
factory Tuple.fromJson(Map<String, dynamic> json) {
return Tuple(
item1: json['item1'],
item2: json['item2'],
);
}
}
Call it however you want!
Tuple<double, double>(i1, i2);
or
Tuple<double, double>.fromJson(jsonData);
You can create a class to return multiple values
Ej:
class NewClass {
final int number;
final String text;
NewClass(this.number, this.text);
}
Function that generates the values:
NewClass buildValues() {
return NewClass(42, 'foobar');
}
Print:
void printValues() {
print('${this.buildValues().number} ${this.buildValues().text}');
// 42 foobar
}
The proper way to return multiple values would be to store those values in a class, whether your own custom class or a Tuple. However, defining a separate class for every function is very inconvenient, and using Tuples can be error-prone since the members won't have meaningful names.
Another (admittedly gross and not very Dart-istic) approach is try to mimic the output-parameter approach typically used by C and C++. For example:
class OutputParameter<T> {
T value;
OutputParameter(this.value);
}
void foo(
OutputParameter<int> intOut,
OutputParameter<String>? optionalStringOut,
) {
intOut.value = 42;
optionalStringOut?.value = 'foobar';
}
void main() {
var theInt = OutputParameter(0);
var theString = OutputParameter('');
foo(theInt, theString);
print(theInt.value); // Prints: 42
print(theString.value); // Prints: foobar
}
It certainly can be a bit inconvenient for callers to have to use variable.value everywhere, but in some cases it might be worth the trade-off.
Dart is finalizing records, a fancier tuple essentially.
Should be in a stable release a month from the time of writing.
I'll try to update, it's already available with experiments flags.
you can use dartz package for Returning multiple data types
https://www.youtube.com/watch?v=8yMXUC4W1cc&t=110s
you can use Set<Object> for returning multiple values,
Set<object> foo() {
return {'my string',0}
}
print(foo().first) //prints 'my string'
print(foo().last) //prints 0
In this type of situation in Dart, an easy solution could return a list then accessing the returned list as per your requirement. You can access the specific value by the index or the whole list by a simple for loop.
List func() {
return [false, 30, "Ashraful"];
}
void main() {
final list = func();
// to access specific list item
var item = list[2];
// to check runtime type
print(item.runtimeType);
// to access the whole list
for(int i=0; i<list.length; i++) {
print(list[i]);
}
}
I try to sort an arrayCollection with this Sort:
private function sortArray(questions:ArrayCollection):void
{
questions.sort = new Sort();
questions.sort.fields = [new SortField("rank")];
questions.sort.compareFunction = rankFunction;
questions.refresh();
}
private function rankFunction(a:int, b:int, array:Array = null):int
{
if(a == b)
{
return 0;
}
if(a>b)
{
return 1;
}
else
{
return -1;
}
}
There are 23 Objects and all have the rank = 0
I expected that nothing will be changed but after the refresh the items at postion 0 and 11 of the ArrayCollection swapped their position.
In the rankFunction, there is always returned 0.
Can anyone tell me what is going wrong here?
ASDoc says that compare function should have following signature:
function [name](a:Object, b:Object, fields:Array = null):int
and that the fields array specifies the object fields.
So Sort doesn't extract field values for you. You should do it yourself.
Concerning your question, it seems that AS3 implicitly converts Objects to ints invoking rankFunction. If so items are compared by some internal code that somehow corresponds to the order of items creation.
How can I convert or Encrypt strings into numbers
eg: addedToStage into/as -1820302713
there is no single/main encryption method.There can be many encryption methods.You can create your own encryption methods.here is a simple one that I created.this example ,encrypts string using a number password.(encrypting string into number is a bad practice.I used string to string):
function encrypt(s:String,password:uint):String{
var ret:String="";
for(var i:uint=0;i<s.length;i++){
var added:uint=s.charCodeAt(i)+password;
added=added>uint.MAX_VALUE?added-uint.MAX_VALUE:added;
ret+=String.fromCharCode(added)
}
return ret;
}
function decrypt(s:String,password:uint):String{
var ret:String="";
for(var i:uint=0;i<s.length;i++){
var added:int=s.charCodeAt(i)-password;
added=added<0?added+uint.MAX_VALUE:added;
ret+=String.fromCharCode(added)
}
return ret;
}
now, let's try this interactive code:
trace(encrypt("StackOverFlow.com",50));//¦¨¤x¡©`¡
trace(decrypt("¦¨¤x¡©`¡",50));//StackOverFlow.com
Here I used to convert letters, to other letters with char code +password.you can have your custom methods.
I H☺P E this helps.
String.replace replaces the first occurrence of a string in a string, but I'd like to replace the last occurrence of a string in a string. Is there an easy way to do it?
You can use the lastIndexOf function to determine where the string you want to replace is, and then add the substring before and after the occurance to get your desired result.
There is an error in the suggested function... here is the corrected one:
public static function replaceLastOccurrence(str:String, find:String, replace:String):String {
var pre:String = str.substr(0, str.lastIndexOf(find));
var post:String = str.substr(str.lastIndexOf(find)+find.length, str.length);
return pre + replace + post;
}
I would check first if there is an occurance at all:
public static function replaceLastOccurrence(str:String, find:String, replace:String):String
{
if (str.lastIndexOf(find) != -1)
{
var pre:String = str.substr(0, str.lastIndexOf(find));
var post:String = str.substr(str.lastIndexOf(find) + find.length, str.length);
return pre + replace + post;
}
else
{
return str;
}
}
otherwise it will mess up the ending of the string if there is no occurance.
is it not possible to define a static const array? i would like to have an optional parameter to a function that is an array of colors,
private static const DEFAULT_COLORS:Array = new Array(0x000000, 0xFFFFFF);
public function myConstructor(colorsArray:Array = DEFAULT_COLORS)
{
}
i know i can use ...args but i actually wanting to supply the constructor with 2 separate arrays as option arguments.
Not possible, but you could this to simulate this behaviour:
private static const DEFAULT_COLORS:Array = new Array(0x000000, 0xFFFFFF);
public function myConstructor(colorsArray:Array = null)
{
colorsArray = colorsArray ? colorsArray : DEFAULT_COLORS;
}
This will not work if your function is coded in a way such that null could be a valid value (to signal some condition, for instance), but probably that's not the case here.
Edit
If you plan to write to colorsArray in myConstructor, it would be wise to make a copy of DEFAULT_COLORS here:
colorsArray = colorsArray ? colorsArray : DEFAULT_COLORS.slice();
The reference to the DEFAULT_COLORS Array is constant, but its contents are not, so you could accidentally change your default values.