函数只返回不变的参数,没用吗?


15

我刚刚在我正在工作的项目中找到此功能:

  -- Just returns the text unchanged.
  -- Note: <text> may be nil, function must return nil in that case!
  function Widget:wtr(text)
      return text
  end

太可悲的是,编码器不再在公司工作。为什么要使一个函数什么都不做,但是返回调用它的参数呢?

这种功能有什么用,在本例中未指定,但在任何情况下都没有用?

由于

function aFunction(parameter)
    return parameter
end

结束于

aFunction(parameter) == parameter

我为什么要写这样的东西

aFunction(parameter) == whatIWantToCheck

代替

parameter == whatIWantToCheck



13
@gnat这到底是怎么回事?
Kilian Foth,2014年

13
??该函数返回其参数链,涉及返回this
Kilian Foth 2014年

11
@gnat问题是为什么有人会写一个除了返回自身以外什么都不做的函数。是的,您可以返回某些对象或值以允许方法链接,但这不是他的问题。他的问题是,为什么有人会写类似的东西,int getParam(int param) { //DO NOTHING return param; } 从方法链的角度来看,这是一个完全多余且不必要的调用,因为您可以将OP的功能放在方法链之外,并且不会有任何区别。
ZeroStatic 2014年

4
这可能是题外话,不适用于lua,但是在PHP中有一个有效的用例-在较旧的版本中,new Foo()->method();语法无效,并且function with($what) { return $what; }; with(new Foo())->method();使用了类似的构造作为解决方法。
DCoder 2014年

Answers:


57

您的问题有点像问数字零的好处是什么,如果每当您将其添加到某项中时,您又获得了相同的值。身份函数就像函数的零。它本身是无用的,但在使用高阶函数的表达式中有时有用,您可以在其中将函数作为参数或将其返回。这就是为什么大多数函数式编程语言在其标准库中都具有id或的原因identity

换句话说,它使一个方便的默认功能。就像您可能希望将其设置offset = 0为默认整数一样,即使使offset不执行任何操作,也可以将其设置filterFunction = identity为默认函数,即使这会使过滤器不执行任何操作。


过滤器功能不应该返回布尔值吗?在这种情况下,“零”过滤器函数将返回true。
Kirill Rakhman 2014年

1
@cypressious一个地图函数。
sapi 2014年

6
或者将其坚持一个设计概念:空对象模式,功能版本
blgt 2014年

@cypressious,这将是对于被作为参数传递的谓词一个filter高阶函数。一阶filter函数具有类型[a] -> [a]
卡尔比勒费尔特

例如,在C#中,我经常使用.OrderBy(x => x)
CodesInChaos 2014年

27

当然。想象一下一个外部API,该API允许您从绝对需要的地方检索内容,但是即使您需要所有结果并希望完全存储它们,也必须为每个查询指定过滤条件和输出格式化程序。

然后,您必须发明一个琐碎的“接受一切”和琐碎的“返回不变”函数来获取数据。wtr正是这样一个琐碎的伪格式器。如果您经常使用该API,那么使该伪辅助函数随处可见可能会非常有用,而不用在查询任何内容时都必须创建匿名函数。(您可以考虑调用它,identity而不是wtr立即知道它什么都不做。)


我还没有真正理解这种感觉,但这就是场景。我想一段时间后,我可能会理解,在致力于这个项目的同时,请牢记您的答案。atm对我来说看起来没用,...如果我得到了原始数据,为什么还要让函数再次给我原始数据,...
Sempie 2014年

3
@Sempie同样,如果API 需要格式化功能,则获取未更改文本的唯一方法是该函数对文本不执行任何操作。
Doval 2014年

3
换句话说:如果您有一个需要传递过滤器/格式参数的函数,而您绝对不能使用null该函数,则可以使用一个空的过滤器函数,该过滤器以“无”进行过滤,以使程序停止抱怨。
ZeroStatic 2014年

3
@Sempie您曾经使用过SQL,对吗?您知道如何包含或不包含WHERE子句吗?这大概是语法糖的问题。从本质上讲,缺少WHERE子句与您拥有一个WHERE继续执行并允许所有操作的子句完全相同。SQL的设计人员不允许您指定一个WHERE子句,而不是强迫您放下一个子句(即使它接受了所有内容),这或多或少是语法糖,为了方便起见,他们只是为您提供了该选项。 ..
Panzercrisis 2014年

5
可能值得注意的是,在许多情况下,让代码无条件地调用可能会或可能不会做有用事情的虚拟方法或委托比让代码确定是否需要调用并跳过是否调用要更快,更干净。
supercat 2014年

15

这不仅仅是多态吗?

从我有经验的Qt tr()wtr()方法都应该是(在那里,在使用Qt的在本地化)Widget的文本。

因此,通过返回不变的文本,此方法仅表示:Widget does no localization (translation of the text) by default. Override this function to enable your own logic


1
没意识到这是QT问题-显然这就是答案。
Corley Brigman 2014年

8

一个很常见的情况是“后来增加的功能”。因此,程序员认为以后可以对该功能进行一些更改。由于您将其作为函数而不是参数本身进行访问,因此您可以轻松地对其进行全局更改。假设您有一个具有以下内容的索引:

function getIndex(index)
    return index
end

并且因为您的索引从0开始,所以一切都很好。稍后您在其他地方更改了一个组件,该组件需要您转换索引才能从1开始。您将不得不在代码的各处添加数百个index + 1。但是使用这样的方法,只需说:

 function getIndex(index)
    return index+1
end

而且你还好 诸如此类的功能可能会很快导致过度设计,但在某些时候它们很有道理!


2
是的,尽管它的值得指出的是刊登的OP功能的doctstring并没有表明,这是在他的案件的功能的目的。
Mark Amery 2014年

6

这样的存根函数在类型继承情况下很常见。基类可能没有任何用处,但派生类可能会对输入进行各种操作。在基类中声明存根函数可以使所有派生类具有该名称的功能,而单个派生类可以用更详尽,更有用的方法来覆盖它。


5

另一种情况类似于在python和C#中使用属性,但是在没有该功能的语言中使用。

通常,您可以将某些内容声明为类的成员。假设“名称”为字符串。这意味着您可以像这样访问它:

someobject.name

稍后,您确定名称确实需要取决于对象中的内容。因此,它实际上应该是一个功能。糟糕!即使没有参数,这也意味着现在必须将访问它的所有代码更改为

someobject.name()

但是,如果您有很多此调用的实例,那么发生任何错误的机会就非常低-不会进行此更改的地方,到达该点时程序将崩溃,等等。

使用C#/ Python中的属性,您可以用函数代替以前的属性,同时仍然可以像访问属性一样访问它,即无需更改。您甚至不必事先计划。

如果您的语言没有这种功能,则您必须提前计划,但是您仍然可以像以前一样支持它,方法是从一开始就将其设置为一项功能,而该功能不会执行任何操作。刚开始时,它不会做任何有趣的事情,看起来应该将其删除,并且这种类型的许多功能从未更改过。但是后来,如果您意识到实际上在每次调用时Widget.wtr都需要去除一些特殊字符,那没什么大不了的-它已经是一个函数,只需将其添加进去就可以了。

TL; DR这可能是明智的程序员,需要为将来的更改进行预先计划。


3
如果此方法依赖于其他任何方法,那将是有道理的,但并非如此。它不是属性,获取器/设置器或字段。该方法目前不执行任何操作。他计划未来更改的唯一方法是是否必须更改此方法的逻辑。
Matthew Steeples 2014年

1
它不必...意味着现在,我不处理这些数据,但是以后,如果我想处理它,则该数据的每个用户都可以免费获得处理后的数据。愚蠢的例子:假设您将字符串打印到屏幕上,并且通常这样做print data。然后,您意识到所有字符串都必须是大写字母-您必须去查找程序中的每个打印件并更改为print data.upper()。但是,如果您有,def cdata(data): return data并且到处都说print cdata(data),那么您只需更改为def cdata(data): return data.upper(),这是唯一的更改。
Corley Brigman 2014年

我明白你的意思了。这更有意义
Matthew Steeples

2

它不是没有用的,实际上它可能非常有用,因为它使您的代码更加统一和灵活。

举例来说,假设您有一个人员列表和一个下拉菜单,供用户选择是否要查看“全部”还是仅查看“男性”或“女性”。

您可以将“全部”作为特殊情况处理,在这种情况下,您将需要一个额外的if和以明确检查这种情况,或者您可以拥有一个仅返回其参数的过滤器函数(例如,允许所有内容通过),分配用于“全部”情况。


4
这不适合这种情况。我的意思是一个返回他的参数的函数,在任何情况下都不要做任何其他事情。
Sempie 2014年

@Sempie:那是他的意思。如果您有一个Filter带有MaleFilter和的FemaleFilter子类的类或接口,并且您的代码需要一些过滤器,那么处理不做任何事情(不返回其参数不变)的过滤器All。该函数从不执行任何操作,但可以代替执行该操作的操作。
Magus 2014年

@Magus,但是在您的方案中,该函数是某种占位符,或者将在以后替换,或者仅由于旧函数已过时而已而存在,但程序需要此传递。无论如何,这不是移交。该函数不会像过滤器那样将未更改的参数提供给另一个函数,而是将其返回给调用函数。
森培(Sempie),2014年

@Sempie不,它既不是安慰剂,也不用作临时通道。这是一个有用的编码(和数学)概念,即“身份”功能。而且,是的,无论是返回到“另一个函数”还是返回到调用函数,它仍然是一个切换。关键是“身份”函数可以是调用函数调用的许多可能函数之一,并且可以使用避免在被调用函数不需要执行任何操作时使用if和特殊框。
Hejazzman,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.