LINUX.ORG.RU

Запрет на вызов функций функций, определённых ниже по тексту - за и против

 ,


0

2

Я быстренько глянул. На Си давно не писал, там вроде нельзя. В Лиспе можно, в Яве можно. В Паскале (Дельфи) вроде нельзя. В tcl можно.

Понятно, что для очень многих синтаксисов (может быть, и для Си тоже) технически легко разрешить обращаться к функциям, определённым ниже по тексту. Но я вижу одно мощное «за» запрет такого обращения - проще сделать хорошую поддержку IDE. Обычно в процессе редактирования текст до положения курсора - корректный, а ниже - сломанный. И, допустим, мы хотим в лексически корректном тексте выделить цветом ошибочные обращения к функциям. Если мы обязаны декларировать «forward reference», с этим нет проблем. Если не обязаны, то как только мы сломали текст в текущей позиции курсора, все функции, определённые ниже, строго говоря, исчезли и их больше нет. Поэтому мы не можем ничего проверить, пока текст снова всего файла снова не станет правильным. И так оно будет мелькать от каждой буквы. Дальше мы начнём кешировать, выдумывать таймауты и т.п. Но это всё как-то гнилостно.

Для собственно разработки мне кажется менее удобным требовать определения заранее. Красивая мода начинать с функции main и дальше вниз её детализировать. И не нужно повтора текста. Можно просто писать код и не отвлекаться на декларирование.

Приведите, пожалуйста, свои «за» и «против» необходимости декларировать ф-ии, к-рые будут использованы до места определения.

Насколько вам досаждает необходимость декларировать функции заранее в тех языках, где это необходимо. Я пишу почти всё время только на лиспе и уже не могу здраво оценить.

★★★★★

Последнее исправление: den73 (всего исправлений: 4)

Приведите, пожалуйста, свои «за» и «против» необходимости декларировать ф-ии, к-рые будут использованы до места определения.

Даже когда тебе заранее дали API в виде документации, которое тебе следует реализовать, не вижу смысла начинать с хидера, в котором пишешь декларацию, а потом пилишь реализацию. Ибо тестировать как-то нужно в процессе разработки, а с функциями без реализации компилятор насыпет ероров. Если в ответ запилить «заглушки» - зачем тогда вообще надо было готовить хидер?

Короче для меня декларация функций - в последнюю очередь.

Иногда ситуация вынуждает это делать когда приходится работать с лапшекодом.

По поводу запрета не понял вообще. Что и когда ты хочешь запрещать? Как это должно выглядеть?

Обычно в процессе редактирования текст до положения курсора - корректный, а ниже - сломанный.

Когда редактируешь существующий код - то это утверждение полная чушь.
Когда пишешь новый - до положения курсора - корректный, а ниже - отсутствующий.

reprimand ★★★★★
()
Ответ на: комментарий от reprimand

Ибо тестировать как-то нужно в процессе разработки, а с функциями без реализации компилятор насыпет ероров.

Понятно. Значит, нужно, чтобы это были ворнинги, а не ероры, и будет легче.

По поводу запрета не понял вообще. Что и когда ты хочешь запрещать? Как это должно выглядеть?

Потребовать = запретить ссылаться на функции, определённые ниже. Соответственно, обращение к функции, определённой ниже, будет давать ошибку компиляции.

Когда редактируешь существующий код - то это утверждение полная чушь.

Или ты написал не подумав. Или я не понял светлую мысль, как ты собираешься поступить в этом случае:

void foo () { /* - я только что добавил или стёр открытие комментария
А что дальше - не так уж и важно. 

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 3)

проще сделать хорошую поддержку IDE

Не вижу вообще никакой проблемы.

x3al ★★★★★
()

Понятно, что для очень многих синтаксисов (может быть, и для Си тоже) технически легко разрешить обращаться к функциям

В Си можно. Только вот тогда компилятор будет считать, что её тип - int(...).

И так оно будет мелькать от каждой буквы.

Пусть мелькает.

Приведите, пожалуйста, свои «за»

Нет таких.

Насколько вам досаждает необходимость декларировать функции заранее в тех языках, где это необходимо.

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

Esper
()
Ответ на: комментарий от den73

Понятно. Значит, нужно, чтобы это были ворнинги, а не ероры, и будет легче.

Ну, если эти функции не используются в коде, то можно и ворнинги сделать, да.

Потребовать = запретить ссылаться на функции, определённые ниже. Соответственно, обращение к функции, определённой ниже, будет давать ошибку компиляции.

ЕМНИП, в Си такое поведение по дефолту

Или ты написал не подумав. Или я не понял светлую мысль, как ты собираешься поступить в этом случае:

Можно другой пример либо больше объяснений?

reprimand ★★★★★
()

В Паскале (Дельфи) вроде нельзя

Опережающее объявление, ключевое слово forward.

procedure Show(const s: String); forward;
procedure Test;
begin
  Show('Test');
end;

bormant ★★★★★
()

Какое-то ретроградство. В современных языках борются за то, чтобы можно было вызвать локальную функцию, определенную ниже по тексту внутри другой внешней функции. Это можно сделать в haskell и частично в scala / F#.

dave ★★★★★
()

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

В 1С сделано просто. Синтаксический разбор работает попроцедурно. То есть

Функция А(Парам1)
    П = Парам1 + ФункцияСДлинны<<курсор>
  
Функция ФункцияСДлиннымНазванием(Парам1, Парам2)
КонецФункциии  

Здесь <курсор> — положение курсора. Так вот при нажатии автодополнения он дополнит до ФункцияСДлиннымНазванием, так как «Функция ФункцияСДлиннымНазванием» явно указывает, что предыдущая единица разбора закончилась. Многострочных комментариев вида /* */ в 1С нет. Есть кнопка в IDE «закомментировать блок», которая в начале каждой строки помеченного куска ставит «//». И аналогично «раскомментировать блок».

Красивая мода начинать с функции main и дальше вниз её детализировать.

Да. И в библиотеках реализацию API лучше держать поближе к началу. Его чаще приходится читать.

Насколько вам досаждает необходимость декларировать функции заранее в тех языках, где это необходимо.

С поддержкой IDE (когда при смене сигнатуры автоматически меняется сигнатура определения) — не досаждает. Без поддержки — неудобно. Приходится держать два окна на один файл.

Я пишу почти всё время только на лиспе и уже не могу здраво оценить.

На лиспе ровно эта ситуация с (defpackage ... (:export :foo ...)) и (defun foo ...).

monk ★★★★★
()

проще сделать хорошую поддержку IDE

Языки программирования следует дизайнить для пользователей, а не для машин, компиляторов, и их разработчиков. Человеческие слабости бесят дизайнеров и усложняют разработку IDE, но это ваши инженерные задачи, которые не надо перекладывать на голову пользователям.

В частности, с некорректными программами в IDE можно работать нормально, если прекратить попытки сделать всё «простенько» и принять тот факт, что текст в редакторе может быть частично неграмматичен. И решать проблему не с помощью forward references, чтобы получить максимум информации до сломанного текста и избежать работы с ним, а зайти с другого конца: дизайнить язык так, чтобы даже со сломанным текстом посередине можно было идентифицировать сломанный кусок, ресинхронизироваться, и продолжить анализ корректной части. Ну, правда, чем более «гибкий» язык, тем сложнее это сделать, но это тоже инженерная задача.

ilammy ★★★
()

императивщина и архаизм, который был оправдан во времена перфокарт и однопроходных компиляторов

anonymous
()

«против»!!!

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

Такое есть мало где. Обычно, чтобы добраться до реального кода приходится просканить кучу деклараций, импортов, неинтересных «утилит», и т.п. В лучших случаях текст начинается с описания, из которого в редких случаях понятно, что искать. Но оно избыточно, и, с некоторой вероятностью неактуально, в отличии от кода.

DonkeyHot ★★★★★
()
Ответ на: комментарий от monk

Многострочных комментариев вида /* */ в 1С нет.

А многострочные строковые литералы?

«Функция ФункцияСДлиннымНазванием» явно указывает, что предыдущая единица разбора закончилась.

Спасибо за отсутствие классов и локальных функций.

(defpackage ... (:export :foo ...)) и (defun foo ...)

чем-то похоже, но не совсем то

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

А многострочные строковые литералы?

МногострочныйЛитерал = "Выглядит
| примерно так.
| В начале каждой строки надо ставить палку"
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от ilammy

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

Во-первых, при определённом количестве МП уже не так понятно, кто есть кто.

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

Ну вот я её и пытаюсь решить. Какие примеры хороших решений ты можешь привести?

Инженерные задачи решаются путём компромисса, который затрагивает и конечного пользователя. Языки бывают не только «гибкие», но и расширяемые. Вложенные функции, нарушение баланса скобок, многострочные комментарии, многострочные строковые литералы - вот 4 источника неприятностей по нашей теме.

В лиспе зачастую среда считает, что начало определения - это регексп «^\(def». Это просто, понятно, стабильно работает, но когда определения вложены и с отступом, выясняется, что это лишь дешёвый «хак».

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

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Спасибо за отсутствие классов и локальных функций.

Добавить к Функция и Процедура ключевое слово Класс несложно. Локальные функции можно называть словом «ЛокальнаяФункция» или чем-то подобным. В Common Lisp вообще labels и flet придумали, чтобы defun внутри defun не делать.

monk ★★★★★
()
Ответ на: комментарий от den73

Какие примеры хороших решений ты можешь привести?

Чаще всего это сводится к тому, что явно помечаются концы разнообразных блоков и поощряется деление на блоки меньшего размера и меньшее количество блоков. Вот эти все КонецФункции, правила «не больше 50 строк на функцию» и «один класс — один файл», и подобное.

  • Явные маркеры позволяют обоснованно считать, что блок закончился, какой бы бред внутри не находился. Соответственно, если при синтаксическом разборе обнаруживается ошибка, что можно просто пропустить один блок.
  • Если блоки имеют небольшой размер, то можно без особых проблем пропустить один из них, не потеряв слишком уж много информации.
  • Если блоков ожидается немного, то неожиданное начало блока тоже можно использовать в качестве синхронизации. Например, если нельзя вложенные функции, то внезапное начало функции означает, что где-то перед ним пропустили закрытие предыдущей. Или если можно, например, вложенные классы, но нельзя их объявлять посреди методов.

Языки бывают не только «гибкие», но и расширяемые.

Вот я именно об этой расширяемости и говорю. Чем больше всего можно переопределить, тем сложнее разбирать исходник и тем бесполезнее становится идентификация ошибок. Pascal с его фашистским синтаксисом разбирать проще и устойчивее, чем всякие Perl6, TeX и Common Lisp, где можно хачить readtable и нужна полная реализация языка вместе с библиотеками для разбора кода, который потенциально можно написать.

Инженерная задача в том и состоит, чтобы ограничить эту расширяемость, оставив язык удобным. Чем более расширяемый язык, тем больше «ошибок» становятся легальными конструкциями. Глупо пытаться одновременно сесть на два стула.

В лиспе зачастую среда считает, что начало определения - это регексп «^\(def». Это просто, понятно, стабильно работает, но когда определения вложены и с отступом, выясняется, что это лишь дешёвый «хак».

Один из вариантов решения: административный.

Например, в тех же Лиспах парсер легко свести с ума, поставив закрывающую скобку немного не там. Парсер Python точно так же чувствителен к отступам. Но в обоих случаях это не вызывает существенных проблем, если код преимущественно пишется во всяких емаксах, которые автоматически принудительно выравнивают его, вставляют закрывающие скобочки, и подсвечивают sexprы, так что пользователю нужно приложить усилия, чтобы написать и проглядеть неправильный код.

Точно так же может работать и предпочтительный стиль кодирования и именования. Если людям для написания потенциально неправильного кода потребуется прилагать сознательные усилия и/или терпеть уродливый код, то возникающих проблем будет меньше.

  • Если в коде не принято делать большие вложенные функции, то будет меньше проблем с тем, что где определяется и когда всё это кончится.
  • Если принято объявляющие макросы начинать с def или define, то их будут реже путать с другими.
  • Если сложные макросы вдалбливаются в подкорку начиная с первых же тьюториалов, то в простых случаях почти не будет ошибок.
  • Если ещё более сложным макросом можно пользоваться только с маном в обнимку и в самом мане через строчку примеры использования, то ошибок будет меньше и с этим макросом.

Да, парсер при этом вполне может сходить с ума, если обнаруживает ошибки в коде. Но если пользователи выдрессированы не делать ошибки, которые не удобны парсеру, то его плохое поведение в подобных случаях не вызывает существенных проблем. Как в анекдоте с советом доктора: «А вы так не делайте».

многострочные комментарии, многострочные строковые литералы

Не вижу проблемы. Или это речь о том, что исходники нельзя будет корректно парсить и обрабатывать с помощью grep/sed/awk?

ilammy ★★★
()
Ответ на: комментарий от ilammy

Вот начало твоей речи:

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

А вот конец:

если пользователи выдрессированы не делать ошибки, которые не удобны парсеру

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от ilammy

Вот эти все КонецФункции

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

Pascal с его фашистским синтаксисом разбирать проще и устойчивее, чем всякие Perl6, TeX и Common Lisp

Да, это верно и это одна из причин, по которой я решил создавать свой язык. Может быть, даже это основная причина.

den73 ★★★★★
() автор топика
Ответ на: комментарий от ilammy

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

Угу, за это и боремся.

многострочные комментарии, многострочные строковые литералы

Не вижу проблемы.

Внутри многострочного строкового литерала может быть абсолютно что угодно, в том числе и валидный исходный текст. В лиспе достаточно поставить одну кавычку - и сразу весь нижележащий текст инвертируется: кто был ничем, тот станет всем и наоборот. Т.е. была функция ниже, а она стала строчкой. Была строчка - она стала функцией. Если гуй при этом показывает, допустим, список функций в файле, то ему придётся отвратительно мигать.

den73 ★★★★★
() автор топика
Ответ на: комментарий от monk

Многострочных комментариев вида /* */ в 1С нет. Есть кнопка в IDE >«закомментировать блок», которая в начале каждой строки помеченного куска >ставит «//».

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

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

опр.функ Ф()
  если 1 == 1 то 
    пусть исходник = (: 
м"опр.функ Ю()
  вернуть 123
кнф
"м :)
    напечатать исходник
  кне
кнф
- это некрасиво, поскольку отступы ломаются. А если потребовать палок, то будет гораздо красивее:
опр.функ Ф()
  если 1 == 1 то 
    пусть исходник = (:
      м"опр.функ Ю()
       |  вернуть 123
       |кнф"м :)
    напечатать исходник
  кне
кнф
На самом деле я хотел сделать эти палки опциональными в последующих версиях, но получается, что лучше с них сразу начать в качестве основного варианта.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)

это не запрет, а ожидаемый результат от однопроходного компилятора, каким раком он поймёт во что ему транслировать вызов функции, если ты раньше ему прототип не показал?

anonymous
()

Касаемо ресинхронизации - в это я всё как-то не верю. Даже если мы разберёмся с многострочными константами и комментариями, останется ещё миллион возможных проблем: незакрытый список параметров функции, вложенные друг в друга локальные функции, временно/ошибочно составленные цитаты (quote в лиспе), переименованная функция, которая делает невалидным код, ссылающийся на старое имя (в т.ч. и выше точки определения функции). Если пойти этим путём, парсер будет состоять из миллиона эвристик и всё равно в итоге будет криво и ужасно.

Если ещё подумать о том, что нам нужно показывать пользователю «code explorer» со списком функций, и чтобы он не так много мигал во время редактирования, то остаётся только подход, основанный на отслеживании истории действий. При открытии файла мы его изначально парсим и запоминаем конец каждого блока. Далее, когда мы что-то редактируем, у нас есть стек вложенности блоков, в которых мы находимся. На него-то и будем опираться. Всё, что снаружи ныне редактируемого блока, не парсится заново. На экране соответственно (почти) ничего не мигает. А дальше, видимо, нужно нажать кнопку «проверить исходный текст на корректность», как в 1С. Потому что только сам пользователь знает, закончил он редактировать функцию или просто задумался. Всякие варианты с таймаутами, которые слишком умно и не вовремя решат, что пора уже распарсить текст и насыпать полный экран ошибок или перекрасить в красный цвет, обычно только раздражают.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Хаха, оказывается есть ещё одна проблема, уже не связанная с IDE. Я борюсь за то, чтобы можно было решать конфликты имён. Допустим, есть пакет П и в нём символ З, именующий запись с полем Ж. И есть функция с именем Ж. И вот я хочу создать литерал (константу) этой записи, у которой поле Ж равно символу Ж.

Определение записи порождает своё простр-во имён, в котором живут имена полей, а именно Ч.З. Имя поле будет Ч.З:Ж Имя функции - Ч:Ж. Т.е. это два разных символа.

Внутри литерала пр-ва имён будут временно сливаться с автоматическим устранением конфликтующих символов, как в конструкции select ... в SQL. Т.е., внутри определения записи мы не увидим ни одной Ж.

Ясно, что до этого места уже никто не дочитал, разве кроме Монка, но и ладно.

Итого получаем следующий код:

в-пакете :П

опр.функ Ж ()
кнф

переменная ю 
  = З П.З:Ж П:Ж кнЗ 
  глобальная да
кнп

В чём здесь проблема с порядком определений? Что если мы переставим местами определения функции и переменной, то у нас при первом чтении не будет символа П:Ж, а значит, не будет и конфликта. В итоге мы можем написать вот так:

в-пакете :П

переменная ю 
  = З Ж Ж кнЗ 
  глобальная да
кнп

опр.функ Ж ()
кнф

И не получим никакого предупреждения от лексера при первом чтении. При втором чтении Ж исчезнут и мы получим ошибку чтения. Очень нехорошо.

Эта проблема скорее касается символов, а не функций и скорее относится к лиспообразным языкам с горячей заменой кода.

И тут я вспоминаю ещё про одну, более страшную проблему. В лиспе мы можем сослаться на функцию или на макрос, определённый в следующем файле. В динамической разработке это прокатывает, но при полной пересборке получается криво - макрос не расширяется, или мы можем вызвать функцию до того, как она будет определена.

В общем, пока мы потребуем деклараций вперёд, а там может быть и отменим.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Вот начало твоей речи:

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

А вот конец:

если пользователи выдрессированы не делать ошибки, которые не удобны парсеру

Так я и не говорю, что это хорошее решение. Но вариант.

ilammy ★★★
()
Ответ на: комментарий от den73

Если гуй при этом показывает, допустим, список функций в файле, то ему придётся отвратительно мигать.

Если вставить только открывающую кавычку, то образуется некорректная программа с незакрытой строкой. Компилятор просто ругнётся, что вот здесь начинается строка, которая неправильно закрыта. IDE вполне можно научить в этом случае не трогать то, что она распарсила раньше, когда этой ошибочной строки не было.

ilammy ★★★
()
Ответ на: комментарий от den73

то остаётся только подход, основанный на отслеживании истории действий

Не остаётся, а так и следует делать. Нельзя в IDE прикинуться шлангом и игнорировать тот факт, что мы работаем с редактируемым, изменяемым текстом.

ilammy ★★★
()
Ответ на: комментарий от ilammy

Ну это пока слишком общо, чтобы быть руководством к конкретному действию. То, что я написал про вложенные блоки, более конкретно, чем то, что ты написал, но всё ещё нельзя сказать, что я чётко понимаю, как это сделать. Потому что если посмотрим стек вложенных блоков, то при любом редактировании всегда на дне стека будет блок «весь файл» и тогда моя фраза «всё, что вне редактируемого блока, не парсим заново», теряет смысл. Т.е. нужно решить, на каком уровне вложенности остановиться и считать, что все поломки текста делаются локально в этом блоке. Т.е. опять эвристика, которая будет где-то работать хорошо, а где-то плохо.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

Если гуй при этом показывает, допустим, список функций в файле, то ему придётся отвратительно мигать.

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

Esper
()

вызов функций функций, определённых ниже по тексту

На Си давно не писал, там вроде нельзя.

В Си совершенно точно можно.

tailgunner ★★★★★
()
Ответ на: «против»!!! от DonkeyHot

Обычно, чтобы добраться до реального кода приходится просканить кучу деклараций, импортов, неинтересных «утилит», и т.п.

Или просто перейти в конец файла.

tailgunner ★★★★★
()
Ответ на: комментарий от den73

никто не обязывает компилятор быть однопроходным.

Ещё раз, никто не называет это запретом, это ограничение накладывается, если ты создаёшь компилятор однопроходным и разработчики языка Си именно обязали компилятор быть однопроходным.

В этом случае, если компилятор встречает вызов функции, до её определения, он может только догадываться, какие типы принимаются на вход, какие возвращаются

anonymous
()
Ответ на: комментарий от den73

Т.е. была функция ниже, а она стала строчкой. Была строчка - она стала функцией. Если гуй при этом показывает, допустим, список функций в файле, то ему придётся отвратительно мигать.

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

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от den73

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

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

monk ★★★★★
()
Ответ на: комментарий от tailgunner

Или просто перейти в конец файла.

Ну да, alias vim='vim «+$» «+?^}» +«norm %»', и костыли почти незаметны:)

DonkeyHot ★★★★★
()
Ответ на: комментарий от monk

Ну, не сказать, чтобы я что-то понял, не зная, что является разделителем в Хаскеле. Там довольно аскетичная среда. И насколько я понял вот отсюда, http://www.haskell.ru/lexemes.html, одинарная кавычка даёт однострочный литерал. Т.е. даже проблемы мигающих строчек нет.

В районе 14.31 вроде он делает completion, но это может быть даже просто completion на уровне слов - тут достаточно лексера самого примитивного (есть в емаксе dynamic completion обычно).

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

В общем, если вкратце, то он делает разбор по формам верхнего уровня и выдаёт первую ошибку синтаксического разбора, на которую наткнулся. Анализ делается после каждого перевода строки.

monk ★★★★★
()
Ответ на: комментарий от monk

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

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

Может быть, будет утилита, которая сама генерирует эти объявления.

Касаемо алгоритма раскраски, ща напишу документ, чтобы не забыть потом, и дам на него здесь ссылку.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

И мне понравилось, что не успел я решить взять палки для строк, как они тут же нашлись и в Хаскеле.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

вот попытался описать алгоритм, но по-моему полный бред. Надо, наверное, смотреть, как делают «настоящие» IDE.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Да это же обсуждали чуть ли не 40 лет назад?

https://books.google.ru/books?id=7EES26vGz38C&lpg=PA119&ots=CvyLYzUej...

см. «Стратегии восстановления после ошибок»

Красивая мода начинать с функции main и дальше вниз её детализировать. И не нужно повтора текста.

Кстати, есть еще один подход. Можно держать отдельно определения типов, глобальных переменных, функций и операторов и т.п. Как делают во многих РСУБД, например. Вместо простыни текста получаются слабо зависящие друг от друга куски. Хотя, в вашей терминологии это получается «определение выше по тексту»

Вот интересно, какие языки программирования будут существовать лет через 100? Будет ли их много или все унифицируется? Будут ли это языки близкие к естественным или наоборот строго формальные? Как вообще будет выглядеть процесс программирования?

Ну, «программирование в браузере» уже с нами, скорее всего это и станет основной IDE в близком будущем (с гиперссылками по коду и картинками в каментах), а вот что будет с самими языками?

Deleted
()
Ответ на: комментарий от Deleted

Да это же обсуждали чуть ли не 40 лет назад?

Угу, я уже понял, что нужно ничего обсуждать, а просто взять какой-нибудь подходящий код, который это умеет, и перевести его на лисп. Scintilla, Eclipse, Atom или что-то ещё подобное. Во всяком случае, в языке заложено достаточно много для того, чтобы это было осуществимо - не хуже, чем в аналогах. Именованные закрывающие скобки, убраны многострочные комментарии, аккуратные многострочные литералы строк. Практически максимум доступного для полноценного языка. Сейчас я проектирую язык, а не ИСР, поэтому этих решений на данный момент достаточно.

Можно держать отдельно определения типов, глобальных переменных, функций и операторов и т.п. Как делают во многих РСУБД, например. Вместо простыни текста получаются слабо зависящие друг от друга куски.

Я знаю такой способ. Имея ДНК, но не имея курицы или яйца, новую курицу не получается создать. Поэтому я в своих трёх проектах СУБД имел скрипт, к-рый содержал всё, кроме определений таблиц, и который позволял все вьюхи, процедуры и триггеры пересоздать полностью с нуля.

Потом я это интегрировал с редактором и получился своего рода «SLIME для SQL». Может быть я и не прав, но текст пока что более надёжен, именно ввиду недостаточного набора инструментов. Например, есть системы контроля версий для текста, но их нет для метаданных СУБД (или мне неизвестны).

Кроме того, кроме самих определений, для динамических и расширяемых языков важен и «скрипт инициализации», который накатывает книгу Бытия с 1-го по 5-й день Творения, или, если больше угодно душе, эволюцию от первичного бульона по курицу.

В лисповых системах обычно скрипт инициализации совмещён собственно с исходными текстами системы и в этом тоже свой профит есть, потому что видны причинно-следственные связи.

Ну, «программирование в браузере» уже с нами, скорее всего это и станет основной IDE в близком будущем

Я надеюсь застать день, когда современные браузеры будут похоронены вместе со своими ужасными веб-приложениями и отвратительным JavaScript-ом, который недоязык. Я вот когда пользуюсь Google Docs, всегда с ностальгией вспоминаю Microsoft Word 6.0, в котором было уже абсолютно всё, что надо и чего в Google Docs нет. Притом, что 4 Мб памяти для его работы было более чем достаточно, а для современных браузеров не хватает 1 Гб (в 250 раз больше!)

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)

В tcl можно.

а вот и не угадал :-) нельзя на самом деле.

ps/ по теме - если интерпретация двух-проходная или есть/возможно позднее связывание, то почему-бы и нет? отчего запрещать то что технологически возможно?? ради чтобы кто-нить не выстрелил себе в пятку..да ну нафик - пусть стреляет в полном праве.

pps/ а вот принципиальная невозможность превентивного декларирования вот зло из злов..Знаком с подобными языками, впечатления непечатны :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Как нельзя? Может это иллюзия? Или я что-то не то под не тем понимаю? Но не суть, tcl вообще далёк от идеала, я могу это делать в лиспе.

ради чтобы кто-нить не выстрелил себе в пятку..да ну нафик - пусть стреляет в полном праве.

Я дал ссылку почему. Там проблема в пространствах имён, а не в декларациях. Хотя и право выстрелить в пятку мне лично нужно лишь в том случае, если я могу сначала посмотреть в прицел и сам принять решение, нажимать ли на спусковой крючок.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Как нельзя? Может это иллюзия? Или я что-то не то под не тем понимаю?

tcl получает выражение и сразу его выполняет. Он не знает что там далее, за границами выражения и предположений на этот счёт не строит. Если нужной процедуры нет, будет ошибка. Максимум что дозволено - самому поймать эту ситуацию через «unknown» и принять меры (например автосгенерить функцию)

Я дал ссылку почему. Там проблема в пространствах имён, а не в декларациях. Хотя и право выстрелить в пятку мне лично нужно лишь в том случае, если я могу сначала посмотреть в прицел и сам принять решение, нажимать ли на спусковой крючок.

в топике ссылок нет, а далее по треду их более одной :-) которую вы считаете достаточным пояснением непонятно..

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Если нужной процедуры нет, будет ошибка.

Это если процедуру сразу выполнять. А если просто определить процедуру, которая вызывает процедуру, определённую позже, то всё хорошо.

P.S. Если в твоём смысле, то в Лиспе и Схеме тоже нельзя.

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.