Автор Тема: Новые вопросы новичка...  (Прочитано 3117 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн metton

  • access granted
  • Старожил
  • ****
  • Сообщений: 320
  • +0/-0
  • 2
    • Просмотр профиля
    • http://bluejack.ru/
Новые вопросы новичка...
« : 13 Апреля 2003, 23:49:01 »
Всем привет!
В процессе изучения Perl-а по мануалке возникли следующие вопросы:

1. Почему при фразе в мануале по Перлу:
"The elements we\'re getting from the array start with a $ because we\'re getting just a single value out of the array -- you ask for a scalar, you get a scalar."
имеет место быть такая конструкция: @foo_ar0000[0], так же как и $foo_ar0000[0], возвращающая первый элемент из массива @foo_ar0000?
Почему также @foo_ar0000[0] и @foo_ar0000->
  • суть одно и то же, иными словами, что делает оператор -> ? И почему тогда $foo_ar0000[0] и $foo_ar0000->
  • не одно и то же, и %foo_hash0000->{"apple"} и %foo_hash0000{"apple"} не одно и то же?


Вот пример кода:

my @foo_ar0000 = ("camel", 23, 1.23);
print ("\\@foo_ar0000[0]: ", @foo_ar0000[0], "
\\n");
print ("\\$foo_ar0000[0]: ", $foo_ar0000[0], "
\\n");
print ("\\@foo_ar0000->
  • : ", @foo_ar0000->
  • , "
    \\n");

print ("\\$foo_ar0000->
  • : ", $foo_ar0000->
  • , "
    \\n");


my %foo_hash0000 = ("apple", "red", "banana", "yellow");
print ("\\%foo_hash0000{\\"apple\\"}: ", %foo_hash0000->{"apple"}, "
\\n");
print ("\\%foo_hash0000->{\\"apple\\"}: ", %foo_hash0000{"apple"}, "
\\n");

(последняя сточка выдаёт ошибку)


2. Почему, когда я пытаюсь использовать примечание из мануала по перлу ("You can also extend an array by assigning
to an element that is off the end of the array."): присвоить, например, 2300 элементу что-либо, а затем распечать массив, то скрипт начинает "подвисать"; причём, начинает виснуть на разных значениях индексов: иногда - начиная с 10, иногда - с 23?

Например:
my @foo_ar0001 = ("camel", 23, 1.23, "metton_bar");
print ("\\@foo_ar0001: ", @foo_ar0001, "
\\n");
print ("\\@foo_ar0001*1: ", @foo_ar0001*1, "
\\n");
print ("\\$#foo_ar0001: ", $#foo_ar0001*1, "
\\n");
$#foo_ar0001 = 10;
print ("\\$foo_ar0001[22] = 10;
\\n");
print ("\\@foo_ar0001: ", @foo_ar0001, "
\\n");
print ("\\@foo_ar0001*1: ", @foo_ar0001*1, "
\\n");
print ("\\$#foo_ar0001: ", $#foo_ar0001*1, "
\\n");
$foo_ar0001[2300] = "13rd element";
print ("\\$foo_ar0001[22] = 22;
\\n");
print ("\\@foo_ar0001: ", @foo_ar0001, "
\\n");
print ("\\@foo_ar0001*1: ", @foo_ar0001*1, "
\\n");
print ("\\$#foo_ar0001: ", $#foo_ar0001*1, "
\\n");
- виснет, а если убрать 3-ю с конца строчку, то всё нормально...


3. Не понимаю вот этого отрывка из мануала:
If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash. This is pretty much useful only to find out whether Perl\'s internal hashing algorithm is performing poorly on your data set. For example, you stick 10,000 things in a hash, but evaluating %HASH in scalar context reveals "1/16", which means only one out of sixteen buckets has been touched, and presumably contains all 10,000 of your items. This isn\'t supposed to happen.
А именно, что такое bucket (не перевод, а именно ЧТО ЭТО), и что возвращает хэш в скалярном контексте?
И ещё: $#hash0000 возвращает -1. Что это за значение?

Заранее спасибо!
 BlueJacking среди нас

Оффлайн metton

  • access granted
  • Старожил
  • ****
  • Сообщений: 320
  • +0/-0
  • 2
    • Просмотр профиля
    • http://bluejack.ru/
Новые вопросы новичка...
« Ответ #1 : 14 Апреля 2003, 20:24:16 »
Люди!
Ответьте, плз!
 BlueJacking среди нас

Оффлайн КшЫуфксрук

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 99
  • +0/-0
  • 0
    • Просмотр профиля
    • http://risearch.org/
Новые вопросы новичка...
« Ответ #2 : 14 Апреля 2003, 20:29:44 »
А документацию читать не пробовали? Нет, я конечно понимаю, что Перл иногда позволяет писать странные вещи, и они будут работать. Но это не значит, что можно придумывать различные конструкции и ждать, что они заработают. Пару раз вам "повезло", и то, что вы написали, работало так, как хотелось, но не потому, что так должно быть, а просто так совпало.

1) @foo_ar0000[0] возвращает не первый элемент массива, а список, состоящий из первого элемента массива. А оператор "->" означает разыменование ссылки. Подробнее в документации - perlref, perlreftut, perldsc, perllol.

2) Ничего не виснет. Хотя я предпочитаю писать scalar(@array).

3) Что такое bucket можно понять, прочитав описание структуры хешей в любой книге по структурам данных и алгоритмам. Только все равно эта информация никак не поможет при программировании на Перле. Просто примите как данность, что он возвращает такую штуку в скалярном контексте. А для того, чтобы узнать, сколько ключей находится в хеше, нужно использовать такую конструкцию - scalar keys %hash.

Оффлайн metton

  • access granted
  • Старожил
  • ****
  • Сообщений: 320
  • +0/-0
  • 2
    • Просмотр профиля
    • http://bluejack.ru/
Новые вопросы новичка...
« Ответ #3 : 14 Апреля 2003, 21:25:24 »
КшЫуфксрук
Огромное спасибо :)

> А документацию читать не пробовали?
Я по ней и изучаю...

> @foo_ar0000[0] возвращает не первый элемент массива, а
> список, состоящий из первого элемента массива

Вот за это отдельное спасибо - терь понятно :)

> А оператор "->" означает разыменование ссылки.
Это как в Си * (взять адрес и возвратить то что по нему лежит)?

> Ничего не виснет.
А у меня всё время виснет... =(
Почему такое может быть, не знаешь?

> Хотя я предпочитаю писать scalar(@array).
Тут ты, видимо, не совсем меня понял. Виснет не из-за @foo_ar0001*1, а из-за присвоения элементу с индексом, большим какому-то (всё время разному - иногда - 12, иногда - 23). Вот такая комбинаяция строк кода, например, по любому виснет:
$foo_ar0001[2300] = "13rd element";
print ("\\@foo_ar0001: ", @foo_ar0001, "
\\n");

> Просто примите как данность, что он возвращает такую штуку в
> скалярном контексте. А для того, чтобы узнать, сколько ключей
> находится в хеше, нужно использовать такую конструкцию - scalar
> keys %hash.
Но всё же (понятно, что scalar keys %hash возвращает количество) хотелось бы узнать, что это за штука. Сначала я подумал, что это "количество пар ключ-значение"/"количество зарезервированных для данного хэша (пустых) ключей". Но потом я увидел, что, например, при приведённом выше кэше с такой строчкой кода:
keys(%hash0000) = 1;
хэш в скалярном контексте возвращает 7/16, хотя ключей УЖЕ 8. Тут я прочитал ещё раз этот раздел документации (perldata), и обратил внимание на строчку, на которую до этого не обратил внимания так как не очень-то верилось глазам:
If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash. This is pretty much useful only to find out whether Perl\'s internal hashing algorithm is performing poorly on your data set.
Т.е. это плохая совместимость перла с моим data set (хм... набор данных... имеется ввиду набор данных в данном хэше?) или всё же можно как-то предсказать, а, следовательно, использовать (нет, я, конечно, понимаю - можно и непредсказуемому значению найти применение - чем не генератор случайных чисел? :)) это значение?
 BlueJacking среди нас

Оффлайн КшЫуфксрук

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 99
  • +0/-0
  • 0
    • Просмотр профиля
    • http://risearch.org/
Новые вопросы новичка...
« Ответ #4 : 14 Апреля 2003, 22:58:24 »
> Это как в Си * (взять адрес и возвратить то что по нему лежит)?

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

> Вот такая комбинаяция строк кода, например, по любому виснет:

$foo_ar0001[2300000] = "13rd element"; - не виснет
$foo_ar0001[23000000] = "13rd element"; - немного подтормаживает, потому как памяти не хватает и приходится своп задействовать.
$foo_ar0001[230000000] = "13rd element"; - выдает "Out of memory!".

> Сначала я подумал, что это "количество пар ключ-значение"/"количество зарезервированных для данного хэша (пустых) ключей".

Почти так. Только хеш резервирует не ключи, а "bucket". В двух словах хеш работает примерно так:

Создается таблица из N ячеек (в случае Перла в каждой ячейке будет находится "ссылка" на линейный список). Для каждого ключа вычисляется некая функция, которая возвращает число в пределах 0-N. Данная пара ключ-значение помещается в линейный список с номером равным hashfunction($key) (данный линейный список просто просматривается и если такой ключ там уже был, значение заменяется на новое, если не было, добавляется в конец списка).

То есть хеш просто раскидывает данные по многим линейным спискам, чтобы ускорить поиск. И строка 7/16 означает, что в данный момент зарезервировано 16 линейных списков (при добавлении данных хеш иногда перестраивается), из которых в семи есть хотя бы один элемент.

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28