Використання граматики природної мови у вільному API


14

Я замислююся над абстракцією запитів щодо API WebSQL / Phonegap Database, і мені здається, що я приваблюю та сумніваюсь, визначаючи вільний API, який імітує використання природних граматик англійської мови.

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

//find user where name equals "foo" or email starts with "foo@"
find("user").where("name").equals("foo").and("email").startsWith("foo@")

//find user where name equals "foo" or "bar"
find("user").where("name").equals("foo").or("bar");

//find user where name equals "foo" or ends with "bar"
find("user").where("name").equals("foo").or().endsWith("bar");

//find user where name equals or ends with "foo"
find("user").where("name").equals().or().endsWith("foo");

//find user where name equals "foo" and email is not like "%contoso.com"
find("user").where("name").equals("foo").and("email").is().not().like("%contoso.com");

//where name is not null
find("user").where("name").is().not().null();

//find post where author is "foo" and id is in (1,2,3)
find("post").where("author").is("foo").and("id").is().in(1, 2, 3);

//find post where id is between 1 and 100
find("post").where("id").is().between(1).and(100);

Редагування на основі відгуків Квентіна Прадета : Крім того, здається, API повинен підтримувати як множинні, так і форми однини дієслова, так:

//a equals b
find("post").where("foo").equals(1);

//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);

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


Редагувати щодо групування : Одне "речення" - це одна група, а пріоритет визначений у SQL: зліва направо. Кілька угруповань можуть бути виражені кількома whereвисловлюваннями:

//the conjunctive "and()" between where statements is optional
find("post")
  .where("foo").and("bar").equal(2).and()
  .where("baz").isLessThan(5);

Як бачимо, визначення кожного методу залежить від граматичного контексту, в якому він перебуває. Наприклад, аргумент "методів сполучення" or()і його and()можна або залишити, або посилатись на ім'я поля або очікуване значення.

Мені це здається дуже інтуїтивно зрозумілим, але я хотів би почути ваші відгуки: чи це хороший, корисний API, чи я мушу зробити задній план для більш прямої реалізації?

Для запису: ця бібліотека також надасть більш звичайний, безпливний API на основі об'єктів конфігурації.


1
Також ланцюжок - чому jQuery дуже відомий. Досить прямо, послідовно та зрозуміло.
Йосип

3
Це цікаво! Ви, напевно, повинні запитати це у програмістів.
Бенджамін Груенбаум

2
Як би ви впоралися з групуванням? Еквівалент: ... where foo = 1 or (bar = 2 and qux = 3)?

7
IMO такого роду вільне API є жахливим. Наприклад, відсутність переваги оператора дратує. Я б розбирав where("name").equals("foo").or("bar")як (name=="foo")or bar. Тоді незрозуміло, коли рядок представляє буквальне значення, а коли в ньому представлено назву стовпця, ...
CodesInChaos

4
btw. якщо ви хочете використовувати DSL для запиту до бази даних, ви можете використовувати вже існуючий DSL під назвою SQL.
CodesInChaos

Відповіді:


23

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

  • Це додає більше сюрпризів, оскільки ви вносите неоднозначність
  • Ваші користувачі захочуть використовувати конструкції, які ви не охоплювали б, наприклад. find("user").where("name").and("email").equals("foo");
  • Важко повідомляти про помилки: що ти можеш зробити find("user").where("name").not().is().null();?

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

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

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

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

якщо це неоднозначно, воно не є чітко визначеним. Якщо це неоднозначно, потенційного результату існує не один, і щось потрібно вибрати один з них. Або вибір буде чітко визначеним, або мовний аналізатор вибереться навмання. Отже, неоднозначність у мові програмування нормально, якщо ви хочете стохастичну мову (1 + 1 може бути рівним 2, а іноді може дорівнювати 1 або 3) на відміну від детермінованої (1 + 1 завжди дорівнює 2).
Майкл Паулуконіс

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

+1 Добре розуміє контекстну чутливість його конкретної реалізації вільного API. Мені сподобалася ідея його вільного API на перший погляд, але не придивилася так уважно, щоб побачити це. Однозначно величезна проблема.
Джиммі Хоффа

якщо він робить граматику однозначною та контекстною вільною, то в чому проблема? впевнені, що вони можуть захотіти видалити множину віршів однини форм дієслів і подібних речей, але це не змінює ядра того, що вони намагалися зробити. У вас би не було is()або equal()тільки equals(). Після цього ви не бачите своєї проблеми із помилками в повідомленні. null()Також стане буквальним для порівняння, а не синтаксичною функцією. find("user").where("name").is().not().null();стаєfind("user").where("name").not().equals(null);
WHN

3

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

Ви представляєте те, що я розглядаю як конкретний синтаксис для SQL запитів. Я твердо вірю, що конкретний синтаксис ніколи не може допомогти мові, тільки зашкодить, якщо це погано.

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

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

Оскільки ви згадали, що ви також надасте "більш звичайний API", це здається, що ви вже все це знаєте. На це я кажу "Добре!" Але це не означає, що ви також не можете паралельно розробляти свій вільний API! Єдине абстрактне визначення синтаксису може підтримувати кілька конкретних синтаксисів. Хоча вам слід пам’ятати, що абстрактний синтаксис - це справжня справа, конкретний синтаксис також може бути дуже корисним.


2

Окрім дуже хороших моментів Квентіна Прадета, я сумніваюся у передбачуваних перевагах цієї мови.

Імовірно, граматика, близька до природної мови, полягає в тому, щоб зробити її доступною. Але SQL вже досить близький до природної мови. Чи один із них насправді ближче до англійської, ніж інший?

find("user").where("name").equals("foo")

select user from table where name = 'foo'

Я не бачу вигоди від вашої граматики з точки зору інтуїтивності чи читабельності. Насправді версія SQL виглядає більш читаною (і її легше набирати) через пробіл.


2

Існує ряд поганих, ніж ідеальних дизайнерських рішень, які, здається, були прийняті при розгляді цього API.

Перше - питання корисності - якій цілі вона служить? Здається, це створює структуру даних, яка буде компілюватися в діалект SQL. Між іншим, граматика видається обмеженим набором SQL. Питання "яка перевага для цього використовується лише за допомогою SQL?" стає ключовим. Якщо писати більш громіздко, використовуючи вільний інтерфейс, ніж просто записувати рядок із відповідною інтерполяцією, то не вдасться писати за допомогою цього API.

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

У SQL є більше частин, ніж це API. Приєднання (у будь-якій їх безлічі форм), зокрема, відсутні у наборі прикладів. Підзапити ( foo in (select id from bar)), об'єднання та групи - це декілька речей, які часто використовуються. Складні угруповання логіки, схоже, не є інтуїтивно зрозумілими.

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

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

В API немає зайвої надмірності заради англійської мови. Зокрема equal()проти equals()того, щоб робити те саме. Хоча я не впевнений у цьому, я вважаю, що is()це необов’язковий додаток заради відповідності англійській мові. Я вітаю будь-кого слухати мою скандал про надмірність методів в рубіні в чаті - не робіть однакової помилки.

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

RFC 1925 - Дванадцять мережевих правд

(12) У дизайні протоколів досконалість була досягнута не тоді, коли не залишається нічого додати, а коли немає нічого, що можна забрати.

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