Функція повертає лише незмінний параметр, марний?


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 Як на Землі це дублікат?
Кіліан Фот

13
Так? Ця функція повертає свій параметр - ланцюжок включає повернення this.
Кіліан Фот

11
@gnat Питання в тому, чому хтось коли-небудь писав би функцію, яка нічого не робить, крім повернення себе. Так, ви можете повернути певні об'єкти чи значення, щоб дозволити ланцюжок методів, але це не його питання. Його питання полягає в тому, чому хтось коли-небудь напише щось подібне int getParam(int param) { //DO NOTHING return param; } З точки зору ланцюга методів - це абсолютно зайвий і непотрібний виклик, оскільки ви можете залишити функцію ОП поза ланцюгом методів, і це не призведе до жодної різниці.
ZeroStatic

4
Це, ймовірно, офтопік і не застосовується до lua, але для цього в PHP є дійсний приклад використання - у старих версіях new Foo()->method();синтаксис був неприйнятним, і такі конструкції, як, наприклад function with($what) { return $what; }; with(new Foo())->method();, використовувались як вирішення.
DCoder

Відповіді:


57

Ваше запитання на зразок запитання, що є корисним від нуля, якщо кожен раз, коли ви додаєте його до чогось, ви отримуєте те саме значення. Функція ідентичності - це як нуль для функцій. Вигляд марний сам по собі, але час від часу корисний як частина виразу, використовуючи функції вищого порядку, де ви можете взяти функцію як параметр або повернути її в результаті. Ось чому більшість функціональних мов програмування мають idабо identityмають стандартну бібліотеку.

По-іншому, це робить зручною функцією за замовчуванням. Як і ви, можливо, хочете встановити offset = 0ціле число за замовчуванням, хоча це робить зсув нічого не робити, це може стати в нагоді мати можливість встановити filterFunction = identityяк функцію за замовчуванням, навіть якщо це змушує фільтр нічого не робити.


Чи не повинна функція фільтра повертати булеве значення? У цьому випадку функція фільтра "нуль" була б тією, яка повертає істину.
Кирило Рахман

1
@cypressious Функція карти, значить.
сапі

6
Або дотримуватися його під дизайнерською концепцією: Null object pattern , function edition
blgt

@cypressious, це було б для предиката, який передається як аргумент у функцію filterвищого порядку. Функція першого порядку filterмає тип [a] -> [a],
Карл Білефельдт,

Наприклад, у C #, яку я часто використовую.OrderBy(x => x)
CodesInChaos,

27

Звичайно. Уявіть зовнішній API, який дозволяє отримати речі звідти, де вам абсолютно потрібні, але вам потрібно вказати критерії фільтру та формати виведення для кожного запиту, навіть якщо ви хочете, щоб усі результати та хотіли отримати їх точно так само, як збережені.

Тоді вам доведеться вигадати тривіальну функцію "прийняти все" і тривіальну функцію "повернення незмінною", щоб отримати дані. wtrсаме такий тривіальний псевдоформатор. Якщо ви багато використовуєте цей API, це може бути дуже корисно, щоб ця псевдопомічна функція лежала, а не створювала анонімну функцію кожного разу, коли ви щось запитуєте. (Ви можете identityскоріше зателефонувати , ніж зателефонувати , wtrщоб зрозуміти, що це нічого не робить.)


Я ще не дуже зрозумів сенс, але саме такий сценарій. Я можу зрозуміти через деякий час, працюючи над цим проектом, маючи на увазі вашу відповідь. atm, мені здається, марно, ... якщо я отримав rawdata, чому б я хотів, щоб функція знову давала мені rawdata, ...
Sempie

3
@Sempie Знову ж таки, якщо API вимагає функції форматування, єдиний спосіб отримати незмінний текст - це якщо функція нічого не робить для тексту.
Doval

3
Іншими словами: Якщо у вас є функція, яка вимагає передачі аргументів фільтра / формату, і ви абсолютно не можете використовувати її nullяк аргумент, ви використовуєте порожню функцію фільтра, яка фільтрує "нічого", щоб програма перестала скаржитися.
ZeroStatic

3
@Sempie Ви працювали з SQL, правда? Ви знаєте, як ви можете включити або не включити WHEREпункт? Це сильно питання синтаксичного цукру. По суті відсутність цього WHEREпункту точно така ж, як якщо б у вас була WHEREпропозиція, яка просто йде вперед і дозволяє все. Той факт, що дизайнери SQL дозволяють вам не вказувати WHEREпункт, замість того, щоб змусити вас відкласти його, навіть коли він приймає все, є більш-менш синтаксичним цукром, і вони просто надали вам цей варіант для простої зручності. ..
Panzercrisis

5
Можливо, варто відзначити, що в багатьох випадках швидше і чіткіше беззастережно викликати код віртуальним методом або делегувати, що може чи не може зробити щось корисне, ніж код визначити, чи потрібен дзвінок, і пропустити його, якщо ні.
supercat

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 - це, очевидно, відповідь.
Корлі Бригман

8

Дуже поширеним випадком цього є "пізніше додана функціональність". Тож програміст подумав, що пізніше можна змінити цю функцію. Оскільки ви отримуєте доступ до нього як до функції, а не як до самого параметра, ви можете легко змінити це в глобальному масштабі. Скажімо, у вас є індекс із:

function getIndex(index)
    return index
end

а оскільки ваш індекс починається з 0, це все добре. Пізніше ви зміните компонент десь в іншому місці, цей компонент потребує перекладу вашого індексу, починаючи з 1. Вам доведеться додавати сотні індексу + 1 скрізь у свій код. Але з таким методом просто скажіть:

 function getIndex(index)
    return index+1
end

і ти добре. Такі функції можуть швидко призвести до надмірної інженерії, але в деяких моментах вони мають багато сенсу!


2
Так, хоча варто відзначити , що doctstring функції , розміщений OP зовсім НЕ передбачає , що це призначення функції в його випадку.
Марк Амері

6

Такі функції заглушок часто зустрічаються в ситуаціях успадкування типів. Базовий клас не може робити нічого корисного, але похідні класи можуть робити різні речі із вхідними даними. Оголошення функції заглушки в базовому класі дозволяє всім похідним класам мати функцію цього імені, а окремі похідні класи переосмислювати її на щось більш детальне та корисне.


5

Один додатковий сценарій схожий на використання в властивостях python та C #, але в мовах, які не мають цієї функції.

Взагалі, ви можете декларувати щось як просто члена класу; скажімо, "ім'я" як рядок. Це означає, що ви отримуєте доступ до нього так:

someobject.name

Пізніше ви вирішите, що ім’я дійсно має залежати від того, що знаходиться в об’єкті. Так це дійсно має бути функцією. На жаль! Навіть не маючи аргументів, це означає, що весь код, який має доступ до нього, зараз має бути змінений

someobject.name()

Але якщо у вас є багато випадків цього дзвінка, шанси нічого не піти з цим доволі низькі - десь ця зміна не буде здійснена, програма вийде з ладу, коли ви дістанетесь до цього пункту тощо.

Властивості в C # / Python дозволяють замінити функцію на те, що раніше було атрибутом, при цьому все ще дозволяють їй отримати доступ як атрибут, тобто без змін. Вам навіть не потрібно планувати заздалегідь.

Якщо у вашій мові цього немає, потрібно планувати заздалегідь, але ви все одно можете підтримувати її так, як це робили люди раніше, зробивши її з початку функцією, яка нічого не робить. На початку це не зробить нічого цікавого, і схоже, що його слід видалити, і багато функцій цього типу ніколи не змінюються. Але пізніше, якщо ви усвідомлюєте, що справді кожного разу, коли вам дзвонить Widget.wtr, потрібно зняти спеціальних символів, це вже не так вже й важливо - це вже функція, ви просто додаєте це і все готово.

TL; DR Це може бути просто мудрим програмістом, який планує майбутнє зміни.


3
Це мало б сенс, якби цей метод залежав від чогось іншого, але це не так. Це не власність, геттер / сетер чи поле. Це метод, який наразі нічого не робить. Єдиний спосіб, коли він планує майбутні зміни, це якщо логіка цього методу повинна змінитися.
Метью Стіплз

1
Це не повинно ... це означає, що зараз я не оброблю ці дані, але пізніше, якщо я хочу їх обробити, кожен користувач цих даних отримує оброблені дані безкоштовно. Дурний приклад. Скажімо, ви друкуєте рядки на екрані, і зазвичай це робите print data. Потім пізніше ви зрозумієте, що всі рядки повинні бути великими літерами - вам доведеться шукати кожен друк у вашій програмі та змінювати на print data.upper(). Але якщо у вас є def cdata(data): return dataі скрізь говорить print cdata(data), то ви просто переходите на def cdata(data): return data.upper()це, і це єдина зміна.
Корлі Бригман

Я бачу, що ти там маєш на увазі. Це має більше сенсу
Меттью Стіплз

2

Це не марно, насправді він може бути надзвичайно корисним, оскільки робить ваш код більш рівномірним та гнучким.

Скажімо, наприклад, що у вас є список людей і спадне меню, щоб користувач міг вибрати, чи ми хочемо бачити "всіх" або лише тих, хто "чоловічий" або "жіночий".

Ви можете обробляти "всі" як окремий випадок, і в цьому випадку вам знадобиться додатковий, якщо і явно перевірити цей випадок, або ви можете мати функцію фільтра, яка просто повертає його параметр (наприклад, дозволяє все пройти), призначений для використання у справі "всі".


4
Це не відповідає сценарію. Я мав на увазі функцію, яка повертає його параметри і ні в якому разі не робити нічого іншого.
Sempie

@Sempie: Ось що він говорить. Якщо у вас є Filterклас або інтерфейс з MaleFilterі FemaleFilterпідкласи, і ваш код вимагає фільтр, фільтр , який не робить нічого (повертає параметр без змін), як ви справляєтеся All. Функція ніколи нічого не робить, але може бути замінена на ту, яка робить.
Магз

@Magus, але у вашому сценарії функція - це якийсь заповнювач, який або буде замінено пізніше, або просто існує, тому що стара функція застаріла, але програмі потрібно це проходження. У всякому разі, це не передача. Функція не дає незмінному параметру іншій функції, як це міг би зробити фільтр, але повертає його до викличної функції.
Семпі

@Sempie Ні, це ні заповнювач, не це використання як тимчасовий прохід. Це корисне кодування (і математичне) поняття, функція "ідентичність". І так, це все-таки хендовер, повертає його до "іншої функції" або до викликуючої функції. Ключовим є те, що функція "ідентичність" може бути однією з багатьох можливих функцій, викликаних функцією виклику, і використовується щоб уникнути, якщо і спеціальний кожух, коли викликаній функції нічого не потрібно робити.
Hejazzman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.