这种Imperative编码风格的等效Scala代码是什么?

时间:2015-11-13 19:22:37

标签: scala

在下面找到命令式样式代码:

private boolean placePieceOnBoard(Results results, 
                                  ChessLayout chessLayout,
                                  List<ChessPiece> piecesToPlace, 
                                  int pieceIndex, 
                                  int startOffset) {
    if(pieceIndex == piecesToPlace.size()) {
        results.addLayout(chessLayout);
        return true;
    }
    else {
        ChessPiece chessPiece = piecesToPlace.get(pieceIndex);
        int offset = startOffset;
        while(offset < chessLayout.getBoardLength()) {

            int placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset);
            if( placedOffset == ChessLayout.NULL_OFFSET ) 
                break;
            else {
                logger.debug("piece {} ({}) moved", pieceIndex, chessPiece);

                placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1);

                chessLayout.removeChessPiece(chessPiece);
                offset = placedOffset + 1;
            }
        }
        return false;
    }
}

在这里,我有兴趣了解如何在循环中以功能方式转换对偏移的更改,如何从循环中进行早期中断等。

1 个答案:

答案 0 :(得分:1)

这是Scala强大优势之一的一个很好的演示 - 从命令式Java代码到功能代码的逐步,轻松迁移。

要转换为Scala,您不需要立即100%运行。您可以轻松地将所有内容转换为Scala,如下所示:

def placePieceOnBoard(results: Results, 
                      chessLayout: ChessLayout,
                      piecesToPlace: List[ChessPiece], 
                      pieceIndex: Int, 
                      startOffset: Int) {
    if (pieceIndex == piecesToPlace.size()) {
        results.addLayout(chessLayout)
        true
    }
    else {
        val chessPiece = piecesToPlace.get(pieceIndex)
        var offset = startOffset
        while(offset < chessLayout.getBoardLength) {

            val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)
            if( placedOffset == ChessLayout.NULL_OFFSET ) 
                break
            else {
                logger.debug("piece {} ({}) moved", pieceIndex, chessPiece)

                placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1)

                chessLayout.removeChessPiece(chessPiece)
                offset = placedOffset + 1
            }
        }
        false
    }
}

请注意,我们在详细程度方面已有一些小的改进:不再有; s,没有冗余类型签名,可变变量在可能的情况下转换为常量,消除了返回语句和函数括号。注意我将piecesToPlace的参数类型更改为scala列表,您需要使用调用站点上的scala-java converters进行编译。

接下来,我们可以开始使它更具功能......但是,这个功能可能不是你应该开始的地方,因为你在几个地方调用状态变异函数。例如,您可以从ChessLayout开始:

chessLayout.removeChessPiece(chessPiece)

val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)

这些方法改变了ChessLayout,这不是功能风格。您可以修改removeChessPiece以返回删除该部分的新ChessLayoutplacePieceInNextAvailablePosition可以返回(ChessLayout, Int)的元组。一旦停止从placePieceOnBoard调用的任何函数处于变异状态,就可以将其转换为函数样式。