La funzione restituisce solo un parametro invariato, inutile?


15

Ho appena trovato questa funzione nel progetto a cui sto lavorando:

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

Troppo triste, il programmatore non funziona più in azienda. Perché uno dovrebbe fare una funzione che non fa nulla, ma restituisce il parametro con cui viene chiamato?

C'è qualche utilità per tale funzione, non specificata in questo esempio, ma in generale in ogni caso?

A causa di

function aFunction(parameter)
    return parameter
end

Termina tra

aFunction(parameter) == parameter

Perché dovrei scrivere qualcosa del genere

aFunction(parameter) == whatIWantToCheck

invece di

parameter == whatIWantToCheck

?


possibile duplicato dello stile
gnat,

13
@gnat Come diavolo è un duplicato?
Kilian Foth,

13
Eh? Questa funzione restituisce il suo parametro - il concatenamento comporta il ritorno this.
Kilian Foth,

11
@gnat La domanda è perché qualcuno dovrebbe mai scrivere una funzione che non fa altro che restituire se stessa. Sì, puoi restituire determinati oggetti o valori per consentire il concatenamento del metodo, ma non è questa la sua domanda. La sua domanda è: perché qualcuno dovrebbe mai scrivere qualcosa del genere. int getParam(int param) { //DO NOTHING return param; } Dal punto di vista del concatenamento di metodi è una chiamata completamente ridondante e superflua in quanto è possibile lasciare la funzione del PO fuori da una catena di metodi e non farebbe alcuna differenza.
ZeroStatic,

4
Questo è probabilmente offtopico e non si applica a lua, ma esiste un caso d'uso valido per questo in PHP - nelle versioni precedenti, new Foo()->method();non era una sintassi valida e costrutti come quelli function with($what) { return $what; }; with(new Foo())->method();erano usati come soluzione alternativa.
DCoder

Risposte:


57

La tua domanda è un po 'come chiedere qual è il valore del numero zero se ogni volta che lo aggiungi a qualcosa ottieni lo stesso valore. Una funzione di identità è come lo zero per le funzioni. Un po 'inutile da solo, ma occasionalmente utile come parte di un'espressione usando funzioni di ordine superiore, in cui è possibile prendere una funzione come parametro o restituirla come risultato. Ecco perché la maggior parte dei linguaggi di programmazione funzionale ha una ido identitynella loro libreria standard.

Detto in altro modo, rende una comoda funzione predefinita. Proprio come potresti voler impostare offset = 0come numero intero predefinito, anche se ciò fa sì che un offset non faccia nulla, potrebbe essere utile essere in grado di impostare filterFunction = identitycome funzione predefinita, anche se il filtro non fa nulla.


Una funzione filtro non dovrebbe restituire un valore booleano? In questo caso la funzione filtro "zero" sarebbe quella che restituisce vero.
Kirill Rakhman,

1
@cypressious Una funzione cartografica, quindi.
sapi,

6
O per attenersi a un concetto di design: modello di oggetti nulli , edizione funzioni
blgt

@cypressious, sarebbe per un predicato che viene passato come argomento in una filterfunzione di ordine superiore. Una funzione del primo ordine filterha il tipo [a] -> [a],
Karl Bielefeldt,

Ad esempio in C # uso spesso.OrderBy(x => x)
CodesInChaos

27

Sicuro. Immagina un'API esterna che ti consenta di recuperare cose da qualche parte di cui hai assolutamente bisogno, ma devi specificare i criteri di filtro e i formatter di output per ogni query, anche se vuoi tutti i risultati e vuoi ottenerli esattamente come memorizzati.

Quindi dovresti inventare una banale funzione "accetta tutto" e una banale funzione "restituisci invariato" per ottenere i dati. wtrè proprio uno pseudo-formatter così banale. Se usi molto quell'API, può essere molto utile avere questa funzione pseudo-helper in giro piuttosto che dover creare una funzione anonima ogni volta che esegui una query su qualcosa. (Potresti considerare di chiamarlo identitypiuttosto che in wtrmodo che sia immediatamente chiaro che non fa nulla.)


Non ho ancora capito bene il senso, ma questo è esattamente lo scenario. Potrei capire dopo un po ', lavorando a questo progetto, tenendo a mente la tua risposta, credo. atm mi sembra inutile, ... se avessi i dati grezzi, perché dovrei desiderare una funzione per darmi di nuovo i dati grezzi, ...
Sempie,

3
@Sempie Ancora una volta, se l'API richiede una funzione di formattazione, l'unico modo per ottenere il testo inalterato è se la funzione non fa nulla per il testo.
Doval,

3
In altre parole: se si dispone di una funzione che richiede il passaggio di argomenti filtro / formato e non è assolutamente possibile utilizzare nullcome argomento, si utilizza una funzione filtro vuota che filtra con "nulla" per impedire al programma di smettere di lamentarsi.
ZeroStatic,

3
@Sempie Hai lavorato con SQL, giusto? Sai come puoi includere o meno una WHEREclausola? È vagamente una questione di zucchero sintattico. Essenzialmente l'assenza di una WHEREclausola è esattamente la stessa di una WHEREclausola che va avanti e consente tutto. Il fatto che i progettisti di SQL non ti permettano di specificare una WHEREclausola, invece di forzarne una, anche quando accetta tutto, è più o meno lo zucchero sintattico e ti hanno appena fornito questa opzione per comodità. ..
Panzercrisis,

5
Potrebbe valere la pena notare che in molti casi è più veloce e più pulito avere un codice che chiama incondizionatamente un metodo virtuale o un delegato che potrebbe o meno fare qualcosa di utile, piuttosto che avere un codice per determinare se la chiamata è necessaria e saltarla in caso contrario.
Supercat,

15

Non è solo un polimorfismo?

Dalla mia esperienza con Qt tr() e wtr()metodi dovrebbero essere usati (lì, in Qt ) nella localizzazione del Widgettesto.

Così, con il ritorno di testo invariato questo metodo dice solo: Widget does no localization (translation of the text) by default. Override this function to enable your own logic.


1
non avevo capito che questa era una cosa QT - questa è ovviamente la risposta.
Corley Brigman,

8

Un caso molto comune per questo è la "funzionalità aggiunta successivamente". Quindi il programmatore ha pensato che potrebbero esserci delle modifiche a quella funzione in seguito. Poiché si accede ad esso come una funzione e non come il parametro stesso, è possibile modificarlo facilmente a livello globale. Diciamo che hai un indice con:

function getIndex(index)
    return index
end

e poiché il tuo indice inizia da 0, va tutto bene. Successivamente cambi un componente da qualche altra parte, questo componente ha bisogno che tu traduca il tuo indice per iniziare da 1. Dovresti aggiungere centinaia di indici + 1 ovunque nel tuo codice. Ma con un metodo come questo, basta dire:

 function getIndex(index)
    return index+1
end

e tu stai bene. Funzioni come questa possono portare rapidamente a un eccesso di ingegneria, ma ad alcuni punti hanno molto senso!


2
Sì, anche se vale la pena notare che la dottstring della funzione pubblicata dall'OP non suggerisce che questo sia lo scopo della funzione nel suo caso.
Mark Amery,

6

Le funzioni di stub come questa sono comuni nelle situazioni di ereditarietà del tipo. La classe base potrebbe non fare nulla di utile, ma le classi derivate potrebbero fare varie cose con gli input. La dichiarazione della funzione stub nella classe base consente a tutte le classi derivate di avere una funzione con quel nome e le singole classi derivate possono sovrascriverla con qualcosa di più elaborato e utile.


5

Uno scenario aggiuntivo è simile all'uso in Python e C # delle proprietà, ma in linguaggi che non dispongono della funzione.

In generale, puoi dichiarare qualcosa come solo un membro della classe; diciamo "nome" come stringa. Ciò significa che si accede in questo modo:

someobject.name

Successivamente, decidi che il nome deve davvero dipendere da cosa c'è nell'oggetto. Quindi dovrebbe davvero essere una funzione. Oops! Anche senza argomenti, ciò significa che tutto il codice che vi accede ora deve essere modificato

someobject.name()

Ma se hai molte istanze di questa chiamata, le possibilità che nulla vada storto sono abbastanza basse: da qualche parte questa modifica non verrà effettuata, il programma andrà in crash quando arriverai a quel punto, ecc.

Le proprietà in C # / Python ti consentono di sostituire una funzione in quello che era un attributo, pur consentendo l'accesso a esso come un attributo, cioè senza alcuna modifica. Non devi nemmeno aver pianificato in anticipo.

Se la tua lingua non lo possiede, devi pianificare in anticipo, ma puoi comunque sostenerlo come facevano prima le persone rendendolo una funzione dall'inizio che non fa nulla. All'inizio, non farà nulla di interessante e sembra che debba essere rimosso e molte funzioni di questo tipo non vengono mai modificate. Ma più tardi, se ti rendi conto che davvero ogni volta che chiami Widget.wtrdevi rimuovere alcuni personaggi speciali, non è un grosso problema - è già una funzione, lo aggiungi e il gioco è fatto.

TL; DR Questo potrebbe essere solo un programmatore saggio che pianifica in anticipo per i cambiamenti futuri.


3
Ciò avrebbe senso se questo metodo dipendesse da qualcos'altro, ma non lo è. Non è una proprietà, getter / setter o un campo. È un metodo che al momento non fa nulla. L'unico modo in cui sta pianificando cambiamenti futuri è se la logica di questo metodo dovrà cambiare.
Matthew Steeples,

1
Non deve ... significa che in questo momento non elaboro questi dati, ma in seguito, se voglio elaborarli, ogni utente di quei dati ottiene i dati elaborati gratuitamente. Esempio stupido: diciamo che stampi stringhe sullo schermo e di solito lo fai print data. Successivamente, ti rendi conto che tutte le stringhe devono essere in maiuscolo - dovresti andare a trovare ogni stampa nel tuo programma e passare a print data.upper(). Ma se hai def cdata(data): return datae lo dice ovunque print cdata(data), allora cambi solo def cdata(data): return data.upper()ed è l'unico cambiamento.
Corley Brigman

Capisco cosa intendi lì. Questo ha più senso
Matthew Steeples,

2

Non è inutile, in realtà può essere estremamente utile, perché rende il codice più uniforme e flessibile.

Supponiamo, ad esempio, che tu abbia un elenco di persone e un menu a discesa che l'utente possa selezionare se vogliamo vedere "tutto" o solo quelli che sono "maschi" o "femminili".

Puoi gestire "tutto" come un caso speciale, nel qual caso avrai bisogno di un extra se e per verificare esplicitamente questo caso, oppure puoi avere una funzione di filtro che restituisce semplicemente il suo parametro (ad esempio, consente a tutto di passare), assegnato per essere utilizzato per il caso "tutto".


4
Questo non si adatta allo scenario. Intendevo una funzione che restituisce i suoi parametri e, in nessun caso, non fa nient'altro.
Sempie,

@Sempie: è quello che sta dicendo. Se hai una Filterclasse o un'interfaccia con MaleFiltere FemaleFiltersottoclassi e il tuo codice richiede un filtro, un filtro che non fa nulla (restituisce il suo parametro invariato) è come lo gestisci All. La funzione non fa mai nulla, ma può essere sostituita con una che lo fa.
Magus,

@Magus, ma nel tuo scenario la funzione è una sorta di segnaposto che verrà sostituita in seguito o esiste solo perché la vecchia funzione è diventata obsoleta ma il programma ha bisogno di questo passthrough. Comunque, non è un passaggio di consegne. La funzione non fornisce il parametro invariato a un'altra funzione, come potrebbe fare un filtro, ma lo restituisce alla funzione chiamante.
Sempie,

@Sempie No, non è né un segnaposto né un passthrough temporaneo. È una nozione di codifica (e matematica) utile, la funzione "identità". E, sì, è ancora un passaggio di consegne, sia che lo restituisca a "un'altra funzione" o alla funzione chiamante. La chiave è che la funzione "identità" può essere una delle molte funzioni possibili chiamate dalla funzione chiamante e viene utilizzata per evitare if e casi speciali quando la funzione chiamata non deve fare nulla.
Hejazzman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.