Diciamo che sto programmando un gioco di scacchi. A un certo punto devo controllare, quali mosse sono valide per un dato pezzo. Quale sarebbe il modo corretto di selezionare la corretta funzione di ricerca del percorso per un dato brano (re, regina, ecc.)?
Ho trovato tre diversi approcci:
- Memorizza il metodo di definizione del percorso (insieme agli altri dati) all'interno di un record (simile al modello di strategia; troppo orientato agli oggetti?)
- Crea un
PieceType
Unione discriminata con tutti i tipi di pezzi e memorizza un valore di questo tipo nel record. Seleziona la corretta funzione di path-path tramite la corrispondenza del pattern - Crea un% record di tipo% co_de che memorizza i dati e un
PieceData
DU, in cui tutti i casi rappresentano tipi di pezzi diversi e sono di tipoPiece
. La corrispondenza del modello viene anche utilizzata per selezionare la funzione corretta.
Ecco alcuni esempi di codice, che dimostrano i diversi approcci:
// The piece "constructor" is private as to only allow creating pieces via
// the provided construct functions for each piece type
type Piece = private { Position:Position; Pathfinder:Position->Board->Position list }
let kingPathfinder position board =
// Check and return all possible targets for a king
let createKing position =
{ Position=position; Pathfinder=kingPathfinder }
let getPossibleTargets { Position=position; Pathfinder=pathfinder } board =
pathfinder position board
#### #### ####
type PieceType =
| King
| ...
type Piece = { Position:Position; PieceType:PieceType }
let kingPathfinder position board =
// Check and return all possible targets for a king
let createKing position =
{ Position=position; PieceType=King }
let getPossibleTargets { Position=position; PieceType=pieceType } board =
match pieceType with
| King -> kingPathfinder position board
| ...
#### #### ####
type PieceData = { Position:Position }
type Piece =
| King of PieceData
| ...
let kingPathfinder position board =
// Check and return all possible targets for a king
let createKing position =
King { Position=position }
let getPossibleTargets piece board =
match piece with
| King { Position:position } ->
kingPathfinder position board
La mia domanda ora è: quale di questi tre approcci è preferito nella programmazione funzionale? O c'è un altro modo migliore?