Related
I am ne to dart.
In python it was
[["A","B"],["C","D","E"],["F","G"]]
In dart It was Showing error Help me
If you are receiving the data, at runtime, in the mentioned form, you would not easily be able to use the spread operator, as the others have suggested.
Instead, you can use the expand function and create a new list based on this result like this:
void main() {
final list = [["A","B"],["C","D","E"],["F","G"]];
final list2 = [...list.expand((e) => e)];
print(list2); // [A, B, C, D, E, F, G]
}
void main() {
// example 1
print([...['A', 'B'], ...['C', 'D', 'E'], ...['F', 'G']]);
// output: [A, B, C, D, E, F, G]
// example 2
var characters1 = <String>['A', 'B'];
var characters2 = <String>['C', 'D', 'E'];
var characters3 = <String>['F', 'G'];
var allCharacters = [...characters1, ...characters2, ...characters3];
print(allCharacters);
// output: [A, B, C, D, E, F, G]
}
Read here for more about the spread operator ...
Just use spread operator '...'
[...["A","B"],...["C","D","E"],...["F","G"]]
Hope it helps
I'm working on some generic list utility functions and there seems to be an issue with the type inference for a generic function when the primary variables are lists. This is demonstrated with the following code:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
When I use this code as-is, the type inference within the lambda sets a and b to be Object?, which results in the following error message:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'.
Try adding a null check to the target ('!').
Doing what the error message says changes the message to the following:
The operator '+' isn't defined for the type 'Object'.
Try defining the operator '+'.
The issue obviously is that type inference is assigning the parameters to Object? instead of the expected int. This can be worked around by either typing the parameters or explicitly passing the generic type to the function:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
However, that's an added level of verbosity that I don't want to have to force the users of these utility functions to have to do (not to mention it will be a support issue when I have to explain to them to do this). Is there a way to change the function signature to make it so type inference works as expected?
This is basically Dart List.fold vs List.reduce type inference, but in your case you could sidestep the problem by making your function an extension method so that T is deduced from the receiver instead of from the arguments:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
I've got more of my expression parser working (Dart PetitParser to get at AST datastructure created with ExpressionBuilder). It appears to be generating accurate ASTs for floats, parens, power, multiply, divide, add, subtract, unary negative in front of both numbers and expressions. (The nodes are either literal strings, or an object that has a precedence with a List payload that gets walked and concatenated.)
I'm stuck now on visiting the nodes. I have clean access to the top node (thanks to Lukas), but I'm stuck on deciding whether or not to add a paren. For example, in 20+30*40, we don't need parens around 30*40, and the parse tree correctly has the node for this closer to the root so I'll hit it first during traversal. However, I don't seem to have enough data when looking at the 30*40 node to determine if it needs parens before going on to the 20+.. A very similar case would be (20+30)*40, which gets parsed correctly with 20+30 closer to the root, so once again, when visiting the 20+30 node I need to add parens before going on to *40.
This has to be a solved problem, but I never went to compiler school, so I know just enough about ASTs to be dangerous. What "a ha" am I missing?
// rip-common.dart:
import 'package:petitparser/petitparser.dart';
// import 'package:petitparser/debug.dart';
class Node {
int precedence;
List<dynamic> args;
Node([this.precedence = 0, this.args = const []]) {
// nodeList.add(this);
}
#override
String toString() => 'Node($precedence $args)';
String visit([int fromPrecedence = -1]) {
print('=== visiting $this ===');
var buf = StringBuffer();
var parens = (precedence > 0) &&
(fromPrecedence > 0) &&
(precedence < fromPrecedence);
print('<$fromPrecedence $precedence $parens>');
// for debugging:
var curlyOpen = '';
var curlyClose = '';
buf.write(parens ? '(' : curlyOpen);
for (var arg in args) {
if (arg is Node) {
buf.write(arg.visit(precedence));
} else if (arg is String) {
buf.write(arg);
} else {
print('not Node or String: $arg');
buf.write('$arg');
}
}
buf.write(parens ? ')' : curlyClose);
print('$buf for buf');
return '$buf';
}
}
class RIPParser {
Parser _make_parser() {
final builder = ExpressionBuilder();
var number = char('-').optional() &
digit().plus() &
(char('.') & digit().plus()).optional();
// precedence 5
builder.group()
..primitive(number.flatten().map((a) => Node(0, [a])))
..wrapper(char('('), char(')'), (l, a, r) => Node(0, [a]));
// negation is a prefix operator
// precedence 4
builder.group()..prefix(char('-').trim(), (op, a) => Node(4, [op, a]));
// power is right-associative
// precedence 3
builder.group()..right(char('^').trim(), (a, op, b) => Node(3, [a, op, b]));
// multiplication and addition are left-associative
// precedence 2
builder.group()
..left(char('*').trim(), (a, op, b) => Node(2, [a, op, b]))
..left(char('/').trim(), (a, op, b) => Node(2, [a, op, b]));
// precedence 1
builder.group()
..left(char('+').trim(), (a, op, b) => Node(1, [a, op, b]))
..left(char('-').trim(), (a, op, b) => Node(1, [a, op, b]));
final parser = builder.build().end();
return parser;
}
Result _result(String input) {
var parser = _make_parser(); // eventually cache
var result = parser.parse(input);
return result;
}
String parse(String input) {
var result = _result(input);
if (result.isFailure) {
return result.message;
} else {
print('result.value = ${result.value}');
return '$result';
}
}
String visit(String input) {
var result = _result(input);
var top_node = result.value; // result.isFailure ...
return top_node.visit();
}
}
// rip_cmd_example.dart
import 'dart:io';
import 'package:rip_common/rip_common.dart';
void main() {
print('start');
String input;
while (true) {
input = stdin.readLineSync();
if (input.isEmpty) {
break;
}
print(RIPParser().parse(input));
print(RIPParser().visit(input));
}
;
print('done');
}
As you've observed, the ExpressionBuilder already assembles the tree in the right precedence order based on the operator groups you've specified.
This also happens for the wrapping parens node created here: ..wrapper(char('('), char(')'), (l, a, r) => Node(0, [a])). If I test for this node, I get back the input string for your example expressions: var parens = precedence == 0 && args.length == 1 && args[0] is Node;.
Unless I am missing something, there should be no reason for you to track the precedence manually. I would also recommend that you create different node classes for the different operators: ValueNode, ParensNode, NegNode, PowNode, MulNode, ... A bit verbose, but much easier to understand what is going on, if each of them can just visit (print, evaluate, optimize, ...) itself.
I wrote a function and it complies, but I'm not sure if it works the way I intend it to or how to call it in the terminal. Essentially, I want to take a string, like ("age",5),("age",6) and make it into a list of tuples [("age1",5)...]. I am trying to write a function separate the commas and either I am just not sure how to call it in the terminal or I did it wrong.
items :: Parser (String,Integer) -> Parser [(String,Integer)]
items p = do { p <- sepBy strToTup (char ",");
return p }
I'm not sure what you want and I don't know what is Parser.
Starting from such a string:
thestring = "(\"age\",5),(\"age\",6),(\"age\",7)"
I would firstly remove the outer commas with a regular expression method:
import Text.Regex
rgx = mkRegex "\\),\\("
thestring' = subRegex rgx thestring ")("
This gives:
>>> thestring'
"(\"age\",5)(\"age\",6)(\"age\",7)"
Then I would split:
import Data.List.Split
thelist = split (startsWith "(") thestring'
which gives:
>>> thelist
["(\"age\",5)","(\"age\",6)","(\"age\",7)"]
This is what you want, if I correctly understood.
That's probably not the best way. Since all the elements of the final list have form ("age", X) you could extract all numbers (I don't know but it should not be difficult) and then it would be easy to get the final list. Maybe better.
Apologies if this has nothing to do with your question.
Edit
JFF ("just for fun"), another way:
import Data.Char (isDigit)
import Data.List.Split
thestring = "(\"age\",15),(\"age\",6),(\"age\",7)"
ages = (split . dropBlanks . dropDelims . whenElt) (not . isDigit) thestring
map (\age -> "(age," ++ age ++ ")") ages
-- result: ["(age,15)","(age,6)","(age,7)"]
Or rather:
>>> map (\age -> ("age",age)) ages
[("age","15"),("age","6"),("age","7")]
Or if you want integers:
>>> map (\age -> ("age", read age :: Int)) ages
[("age",15),("age",6),("age",7)]
Or if you want age1, age2, ...:
import Data.List.Index
imap (\i age -> ("age" ++ show (i+1), read age :: Int)) ages
-- result: [("age1",15),("age2",6),("age3",7)]
I am using Scala's combinator parser as follows:
def a = b ~ c ^^ { case x ~ y => A(x,y) }
def b = ... { B() }
def c = ... { C() }
now I have a feature change that change within the parsing of the reference of previously parsed B to be a val in C. So C's constructor is something like:
C(ref:B)
I can imagine, the only way to achieve this is a dirty patch work by assigning the instance of parsed B object to def c in between the parsing of a. Something like following:
var temp:B = null
def a = ( b ^^ { case x => temp = x } )
~ c(temp) ^^ {case x ~ y => A(x,y} )
Is there a standard, clean way of doing this? The definition of a can't be broken, it is used in many places in rest of the code.
The other solution is to use var instead of val and have following:
def a = (b ~ c ) ^^ { case x ~ y => y.ref = c ; A(x,y) }
But this is also not acceptable as it would "work" now, but it would involve extra effort and boiler-plate code in future development.
I've not tested this code, as this is a small part and all the changes require a lot of effort so want the expert opinion first.
Without changing the definition of a, there is no way to do this cleanly. The ~ combinator produces a new Parser which applies b and c in sequence, then tuples (well, logically tuples) up the results and returns them as its result. The key point is that the application of c is not a function of the output of b, thus there is nothing you can do to get the results of b inside the application of c.
What I would do is add a new combinator which does what you want. I'm not feeling particularly creative name-wise, but I think this should give you a rough idea:
implicit def cleverParserSyntax[A](left: Parser[A]) = new {
def ~%[B](right: A => Parser[B]): Parser[A ~ B] = for {
lr <- left
rr <- right(lr)
} yield new ~(lr, rr)
}
def a = b ~% c ^^ { case x ~ y => A(x,y) }
def b = ... { B() }
def c(res: B) = ... { C(res) }
I'm not sure if I understand the problem correctly but if C depends on B why not express this in functional way?
case class B(...)
case class C(b: B, ...)
case class A(b: B, c: C)
def b: Parser[B] = ... ^^ { B(...) }
def c: Parser[B => C] = ... ^^ { C(_, ...) }
def a: Parser[A] = b ~ c ^^ { A(b, c(b)) }
This way your problem is solved and you have your dependencies expressed explicitly and in concise way.
I'd do this:
case class B(x: String)
case class C(b: B, x: String)
case class A(b: B, c: C)
class MyParser extends RegexParsers {
def a = b >> c ^^ { case x ~ y => A(x, y) }
def b = "\\w+".r ^^ B
def c(b: B) = "\\d+".r ^^ (x => new ~(b, C(b, x)))
}
Now, if B happens much before C, things get more complicated. I suggest, if things get that hairy, to search for the paper about Scala parser, which goes into a lot of very advanced features.