0

この関数の例を考えてみましょう:

最初の例

;;; Lisp
(defun foo (x y z)
  (let ((tmp))
    (setf tmp (operation1 x y z))
    (setf tmp (operation2 tmp y z))
    (setf tmp (operation3 tmp y z))
    (setf tmp (operation4 tmp y z))
    ...
    (setf tmp (operationN tmp y z))
    tmp))

// PHP
function foo($x, $y, $z)
{
  $tmp = operation1($x, $y, $z);
  $tmp = operation2($tmp, $y, $z);
  $tmp = operation3($tmp, $y, $z);
  ...
  return operationN($tmp, $y, $z);  
}

私の先生は、関数型プログラミングでは、戻り値を temp 変数に格納するのではなく、すぐに次の関数に渡すべきだと教えてくれました。

2 番目の例

;;; Lisp
(defun foo (x)
  (operationN
    (... 
      (operation3
        (operation2
          (operation1 x y z) 
        y z)
       y z)
    y z)
  y z)
)

// PHP
function foo($x, $y, $z)
{
  return operationN(
    ...(
     operation3(
      operation2(
        operation1($x, $y, $z),
        $y, $z),
      $y, $z),
     $y, $z),
    $y, $z);
}

これは非常に単純な例であり、残りの引数には他の関数が適用される可能性があると考えてください。私の意見では、最初の例の方が読みやすいです。

  1. 関数型プログラミングの方法でこのコードをフォーマットする適切な方法は何ですか?
  2. プログラミング時にコードの読みやすさまたは適切なコード構文を優先する必要がありますか (深さのレベルに依存する必要があります)?
4

1 に答える 1

3

コードが扱いにくくなっているということは、多くの場合、1 つの関数に多くの責任が与えられていることを示しています。
私の意見では、両方の言語で「適切な」方法は、より小さな関数にリファクタリングすることです。

もちろん、このリファクタリングは実際の問題に依存しますが、例の簡単な内訳は

(defun operations1-2 (x y z)
  (operation2 (operation1 x y z) y z))

(defun operations1-3 (x y z)
  (operation3 (operations1-2 x y z) y z))

(defun operations1-4 (x y z)
  (operation4 (operations1-3 x y z) y z))

...

(defun foo (x y z)
  (operationN (operations1-N-1 x y z) y z))

もちろん、常に意味のある方法でそれを行うことはできませんが、深くネストされた関数アプリケーションよりも優れたシーケンシャルな let バインディングもあります。

(defun foo (x y z)
  (let* 
      ((tmp (operation1 x y z))
       (tmp2 (operation2 tmp y z))
       (tmp3 (operation3 tmp2 y z))
       (tmp4 (operation4 tmp3 y z))
       (...))
    (operationN tmpN-1 y z)))
于 2013-03-18T13:01:52.597 に答える