2016-08-02 2 views
0

함수 내에서 별도의 개인 함수를 사용해야하는시기는 언제입니까? 함수 내에서 별도의 개인 함수를 사용해야하는시기는 언제입니까?

나는 내가 쓴 함수가 상당히 긴 것을 관찰 :

let optionsFor piece (positions:Space list) = 

    let yDirection = match piece with 
        | Black _ -> -1 
        | Red _ -> 1 

    let sourceX , sourceY = 
     match piece with 
     | Black (checker , pos) -> pos 
     | Red (checker , pos) -> pos 

    let optionsForPiece = 
     (fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) || 
        pos = ((sourceX + 1) , (sourceY + yDirection))) 

    let availableSelection = 
     (fun space -> match space with 
         | Available pos -> Some pos 
         | Allocated _ -> None) 

    let availablePositions = 
     positions |> List.filter toAvailable 
        |> List.choose availableSelection 

    availablePositions |> List.filter optionsForPiece 

따라서, 나는 여러 개의 작은 함수로 위의 기능을 리팩토링 고려했다.

그러나 함수 프로그래밍에 이것이 필요한지 확실하지 않습니다.

내부 기능에 대한 현재 권장 사항과 비공개 기능으로 추출하는 기능은 무엇이 있습니까?

부록 :

open NUnit.Framework 
open FsUnit 

(* Types *) 
type Black = BlackKing | BlackSoldier 
type Red = RedKing | RedSoldier 

type Coordinate = int * int 

type Piece = 
    | Black of Black * Coordinate 
    | Red of Red * Coordinate 

type Space = 
    | Allocated of Piece 
    | Available of Coordinate 

type Status = 
    | BlacksTurn | RedsTurn 
    | BlackWins | RedWins 

(* Functions *) 
let black coordinate = Allocated (Black (BlackSoldier , coordinate)) 
let red coordinate = Allocated (Red (RedSoldier , coordinate)) 

let startGame() = 
    [ red (0,0); red (2,0); red (4,0); red (6,0) 
     red (1,1); red (3,1); red (5,1); red (7,1) 
     red (0,2); red (2,2); red (4,2); red (6,2) 

     Available (1,3); Available (3,3); Available (5,3); Available (7,3) 
     Available (0,4); Available (2,4); Available (4,4); Available (6,4) 

     black (1,5); black (3,5); black (5,5); black (7,5) 
     black (0,6); black (2,6); black (4,6); black (6,6) 
     black (1,7); black (3,7); black (5,7); black (7,7) ] , BlacksTurn 

let private toAvailable = 
    (fun space -> match space with 
        | Available pos -> true 
        | _    -> false) 

let available (positions:Space list) = positions |> List.filter toAvailable 

let optionsFor piece (positions:Space list) = 

    let yDirection = match piece with 
        | Black _ -> -1 
        | Red _ -> 1 

    let sourceX , sourceY = 
     match piece with 
     | Black (checker , pos) -> pos 
     | Red (checker , pos) -> pos 

    let optionsForPiece = 
     (fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) || 
        pos = ((sourceX + 1) , (sourceY + yDirection))) 

    let availableSelection = 
     (fun space -> match space with 
         | Available pos -> Some pos 
         | Allocated _ -> None) 

    let availablePositions = 
     positions |> List.filter toAvailable 
        |> List.choose availableSelection 

    availablePositions |> List.filter optionsForPiece 
+0

이것이 [코드 검토] (http://codereview.stackexchange.com/)에 더 적합한 지 궁금합니다. – s952163

+1

내 코드는 컨텍스트로 사용됩니다. 나는이 질문에 코드가 필요 없다고 생각한다. 나는 각 옵션에 대해 찬반 양론을 찾고 있다고 생각한다. –

+0

이것이 무엇인지 묻는 것이 확실하지 않지만 사용법 및 외부 (기능 및 모듈 및 기타 .NET 코드)에서 함수에 액세스하려는 경우이 작업을 수행해야합니다. 많은 작은 함수와 내부 함수를 정의하는 것은 잘못된 것이 아닙니다. – s952163

답변

4

이 더 의견을 기반으로,하지만 난 내 의견을 제공 할 수 있습니다.

"helper"함수가 이 "main"함수를 사용하여과 매우 연관되어 있으면 내포 된 함수로 쓰는 것이 좋습니다. 서로 밀접하게 연관되어 있지 않으면 헬퍼 함수를 ​​별도의 함수로 작성합니다. 다른 모듈의 다른 코드에 언제 유용할지 모르기 때문에 비공개로 설정하지 않을 수도 있습니다.

내부 함수 의 밀접하게 연결된 내부 함수의 예는 재귀 적 함수 프로그래밍에서 글자가 쓰이는 일종의 loop-with-accumulator 함수입니다.

module BinarySearchTree 

type Node<'T> = 
    { left: Node<'T> option 
     value: 'T 
     right: Node<'T> option } 

let singleton v = { left = None; value = v; right = None } 

let rec insert v t = 
    if v <= t.value 
     then match t.left with 
      | None -> { t with left = singleton v |> Some } 
      | Some n -> { t with left = insert v n |> Some } 
     else match t.right with 
      | None -> { t with right = singleton v |> Some } 
      | Some n -> { t with right = insert v n |> Some } 

let fromList l = 
    match l with 
    | [] -> failwith "Can't create a tree from an empty list" 
    | hd::tl -> 
     tl |> List.fold (fun t v -> insert v t) (singleton hd) 

let toList t = 
    let rec loop acc = function 
     | None -> acc 
     | Some node -> 
      (loop [] node.left) @ (node.value :: (loop [] node.right)) 
    loop [] (Some t) 

이 마지막 toList 기능을 살펴 보자 : 예를 들어, 여기에 내가 F # 프로그래밍 연습을 위해 쓴 일부 코드입니다. 그것은 loop이라고 불리는 내부 함수를 가지고 있습니다. 이것은 독립적 인 함수로는 의미가 없습니다. 너무 toList 함수와 관련되어 있으며 내부 함수로 유지하는 것이 좋으며 toList 외부에서는 액세스 할 수 없습니다.

그러나 fromList 함수를 작성할 때 내부 함수로 insert을 정의하지 않았습니다. insert 기능은 fromList의 기능과는 별도로 자체적으로 유용합니다. 그래서 나는 별도의 기능으로 insert을 썼다. fromList이 내 코드에서 실제로 insert을 사용하는 유일한 기능이지만 은 나중에 반드시 일 수 있습니다. fromArray 함수를 쓸 수도 있습니다. 효율성을 위해 fromList을 다시 사용하고 싶지 않습니다. (fromArraylet fromArray a = a |> List.ofArray |> fromList으로 쓸 수는 있지만 불필요한 목록을 만듭니다. 끝나면 버릴 것입니다. 효율성을 고려하여 배열을 직접 반복하고 insert을 호출하십시오. 적절한).

따라서 동일한 모듈에서 중첩 된 내부 함수와 별도의 함수를 사용하는 것이 좋습니다. 이제 코드를 살펴 보겠습니다.

  • yDirection -이 가변이지만, 파라미터로서 piece 촬영 기능으로 전환 할 수있다. 함수로서 많은 다른 함수에서 유용 할 수있는 것처럼 보입니다. 내 판단 : 별도.
  • sourceXsourceY -이 변수가 아닌 함수입니다,하지만 당신은 튜플을 반환 source라는 함수에 그 match를 켠 다음 sourceXsourceY의 값을 설정하기 위해 optionsFor 함수를 호출 할 수 있습니다. 내 의견으로는, source 기능은 별도 기능으로 대부분의 의미를 만듭니다.
  • optionsForPiece -이 함수는 optionsFor 함수와 밀접하게 관련되어있어 다른 곳에서 호출하지 않으려 고합니다. 내 판단 : 중첩.
  • availableSelection - 이것은 여러 상황에서 유용 할 수 있습니다. 단지 optionsFor이 아닙니다. 내 판단 : 별도.
  • availablePositions - 이것은 변수이지만 positions을 매개 변수로 사용하는 함수로 쉽게 바뀔 수 있으며 사용할 수있는 값을 반환합니다. 다시 말하지만, 이는 여러 상황에서 유용 할 수 있습니다. 내 판단 : 별도.

그래서 분할 밖으로 그들이 다시 사용할 수있는 것처럼 보일 모든 기능에 의해, 우리는 다음에 아래로 optionsFor 기능을 입수했습니다

다시 방문 할 때 더 많은 읽을 수 있어요
// Functions yDirection, source, availableSelection, 
// and availablePositions are all defined "outside" 

let optionsFor piece (positions:Space list) = 

    let yDir = yDirection piece 

    let sourceX , sourceY = source piece 

    let optionsForPiece pos = 
     pos = ((sourceX - 1) , (sourceY + yDir)) || 
     pos = ((sourceX + 1) , (sourceY + yDir)) 

    positions |> availablePositions |> List.filter optionsForPiece 

나중에 코드를 작성하고 더 많은 재사용 가능한 기능 (예 : availableSelections)을 사용하면 코드의 다음 비트를 작성할 때 이점이 있습니다.

관련 문제