Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Типы данных в Perl
Форумы портала PHP.SU » » Уроки и статьи по Perl/Python/.NET » Типы данных в Perl

Страниц (1): [1]
 

1. JustUserR - 12 Ноября, 2009 - 16:30:54 - перейти к сообщению
Как запускать Perl-скрипты

На самом деле Perl является достаточно мощным языком, и поддерживает различные типы и операции над ними, но для новичков некоторые операции являются непривычними, и могут не согласовываться со знаниями полученными из других языков
Дальнеший материал изложен на основе моего диалога с одним новичком в Perlе

1) Итак общеизвестно, что в Perl имеются 4 основных типа данных - скаляр $ (Число, строка или ссылка), массив @ (Одномерный массив скалярных элементов), хеш % (Ассоциативный массив) и процедура & (Исполняемый кусок кода, в Perl исполняемый код почти наравне с данными)
Мы можем с легкостью создавать ссылку на любой из данных элементов, с помощью оператора \, это будет так называемая жесткая ссылка
CODE (perl):
скопировать код в буфер обмена
  1. $sv_vr="ABC"; # Создали скалярную переменную типа строка, напомню что двойные кавычки отличатся от одиночных наличием интерполяции (Подстановки переменных в них)
  2. $sv_ref=\$sv_var; # Создали ссылку на это скалярную переменную
  3. @ar_vr=(1,2,3); # Создали массив из численных элементов
  4. $ar_ref=\@ar_vr; # Создали ссылку на этот массив

Для получения доступа к объекту обратно по ссылке, применяется символика данного типа
CODE (perl):
скопировать код в буфер обмена
  1. $n_sv_vr=$$sv_ref; # В переменной $n_sv_vr получим копию, сделанную с переменной $sv_vr
  2. @n_ar_vr=@$ar_ref; # В переменной @n_ar_vr получим копию, сделанную с переменной @ar_vr

Заметим, что если копировать только ссылка на объекты, но сами объекты разумеется копироваться не будут, чего и следовало ожидать
Таких уровней вложенности может быть сколь угодно много, кстати именно таким же образом можно создавать многомерные массивы, то есть в многомерном массиве на самом деле будут храниться не другие массивы, а просто ссылки на них, что весьма логично
CODE (perl):
скопировать код в буфер обмена
  1. @a1=(1,2,3); @a2=("a","b","c"); # Создали два массива
  2. @am=(\@a1,\@a2); # Создали массив ссылок на массивы
  3. print ${$am[0]}[1]; # Выведет 2, так как $am[0] это фактически ссылка на массив @a1, @{$am[0]} это фактически ключ доступа к массиву @a1, тогда ${$am[0]}[1] это второй элемент массива @a1 (Нумерация разумеется, с нуля) Кстати необходимо помнить, что в пути доступа к некоторому конечному элементу многомерного массива (То есть не к подмассиву, а именно к конечному элементу) могут встречаться только знаки [b]$[/b] (И некоторые другие), но знаков [b]@[/b] быть не может в принципе, если они у вас вдруг встретились, то это логическая ошибка

Способ указанный выше, работает хорошо, однако на практике создание многомерных массивов таким образом, а также доступ к их элементам может быть затруднителен, поэтому используется альтернативная схема доступа
CODE (perl):
скопировать код в буфер обмена
  1. $am=[[1,2,3],["a","b","c"]]; # Фактически то же самое, что и выше
  2. print $am->[0]->[1]; # Выведет 2 как и выше, только теперь не нужно шаманство с фигурными скобками и знаками [b]$[/b]
  3. print $am->[0][1]; # То же самое, так как оператор [b]->[/b] немного изменяет функцию квадратных скобок, и как бы подставляет [b]->[/b] между скобками автоматически Если вам не нужно такое поведение, то придется использовать способ, указанный выше (С фигурными скобками и знаками [b]$[/b])

Все это также отлично работает и с хешами, только все квадратные скобки меняются на фигурные, и заместо индексов массива появлятся ключи хеша Разумеется, с помощью первого способа также можно работать с хешами, но мы рассмотрим более простой, второй способ
CODE (perl):
скопировать код в буфер обмена
  1. $hc={x=>{a=>1,b=>2,c=>3},y=>{m=>4,n=>5}}; # Создаем многомерный хеш (Обратите внимание на отсутствие кавычек у ключей хеша, это можно делать для анлгийский слов без пробема, иначе кавычки обязательно нужны)
  2. print $hc->{y}{m}; # Выведет 4, все по полной аналогии с массивами, как и обещалось ранее

Что касается процедур, то с ними тоже можно делать много интересного, но это будет рассмотрено отдельно
Итак, на этом можно закончить краткий экскурс, к типам данных и ссылкам? Нет нельзя, потому что обычно из ассмотрения выбывают еще два важных типа, которые важные сколько применением, сколько некоторыми важными сведениями об общих сведениях о ссылках
Эти типы данных - FILEHANDLER и FORMAT, и предназначены они соответственно для работы с файловыми дескрипторами и щаблонами форматов Чем же они так особенны? А тем что весь предыдущий механизм использования ссылок для них не будет работать
CODE (perl):
скопировать код в буфер обмена
  1. fopen(FH,"file.txt") # Именно таким образом создается файловый дескриптов FH
  2. format FM ... # На самом деле форматы используются редко, а в web-программировании вообще не нужны, но тут дело принципа

И что же мы видим, получаем что переменная одного из этих типов в Perl, не имеет никакого значка - идентификатора типа, и собственно разыменовать ее никак нельзя, равно как нельзя поставить знак получения ссылки \ перед ней Как же быть? На самом деле можно воспользоваться другим подходом, к Perl-переменной можно обращаться другим методом
CODE (perl):
скопировать код в буфер обмена
  1. *vr_name; # Означем все переменные с именем vr_name - это может быть и скаляр, и массив, и тот же FILEHANDLER Такое имя переменной со [b]*[/b] называется TYPEGLOB
  2. *FH{FILEHANDLE}; # То же самое, что и FH при подстановке в дескриптор, но такая переменная уже является настоящий
  3. $fh_rf=\*FH{FILEHANDLE}; # А вот таким образом, мы получили заветную ссылку на дескриптор FH

Хотя это и будет работать, на практике такой подход применяется редко, дело в том что Perl в некоторых случаях может по общему TYPEGLOB сам выбирать нужный подтип (Это в первую очередь касается FILEHANDLER), и поэтому допустима такая запись
CODE (perl):
скопировать код в буфер обмена
  1. fopen(*FH,"file.txt"); # Perl сам подставил заместо *FH выражение *FH{FILEHANDLER}, учтите что в Perl переменные создаются на ходу

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

2) Основными и используемыми по умолчанию в Perlе являются глобальные динамические переменные, которые как бы никогда не создаются и не удаляются, с ними можно работать по первому обращению, а чтобы очистить содержимое переменной можно присвоить ей значение undef
Однако в Perl также можно создавать локальные и лексические переменные, что тоже связано с определенными особенностями, которые как раз стоит рассмотреть
CODE (perl):
скопировать код в буфер обмена
  1. our $sv; # То же самое что и просто $sv, от такого объявления ничего по сути не меняется, если выключена use strict

Предже чем рассмотреть локальные и лексические переменные, надо определиться с понятием области видимости Если использовать только глобальные переменные, то никакой области видимости не будет вообще, так как переменные могут быть достутны отовсюду Иначе мы можем вводить различные области видимости, в блоках и процедурах
CODE (perl):
скопировать код в буфер обмена
  1. my $sc_vr_1="ABC"; # Идентификатор my перед объявлением перменной делает ее локальной, если объявить переменную с my в глобальной области видимости, то от этого она не станет глобальной (Конечно в плане обращения, к ней можно будет обратиться отовсюду, но правило перекрытия локальный перменных на нее будет действовать, и она уже не будет диманической)
  2. {my $sc_vr_2=10; print $sc_vr_1; print $sc_vr_2; } # Создали блок, в Perl не обязательно связывть блок с if(1) {}, можно просто писать фигурные скобки Такая конструкция выведет ABC и 10
  3. print $sc_vr_1; print $sc_vr_2; # Мы вышли из блока и локальная переменная удалилась, поэтому выведен ABC и undef

Однако в Perl помимо our и my, есть еще и local, предназначение которой на первой взгляд является немного странным, а именно при объявлении переменной как local идет работа с глобальной одноименной переменной, но значение глобальной переменной сохраняется Perlом в секретное место (В плане того что к старому значению, получить доступ нельзя), а по выходу из блока где была объявлена переменная local, глобальная переменная восстанавливает свое старое значение (Если ее ранее не было, то она получает значение undef)
Практическая пользя от local достагается только тогда, когда используется набор выполняемый процедур, где одна выполняет другую и при этом процедуры используют глобальные переменные В таком случае процерура, которая была вызвана более первой, может подменить значение глобальной переменной, и вызываемая ей функция будет использовать именно его Заметим, что в роли глобальной переменной может выступать и локальная, лишь бы она была определена в более главном блоке, и была полностью видема из процедур
CODE (perl):
скопировать код в буфер обмена
  1. my $sv=10; &sv1; # Локальная переменная, с фактически глобальной областью видимости, а также вызов первой процедуры
  2. sub s1 {my $sv=20; print $sv; &s2;} # Первая процедура изменяет внутри себя переменную $sv (По правилу перекрытия локальных переменных), и будет выведено значение 20
  3. sub s2 {print $sv;} # Вторая процедура видит глобальное значение $sv==10, и выведет именно 10

А теперь рассмотрим случай с local (Заметим что никакой странности в таком поведении нет, потому что в Perl нет параллельно-выполняющихся потоков, и всегда будет четко видно, изменена или не изменена ли переменная с помощью local)
CODE (perl):
скопировать код в буфер обмена
  1. my $sv=10; &s1; # Локальная переменная, с фактически глобальной областью видимости, а также вызов первой процедуры
  2. sub s1 {local $sv=20; print $sv; &s2;} # Первая процедура фактически на время своего выполнения изменяет значение переменной $sv на 20, и поэтому будет выведено 20
  3. sub s2 {print $sv;} # Вторая процедура видит глобальное значение $sv==20, и выведет 20
  4. &s2; # А это вызов второй процедуры уже без влияний первой, соответсвенно будет выведено опять 10




To be continued...
2. movEAX - 13 Ноября, 2009 - 14:23:03 - перейти к сообщению
Хороший урок, но текст прям "месиво"))
3. Ch_chov - 13 Ноября, 2009 - 14:33:09 - перейти к сообщению
CODE (perl):
скопировать код в буфер обмена
  1. print ("Перловая подсветка работает!!!");
4. Champion - 13 Ноября, 2009 - 15:45:00 - перейти к сообщению
Ща буду вопросами тебя обсыпасть) С понедельника изучаю перл, надеюсь у тебя лучше получилось объяснить то, что я в других книжках не понял)
5. JustUserR - 13 Ноября, 2009 - 18:18:07 - перейти к сообщению
Товарищи movEAX, Ch_chov - спасибо за отзывы и подсказку
Champion - спасибо за отзыв, это хорошо что будешь вопросами осыпать, опробую свою консультацию на тебе Улыбка
PS Урок еще не закончен, как написано внизу To be continued
6. EuGen - 14 Ноября, 2009 - 16:04:00 - перейти к сообщению
Присоединюсь к обмену опытом, что-то наверное сам почерпну, чему-то смогу научить при необходимости
7. Champion - 20 Ноября, 2009 - 16:36:53 - перейти к сообщению
JustUserR пишет:
напомню что двойные кавычки отличатся от одиночных наличием интерполяции (Подстановки переменных в них)
Наверное, это все-таки интерпретация.
Цитата:
Интерполяция в математике и статистике, отыскание промежуточных значений величины по некоторым известным её значениям
8. JustUserR - 21 Ноября, 2009 - 13:05:51 - перейти к сообщению
Champion пишет:
Наверное, это все-таки интерпретация.
Может быть это неудачный термин, в связи с тем что в математике он означает другое, но всетаки это называется именно так - можете посмотреть оригинальную литературу, скажем Learning Perl или Programming Perl

Кстати в Perl не двойной интерполяции переменных, что означает то что если в строку интерполируетс другая строка, и эта другая строа содержит переменные, то они не будут интерполированы второй раз Таким образом, чтобы запртить интерполяцию переменных в строках, можно заместо имени строки $str в выражениях подстановки писать "$str" Хотя более верный вариант это одиночные кавычки
9. Champion - 17 Декабря, 2009 - 09:35:02 - перейти к сообщению
Может, я чересчур придираюсь, но захотел я на практике попрактиковаться, пощупать типы данных. А как? Где взять перл? Как оформить программу? Требую Hello World!
(Добавление)
Хотя бы в самом начале что-то типа:
Все примеры вы можете попробовать у себя, ставим перл так-то отуда-то, пишем скрипт
CODE (perl):
скопировать код в буфер обмена
  1. #!/где/там/у/нас/перл
  2. print "Uhhh!"
10. JustUserR - 17 Декабря, 2009 - 13:28:33 - перейти к сообщению
Champion пишет:
Может, я чересчур придираюсь, но захотел я на практике попрактиковаться, пощупать типы данных. А как? Где взять перл? Как оформить программу? Требую Hello World!
Хотя бы в самом начале что-то типа:
Все примеры вы можете попробовать у себя, ставим перл так-то отуда-то, пишем скрипт
Нет вы совершенно правы, я начал статью http://forum.php.su/topic.php?fo...m=65&topic=3 , где изложил теорию, как работает CGI и Perl в общем, чтобы стало понятнее Улыбка В ближайшее время буду дописывать и пополнять
Буду раз любым комментариям и критике Улыбка

 

Powered by ExBB FM 1.0 RC1