Функция возвращает только неизмененный параметр, бесполезно?

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

?

Sempie
источник
13
@gnat Как же это дубликат?
Килиан Фот
13
А? Эта функция возвращает свой параметр - цепочка предполагает возврат this.
Килиан Фот
11
@gnat Вопрос в том, почему кто-то может написать функцию, которая ничего не делает, кроме как возвращает себя. Да, вы можете вернуть определенные объекты или значения, чтобы разрешить цепочку методов, но это не его вопрос. Его вопрос состоит в том, почему кто-то когда-либо написал что-то вроде int getParam(int param) { //DO NOTHING return param; } С точки зрения цепочки методов, это совершенно избыточный и ненужный вызов, поскольку вы можете оставить функцию OP вне цепочки методов, и это не будет иметь никакого значения.
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
Или придерживаться концепции дизайна: шаблон нулевого объекта , издание функций
blgt
@cypressious, это было бы для предиката, который передается в качестве аргумента в функцию filterболее высокого порядка. Функция первого порядка filterимеет тип [a] -> [a]:
Карл Билефельдт
Например, в C # я часто использую.OrderBy(x => x)
CodesInChaos
27

Конечно. Представьте себе внешний API, который позволяет вам извлекать вещи из того места, которое вам абсолютно необходимо, но вы должны указать критерии фильтра и выходные форматеры для каждого запроса, даже если вы хотите получить все результаты и получить их в точности как сохраненные.

Тогда вам придется изобрести тривиальную функцию «принять все» и тривиальную функцию «вернуть без изменений», чтобы получить данные. wtrименно такой тривиальный псевдо-форматер. Если вы часто используете этот API, может быть очень полезно иметь эту псевдо-вспомогательную функцию, а не создавать анонимную функцию всякий раз, когда вы что-то запрашиваете. (Вы можете подумать об этом, identityа не о wtrтом, чтобы сразу было ясно, что ничего не происходит.)

Килиан Фот
источник
Я еще не совсем понял смысл, но это именно тот сценарий. Думаю, через некоторое время я пойму, что работаю над этим проектом, помня о вашем ответе. для меня это кажется бесполезным, ... если я получил необработанные данные, зачем мне функция, которая снова дает мне необработанные данные, ...
Семпи
3
@Sempie Опять же, если API требует функции форматирования, единственный способ получить неизмененный текст - это если функция ничего не делает с текстом.
Довал
3
Другими словами: если у вас есть функция, требующая передачи аргументов фильтра / формата, и вы абсолютно не можете использовать ее nullв качестве аргумента, вы используете пустую функцию фильтра, которая фильтрует «ничего», чтобы программа перестала жаловаться.
ZeroStatic
3
@Sempie Вы работали с SQL, верно? Вы знаете, как вы можете включить или не включать WHEREпункт? Это вопрос синтаксического сахара. По сути, отсутствие WHEREпредложения точно такое же, как если бы у вас было WHEREпредложение, которое просто идет вперед и позволяет все. Тот факт, что разработчики SQL позволяют вам не указывать WHEREпредложение, вместо того, чтобы заставлять его опускать его, даже когда он принимает все, является более или менее синтаксическим сахаром, и они просто предоставили вам эту опцию для простого удобства. ..
Panzercrisis
5
Может быть, стоит отметить, что во многих случаях быстрее и чище заставить код безоговорочно вызывать виртуальный метод или делегат, который может или не может сделать что-то полезное, чем чтобы код определял, нужен ли вызов, и пропускает его, если нет.
суперкат
15

Разве это не просто полиморфизм?

Из моего опыта работы с Qt tr() и wtr()методами предполагается использовать (там, в Qt ) локализацию Widgetрусского текста.

Так, возвращая неизменный текст этого метод просто говорит: Widget does no localization (translation of the text) by default. Override this function to enable your own logic.

GreenScape
источник
1
не понимал, что это была вещь QT - это, очевидно, ответ.
Корли Бригман
8

Очень распространенный случай для этого - «позже добавленная функциональность». Поэтому программист подумал, что в этой функции могут быть некоторые изменения позже. Поскольку вы обращаетесь к нему как к функции, а не как к самому параметру, вы можете легко изменить это глобально. Допустим, у вас есть индекс с:

function getIndex(index)
    return index
end

и так как ваш индекс начинается с 0, все в порядке. Позже вы изменяете компонент где-то еще, этот компонент требует, чтобы вы перевели свой индекс, чтобы начать с 1. Вы должны были бы добавить сотни индексов + 1 везде в вашем коде. Но с помощью такого метода просто скажите:

 function getIndex(index)
    return index+1
end

и ты в порядке. Подобные функции могут быстро привести к чрезмерному проектированию, но в некоторых случаях они имеют большой смысл!

reggaemuffin
источник
2
Да, хотя стоит отметить, что строка доктрины функции, опубликованная OP, не предполагает, что это является целью функции в его случае.
Марк Амери
6

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

jackr
источник
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

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

Скажем, например, что у вас есть список людей и выпадающий список, который пользователь может выбрать, хотим ли мы видеть «все» или только те, которые являются «мужчинами» или «женщинами».

Вы можете обрабатывать «все» как особый случай, и в этом случае вам понадобится дополнительный if и для явной проверки этого случая, или у вас может быть функция фильтра, которая просто возвращает свой параметр (например, позволяет всему проходить), назначен для использования в случае «все».

Hejazzman
источник
4
Это не соответствует сценарию. Я имел в виду функцию, которая возвращает его параметры и ни в коем случае не делает ничего другого.
Семпи
@Sempie: это то, что он говорит. Если у вас есть Filterкласс или интерфейс с MaleFilterи FemaleFilterподклассами, и ваш код требует некоторого фильтра, то как вы обрабатываете фильтр, который ничего не делает (возвращает свой параметр без изменений) All. Функция никогда ничего не делает, но может быть заменена той, которая делает.
Волхв
@Magus, но в вашем сценарии эта функция является своего рода заполнителем, который либо будет заменен позже, либо будет существовать только потому, что старая функция устарела, но программе необходимо это выполнить. Во всяком случае, это не передача. Функция не передает неизмененный параметр другой функции, как мог бы сделать фильтр, но возвращает его вызывающей функции.
Семпи
@ Образец Нет, это не плацдарм и не временный проход. Это полезное кодовое (и математическое) понятие, функция «идентичность». И, да, это все еще передача, независимо от того, возвращает ли она «другой функции» или вызывающей функции. Ключ в том, что функция «identity» может быть одной из многих возможных функций, вызываемых вызывающей функцией, и используется чтобы избежать if и special-case, когда вызываемой функции не нужно ничего делать.
Hejazzman