I need to exit a for
loop on line 163 and 167 if the statement at line 168 if the statement is true. The way I do this now is by having this AllowLoop logic
.
Is there a better way to exit a for loop?
Hey @JoeriDukker,
Verse doesn’t support breaking/continueing from for
loops, so the way you’re doing things is correct. However, I can think of some ways to clean up the code you posted using other Verse characteristics.
# Move the validity check to its own function. Here I've made the function <decides>
# as that is the idomatic way of writing "IsValid" style checks in the Verse standard libraries.
IsTargetTileValid(TargetTile:int, Piece:piece)<decides><transacts>:void =
for (OtherPiece : AllPieces):
if (TargetTile = OtherPiece.Pos and Piece.Color = OtherPiece.Color)
# "false?" forces a failure of IsTargetTileValid[]
false?
# (1) Using the new IsTargetTileValid to clean things up a bit
GetPossibleSlidingMoves(Piece:chess_piece, Direction:direction_indices):[]move =
var Moves:[]move = array{}
StartTile := Piece.Pos
for (DirectionIndex : DirectionIndices):
Range := NumTilesToEdge(StartTile, DirectionIndex)
Print("Checking direction index {DirectionIndex} with EdgeDist = {Range}")
# 1. Loop from 1..Range instead of 0..Range. This removes the N<>0 check.
# 2. Check IsTargetValid in the for loop. If it fails, the loop continues
# to the next iteration
for:
N := 1..Range
TargetTile := StartTile + DirectionOffsets(DirectionIndex) * N
# If IsTargetTileValid[] fails the loop will continue to the next iteration
IsTargetTileValid[TargetTile, Piece]
do:
Print("Added move")
set Moves += array{ move{ Start := StartTile, arget := TargetTile }}
return Moves
If we want to go further there are two additional steps that can be taken to remove even more code. I’ll break them down below.
# (2) Using for's power to emit arrays for the inner loop
GetPossibleSlidingMoves(Piece:chess_piece, Direction:direction_indices):[]move =
var Moves:[]move = array{}
StartTile := Piece.Pos
for (DirectionIndex : DirectionIndices):
Range := NumTilesToEdge(StartTile, DirectionIndex)
Print("Checking direction index {DirectionIndex} with EdgeDist = {Range}")
# For loop creates a new array containing the item emitted from the "do" block
NewMoves:[]move = for:
N := 1..Range
TargetTile := StartTile + DirectionOffsets(DirectionIndex) * N
# If IsTargetTileValid[] fails the loop will continue to the next iteration
IsTargetTileValid[TargetTile, Piece]
do:
# Return a new move that will be added to NewMoves automatically
move{ Start := StartTile, Target := TargetTile }
# Append the whole NewMoves array at once to Moves.
set Moves += NewMoves
return Moves
# (3) Using for's power to loop over multiple items. This turns nested for loops into one loop.
GetPossibleSlidingMoves(Piece:chess_piece, Direction:direction_indices):[]move =
Moves := for:
DirectionIndex : DirectionIndices
Range := NumTilesToEdge(StartTile, DirectionIndex)
# Now this loop will go over all the combinations of (DirectionIndex, N)
N := 1..Range
TargetTile := Piece.Pos + DirectionOffsets(DirectionIndex) * N
# If IsTargetTileValid[] fails the loop will continue to the next iteration
IsTargetTileValid[TargetTile, Piece]
do:
# Return a new move that will be added to NewMoves automatically
move{ Start := StartTile, arget := TargetTile }
return Moves
Thanks a ton!
Take a look at the “Effect Specifiers” section of this document. It outlines the types of effects you can add to your functions. If no specifier is provided then the system precautiously uses the no_rollback
effect, which is not allowed to be used in failure contexts like the clause section of an if
or for
.
In this case your NumTilesToEdge
and DirectionOffsets
functions likely require one of <transacts>
, <varies>
, or <computes>
depending on what they’re doing. Adding one of those specifiers will indicate that they can be used in the for
loop context.
In nearly all my functions I use Print to print errors. But when I use the effect specifier that my function needs I can no longer use Print because Print has the no_rollback effect. Any idea how I can use the specifiers and also log/print errors