Як називається функція, яка не приймає аргументів і нічого не повертає? [зачинено]


80

У java.util.functionпакеті Java 8 ми маємо:

  • Функція : бере один аргумент, видає один результат.
  • Споживач : Бере один аргумент, нічого не дає.
  • Постачальник : не приймає аргументів, дає один результат.
  • ... : Інші справи, що стосуються примітивів, 2 аргументи тощо ...

Але мені потрібно розібратися зі справою " не бере аргументів, нічого не дає ".

У цьому немає нічого java.util.functionnal.

Отже, питання:

Як називається функція, яка не бере аргументів і нічого не повертає ?

У Java 8 його визначення було б:

@FunctionalInterface
public interface InsertANameHere {
    void execute();
}

Виконавець вже існує і має іншу мету: " Об'єкт, який виконує подані завдання Runnable ". Підпис не відповідає ( execute(Runnable):void) і не є навіть функціональним інтерфейсом .

Виконання існує, але воно сильно пов'язане з контекстом нитки:

  • Пакет є java.lang, ні java.util.function.
  • Javadoc заявляє: " Інтерфейс Runnable повинен бути реалізований будь-яким класом, екземпляри якого призначені для виконання потоком ".
  • Назва "Runnable" підказує деякий запущений код всередині потоку.

28
"Але немає нічого для" Не бере аргументів, нічого не виробляє. "" - Виконується ?
користувач11153

11
Я думаю, що javadoc for Runnableзастарілий на даний момент, тому що Runnable також використовується іншими класами, ніж Thread( Executorнаприклад).
SpaceTrucker

13
@superbob Це не означає, що Runnables може бути .run()лише Threads. Насправді вони дуже часто використовуються саме для цілей, описаних у питанні
blgt

5
@superbob Це було його початковою метою, але, оскільки Java 8, вона була "модернізована" як функціональний інтерфейс. Ось чому ви нічого не знайшли в java.util.function упаковці.
користувач11153

5
Semi-Snark: ImpureFuntion, оскільки він, безумовно, покладається лише на побічні ефекти, інакше це не-оп. ( en.wikipedia.org/wiki/Pure_function#Impure_functions ) Більш серійно: імператив (зробіть щось), який би принаймні відповідав семантиці виконання void ();
Крістіан Н

Відповіді:


71

Вибір Яви зробити це таким чином з окремим ім'ям для кожної сукупності було дурним. Емуляції це не зовсім варто. Однак, якщо вам потрібно заради послідовності або ви пишете дуже загальний код бібліотеки, пропозиції Конрада хороші. Я можу кинути Procedureна ринг.

Використання псевдофункціональної парадигми не означає, що нормальні принципи іменування повинні виходити з вікна. Інтерфейси майже завжди повинні називатися тим, що вони роблять , а не за якоюсь загальною синтаксичною ідеєю. Якщо функції розміщені в стеку скасування, їх слід назвати UndoFunction. Якщо вони викликаються з подій GUI, вони повинні бути названі GUIEventHandler. Друзі не дозволяють друзям увічнювати погані угоди про іменування.


Procedureтеж добре. Для контексту я розробляю загальну бібліотеку, якій потрібно обробляти подібну "структуру".
superbob

18
Мені подобається Procedureз моїх паскальних днів. А Procedureмає побічні ефекти, а Functionні. Оскільки ви не повертаєте значення, єдине, що він може зробити, - це побічний ефект.
Спенсер Ратбун

Я міг би бути схильний використовувати ProcedureRIR<T1,T2>для void proc(T1, int, T2), а також для інших типів - можливе створення більшості з них на вимогу , а не намагатися втиснути в будь-якій можливій комбінації типів.
supercat

1
Дійсно, реальне функціональне програмування взагалі не заохочує угорське іменування стилю. Це скоріше менталітет парадигми oo, ніж функціональний.
slebetman

3
If the functions are placed into an undo stack, they should be named UndoFunction.Існує різниця між тим, що називати функцію і надавати їй інший тип. У функціональному стилі ви б не створити UndoFunctonтип , тому що тепер ви не можете передати його flip, curry, compose, filter, mapі т.д. На мій погляд , що є справжньою причиною рішення Java, щоб дати функції з різними арность різні імена дурна. Звичайно, якщо ви збираєтесь використовувати побічні ефекти, називайте це будь-яким; ви вже викинули композицію у вікно, і, певно, також не використовуєте функції.
Довал

33

У світі java його називають Runnable. У світі C # його називають Action.

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

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

Отже, у Java у мене є власний набір функціональних інтерфейсів, які я називаю Procedures, визначених так:

public interface Procedure
{
    void invoke();
}

public interface Procedure1<T1>
{
    void invoke( T1 argument1 );
}

... (ви отримуєте малюнок.)

І у мене також є аналогічний набір інтерфейсів під назвою Functions, визначений аналогічно, причому перший загальний параметр є типом повернення:

public interface Function<R>
{
    R invoke();
}

public interface Function1<R,T1>
{
    R invoke( T1 argument1 );
}

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

ПРИМІТКА: Я в основному погоджуюся з твердженням Карла Білефельдта про те, що "нормальні принципи іменування повинні [не] виходити з вікна" і "Інтерфейси майже завжди повинні називатися тим, що вони роблять, а не за якоюсь загальною синтаксичною ідеєю". Але зауважте, що навіть він дозволяє це «майже завжди». Іноді виникає потреба у (по суті анонімних) процедурах та функціях, і це те, про що задається ОП, і саме це я відповідаю.

Поправка 2017-11-10:

Ви можете запитати, чому Function1<R,T1>замість цього Function1<T1,R>? Це може піти в будь-який бік, але я маю перевагу повернутих значень зліва, тому що мені подобається дотримуватися конвенції іменування "конвертувати з" (призначення-з-джерела) на відміну від "перетворити в" (джерело-в) -дестинація) конвенція. (Що насправді скоріше випадковість, ніж конвенція, в тому сенсі, що, швидше за все, ніхто ніколи не думав про це, бо якби вони взагалі не задумалися, вони приїхали б до конвенції "перетворення з". )

Про це я читав у Joel Spolksy - Зробити невірний код Помилковим , це дуже довга стаття, яку я рекомендую прочитати в повному обсязі, але якщо ви хочете перейти прямо до справи, знайдіть "TypeFromType", але в дамо вам TL; DR, ідея полягає в тому, що myint = intFromStr( mystr )це набагато краще myint = strToInt( mystr ), тому що в першому випадку назви типів близькі до пов'язаних значень, тому ви можете легко побачити, що 'int' збігається з 'int' і 'str' збігається з 'str'.

Отже, розширення я схильний впорядковувати речі так, як вони збираються відображатися в коді.


1
Це рішення справді добре, воно здається навіть куленебезпечнішим, ніж власний постачальник, споживач, BiFunction, ..., оскільки він містить усе лише до двох концепцій. Це нагадує мені відповідь @Karl Bielefeldt про " вибір Яви зробити це саме так, з окремою назвою для кожної артерії [що] було дурним ". Єдиним "недоліком" є те, що він не обробляє примітивні типи та їх комбінації (такі цікаві речі, як DoubleToLongFunction, ToLongBiFunction, ...). Але примітиви - це ще одна проблема ...
superbob

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

1
Якби я міг прийняти 2 - й відповіді, я б вибрав Yours завдяки процесуального N , функція N пропозиції. Я все-таки відмовився від цього.
superbob

Чому це не так Function1<T1, R>?
ErikE

@ErikE - це дуже гарне запитання, і я змінив свою посаду, щоб відповісти на неї.
Майк Накіс

18

Чому ні Command? Зважаючи на те, що він не бере даних і не повертає даних, але припускаючи, що викликати це викликає певний ефект (інакше це було б досить безглуздо), я думаю, що це єдине, що він може зробити - запустити дію, зробити щось.

Якщо говорити про це, Actionу .NET також є загальний делегат. На відміну від Java, Consumerвона може приймати від 0 до 16 аргументів; Іншими словами, найпростіша його версія не має жодної - див. MSDN .

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


1
Commandце добре. Його можна переплутати з шаблоном Command, але це може бути рішенням.
superbob

7
Я люблю Actionбільше Command. Команда звучить більше як щось, що отримується та оцінюється, тоді як дія виконується за її побічними ефектами.
Бергі

7
Гм ... як це не може бути шаблон команди? Ви створили саме сутність Command! Він навіть має традиційно названий execute()метод. 0_o '
хіджар

1
Не подобається пропозиція дій, оскільки це загальний (і хороший) інтерфейс Swing. Командування розумне.
user949300

@ user949300, але це залежить від контексту - Java - це великий світ, який ти бачиш, я розробник Android (зараз) і у мене немає ідіосинкрасій, пов’язаних з J2EE; з тією, яку використовує ваша рамка.
Конрад Моравський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.