La fonction ne renvoie que des paramètres inchangés, inutile?

15

Je viens de trouver cette fonction dans le projet sur lequel je travaille:

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

Dommage, le codeur ne travaille plus dans l'entreprise. Pourquoi créer une fonction qui ne fait rien, mais renvoie le paramètre avec lequel elle est appelée?

Y a-t-il une utilité à une telle fonction, non spécifiée dans cet exemple, mais globale dans tous les cas?

En raison de

function aFunction(parameter)
    return parameter
end

Fini dans

aFunction(parameter) == parameter

Pourquoi devrais-je écrire quelque chose comme

aFunction(parameter) == whatIWantToCheck

au lieu de

parameter == whatIWantToCheck

?

Sempie
la source
doublon possible du style
gnat
13
@gnat Comment diable est-ce un doublon?
Kilian Foth,
13
Hein? Cette fonction renvoie son paramètre - le chaînage implique le retour this.
Kilian Foth,
11
@gnat La question est de savoir pourquoi quelqu'un écrira jamais une fonction qui ne fait rien d'autre que se retourner elle-même. Oui, vous pouvez renvoyer certains objets ou valeurs pour permettre le chaînage de méthodes, mais ce n'est pas sa question. Sa question est de savoir pourquoi quelqu'un écrirait quelque chose comme int getParam(int param) { //DO NOTHING return param; } Du point de vue du chaînage de méthode, c'est un appel complètement redondant et inutile car vous pouvez laisser la fonction de l'OP hors d'une chaîne de méthodes et cela ne ferait aucune différence.
ZeroStatic
4
Ceci est probablement hors sujet et ne s'applique pas à lua, mais il existe un cas d'utilisation valide pour cela en PHP - dans les anciennes versions, new Foo()->method();n'était pas une syntaxe valide, et des constructions comme function with($what) { return $what; }; with(new Foo())->method();ont été utilisées comme solution de contournement.
DCoder

Réponses:

57

Votre question revient à demander quel est le bien du nombre zéro si chaque fois que vous l'ajoutez à quelque chose, vous obtenez la même valeur. Une fonction d'identité est comme le zéro pour les fonctions. Un peu inutile en soi, mais parfois utile dans le cadre d'une expression utilisant des fonctions d'ordre supérieur, où vous pouvez prendre une fonction en paramètre ou la renvoyer en conséquence. C'est pourquoi la plupart des langages de programmation fonctionnels ont un idou identitydans leur bibliothèque standard.

Autrement dit, cela fait une fonction par défaut pratique. Tout comme vous pouvez définir offset = 0un entier par défaut, même si cela fait qu'un décalage ne fait rien, il peut être utile de pouvoir le définir filterFunction = identitycomme fonction par défaut, même si cela fait que le filtre ne fait rien.

Karl Bielefeldt
la source
Une fonction de filtrage ne devrait-elle pas renvoyer une valeur booléenne? Dans ce cas, la fonction de filtre "zéro" serait celle qui renvoie vrai.
Kirill Rakhman,
1
@cypressious Une fonction de carte, alors.
sapi
6
Ou pour le coller sous un concept de design: motif d'objet nul , édition de fonctions
blgt
@cypressious, ce serait pour un prédicat qui est passé comme argument dans une filterfonction d'ordre supérieur. Une fonction de premier ordre filtera le type [a] -> [a],
Karl Bielefeldt
Par exemple en C # j'utilise souvent.OrderBy(x => x)
CodesInChaos
27

Sûr. Imaginez une API externe qui vous permet de récupérer des éléments dont vous avez absolument besoin, mais vous devez spécifier des critères de filtrage et des formateurs de sortie pour chaque requête, même si vous voulez tous les résultats et les obtenir exactement tels qu'ils sont stockés.

Ensuite, il faudrait inventer une fonction triviale "tout accepter" et une fonction triviale de "retour inchangé" pour accéder aux données. wtrest précisément un pseudo-formateur trivial. Si vous utilisez beaucoup cette API, il peut être très utile d'avoir cette fonction pseudo-assistante plutôt que de créer une fonction anonyme chaque fois que vous interrogez quelque chose. (Vous pourriez envisager de l'appeler identityplutôt que wtrpour qu'il soit immédiatement clair qu'il ne fait rien.)

Kilian Foth
la source
Je n'ai pas encore vraiment compris le sens, mais c'est exactement le scénario. Je pourrais comprendre après un certain temps, travailler sur ce projet tout en gardant votre réponse à l'esprit, je pense. atm cela me semble inutile, ... si j'ai les données brutes, pourquoi voudrais-je qu'une fonction me donne à nouveau les données brutes, ...
Sempie
3
@Sempie Encore une fois, si l'API nécessite une fonction de mise en forme, la seule façon d'obtenir le texte non modifié est si la fonction ne fait rien au texte.
Doval
3
En d'autres termes: si vous avez une fonction qui nécessite le passage d' arguments de filtre / format et que vous ne pouvez absolument pas l' utiliser nullcomme argument, vous utilisez une fonction de filtre vide qui filtre avec `` rien '' pour que le programme cesse de se plaindre.
ZeroStatic
3
@Sempie Vous avez travaillé avec SQL, non? Vous savez comment vous pouvez inclure ou ne pas inclure une WHEREclause? C'est vaguement une question de sucre syntaxique. Essentiellement, l'absence d'une WHEREclause est exactement la même que si vous aviez une WHEREclause qui va de l'avant et permet tout. Le fait que les concepteurs de SQL ne vous permettent pas de spécifier une WHEREclause, au lieu de vous en forcer une, même quand il accepte tout, est plus ou moins du sucre syntaxique, et ils vous ont juste fourni cette option pour plus de commodité. ..
Panzercrisis
5
Il peut être intéressant de noter que dans de nombreux cas, il est plus rapide et plus propre d'avoir du code appeler inconditionnellement une méthode virtuelle ou un délégué qui pourrait ou ne pourrait pas faire quelque chose d'utile, que de demander au code de déterminer si l'appel est nécessaire et de l'ignorer sinon.
supercat
15

N'est-ce pas juste un polymorphisme?

D'après mon expérience avec Qt tr() et les wtr()méthodes sont censées être utilisées (là, en Qt ) dans la localisation du Widgettexte de.

Ainsi, en retournant le texte inchangé cette méthode dit simplement: Widget does no localization (translation of the text) by default. Override this function to enable your own logic.

GreenScape
la source
1
ne réalisait pas que c'était une chose QT - c'est évidemment la réponse.
Corley Brigman,
8

Un cas très courant pour cela est «la fonctionnalité ajoutée ultérieurement». Le programmeur a donc pensé qu'il pourrait y avoir des changements à cette fonction plus tard. Puisque vous y accédez en tant que fonction et non en tant que paramètre lui-même, vous pouvez facilement le modifier globalement. Disons que vous avez un index avec:

function getIndex(index)
    return index
end

et puisque votre index commence à 0, tout va bien. Vous modifiez plus tard un composant ailleurs, ce composant a besoin de vous pour traduire votre index pour commencer à 1. Vous devrez ajouter des centaines d'index + 1 partout dans votre code. Mais avec une méthode comme celle-ci, dites simplement:

 function getIndex(index)
    return index+1
end

et tu vas bien. Des fonctions comme celle-ci peuvent rapidement conduire à une sur-ingénierie mais à certains moments, elles ont beaucoup de sens!

reggaemuffin
la source
2
Oui, mais il convient de noter que la doctrine de la fonction publiée par le PO ne suggère pas que c'est le but de la fonction dans son cas.
Mark Amery
6

Les fonctions de remplacement comme celle-ci sont courantes dans les situations d'héritage de type. La classe de base peut ne rien faire d'utile, mais les classes dérivées peuvent faire diverses choses avec les entrées. La déclaration de la fonction stub dans la classe de base permet à toutes les classes dérivées d' avoir une fonction de ce nom, et aux classes dérivées individuelles de la remplacer par quelque chose de plus élaboré et utile.

jackr
la source
5

Un scénario supplémentaire est similaire à l'utilisation en python et C # des propriétés, mais dans les langages qui n'ont pas cette fonctionnalité.

En général, vous pouvez déclarer quelque chose comme un simple membre de la classe; disons, «nom» comme une chaîne. Cela signifie que vous y accédez comme ceci:

someobject.name

Plus tard, vous décidez que le nom doit vraiment dépendre de ce qui se trouve dans l'objet. Donc ça devrait vraiment être une fonction. Oups! Même sans argument, cela signifie que tout le code qui y accède doit maintenant être changé en

someobject.name()

Mais si vous avez beaucoup d'exemples de cet appel, les chances que rien ne se passe mal avec cela sont assez faibles - quelque part ce changement ne sera pas effectué, le programme se bloquera lorsque vous arriverez à ce point, etc.

Les propriétés en C # / Python vous permettent de substituer une fonction à ce qui était auparavant un attribut, tout en permettant d'y accéder comme un attribut, c'est-à-dire sans changement. Vous n'avez même pas besoin d'avoir planifié à l'avance.

Si votre langue n'a pas cela, vous devez planifier à l'avance, mais vous pouvez toujours le soutenir comme les gens le faisaient auparavant en en faisant une fonction depuis le début qui ne fait rien. Au début, cela ne fera rien d'intéressant, et semble devoir être supprimé, et de nombreuses fonctions de ce type ne sont jamais modifiées. Mais plus tard, si vous réalisez que chaque fois que vous appelez, Widget.wtrvous devez supprimer certains caractères spéciaux, ce n'est pas grave - c'est déjà une fonction, il vous suffit d'ajouter cela et vous avez terminé.

TL; DR Cela pourrait être un programmeur avisé qui planifie à l'avance les changements futurs.

Corley Brigman
la source
3
Cela aurait du sens si cette méthode dépendait d'autre chose, mais ce n'est pas le cas. Ce n'est pas une propriété, un getter / setter ou un champ. C'est une méthode qui ne fait actuellement rien. La seule façon dont il prévoit de futurs changements est que la logique de cette méthode doive changer.
Matthew Steeples
1
Cela ne doit pas ... cela signifie qu'en ce moment, je ne traite pas ces données, mais plus tard, si je veux les traiter, chaque utilisateur de ces données obtient les données traitées gratuitement. Exemple stupide: disons que vous imprimez des chaînes à l'écran, et vous le faites habituellement print data. Plus tard, vous réalisez que toutes les chaînes doivent être en majuscules - vous devez aller chercher chaque impression dans votre programme et passer à print data.upper(). Mais si vous l'avez def cdata(data): return dataet partout le dit print cdata(data), alors vous passez simplement à def cdata(data): return data.upper()et c'est le seul changement.
Corley Brigman,
Je vois ce que tu veux dire là. Cela a plus de sens
Matthew Steeples
2

Ce n'est pas inutile, en fait il peut être extrêmement utile, car il rend votre code plus uniforme et flexible.

Supposons, par exemple, que vous ayez une liste de personnes et une liste déroulante pour que l'utilisateur puisse sélectionner si nous voulons voir "tous" ou seulement ceux qui sont "masculins" ou "féminins".

Vous pouvez soit gérer "tous" comme un cas spécial, auquel cas vous aurez besoin d'un supplément si et pour vérifier explicitement ce cas, soit vous pouvez avoir une fonction de filtre qui retourne simplement son paramètre (par exemple, permet à tout de passer), assigné pour être utilisé pour le cas "tous".

Hejazzman
la source
4
Cela ne correspond pas au scénario. Je voulais dire une fonction qui renvoie ses paramètres et, en aucun cas, ne fait rien d'autre.
Sempie
@Sempie: C'est ce qu'il dit. Si vous avez une Filterclasse ou une interface avec MaleFilteret des FemaleFiltersous - classes, et que votre code nécessite un filtre, un filtre qui ne fait rien (renvoie son paramètre inchangé) est la façon dont vous gérez All. La fonction ne fait jamais rien, mais peut être remplacée par celle qui le fait.
Magus
@Magus, mais dans votre scénario, la fonction est une sorte d'espace réservé qui sera soit remplacée plus tard, soit qui existe simplement parce que l'ancienne fonction est devenue obsolète mais le programme a besoin de ce passthrough. De toute façon, ce n'est pas un transfert. La fonction ne donne pas le paramètre inchangé à une autre fonction, comme le ferait un filtre, mais le renvoie à la fonction appelante.
Sempie
@Sempie Non, ce n'est ni un placeholer ni son utilisation comme un passthrough temporaire. C'est une notion de codage (et mathématique) utile, la fonction "identité". Et, oui, c'est toujours un transfert, qu'il le renvoie à "une autre fonction" ou à la fonction appelante. La clé est que la fonction "identité" peut être l'une des nombreuses fonctions possibles appelées par la fonction appelante, et est utilisée pour éviter if et casse spéciale lorsque la fonction appelée n'a rien à faire.
Hejazzman