В java.util.function
пакете Java 8 мы имеем:
- Функция : принимает один аргумент, выдает один результат.
- Потребитель : принимает один аргумент, ничего не производит.
- Поставщик : не принимает аргументов, дает один результат.
- ... : другие случаи обработки примитивов, двух аргументов и т. Д.
Но мне нужно разобраться с делом «не принимает аргументов, ничего не производит ».
Там нет ничего для этого в java.util.functionnal
.
Итак, вопрос в следующем:
Как называется « функция, которая не принимает аргументов и ничего не возвращает »?
В Java 8 его определение будет следующим:
@FunctionalInterface
public interface InsertANameHere {
void execute();
}
Исполнитель уже существует и имеет другое назначение: « Объект, выполняющий отправленные выполняемые задачи ». Подпись не соответствует ( execute(Runnable):void
) и даже не является функциональным интерфейсом .
Runnable существует, но он тесно связан с контекстом потоков:
- Пакет есть
java.lang
, нетjava.util.function
. - Javadoc заявляет: « Интерфейс Runnable должен быть реализован любым классом, экземпляры которого предназначены для выполнения потоком ».
- Название «Runnable» указывает на некоторый работающий код внутри потока.
java
functional-programming
java8
SuperBob
источник
источник
Runnable
является устаревшим в этой точке, потому что Runnable также используется другими классами, чемThread
(Executor
например).Runnable
s может быть.run()
толькоThread
s. На самом деле они очень часто используются именно для цели, описанной в вопросеjava.util.function
упаковке.Ответы:
Выбор Java сделать это таким образом с отдельным именем для каждой арности был глупым. Это не стоит подражать. Тем не менее, если вам нужно для согласованности или если вы пишете очень общий библиотечный код, предложения Конрада хороши. Я мог бы бросить
Procedure
в ринг.Использование псевдо-функциональной парадигмы не означает, что нормальные принципы именования должны выходить за рамки. Интерфейсы почти всегда должны называться в соответствии с тем, что они делают , а не с какой-то общей синтаксической идеей. Если функции помещены в стек отмены, они должны быть названы
UndoFunction
. Если они вызываются из событий GUI, они должны быть названыGUIEventHandler
. Друзья не позволяют друзьям увековечивать плохие соглашения об именах.источник
Procedure
тоже хорошо. Для контекста я разрабатываю универсальную библиотеку, которая должна обрабатывать такого рода «структуру».Procedure
мои паскальные дни. АProcedure
имеет побочные эффекты, аFunction
нет. Поскольку вы не возвращаете значение, единственное, что он может сделать, - это побочный эффект.ProcedureRIR<T1,T2>
дляvoid proc(T1, int, T2)
, а также для других типов - вероятно, создавая большинство из них по требованию, а не пытаться втиснуть в каждую возможную комбинацию типов.If the functions are placed into an undo stack, they should be named UndoFunction.
Существует разница между именованием функции и присвоением ей другого типа. В функциональном стиле вы бы не создатьUndoFuncton
тип , потому что теперь вы не можете передать егоflip
,curry
,compose
,filter
,map
и т.д. На мой взгляд , что является истинной причиной решения Java, чтобы дать функции с различными арностей разные имена глупа. Конечно, если вы собираетесь использовать побочные эффекты, называйте это как угодно; Вы уже выбросили композицию из окна, и вы, вероятно, тоже не используете функции.В мире Java это называется
Runnable
. В мире C # это называетсяAction
.Но есть лучшее имя, которое хорошо вписывается в более широкий взгляд на вещи.
Более широкий взгляд на вещи наступит позже, когда вы решите, что помимо вашего функционального интерфейса void без параметров вам также необходимо иметь аналогичные функциональные интерфейсы, которые принимают один, два или более аргументов или которые возвращают значение. Когда это произойдет, вы захотите, чтобы имена всех этих сущностей были изоморфными и соответствовали друг другу.
Итак, в Java у меня есть собственный набор функциональных интерфейсов, который я называю
Procedure
s, который определяется следующим образом:... (вы получите картину.)
И у меня также есть подобный набор интерфейсов, называемых
Function
s, определенных подобным образом, с первым универсальным параметром, являющимся типом возврата:Итак, моя точка зрения в том, что
Procedure
это очень хорошее имя, потому что оно хорошо вписывается в более широкий взгляд на вещи. Если позже вы решите использовать аналогичные функциональные интерфейсы с методами, которые принимают аргументы или возвращают значение, вы столкнетесь с этим.ПРИМЕЧАНИЕ: я в основном согласен с утверждением Карла Билефельдта о том, что «нормальные принципы именования не должны выходить за рамки» и что «интерфейсы почти всегда должны называться в соответствии с тем, что они делают, а не с какой-то общей синтаксической идеей». Но учтите, что даже он учитывает «почти всегда». Иногда нужны (по сути, анонимные) процедуры и функции, и это то, о чем спрашивает ОП, и именно на это я отвечаю.
Поправка 2017-11-10:
Вы можете спросить, почему
Function1<R,T1>
вместоFunction1<T1,R>
? Это может произойти в любом случае, но у меня есть предпочтение для возвращаемых значений слева, потому что я предпочитаю следовать соглашению об именах 'convert-from' (destination-from-source), а не 'convert-to' (source-to) конвенция. (На самом деле это скорее случайность, чем соглашение, в том смысле, что, скорее всего, никто никогда не задумывался об этом, потому что, если бы они вообще об этом думали, они бы пришли к соглашению «новообращенных»). )Я читал об этом в статье Джоэла Сполкси - «Как неправильный код выглядит неправильно» , это очень длинная статья, которую я рекомендую прочитать полностью, но если вы хотите перейти непосредственно к конкретному случаю, найдите «TypeFromType», но чтобы дать вам TL; DR, идея в том, что
myint = intFromStr( mystr )
это намного лучше, чемmyint = strToInt( mystr )
, потому что в первом случае имена типов близки к связанным значениям, так что вы можете легко увидеть, что 'int' совпадает с 'int' и «str» совпадает с «str».Поэтому, как правило, я упорядочиваю вещи так, как они будут выглядеть в коде.
источник
Function1<T1, R>
?Почему нет
Command
? Учитывая, что он не принимает никаких данных и не возвращает никаких данных, но при условии, что его вызов вызывает некоторый эффект (в противном случае это было бы довольно бессмысленно), я представляю, что это примерно единственное, что он может сделать - запустить действие, заставить что-то произойти.Кстати,
Action
в .NET также есть общий делегат. В отличие от Java,Consumer
он может принимать от 0 до 16 аргументов; другими словами, самая простая версия этого не берет - см. MSDN .И поскольку имя не подразумевает, что есть что-то, что можно «потреблять», оно также кажется хорошим выбором имени.
источник
Command
это хорошо. Его можно спутать с шаблоном Command, но это может быть решением.Action
больше, чемCommand
. Команда звучит больше как что-то, что принимается и оценивается, в то время как действие выполняется для ее побочных эффектов.execute()
метод. 0_o '