I have noticed that when I have multiple where clauses and multiple asserting clauses, that I get often get syntax errors when I combine them together. The error will say "unexpected token after where". How should I write it to avoid this error? Here is the latest example:
Attempt 1:
def(class game_state game) ->commands [
set(attack, cost),
set(life, cost),
set(abilities, []),
] where cost=(card.cost + (card.loyalty_cost * size(card.school)))
where card=crypt_spells[choices[0]]
// asserting size(choices) = 1 //FIXME: syntax error uncommented
asserting choices != null
where crypt_spells=filter(game.crypt.cards_of(player), value.type='spell')
where player=game.player_obj
I also tried rewriting it a different way, that also resulted in the "unexpected token after where" syntax error.
Attempt 2:
def(class game_state game) ->commands [
set(attack, cost),
set(life, cost),
set(abilities, []),
] where cost=(card.cost + (card.loyalty_cost * size(card.school)))
where card=crypt_spells[choices[0]]
asserting choices != null, size(choices)=1 | choices //FIXME: syntax error
where crypt_spells=filter(game.crypt.cards_of(player), value.type='spell')
where player=game.player_obj
Example 3:
Here is another example that, I think, highlights the problem:
def(class game_state game, class message.play_card info) ->commands
if(info.choices,
([ /* do stuff */ ]
where entry=game.crypt.get_entry(info.choices[0])
asserting size(info.targets)=1 | info.targets /* PARSE ERROR! */
) asserting size(info.choices)=1 | info.choices, /* WORKS */
[ /* else */ ]
)
As you can see from this example, asserting a=b works fine unless it is preceded by a where clause.
Let me try to transform your code into generic debug console code:
f()
where f = def
() -> commands [
debug(['something']),
debug(['more stuff']),
debug(['yet more stuff']),
]
where aaa = (0 + (1 * 2))
where bbb = 4
// asserting 2 + 2 = 4 // FIXME: syntax error uncommented
asserting '000' != null
where ccc = [0, 1, 2, 3]
where ddd = {'0': 0, '1': 1, }
The debug console can execute that:
(debug console):0: ['something']
(debug console):0: ['more stuff']
(debug console):0: ['yet more stuff']
[(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE)]
Let's check that your syntax error is still there, or at least some syntax error, when uncommenting the assertion:
f()
where f = def
() -> commands [
debug(['something']),
debug(['more stuff']),
debug(['yet more stuff']),
]
where aaa = (0 + (1 * 2))
where bbb = 4
asserting 2 + 2 = 4 // FIXME: syntax error uncommented
asserting '000' != null
where ccc = [0, 1, 2, 3]
where ddd = {'0': 0, '1': 1, }
The debug console can't execute:
error parsing formula: formula.cpp:3942 ASSERTION FAILED: Unexpected tokens after
where
At (debug console) 0:
... where bbb = 4 asserting 2 + 2 = 4 // FIXME syntax error uncommen...
^
The engine uses simple parsing, and currently where, asserting and = (and maybe even ,?) can be combined in ways intuitive but not well managed by the parser.
Here, I think it found a secondary = for where before reaching ,, but I don't know. Right now I don't know exactly what is the criteria for finishing parsing of where. You would know by just debugging the parser.
This is an important issue, but maybe not critical and must fix now, as can mostly be managed by including more parens exhaustiveness.
Let's place just one parens pair, let's start by the failing assertion:
f()
where f = def
() -> commands [
debug(['something']),
debug(['more stuff']),
debug(['yet more stuff']),
]
where aaa = (0 + (1 * 2))
where bbb = 4
asserting (2 + 2 = 4) // FIXME: syntax error uncommented
asserting '000' != null
where ccc = [0, 1, 2, 3]
where ddd = {'0': 0, '1': 1, }
The debug console can execute again:
(debug console):0: ['something']
(debug console):0: ['more stuff']
(debug console):0: ['yet more stuff']
[(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE),
(Command Object: N10game_logic12_GLOBAL__N_113debug_commandE)]
2018 May 27 added the error pinpoint location.
Related
Here's the problem in which I encountered this issue:
The function should compare the value at each index position and score a point if the value for that position is higher. No point if they are the same. Given a = [1, 1, 1] b = [1, 0, 0] output should be [2, 0]
fun compareArrays(a: Array<Int>, b: Array<Int>): Array<Int> {
var aRetVal:Int = 0
var bRetVal:Int = 0
for(i in 0..2){
when {
a[i] > b[i] -> aRetVal + 1 // This does not add 1 to the variable
b[i] > a[i] -> bRetVal++ // This does...
}
}
return arrayOf(aRetVal, bRetVal)
}
The IDE even says that aRetVal is unmodified and should be declared as a val
What others said is true, but in Kotlin there's more. ++ is just syntactic sugar and under the hood it will call inc() on that variable. The same applies to --, which causes dec() to be invoked (see documentation). In other words a++ is equivalent to a.inc() (for Int or other primitive types that gets optimised by the compiler and increment happens without any method call) followed by a reassignment of a to the incremented value.
As a bonus, consider the following code:
fun main() {
var i = 0
val x = when {
i < 5 -> i++
else -> -1
}
println(x) // prints 0
println(i) // prints 1
val y = when {
i < 5 -> ++i
else -> -1
}
println(y) // prints 2
println(i) // prints 2
}
The explanation for that comes from the documentation I linked above:
The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:
Store the initial value of a to a temporary storage a0;
Assign the result of a.inc() to a;
Return a0 as a result of the expression.
...
For the prefix forms ++a and --a resolution works the same way, and the effect is:
Assign the result of a.inc() to a;
Return the new value of a as a result of the expression.
Because
variable++ is shortcut for variable = variable + 1 (i.e. with assignment)
and
variable + 1 is "shortcut" for variable + 1 (i.e. without assignment, and actually not a shortcut at all).
That is because what notation a++ does is actually a=a+1, not just a+1. As you can see, a+1 will return a value that is bigger by one than a, but not overwrite a itself.
Hope this helps. Cheers!
The equivalent to a++ is a = a + 1, you have to do a reassignment which the inc operator does as well.
This is not related to Kotlin but a thing you'll find in pretty much any other language
Given this definition for foo:
let foo = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
I'd like to be able to write code like this:
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter().map(|x| x * 2)
} else {
std::iter::empty()
})
.collect();
but that raises an error about the if and else clauses having incompatible types. I tried removing the map temporarily and I tried defining an empty vector outside the closure and returning an iterator over that like so:
let empty = vec![];
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter() //.map(|x| x * 2)
} else {
empty.iter()
})
.collect();
This seems kind of silly but it compiles. If I try to uncomment the map then it still complains about the if and else clauses having incompatible types. Here's part of the error message:
error[E0308]: if and else have incompatible types
--> src/main.rs:6:30
|
6 | .flat_map(|(i, row)| if i % 2 == 0 {
| ______________________________^
7 | | row.iter().map(|x| x * 2)
8 | | } else {
9 | | std::iter::empty()
10 | | })
| |_________^ expected struct `std::iter::Map`, found struct `std::iter::Empty`
|
= note: expected type `std::iter::Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:7:28: 7:37]>`
found type `std::iter::Empty<_>`
Playground Link
I know I could write something that does what I want with some nested for loops but I'd like to know if there's a terse way to write it using iterators.
Since Rust is statically typed and each step in an iterator chain changes the result to a new type that entrains the previous types (unless you use boxed trait objects) you will have to write it in a way where both branches are covered by the same types.
One way to convey conditional emptiness with a single type is the TakeWhile iterator implementation.
.flat_map(|(i, row)| {
let iter = row.iter().map(|x| x * 2);
let take = i % 2 == 0;
iter.take_while(|_| take)
})
If you don't mind ignoring the edge-case where the input iterator foo could have more than usize elements you could also use Take instead with either 0 or usize::MAX. It has the advantage of providing a better size_hint() than TakeWhile.
In your specific example, you can use filter to remove unwanted elements prior to calling flat_map:
let result: Vec<_> = foo.iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0)
.flat_map(|(_, row)| row.iter().map(|x| x * 2))
.collect();
If you ever want to use it with map instead of flat_map, you can combine the calls to filter and map by using filter_map which takes a function returning an Option and only keeps elements that are Some(thing).
I think I messed up when I tried to write one line code in Kotlin, It seems like there is no problem but IntelliJ gives me this error here:
val cards : Array<Card> = Array(52 { i -> Card(i % 13, getSuit(i))})
You have two ways to fix this error.
Place a , between 52 and the lambda
val cards : Array = Array(52, { i -> Card(i % 13, getSuit(i))})
Place the lambda outside of the brackets
val cards : Array = Array(52) { i -> Card(i % 13, getSuit(i))}
I am reading through perl6intro on lazy lists and it leaves me confused about certain things.
Take this example:
sub foo($x) {
$x**2
}
my $alist = (1,2, &foo ... ^ * > 100);
will give me (1 2 4 16 256), it will square the same number until it exceeds 100. I want this to give me (1 4 9 16 25 .. ), so instead of squaring the same number, to advance a number x by 1 (or another given "step"), foo x, and so on.
Is it possible to achieve this in this specific case?
Another question I have on lazy lists is the following:
In Haskell, there is a takeWhile function, does something similar exist in Perl6?
I want this to give me (1 4 9 16 25 .. )
The easiest way to get that sequence, would be:
my #a = (1..*).map(* ** 2); # using a Whatever-expression
my #a = (1..*).map(&foo); # using your `foo` function
...or if you prefer to write it in a way that resembles a Haskell/Python list comprehension:
my #a = ($_ ** 2 for 1..*); # using an in-line expression
my #a = (foo $_ for 1..*); # using your `foo` function
While it is possible to go out of one's way to express this sequence via the ... operator (as Brad Gilbert's answer and raiph's answer demonstrate), it doesn't really make sense, as the purpose of that operator is to generate sequences where each element is derived from the previous element(s) using a consistent rule.
Use the best tool for each job:
If a sequence is easiest to express iteratively (e.g. Fibonacci sequence):
Use the ... operator.
If a sequence is easiest to express as a closed formula (e.g. sequence of squares):
Use map or for.
Here is how you could write a Perl 6 equivalent of Haskell's takewhile.
sub take-while ( &condition, Iterable \sequence ){
my \iterator = sequence.iterator;
my \generator = gather loop {
my \value = iterator.pull-one;
last if value =:= IterationEnd or !condition(value);
take value;
}
# should propagate the laziness of the sequence
sequence.is-lazy
?? generator.lazy
!! generator
}
I should probably also show an implementation of dropwhile.
sub drop-while ( &condition, Iterable \sequence ){
my \iterator = sequence.iterator;
GATHER: my \generator = gather {
# drop initial values
loop {
my \value = iterator.pull-one;
# if the iterator is out of values, stop everything
last GATHER if value =:= IterationEnd;
unless condition(value) {
# need to take this so it doesn't get lost
take value;
# continue onto next loop
last;
}
}
# take everything else
loop {
my \value = iterator.pull-one;
last if value =:= IterationEnd;
take value
}
}
sequence.is-lazy
?? generator.lazy
!! generator
}
These are only just-get-it-working examples.
It could be argued that these are worth adding as methods to lists/iterables.
You could (but probably shouldn't) implement these with the sequence generator syntax.
sub take-while ( &condition, Iterable \sequence ){
my \iterator = sequence.iterator;
my \generator = { iterator.pull-one } …^ { !condition $_ }
sequence.is-lazy ?? generator.lazy !! generator
}
sub drop-while ( &condition, Iterable \sequence ){
my \end-condition = sequence.is-lazy ?? * !! { False };
my \iterator = sequence.iterator;
my $first;
loop {
$first := iterator.pull-one;
last if $first =:= IterationEnd;
last unless condition($first);
}
# I could have shoved the loop above into a do block
# and placed it where 「$first」 is below
$first, { iterator.pull-one } … end-condition
}
If they were added to Perl 6/Rakudo, they would likely be implemented with Iterator classes.
( I might just go and add them. )
A direct implementation of what you are asking for is something like:
do {
my $x = 0;
{ (++$x)² } …^ * > 100
}
Which can be done with state variables:
{ ( ++(state $x = 0) )² } …^ * > 100
And a state variable that isn't used outside of declaring it doesn't need a name.
( A scalar variable starts out as an undefined Any, which becomes 0 in a numeric context )
{ (++( $ ))² } …^ * > 100
{ (++$)² } …^ * > 100
If you need to initialize the anonymous state variable, you can use the defined-or operator // combined with the equal meta-operator =.
{ (++( $ //= 5))² } …^ * > 100
In some simple cases you don't have to tell the sequence generator how to calculate the next values.
In such cases the ending condition can also be simplified.
say 1,2,4 ...^ 100
# (1 2 4 8 16 32 64)
The only other time you can safely simplify the ending condition is if you know that it will stop on the value.
say 1, { $_ * 2 } ... 64;
# (1 2 4 8 16 32 64)
say 1, { $_ * 2 } ... 3;
# (1 2 4 8 16 32 64 128 256 512 ...)
I want this to give me (1 4 9 16 25 .. )
my #alist = {(++$)²} ... Inf;
say #alist[^10]; # (1 4 9 16 25 36 49 64 81 100)
The {…} is an arbitrary block of code. It is invoked for each value of a sequence when used as the LHS of the ... sequence operator.
The (…)² evaluates to the square of the expression inside the parens. (I could have written (…) ** 2 to mean the same thing.)
The ++$ returns 1, 2, 3, 4, 5, 6 … by combining a pre-increment ++ (add one) with a $ variable.
In Haskell, there is a takeWhile function, does something similar exist in Perl6?
Replace the Inf from the above sequence with the desired end condition:
my #alist = {(++$)²} ... * > 70; # stop at step that goes past 70
say #alist; # [1 4 9 16 25 36 49 64 81]
my #alist = {(++$)²} ...^ * > 70; # stop at step before step past 70
say #alist; # [1 4 9 16 25 36 49 64]
Note how the ... and ...^ variants of the sequence operator provide the two variations on the stop condition. I note in your original question you have ... ^ * > 70, not ...^ * > 70. Because the ^ in the latter is detached from the ... it has a different meaning. See Brad's comment.
Is there in GoogleTest something like:
ASSERT_EQ_ONE_OF_TWO(TestValue, Value1, Value2)
which tests if TestValue == Value1 || TestValue == Value2?
This variant:
ASSERT_TRUE(TestValue == Value1 || TestValue == Value2)
is OK, but it does not show in log which value TestValue has if it fails.
Is there in GoogleTest something like
I think No.
is OK, but it does not show in log which value TestValue has if it
fails.
You can add addition log information like this:
TEST (ExampleTest, DummyTest)
{
// Arrange.
const int allowedOne = 7;
const int allowedTwo = 42;
int real = 0;
// Act.
real = 5;
// Assert.
EXPECT_TRUE (real == allowedOne || real == allowedTwo)
<< "Where real value: " << real
<< " not equal neither: " << allowedOne
<< " nor: " << allowedTwo << ".";
}
This code will be produce the following log when fails:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from ExampleTest
[ RUN ] ExampleTest.DummyTest
/home/gluttton/ExampleTest.cpp:13: Failure
Value of: real == allowedOne || real == allowedTwo
Actual: false
Expected: true
Where real value: 5 not equal neither: 7 nor: 42.
[ FAILED ] ExampleTest.DummyTest (0 ms)
[----------] 1 test from ExampleTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ExampleTest.DummyTest
You can use EXPECT_THAT() in combination with a container and the Contains() matcher to achieve this:
EXPECT_THAT((std::array{ Value1, Value2 }), Contains(TestValue));
Note that the braces after array are needed for list initialization and the parentheses around array are needed, because macros (such as EXPECT_THAT()) do not understand braces and would otherwise interpret the two arguments as three arguments.
This will give an output similar to this (created with GTest 1.10)
error: Value of: (std::array{ Value1, Value2 })
Expected: contains at least one element that is equal to 42
Actual: { 12, 21 }
Pro:
Prints all values
one-liner
works out of the box
Con:
Finding the value of TestValue in the output is not easy
Syntax is not straight forward
Modern compiler features are needed
C++11 is needed due to std::array and list initialization (still not available everywhere)
C++17 is needed due to CTAD, use std::initializer_list<T>{ ... } on C++11/14. Alternatively a free function can be used to deduce size and type of the array.
I haven't found anything "baked in" to do what you are asking, but a predicate assertion should be able to handle the type of assertion you are asking for. Additionally, GoogleTest will automatically print out the arguments and their values when the assertion does fail.
The assertion you would use in your case is
ASSERT_PRED3(<insert predicate>, TestValue, Value1, Value2)
The predicate is a function or functor that returns bool, where false fails the assertion. For your predicate, you could use a function like the following:
bool OrEqual(int testValue, int option1, int option2)
{
if (testValue == option1 ||
testValue == option2)
{
return true;
}
else
{
return false;
}
}
Of course, this is a simple example. Since you can provide any function or functor that takes the provided arguments, there is plenty that you can do with predicate assertions.
Here is the documentation: https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#predicate-assertions-for-better-error-messages
You can use the following:
ASSERT_THAT(TestValue, AnyOf(Value1, Value2));
or if you need floating point matching with doubles:
ASSERT_THAT(TestValue, AnyOf(DoubleEq(Value1), DoubleEq(Value2)));