Funktion gibt nur unveränderten Parameter zurück, nutzlos?

15

Ich habe diese Funktion gerade in dem Projekt gefunden, an dem ich arbeite:

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

Zu schade, dass der Programmierer nicht mehr in der Firma arbeitet. Warum sollte man eine Funktion erstellen, die nichts tut, aber den Parameter zurückgibt, mit dem sie aufgerufen wird?

Gibt es eine Verwendung für eine solche Funktion, die in diesem Beispiel nicht angegeben ist, aber insgesamt auf jeden Fall?

Durch

function aFunction(parameter)
    return parameter
end

Endet in

aFunction(parameter) == parameter

Warum sollte ich so etwas schreiben?

aFunction(parameter) == whatIWantToCheck

Anstatt von

parameter == whatIWantToCheck

?

Sempie
quelle
Mögliches Duplikat des Codierungsstils für verkettete Funktionsaufrufe
Mücke
13
@gnat Wie in aller Welt ist das ein Duplikat?
Kilian Foth
13
Huh? Diese Funktion gibt ihre Parameter zurück - bei der Verkettung wird zurückgegeben this.
Kilian Foth
11
@gnat Die Frage ist, warum jemand jemals eine Funktion schreiben würde, die nichts tut als sich selbst zurückzugeben. Ja, Sie können bestimmte Objekte oder Werte zurückgeben, um die Verkettung von Methoden zu ermöglichen, aber das ist nicht seine Frage. Seine Frage ist, warum jemand jemals so etwas schreiben würde. int getParam(int param) { //DO NOTHING return param; } Aus Sicht der Methodenverkettung ist dies ein völlig redundanter und unnötiger Aufruf, da Sie die Funktion des OP aus einer Methodenverkettung herausnehmen können und es keinen einzigen Unterschied machen würde.
ZeroStatic
4
Dies ist wahrscheinlich offtopisch und gilt nicht für lua, aber es gibt einen gültigen Anwendungsfall für PHP - in älteren Versionen new Foo()->method();war die Syntax ungültig und Konstrukte wiefunction with($what) { return $what; }; with(new Foo())->method(); wurden als Workaround verwendet.
DCoder

Antworten:

57

Ihre Frage ist ungefähr so, als würden Sie fragen, was der Wert der Zahl Null ist, wenn Sie bei jeder Addition den gleichen Wert zurückerhalten. Eine Identitätsfunktion ist wie die Null für Funktionen. Eigentlich nutzlos, aber gelegentlich nützlich als Teil eines Ausdrucks mit Funktionen höherer Ordnung, bei dem Sie eine Funktion als Parameter verwenden oder als Ergebnis zurückgeben können. Aus diesem Grund haben die meisten funktionalen Programmiersprachen eine idoder identityin ihrer Standardbibliothek.

Anders ausgedrückt, es ist eine praktische Standardfunktion. So wie Sie vielleicht offset = 0eine Standard-Ganzzahl festlegen möchten , obwohl dadurch ein Offset nichts bewirkt, kann es nützlich sein, filterFunction = identityeine Standardfunktion festzulegen, obwohl der Filter dadurch nichts bewirkt.

Karl Bielefeldt
quelle
Sollte eine Filterfunktion keinen Booleschen Wert zurückgeben? In diesem Fall ist die Filterfunktion "Null" diejenige, die true zurückgibt.
Kirill Rakhman
1
@cypressious Eine Kartenfunktion also.
Sapi
6
Oder um es unter ein Gestaltungskonzept zu kleben: Null-
Objektmuster
@cypressious, das wäre für ein Prädikat, das als Argument an eine filterFunktion höherer Ordnung übergeben wird. Eine filterFunktion erster Ordnung hat den Typ [a] -> [a],
Karl Bielefeldt
Zum Beispiel in C # verwende ich oft.OrderBy(x => x)
CodesInChaos
27

Sicher. Stellen Sie sich eine externe API vor, mit der Sie Dinge von einem Ort abrufen können, den Sie unbedingt benötigen. Sie müssen jedoch Filterkriterien und Ausgabeformatierer für jede Abfrage angeben, auch wenn Sie alle Ergebnisse genau so erhalten möchten, wie sie gespeichert sind.

Dann müssten Sie eine triviale Funktion "Alles akzeptieren" und eine triviale Funktion "Unverändert zurückgeben" erfinden, um an die Daten zu gelangen. wtrist genau so ein trivialer Pseudoformatierer. Wenn Sie diese API häufig verwenden, kann es sehr nützlich sein, diese Pseudohilfsfunktion herumliegen zu lassen, anstatt bei jeder Abfrage eine anonyme Funktion erstellen zu müssen. (Sie könnten es identityeher nennen als, wtrdamit es sofort klar ist, dass es nichts tut.)

Kilian Foth
quelle
Ich habe den Sinn noch nicht wirklich verstanden, aber das ist genau das Szenario. Ich könnte nach einer Weile verstehen, an diesem Projekt zu arbeiten, während ich Ihre Antwort im Hinterkopf habe, denke ich. atm es sieht für mich nutzlos aus, ... wenn ich die Rohdaten bekommen hätte, warum sollte ich eine Funktion haben, die mir die Rohdaten wieder gibt, ...
Sempie
3
@Sempie Wenn für die API eine Formatierungsfunktion erforderlich ist, können Sie den unveränderten Text nur dann abrufen, wenn die Funktion keine Änderungen am Text vornimmt .
Doval
3
Mit anderen Worten: Wenn Sie eine Funktion haben , die erfordert Filter / Format Argumente übergeben werden, und Sie können absolut nicht verwenden nullals Argument verwenden Sie eine leere Filterfunktion , dass die Filter mit ‚nichts‘ , um das Programm aufhören , zu jammern zu machen.
ZeroStatic
3
@Sempie Du hast mit SQL gearbeitet, oder? Sie wissen, wie Sie eine WHEREKlausel entweder einschließen oder nicht einschließen können ? Das ist locker eine Frage des syntaktischen Zuckers. Im Wesentlichen ist das Fehlen einer WHEREKlausel genau so, als ob Sie eine WHEREKlausel hätten, die einfach weitergeht und alles zulässt. Die Tatsache, dass die SQL-Designer Sie keine WHEREKlausel spezifizieren lassen , anstatt Sie zu zwingen, eine niederzuschreiben, selbst wenn sie alles akzeptiert, ist mehr oder weniger syntaktischer Zucker, und sie haben Ihnen diese Option nur zur Vereinfachung bereitgestellt. ..
Panzercrisis
5
Es kann erwähnenswert sein, dass es in vielen Fällen schneller und sauberer ist, wenn der Code bedingungslos eine virtuelle Methode oder einen Delegaten aufruft, der möglicherweise etwas Nützliches tut oder nicht, als wenn der Code feststellt, ob der Aufruf benötigt wird, und ihn überspringt, wenn nicht.
Supercat
15

Ist das nicht nur ein Polymorphismus?

Aus meiner Erfahrung mit Qt tr() und wtr()Methoden soll (dort, in Qt ) bei der Lokalisierung von Widget's Text verwendet werden.

Also, indem unverändert Text Rückkehr diese Methode nur sagt: Widget does no localization (translation of the text) by default. Override this function to enable your own logic.

GreenScape
quelle
1
Ich wusste nicht, dass dies eine QT-Sache ist - das ist offensichtlich die Antwort.
Corley Brigman
8

Ein sehr häufiger Fall hierfür ist "später hinzugefügte Funktionalität". Daher dachte der Programmierer, dass diese Funktion später geändert werden könnte. Da Sie als Funktion und nicht als Parameter darauf zugreifen, können Sie dies leicht global ändern. Nehmen wir an, Sie haben einen Index mit:

function getIndex(index)
    return index
end

und da Ihr Index bei 0 beginnt, ist alles in Ordnung. Wenn Sie später eine Komponente an einer anderen Stelle ändern, müssen Sie für diese Komponente Ihren Index so übersetzen, dass er bei 1 beginnt. Sie müssten überall in Ihrem Code Hunderte von Indizes + 1 hinzufügen. Aber mit einer Methode wie dieser sagen Sie einfach:

 function getIndex(index)
    return index+1
end

und Sie sind in Ordnung. Funktionen wie diese können schnell zu Überentwicklungen führen, machen aber an manchen Stellen sehr viel Sinn!

Reggaemuffin
quelle
2
Ja, obwohl es erwähnenswert ist, dass die Doktrin der Funktion, die vom OP veröffentlicht wird, nicht nahelegt, dass dies in seinem Fall der Zweck der Funktion ist.
Mark Amery
6

Solche Stub-Funktionen sind in Situationen mit Typvererbung üblich. Die Basisklasse macht möglicherweise nichts Nützliches, aber abgeleitete Klassen machen möglicherweise verschiedene Dinge mit den Eingaben. Deklarieren die Stub - Funktion in der Basisklasse ermöglicht alle abgeleiteten Klassen hat eine Funktion dieses Namen, und einzelne abgeleiteten Klassen außer Kraft setzt es mit etwas aufwendigeren und nützlich.

Jackr
quelle
5

Ein weiteres Szenario ähnelt der Verwendung von Eigenschaften in Python und C #, jedoch in Sprachen, die nicht über diese Funktion verfügen.

Im Allgemeinen können Sie etwas nur als Mitglied der Klasse deklarieren. sagen wir mal 'name' als string. Dies bedeutet, dass Sie folgendermaßen darauf zugreifen:

someobject.name

Später entscheiden Sie, dass der Name wirklich von dem abhängen muss, was sich im Objekt befindet. Es sollte also wirklich eine Funktion sein. Hoppla! Sogar ohne Argumente bedeutet dies, dass der gesamte Code, der darauf zugreift, in geändert werden muss

someobject.name()

Aber wenn Sie viele Instanzen dieses Aufrufs haben, ist die Wahrscheinlichkeit, dass nichts schief geht, sehr gering - irgendwo, wo diese Änderung nicht vorgenommen wird, stürzt das Programm ab, wenn Sie an diesem Punkt angelangt sind usw.

Mit den Eigenschaften in C # / Python können Sie eine Funktion durch ein früheres Attribut ersetzen, ohne dass der Zugriff darauf wie bei einem Attribut erfolgt, dh ohne Änderungen. Sie müssen nicht einmal vorausplanen.

Wenn Ihre Sprache das nicht hat, müssen Sie im Voraus planen, aber Sie können es trotzdem so unterstützen, wie es die Leute zuvor getan haben, indem Sie es von Anfang an zu einer Funktion machen, die nichts tut. Am Anfang macht es nichts Interessantes, und es sieht so aus, als ob es entfernt werden sollte, und viele Funktionen dieses Typs werden nie geändert. Aber später, wenn Sie feststellen, dass Widget.wtres keine große Sache ist, einige Sonderzeichen auszublenden, wenn Sie wirklich anrufen - es ist bereits eine Funktion. Fügen Sie das einfach hinzu und Sie sind fertig.

TL; DR Dies könnte ein weiser Programmierer sein, der zukünftige Änderungen plant.

Corley Brigman
quelle
3
Das wäre sinnvoll, wenn diese Methode von etwas anderem abhängen würde, aber nicht. Es ist keine Eigenschaft, kein Getter / Setter oder ein Feld. Es ist eine Methode, die derzeit nichts tut. Nur wenn sich die Logik dieser Methode ändern muss, plant er zukünftige Änderungen.
Matthew Steeples
1
Es muss nicht ... es bedeutet, dass ich diese Daten momentan nicht verarbeite, aber später, wenn ich sie verarbeiten möchte, erhält jeder Benutzer dieser Daten die verarbeiteten Daten kostenlos. Dummes Beispiel: Angenommen, Sie drucken Zeichenfolgen auf den Bildschirm, und das tun Sie normalerweise print data. Später wird Ihnen klar, dass alle Zeichenfolgen in Großbuchstaben geschrieben werden müssen. Sie müssen dann jeden Ausdruck in Ihrem Programm suchen und zu wechseln print data.upper(). Aber wenn Sie haben def cdata(data): return dataund überall sagen print cdata(data), dann wechseln Sie einfach zu def cdata(data): return data.upper()und es ist die einzige Änderung.
Corley Brigman
Ich verstehe, was du dort meinst. Das macht mehr Sinn
Matthew Steeples
2

Es ist nicht nutzlos, es kann sogar äußerst nützlich sein, da es Ihren Code einheitlicher und flexibler macht.

Angenommen, Sie haben eine Liste mit Personen und ein Dropdown-Menü, in dem der Benutzer auswählen kann, ob "alle" oder nur "männliche" oder "weibliche" Personen angezeigt werden sollen.

Sie können entweder "all" als Sonderfall behandeln. In diesem Fall benötigen Sie ein zusätzliches if, um diesen Fall explizit zu prüfen, oder Sie können eine Filterfunktion verwenden, die nur den Parameter zurückgibt (z. B. alles passieren lässt). zugewiesen, um für den "all" -Fall verwendet zu werden.

Hejazzman
quelle
4
Das passt nicht zum Szenario. Ich meinte eine Funktion, die seine Parameter zurückgibt und auf keinen Fall etwas anderes tut.
Sempie
@Sempie: Das sagt er. Wenn Sie eine FilterKlasse oder Schnittstelle mit MaleFilterund FemaleFilterUnterklassen haben und für Ihren Code ein Filter erforderlich ist, verwenden Sie einen Filter, der nichts bewirkt (der seinen Parameter unverändert zurückgibt) All. Die Funktion tut nie etwas, sondern kann durch eine solche ersetzt werden.
Magus
@Magus, aber in Ihrem Szenario ist die Funktion eine Art Platzhalter, der später ersetzt wird oder nur existiert, weil die alte Funktion veraltet ist, aber das Programm dieses Passthrough benötigt. Auf jeden Fall ist es keine Übergabe. Die Funktion gibt den unveränderten Parameter nicht an eine andere Funktion weiter, wie dies ein Filter tun würde, sondern gibt ihn an die aufrufende Funktion zurück.
Sempie
@Sempie Nein, es ist weder ein Platzhalter, noch wird es als temporäres Passthrough verwendet. Es ist ein nützlicher codierender (und mathematischer) Begriff, die "Identitäts" -Funktion. Und ja, es ist immer noch eine Übergabe, ob sie an "eine andere Funktion" oder an die aufrufende Funktion zurückgegeben wird. Der Schlüssel ist, dass die "Identität" eine von vielen möglichen Funktionen sein kann, die von der aufrufenden Funktion aufgerufen und verwendet werden um zu vermeiden, ob und Sonderfälle, wenn die aufgerufene Funktion nichts zu tun hat.
Hejazzman