簡體   English   中英

使用數組的“命名參數”

[英]'Named parameters' using arrays

我的項目中有一些實用程序類,正在考慮使用數組來創建“命名參數”。

我的代碼允許我鏈接方法或單獨使用它們。 例如,我有一個處理字符串的字符串類(有點明顯:))

現在,帶有鏈接的方法示例集如下所示:

print Utils\String::Set('my string')->UcFirst()->UcLast()->Get()

沒有鏈接的同一件事看起來像這樣:

$string = Utils\String::UcFirst('my string');
print Utils\String::UcLast($string);

這適用於某些方法,但是諸如“ Suffix”之類的方法存在問題,該方法具有以下參數:$ string,$ suffix。

這會導致連鎖問題,因為我最終會這樣做

Suffix(null, ' New')

看起來真的不是很好。

在這種情況下,使用數組可以提供命名參數嗎? 然后,我可以執行以下鏈接操作:

Suffix(['suffix' => ' New'])

但是,我不確定這將使維護項目變得困難多少,以及是否值得刪除非鏈接方法以致不需要數組。

我不會走這條路。 用數組代替命名參數的問題在於,您無法將參數定義為必需參數或可選參數,並且無法鍵入提示它們的參數,這將使查找錯誤或增加其他驗證要求更加困難。

如果您不知道該怎么做,請考慮使用該庫編寫代碼的方式。 任何IDE都可以快速顯示方法需要的參數,但是如果僅顯示array ,則必須仔細閱讀文檔。

我什至更進一步,將靜態方法與對象鏈接方法分開。 現在看來,可以使用值參數靜態調用String::Suffix而不使用值參數靜態調用String::Suffix 除了違反E_STRICT標准外,這還將兩個完全不同的接口融合為一種方法。

這就是我實現您的API的方式:

namespace Util;

class String // you might want to change the name to "Strings", "string" is a reserved keyword in PHP 7
{
    public static function Suffix($string, $suffix)
    {
        return (new StringWrapper($string))->Suffix($suffix);
    }
}
class StringWrapper
{
    private $value;
    public function __construct($string)
    {
        $this->value = $string;
    }
    public function Suffix($suffix)
    {
        return new static($this->value . $suffix);
    }
    public function __toString()
    {
        return $this->value; 
    }
}

您會看到String中的靜態接口只是StringWrapper類中實際實現的一個瘦包裝。 StringWrapper是不可變的值對象類型,並提供用於字符串操作的方法。 每個方法調用都會返回該類的新實例,該實例保存修改后的值。 使用__toString您最終可以將其轉換為標量字符串值(這是使用Get()方法執行的操作)

Voilà,不再需要命名參數

看來您正在做的是將前綴從函數應用程序的前綴轉換為前綴表示。 也就是說,您正在編寫x1->f(x2,…,xn)而不是f(x1,x2,…,xn) x1->f(x2,…,xn)

您始終可以只使用前綴表示法來編寫S::UcLast(S::UcFirst("my string")) 簡潔性是通過use Utils\\String as S

要將->用作中綴符號的一部分,您需要一個類似於以下內容的類定義(並且我假設您的實現也是如此)。

class UtilStringProxy
{
  public $string;

  public function __construct($string)
  {
    $this->string = $string;
  }

  public function UcFirst()
  {
    $this->string = S::UcFirst($this->string);
    return $this;
  }

  public function UcLast()
  {
    $this->string = S::UcLast($this->string);
    return $this;
  }

  public function Suffix($suffix)
  {
    $this->string = S::Suffix($this->string, $suffix);
    return $this;
  }

}

第一個論點被揭穿。 這就是我們使f到達中綴位置(在操作數1和2之間)的方式。 然后您可以編寫:

(new UtilStringProxy("my string"))->UcFirst()->UcLast()->Suffix("New")->string

就我個人而言,我沒有看到這樣的願望:

S::Suffix(S::UcLast(S::UcFirst("my string")), "New")

附錄

函數組成是查看此問題的另一種方法。 函數應用程序提供從左到右的讀數,而函數組合僅通過翻轉參數即可提供從左到右或從右到左的讀數。

UtilStringProxy的示例基本上是從左到右的函數組成,為特定的函數集UcFirst, UcLast, Suffix 您可以由此概括。

class Compose
{
  public $f;

  public function __construct(callable $f)
  {
    $this->f = $f;
  }

  public function lr(callable $g)
  {
    $f = $this->f;
    return new Compose(function ($x) use ($f, $g) {
      return $g($f($x));
    });
  }

  public function rl(callable $g)
  {
    $f = $this->f;
    return new Compose(function ($x) use ($f, $g) {
      return $f($g($x));
    });
  }

  public function call($x)
  {
    $f = $this->f;
    return $f($x);
  }

}

我添加了call方法,因為PHP的解析器有一個不幸的弱點,即您無法編寫expr(x)來將expr應用於任何表達式的x -僅僅是某些表達式。 如果只想返回組合函數,請使用->f ,如果要立即應用,請使用->call(x)

使用這個可以寫從左到右的合成:

(new Compose('strtolower'))->lr('ucfirst')->call("hEllo World")

或從右至左組成:

(new Compose('ucfirst'))->rl('strtolower')->call("hEllo World")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM