Другое событие NullPointerException
возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals
для гарантированного непустого объекта.
Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null
.
Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Еще одна вещь, которую вы должны понять об отсутствии оптимизации, - это то, что она составная . Большая часть Rakudo написана на Perl 6 . Так, например, оператор [+]
реализуется методом Any.reduce
(вызывается с $ expression
, установленным в & infix: <+>
), который имеет в качестве внутреннего цикла
for @.list {
@args.push($_);
if (@args == $arity) {
my $res = $expression.(@args[0], @args[1]);
@args = ($res);
}
}
, другими словами, реализацию reduce на чистом Perl, которая сама выполняется Rakudo. Так что не только код, который вы видите, не оптимизируется, но и код, который вы не не видите, что заставляет ваш код работать, также не получает
оптимизирован. Даже экземпляры оператора +
на самом деле являются вызовами методов, поскольку, хотя оператор +
в Num
реализован Parrot, в Rakudo пока нет ничего, что могло бы распознать вас у нас есть два Num
и оптимизация вызова метода, так что до того, как Ракудо найдет мульти-суб-инфикс, существует полная динамическая диспетчеризация: <+> (Num $ a, Num $ b)
и понимает, что все, что он на самом деле делает, - это код операции «добавить». Это разумное оправдание тому, что он в 100-1000 раз медленнее, чем Perl 5 :)
Дополнительная информация от Джонатана Уортингтона о типах изменений, которые должны произойти с объектной моделью Perl 6. (или, по крайней мере, в концепции Ракудо), чтобы сделать вещи быстрыми, сохранив природу Perl 6 «все является вызовом методов».
Поскольку я вижу, что это все еще привлекает внимание ...За прошедшие годы Rakudo / MoarVM получили JIT, встраивание, динамическую специализацию и тонны работы многих людей, оптимизирующих каждую часть системы. В результате большинство этих вызовов методов могут быть "скомпилированы" и имеют почти нулевые затраты времени выполнения. Perl 6 во многих тестах показывает в сотни или тысячи раз быстрее, чем в 2010 году, а в некоторых случаях быстрее, чем Perl 5.
В случае проблемы суммы до 100 000, с которой начался вопрос, Rakudo 2018.06 все еще немного медленнее, чем perl 5.26.2:
$ time perl -e 'use List::Util 'sum'; print sum(1 .. 100000), "\n";' >/dev/null
real 0m0.023s
user 0m0.015s
sys 0m0.008s
$ time perl6 -e 'say [+] 1 .. 100000;' >/dev/null
real 0m0.089s
user 0m0.107s
sys 0m0.022s
Но если мы амортизируем стоимость запуска, запустив код 10 000 раз, мы увидим другую картину:
$ time perl -e 'use List::Util 'sum'; for (1 .. 10000) { print sum(1 .. 100000), "\n"; }' > /dev/null
real 0m16.320s
user 0m16.317s
sys 0m0.004s
$ time perl6 -e 'for 1 .. 10000 { say [+] 1 .. 100000; }' >/dev/null
real 0m0.214s
user 0m0.245s
sys 0m0.021s
perl6 использует на несколько сотен миллисекунд больше, чем perl5, при запуске и компиляции , но затем он выясняет, как произвести фактическое суммирование примерно в 70 раз быстрее.
Конечно, это не потому, что все является объектом , потому что это верно и для ряда других языков (например, Ruby). Нет никаких причин, почему Perl 6 должен был бы быть на несколько медленнее, чем другие языки, такие как Perl 5 или Ruby, но факт в том, что Rakudo не настолько зрел, как Perl или CRuby. Оптимизация скорости еще не проводилась.
Ракудо так медлителен по разным причинам.
Первая и, возможно, самая важная причина заключается в том, что Rakudo еще не выполняет никаких оптимизаций. Текущие цели - больше изучить новые функции и стать более надежными. Вы знаете, они говорят: «Сначала заставь работать, потом исправь, потом сделай быстро».
Вторая причина в том, что parrot еще не предлагает JIT-компиляцию, а сборщик мусора не самый быстрый. Есть планы по созданию JIT-компилятора, и люди работают над ним (предыдущий был сорван, потому что это был только i386 и кошмар обслуживания). Есть также мысли о переносе Rakudo на другие виртуальные машины, но это наверняка подождет до конца июля.
В конце концов, никто не может точно сказать, насколько быстрой будет полная, хорошо оптимизированная реализация Perl 6, пока она у нас не будет, но я действительно ожидаю, что она будет намного лучше, чем сейчас.
Кстати, случай, который вы процитировали [+] 1 .. $ big_number
, можно заставить работать в O (1), потому что 1 .. $ big_number
возвращает диапазон, который самоанализ. Таким образом, вы можете использовать формулу суммы для случая [+] Range
. Опять же, это то, что можно сделать, но это еще не сделано.
Я отправил их на языковой конкурс Fefe в декабре 2008 года. wp.pugs.pl
- это дословный перевод примера Perl 5, ] wp.rakudo.pl
намного шире. У меня две программы, потому что они реализуют разные подмножества спецификации. Информация о сборке пока что устарела.Источники:
#!/usr/bin/env pugs
# Pugs: <http://pugs.blogs.com/> <http://pugscode.org/>
# prerequisite: ghc-6.8.x, not 6.10.x
# svn co http://svn.pugscode.org/pugs/
# perl Makefile.PL
# make
# if build stops because of haskeline, do:
# $HOME/.cabal/bin/cabal update ; $HOME/.cabal/bin/cabal install haskeline
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
my %words;
for =<> {
for .split {
%words{$_}++
}
}
for (sort { %words{$^b} <=> %words{$^a} }, %words.keys) {
say "$_ %words{$_}"
}
#!/usr/bin/env perl6
# Rakudo: <http://rakudo.org/> <http://www.parrot.org/download>
# svn co http://svn.perl.org/parrot/trunk parrot
# perl Configure.pl
# make perl6
# Solution contributed by Frank W. & Moritz Lenz
# <http://use.perl.org/~fw/journal/38055>
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
my %words;
$*IN.lines.split(/\s+/).map: { %words{$_}++ };
for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair {
say $pair
}
Это были результаты в 2008 году:
$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
real 0m2.529s
user 0m2.464s
sys 0m0.064s
$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
real 0m32.544s
user 0m1.920s
sys 0m0.248s
Сегодня:
$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
real 0m5.105s
user 0m4.898s
sys 0m0.096s
$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
Divide by zero
current instr.: '' pc -1 ((unknown file):-1)
Segmentation fault
real 0m3.236s
user 0m0.447s
sys 0m0.080s
Поздние дополнения: сбой был рассмотрен на . Почему я получаю ошибки «делить на ноль», когда я пытаюсь запустить свой сценарий с Ракудо? . Программа Rakudo неэффективна, см. комментарии ниже и http://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/ .