我的项目中有一些Utilities类,并且正在考虑使用数组来创建"命名参数"。
我的代码允许我链接方法或单独使用它们。例如,我有一个处理字符串的字符串类(有点明显:))
现在,带链接的一组示例方法如下所示:
print Utils\String::Set('my string')->UcFirst()->UcLast()->Get()
虽然没有链接的同样的事情看起来像这样:
$string = Utils\String::UcFirst('my string');
print Utils\String::UcLast($string);
这适用于某些方法,但是诸如"后缀"等方法存在问题。它具有以下参数:$ string,$ suffix。
这会导致链接问题,因为我最终会这样做
Suffix(null, ' New')
哪个看起来不太好。
在这种情况下,使用数组是否可以提供命名参数? 然后我就能用链接来做这个:
Suffix(['suffix' => ' New'])
但是我不确定这对维护项目有多难,以及是否值得放弃非链接方法以便不需要数组。
答案 0 :(得分:2)
我不会走这条路。数组作为命名参数的替代方法的问题在于,您无法将参数定义为必需或可选,并且无法键入提示,这会使错误更难找到或增加额外验证的要求。
如果您不熟悉它,请考虑使用此库编写代码的方式。任何IDE都可以快速显示方法所需的参数,但如果它只显示数组,我必须仔细查看文档。
我甚至会进一步将静态方法与对象链接方法分开。现在似乎String::Suffix
可以使用值参数静态调用,而非静态调用而不使用值参数。除了违反E_STRICT标准之外,它还将两个完全不同的接口混合到一个方法中。
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à,不再需要命名参数
答案 1 :(得分:1)
您正在做的事情似乎是从函数应用程序的前缀转换为中缀表示法。也就是说,您正在编写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")