Чому деякі функціональні мови програмування використовують простір для додатків функції?


34

Переглянувши деякі мови функціонального програмування, я завжди цікавився, чому деякі fp-мови використовують один або кілька символів пробілу для застосування функції (та визначення), тоді як більшість (усіх?) Імперативних / об'єктно-орієнтованих мов використовують круглі дужки, що, здається, бути більш математичним способом. Я також вважаю, що останній стиль набагато чіткіший і зрозуміліший, ніж без паронів.

Отже, якщо у нас є функція f (x) = x² , є дві альтернативи її виклику:

  • FP: f x

    Приклади:

    • ML, Ocaml, F #
    • Хаскелл
    • LISP, схема (якось)
  • Non-FP: f(x)

    Приклади:

    • Майже всі імперативні мови (я знаю, дивіться коментарі / відповіді)
    • Ерланг
    • Scala (також дозволяє "нотація оператора" для одиночних аргументів)

Які причини "виходу" з дужок?


9
Щоб зробити це більш заплутаним, ем, я мав на увазі стислий .
День

11
@ Коли ви дізнаєтесь haskell, синтаксис буде однією з найменш заплутаних речей: p
Simon Bergot

5
Ви усвідомлюєте іронію того, що використання дужок було б більш математичним, а потім використання функції експоненції як приклад?
Йорг W Міттаг

12
@День ви шкодите собі, відкидаючи мову через її синтаксис. Звичайно, у вас не було проблем з навчанням xml або sql (це не загальномовні мови, але вони визначають власний синтаксис).
Саймон Бергот

7
Я хотів би зазначити, що сценарії оболонки (наприклад, bash) зазвичай не використовують параметри для виклику команд. Сорт PowerShell має найгірший з обох світів у тому, що функції оголошуються в дужках і викликаються без них.
Кріс Харпер

Відповіді:


59

що здається більш математичним способом

функціональні мови натхненні обчисленням лямбда . У цьому полі дужки не використовуються для застосування функції.

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

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

Каррі - це також вагомий привід використовувати цю умову. У haskell ви можете визначити наступне:

add :: Int -> Int -> Int
add x y = x + y

x = add 5 6 -- x == 11
f = add 5
y = f 6 -- y == 11
z = ((add 5) 6) -- explicit parentheses; z == 11

З паронами ви можете використовувати дві умовні позначення: f(5, 6)(не криво) або f(5)(6)(каррі). Синтаксис haskell допомагає звикнути до поняття currying. Ви все ще можете скористатися версією, яка не випробовується, але більш боляче використовувати її з комбінаторами

add' :: (Int, Int) -> Int
add' (x, y) = x + y
u = add'(5, 6) -- just like other languages
l = [1, 2, 3]
l1 = map (add 5) l -- [6, 7, 8]
l2 = map (\x -> add'(5, x)) l -- like other languages

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

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

Ще один момент: функцію без параметрів слід викликати за допомогою f(). У haskell, оскільки ви маніпулюєте лише незмінними оціненими ледачими значеннями, ви просто записуєте fі розглядаєте це як значення, яке потрібно буде виконати за допомогою деяких обчислень. Оскільки його оцінка не матиме жодних побічних ефектів, немає сенсу мати інше позначення функції без параметрів та її поверненого значення.

Існують також інші умови для застосування функції:

  • Lisp: (fx) - префікс із зовнішніми дужками
  • Далі: xf - постфікс

7
Незначна нітпік: терміни "каррінг" і "висип", а не "уточнення" і "викривлення".
Doval

"non curried", що таке функція, що не вимагає curkell?
Вен

3
@ user1737909 Функція, яка приймає кортеж як аргумент.
Doval

1
@Doval Насправді це має бути "schönfinkeling" і "schönfinkeled". Але добре, історія завжди визначає переможця заднім числом.
Profpatsch

Думаючи про синтаксис дужки карірованія що - щось на зразок f(a, ,b)або add(a, )чи add(, b)буде здаватися більш гнучкими за замовчуванням.
фреснель

25

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

Зауважте, що це не характерно для функціональних мов, наприклад, у Smalltalk , однієї з перших мов OO та мов, натхнених нею ( Self , Newspeak , Objective-C), а також у Io та мовах, натхнених нею (Ioke, Seph), пробіл використовується для викликів методів.

Стиль малих розмов:

anArray sort
anArray add: 2
aString replace: "a" with: "b"

(В останньому випадку назва методу є replace:with:.)

Іо-стиль:

anArray sort
anArray add(2)
aString replace("a", "b")

Scala також дозволяє пробіл для викликів методів:

foo bar(baz)

І залишаючи дужки, якщо є лише один аргумент:

foo bar baz

Ruby також дозволяє скинути дужки:

an_array.sort
an_array.add 2
a_string.replace "a", "b"

використання дужок, що здається більш математичним способом

Не зовсім:

f(x)
sin x
x²
|x|
x!
x + y
xy
½

Математичні позначення еволюціонували протягом тривалого часу жахливо непослідовно.

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


3
Є також аргумент для економії редагування. Зокрема, функціональні мови, як правило, підтримують композицію безпосередньо. Встановлення дужок навколо функції замість аргументу має сенс. Ви повинні зробити це лише "один раз": (е. F. G) x на відміну від e (f (g (x))). Крім того, Хаскелл, принаймні, не заважав би виконувати f (x) замість f x. Це просто не ідіоматично.
номен

18

Парентез для застосування функції - лише одне з багатьох сідла, які нам залишив Ейлер. Як і все інше, математика потребує умовностей, коли існує кілька способів щось зробити. Якщо ваша математична освіта поширюється лише на предмет, що не стосується математики в університеті, ви, мабуть, не надто знайомі з багатьма полями, де застосування функцій відбувається щасливо без жодного з цих дурницьких дужок (наприклад, Диференціальна геометрія, Абстрактна алгебра). І ви навіть не згадуєте функції, які застосовуються infix (майже на всіх мовах), "outfix", як прийняття норми, або схематично (Befunge, Algebraic Topology).

Тому у відповідь я б сказав, що це пов'язано зі значно більшою часткою функціональних програмістів та мовних дизайнерів, які мають велику математичну освіту. Фон Нойман каже: "Молода людина, в математиці ви нічого не розумієте. Ви просто звикаєте до них.", Безумовно, це стосується позначень.


7
Чи не навіть , щоб мене почали f(x)проти sin xпроти проти |x|проти x!проти x + yпроти xyпроти ½проти підсумовування проти невід'ємного VS. ...
Йорг W Mittag

2
+1 за цитатою фон Неймана. +1 для решти відповіді, але не можу дати +2. :(
pvorb

2
Я тут вловлю натяк на елітарність; Я заперечую нейтралітет "конструктори функціональної мови програмування краще освічені" .
CaptainCodeman

7
@CaptainCodeman Він каже, що більш освічений з математики, заява, з якою я згоден. Принаймні, якщо мова йде про Хаскелла, то можна помітити, що обидва поняття мають більш математичний характер, а громада також більш математично схильна. Вони не розумніші, вони краще освічені в математиці.
Павло

5
@CaptainCodeman Ні, оскільки він ніколи не мав на увазі, що вони загалом освіченіші, просто більш освічені з математики. Саме так він сказав: "широка математична освіта". :)
Павло

8

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

Суть полягає в тому, що всі ці дужки прикро читати та відстежувати. Це, мабуть, причина №1, що LISP не є більш популярною. Отже, якщо ви можете отримати силу функціонального програмування без досади надмірних дужок, я думаю, що дизайнери мови збираються йти цим шляхом. Зрештою, мовні дизайнери також є мовними користувачами.

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

val message = line split "," map (_.toByte)

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


2
"Суть полягає в тому, що всі ці дужки дратують читати і відстежувати. Це, мабуть, причина номер 1, що LISP не є більш популярною.": Я не думаю, що дужки є причиною того, що Lisp не користується популярністю: я не думаю їх особливо важко читати, і я вважаю, що інші мови мають набагато незграбніший синтаксис.
Джорджіо

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

"Lost In Stupid Parentheses" - це мій улюблений заголовок LISP. Комп'ютери також можуть використовувати гуманний спосіб вказувати блоки коду та скасовувати надмірність, як у таких мовах, як Wisp .
Cees Timmerman

4

Обидва приміщення помиляються.

  • Ці функціональні мови не використовують простір для застосування функції. Те, що вони роблять, просто розбирає будь-який вираз, який з’являється після функції в якості аргументу.

    GHCi> f 3
    4
    GHCi> f (3)
    4
    GHCi> (f) 3
    4

    Звичайно, якщо ви не використовуєте ні пробілу, ні паронів, він зазвичай не працюватиме, просто тому, що вираз не належним чином маркірується

    GHCi> f3

    <‌interactive>: 7: 1:
        Не в області дії: 'f3'
        Можливо, ви мали на увазі 'f' (рядок 2)

    Але якби ці мови були обмежені лише 1-символьними назвами змінних, то це також працювало б.

  • Також норми математики не вимагають дужок для застосування функції. Математики часто пишуть sin x - для лінійних функцій (зазвичай їх тоді називають лінійними операторами) також аргумент можна писати без паролів, можливо, тому що (як і будь-яка функція у функціональному програмуванні) лінійні функції часто обробляються без прямої подачі суперечка.

Отже, ваше запитання зводиться до: чому для деяких мов потрібні дужки для застосування функції? Ну, мабуть, деякі люди, як ви, вважають це більш читабельним. Я категорично не згоден з цим: одна пара паронів є приємною, але як тільки у вас є ще дві з них вкладених, вона починає плутати. Код Lisp демонструє це найкраще, і майже всі функціональні мови виглядали б схоже захаращеними, якби вам потрібні паролі скрізь. Це не так важливо в імперативних мовах, але головним чином через те, що ці мови недостатньо виразні, щоб писати в першу чергу лаконічні, чіткі однолінійки.


Зрозумів, питання не ідеальне. :) Отже, висновок слід зробити: "Дужки не змінюються".
pvorb

2
Не є також нефункціональними мовами, які одностайні в необхідності використання дужок; для кількох прикладів Smalltalk має object method: args, ціль C має [object method: args], і Ruby і Perl дозволяють опускати дужки в функціях та методах викликів, лише вимагаючи від них неоднозначності.
варення

1

Невелике історичне уточнення: початкові позначення в математиці були без дужок !

Позначення fx для довільної функції x було введено Йоханом Бернуллі близько 1700 року, незабаром після того, як Лейбніц заговорив про функції (власне Бернуллі написав ϕ x ). Але до цього багато людей, де вже використовуються позначення на зразок sin x або lx (логарифм x ) для конкретних функцій x , без дужок. Я підозрюю, що це є причиною того, що багато людей все ще пишуть sin x замість гріха (x) .

Ейлер, який був студентом Бернуллі, прийняв's x Бернуллі і змінив грецьку на латинську літеру, написавши fx . Пізніше він зауважив, що може бути легко сплутати f для "кількості", і вважає, що fx - продукт, тому він почав писати f: x . Отже, позначення f (x) не пов'язане з Ейлером. Звичайно ж, Ейлеру потрібні дужки з тієї ж причини, що нам ще потрібні дужки в функціональних мовах програмування: щоб відрізнити, наприклад, (fx) + y від f (x + y) . Я підозрюю, що люди після Ейлера прийняли дужки як за замовчуванням, оскільки вони в основному бачили, як Ейлер пише складені вирази, такі як f (ax + b). Він рідко писав просто fx .

Детальніше про це див .: Чи Ейлер коли-небудь писав f (x) з дужками? .

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.