Языки неC++ для порождающего программирования?

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

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

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

24
задан Community 23 May 2017 в 12:06
поделиться

13 ответов

Альтернатива метапрограммированию стиля шаблонов является Макростилем, который Вы видите в различных реализациях Lisp. Я предложил бы загрузить Paul Graham На Lisp и также смотреть на Clojure, если Вы интересуетесь Lisp с макросами, которые работают на JVM.

Макросы в Lisp намного более мощны, чем C/C++ разрабатывает и составляет язык самостоятельно - они предназначены для метапрограммирования.

32
ответ дан Lou Franco 28 November 2019 в 22:08
поделиться

Метаязык (ML), конечно: http://cs.anu.edu.au/student/comp8033/ml.html

1
ответ дан Nemanja Trifunovic 28 November 2019 в 22:08
поделиться

Lisp поддерживает форму "метапрограммирования", хотя не в том же смысле как шаблонное метапрограммирование C++. Кроме того, Ваш "статичный" термин мог означать разные вещи в этом контексте, но Lisp также поддерживает статический контроль типов, если это - то, что Вы имеете в виду.

1
ответ дан Ben Collins 28 November 2019 в 22:08
поделиться

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

  • статичный
  • скомпилированный в машинный язык
  • в большой степени оптимизированный для производительности во время компиляции
  • расширяемый с пользовательскими типами данных (ООП в случае C++)
  • чрезвычайно популярный

вынимают любой из них, и 'статическое метапрограммирование', просто не имеет смысла. поэтому, я был бы удивлен, имел ли какой-либо удаленно основной язык что-то как этот, как понято на C++.

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

2
ответ дан jwfearn 28 November 2019 в 22:08
поделиться

Большая работа в Haskell: Предметно-ориентированные языки (DSL's), Исполняемые спецификации, Преобразование Программы, Частичное Приложение, Подготовленное Вычисление. Немного ссылок для запущения Вас:

3
ответ дан ja. 28 November 2019 в 22:08
поделиться

Я рекомендую Haskell. Вот бумага описание ее возможностей метапрограммирования времени компиляции.

4
ответ дан Ben Hoffstein 28 November 2019 в 22:08
поделиться

Языковая семья ML была специально разработана с этой целью. Одна из самых известных историй успеха OCAML библиотека FFTW для высокоэффективного FFTs, который является кодом C, сгенерированным почти полностью программой OCaml.

С наилучшими пожеланиями, Jon Harrop.

2
ответ дан Jon Harrop 28 November 2019 в 22:08
поделиться

язык программирования "D" является C ++-like, но имеет намного лучшую поддержку метапрограммирования. Вот является пример трассировщика лучей записанным использующим только метапрограммированием времени компиляции:

Ctrace

Кроме того, существует ответвление gcc, названное "Понятие GCC", который поддерживает конструкции метапрограммирования, которые тот C++, по крайней мере, еще не делает ().

понятие GCC

6
ответ дан joeld 28 November 2019 в 22:08
поделиться

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

И целевая.NET, таким образом, они могут легко взаимодействовать с C# и другими языками.NET - даже двоичные файлы Java, если Вы используете IKVM.

Редактирование: Для разъяснения я имею в виду макросы в значении слова Lisp, не макросы препроцессора C. Они позволяют определение нового синтаксиса и тяжелого метапрограммирования во время компиляции. Например, Nemerle поставлется с макросами, которые проверят Ваши SQL-запросы против Вашего SQL-сервера во время компиляции.

11
ответ дан Community 28 November 2019 в 22:08
поделиться

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

Бездельничание с этим приблизительно в '98 было тем, что управляло мной для поиска лучших решений. Я мог записать полезные системы, которые полагались на него, но они были адскими. Ввод по абсолютному адресу вокруг в конечном счете ведомого меня к языку Common LISP. Несомненно, шаблонный механизм полон по Тьюрингу, но с другой стороны так intercal.

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

, конечно, существуют другие опции. Никакой другой язык, который я использовал, не делает метапрограммирование лучше, чем Lisp, который является, почему я использую его для кода исследования. Существует много причин, Вы могли бы хотеть попробовать что-то еще, хотя, но это все собирается быть компромиссами. Можно посмотреть на Haskell/ML/OCaml и т.д. Много функциональных языков имеет что-то приближающееся к питанию макросов Lisp. Можно найти некоторую.NET предназначенным материалом, но они являются все довольно крайними (с точки зрения базы пользователей и т.д.). Ни один из крупных игроков на промышленно используемых языках не имеет ничего как это, действительно.

13
ответ дан simon 28 November 2019 в 22:08
поделиться

позвольте мне перечислить немного важных деталей о том, как метапрограммирование работы в шепелявости (или схема , или большой список , или выбирают Ваш любимый "динамический" язык):

  • при выполнении метапрограммирования в шепелявости Вы не должны иметь дело с двумя языками . meta код уровня записан на том же языке как код уровня объектов, который это генерирует. метапрограммирование не ограничено двумя уровнями, и это легче на мозге, также.
  • в шепелявости Вы имеете в наличии компилятор во времени выполнения . на самом деле различие времени компиляции/времени выполнения чувствует себя очень искусственным там и в значительной степени подвергается туда, где Вы помещаете свою точку зрения. в шепелявости с простым вызовом функции можно скомпилировать функции в машинные команды, которые можно использовать с тех пор в качестве объектов первого класса; т.е. они могут быть функциями без имени, которые можно сохранить в локальной переменной или глобальной хеш-таблице, и т.д.
  • , макросы в шепелявости очень просты: набор функций наполнен в хеш-таблице и дан компилятору. для каждой формы компилятор собирается скомпилировать, это консультируется с той хеш-таблицей. если это находит, что функция тогда называет его во время компиляции с исходной формой, и вместо исходной формы это компилирует форму эта функция возвраты. (по модулю некоторые неважные детали), так макросы шепелявости в основном плагины для компилятора .
  • запись шепелявости функционирует в шепелявости, которая оценивает код шепелявости, приблизительно две страницы кода (это обычно называют оценка ). в такой функции Вы имеете все право представлять безотносительно новых правил, которые Вы хотите на meta уровне. (то, чтобы заставлять его работать быстро собирается приложить некоторые усилия хотя... о том же как начальная загрузка нового языка...:)

случайные примеры того, что можно реализовать как пользовательская библиотека метапрограммирование шепелявости использования (это фактические примеры библиотек языка Common LISP):

  • расширяют язык с помощью [1 127], разграниченные продолжения (hu.dwim.delico)
  • реализуют макрос js-to-lisp-rpc, который можно использовать в JavaScript (который сгенерирован от шепелявости). это расширяется в смесь кода js/lisp, который автоматически отправляет (в запросе HTTP) все локальные переменные, на которые ссылаются, декодирует их на стороне сервера, выполняет тело кода шепелявости на сервере и возвращает назад возвращаемое значение стороне JavaScript.
  • добавляют пролог как отслеживание в обратном порядке на язык, который очень эффективно интегрируется с "нормальным" кодом шепелявости (см. экспресс)
  • XML шаблонная обработка расширения к языку Common LISP (включает пример [1 129] макросы читателя , которые являются плагинами для синтаксического анализатора шепелявости)
  • тонна маленького DSL's, как цикл или выполняет итерации для легкого цикличного выполнения
24
ответ дан Community 28 November 2019 в 22:08
поделиться

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

1) данные Программы и программа "абстрактное синтаксическое дерево" универсальны (S-выражения!)

2) defmacro

3) макросы Читателя.

4) MOP

их, реальный вентилятор ума является MOP. Прочитайте "Искусство Протокола Метаобъекта". Это изменит вещи для Вас, я обещаю!

5
ответ дан jfm3 28 November 2019 в 22:08
поделиться

Большинство людей пытаются найти язык, имеющий "окончательное отражение" для самопроверки и что-то вроде "eval" для определения нового кода. Такие языки трудно найти (LISP является ярким контрпримером) и они определенно не являются общепринятыми.

Но другой подход состоит в использовании набора инструментов, которые могут проверять, генерировать программный код и управлять им. Джекпот - такой инструмент сосредоточился на Java. http://jackpot.netbeans.org/

Наш набор инструментов для реинжиниринга программного обеспечения DMS такой инструмент, который работает на C, C ++, C #, Java, COBOL, PHP, Javascript, Ada, Verilog, VHDL и множество других языков. (Он использует интерфейсы производственного качества, чтобы он мог читать все эти языки). Более того, он может делать это на нескольких языках одновременно. См. http://www.semdesigns.com/Products/DMS/DMSToolkit.html

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

2
ответ дан 28 November 2019 в 22:08
поделиться