Perl
مقدمه
Perl یک زبان برنامهنویسی سطع بالای عام منظوره است که توسط مفسر اجرا می شود. Perl یک زبان پویا است. زبان برنامهنویسی پویا به زبانی گفته میشود که بسیاری از کارهایی را که زبانهای برنامهنویسی دیگر در زبان کامپایل انجام میدهند، در زمان اجرا انجام میدهد. این اعمال، میتواند شامل این موارد باشد: افزودن کد جدید(مانند تابع eval که در جاوا اسکریپت بیان کردیم)، توسعهی اشیا (مانند افزودن یا حذف فیلد و یا متد از یک شی موجود و یا تغییر کلاس آن) و یا تغییر سیستم تایپ (مانند استفاده از reflection).
تاریخچه
Perl در ابتدا در سال 1987 توسط لری وال ایجاد شد. هدف از ایجاد این زبان اسکریپتی، تسهیل فرآیند گزارشگیری در یونیکس بود. پس از آن، این زبان دچار تغییرات عمدهای شد و آخرین نسخهی این زبان، که در سال 2012 منتشر شد، نسخهی 5.16 است. همچنین در سال 2000 اعلام شد که این زبان در حال طراحی مجدد است، اما همچنان در حال توسعهی فعال است.
این زبان ویژگیهایی را مرهون زبانهایی مانند C، شل اسکریپت، AWK و sed است. این زبان، ابزارهای قدرتمندی را برای پردازش متن در اختیار کاربران قرار میدهد که بسیاری از محدودیتهای ابزارهای مدرن در یونیکس را نداشت. Perl امکان دستکاری فایلهای متنی را در اختیار کاربران قرار میدهد. این زبان در اواخر دههی 90، به دلیل وجود امکانات پارس کردن، محبوبیت گستردهای را در اسکریپتینگ برای CGI(Common Gateway Interface) به دست آورد.
در مستندات این زبان آمده است که این زبان با هدف عملی بودن(سادگی در استفاده، کارایی، و کامل بودن) ایجاد شده است و نه زیبایی(تمیز بودن، کمینگی...).
آموزش زبان
در ادامه به بررسی زبان به همراه کدهای نمونه میپردازیم. همچنین به نکات مهم این زبان نیز به طور پیوسته، هر جا که لازم بود، اشاره میکنیم.
برای اجرای یک برنامهی Perl، کافی است کد آن را در فایلی، مثلا با نام prog.pl، ذخیره کرده و سپس از دستور زیر استفاده کنیم:
perl prog.pl
و یا میتوان در خط اول فایل مورد نظر قرار داد:
#!/usr/bin/perl
و سپس با تغییر مد فایل به ۷۵۵ با دستور زیر این اسکریپت را اجرا کرد:
./prog.pl
Perl در پردازش فایل ورودیاش، تا حد امکان از خطاها صرف نظر میکند. برای این که از این مفسر بخواهیم که این کار را انجام ندهد، میتوانیم این دو خط را به اول فایلمان بیافزاییم:
#!/usr/bin/perl use strict; use warnings;
در Perl نیازی به داشتن تابعی مانند main نیست. همچنین در این زبان، فضاهای سفید در نظر گرفته نمیشوند به جز در بین دو علامت نقل قول:
print "Hello, World."; # <- this is a comment
نتیجه به این صورت خواهد بود:
Hellow, World.
تعریف متغیر و استفاده از آن در چاپ در خروجی در این زبان به این صورت انجام میپذیرد:
my $animal = "camel"; print "my animal is $animal";
توجه کنید که در این جا ما تایپ متغیر را تعریف نکردیم و این موضوع به صورت ضمنی(implicit) مشخص میشود. بنابراین نوع بررسی تایپ این زبان از نوع ضعیف است. حتی این زبان در صورت لزوم تبدیلات لازم را انجام میدهد.
نکتهی دیگری که در اینجا وجود دارد این است که همان طور که در بالا مشخص است، identifier های این زبان با $ آغاز میشوند. البته این همیشه درست نیست. در حقیقت همیشه با یک sigil آغاز میشوند. بنابراین روشی که این زبان در حل مشکل کلمات کلیدی انتخاب کردهاست این است که identifierها را از کلمات کلیدی با یک کاراکتر در ابتدایشان مشخص میکند. این راه حل بسیار شبیه پیادهسازی php است.
برای تعریف آرایه و استفاده از آن نیز باید به این صورت استفاده کرد:
my @animals = ("camel", "llama", "owl"); print $animals[0];
توجه کنید که برای تعریف آرایه از علامت @ و برای مشخص کردن یک عضو خاص آن از $ استفاده میکنیم.
هم چنین این زبان، انجام برخی کارهای مهم مانند مرتب سازی را به این سادگی در اختیار ما قرار میدهد:
my @sorted = sort @animals; my @reversed = reverse @animals; my @subarray = @animals [1..@#animals]; # note that @#animals gives the last index
داده ساختار دیگری که در این زبان وجود دارد hash نام دارد که همان map در جاوا است! برای تعریف آن میتوان به صورت زیر عمل کرد:
my %fruit_color = ( apple => "red", banana => "yellow", ); print "the color of apple is $fruit_color{'apple'}\n"; my @fruits = keys %fruit_color; my @colors = values %fruit_color;
در این زبان، scope هر متغیر تا انتهای بلاکی است که در آن تعریف شدهاست و همچنین این زبان static scope است.
ساختارهای شرطی و حلقه
در این زبان ساختار شرطی به صورتهای زیر موجود است:
if (condition) { ... } elsif (other condition) { ... } else { }
unless (condition) { # this is a short hand of if(!condition) ... }
دستورهای حلقهای نیز به این صورت وجود دارند:
while (condition) { ... }
unless (condition) { # the same as unless ... }
syntax حلقهی for آن کاملا مانند زبان C است:
for ($i = 0;$i < 10;$i ++) { ... }
همچنین امکان استفاده از foreach نیز در این زبان وجود دارد:
foreach my $key (keys %hash) { ... }
عملگر های Perl
در این زبان تمامی عملگرها دقیقا مشابه زبان C هستند، با یک تفاوت کوچک: برای مقایسهی رشتهها از عملگرهایی مانند eq، ne، lt و ... باید استفاده کرد. دلیل این تفاوت نکتهی جالبی است که به weak typing بودن زبان بر میگردد. در تعریف یک متغیر این زبان، نه تنها در هنگام تعریف تایپی نسبت داده نمیشود، بلکه در هنگام اجرا نیز اگر لازم باشد "72" را به عدد ۷۲ نیز تبدیل میکند. از طرف دیگر، عدد ۱۰۰ به عنوان یک عدد باید از ۹۹ بیشتر باشد، در حالتی که به عنوان یک رشته باید کوچکتر باشد. بنابراین ما نیاز داریم از عملگرهای متفاوتی برای مشخص کردن این تفاوت استفاده کنیم.
استفاده از فایل ورودی و خروجی نیز در این زبان بسیار ساده است:
open (my $in, "<", "input.txt") or die ("Can't open input.txt"); # kind of exception handling! open (my $out, ">", "output.txt"); open (my $log, ">>", "my.log"); my $line = <$in>; # for reading one line my $lines = <$in>; # for reading whole file
توجه کنید که همانطور که قبلا گفته بودیم، این زبان امکان کار با فایل و رشتهها را به شیوهای بسیار ساده در اختیار ما قرار میدهد. کد بالا را با کد معادلش در زبانهای دیگر مانند جاوا مقایسه کنید. طبیعتا، در چنین زبانی باید استفاده از عبارات منظم نیز به سادگی و گستردگی میسر باشد. حال به بیان عبارات منظم در این زبان میپردازیم:
عبارات منظم
بررسی وجود یک زیررشتهی خاص در یک رشتهی موجود به این صورت انجام میشود:
if ($a =~ /foo/) { ... }
برای جانشین کردن یک رشته با رشتهای دیگر نیز از کدهای زیر میتوان استفاده کرد:
$a =~ s/foo/bar/; # substituting first foo with bar $a =~ s/foo/bar/g; # substituting ALL foo's with bar
به عنوان آخرین نکته، میتوان از تکه کد زیر برای استخراج نام کاربری و نام میزبان یک رایانشانی استفاده کرد. عبارات داخل پرانتز، هر کدام، با 1$ و 2$ مشخص میشوند.
if ($email =~ /([^@]+)@(.+)/) { print "Username is $1"; print "Hostname is $2"; }
تعریف زیر رویهها
نوشتن زیر رویه به سادگی کد زیر است:
sub logger { my $logmessage = shift; open my $logfile, ">>", "my.log" or die "could not open log file"; print $logfile $logmessage; }
و صدا زدن این رویه به صورت زیر است:
logger ("We have a logger subroutine");
اما این کد چگونه کار میکند؟ اولا روشن است که با عبارت sub logger مشخص کردهایم که میخواهیم زیر رویهای با نام logger داشته باشیم. اما shift چیست؟ در Perl، ورودیهای یک تابع در متغیری به نام _@ قرار دارند. از طرفی در داخل تعریف توابع، توابعی که با آرایههای کار میکنند مانند push، pop، shift و unshift به صورت پیشفرض این آرگومان را دریافت میکنند. کار تابع shift همانطور که از نامش پیداست، حذف اولین عنصر یک لیست و برگرداندن آن است. بقیهی کار این رویه نیز واضح است.
این نوع پاس دادن آرگومان، خلاف اصول Impossible Error Principle و Defence in Depth Principle است.
شیگرایی در Perl
در Perl شیگرایی به صورت کمینه وجود دارد. البته Perl از مفاهیمی چون inheritance، encapsulation و polymorphism که پایههای شیگرایی هستند پشتیبانی میکند. حتی از وراثت چندگانه نیز پشتیبانی میکند. در این زبان syntax خاصی برای ساخت یک شی وجود ندارد. بلکه اشیا، معمولا دادهساختارهای خود Perl هستند که به صورت صریح به کلاسها نسبت داده میشوند. این انتساب با کمک تابع بطنی bless صورت میگیرد که معمولا در سازندهی شی استفاده میشود.
در این جا، مثالی از تعریف یک کلاس را به همراه سازندهاش میتوانید مشاهده کنید:
package A; sub new { my $class = shift; return bless {}, $class; } my $anInstance = A->new;
در اینجا نکات جالبی دیده میشود. اولا برای تعریف کلاس، از دستور package استفاده میشود! در اینجا ما در حال تعریف کلاس A هستیم. حال، برای این کلاس، متدی با نام new نوشتیم که نقش سازندهی این کلاس را بازی خواهد کرد. توجه کنید که new کلید واژه نیست و هر نام دیگری را میتوان برای این متد میتوان قرار داد. هرچند که در CPAN(Comprehensive Perl Archive Network) مرسوم است که از new استفاده میکنند. حال، این سازنده با کمک دستور shift که پیشتر بیان شد، ابتدا نام کلاسش را میگیرد. سپس با کمک دستور bless مجموعهی فیلدهای این کلاس را که در اینجا hash خالی {} است را به کلاس class$ مربوط میکند. خروجی این تابع شی ساخته شده است که با کمک A->new ساخته میشود.
حال، برای این که این کلاس، کلاس دیگری را توسعه دهد، کافی است از دستور زیر بلافاصله بعد از package استفاده شود:
use parent 'A', 'B', ...;
در این زبان، متد ها را میتوان به همان شیوهی سازنده تعریف نمود و استفاده از فیلدها نیز به این صورت انجام میپذیرد:
package Student; sub new { my $class = shift; my $name = shift; my $id = shift; my $self = { name => $name, id => $id, }; bless $self, $class; }; sub print_info { my $self = shift; print "Student name = $self->{name} ", "and Student id = $self->{id}\n"; }; my $student = Student->new ("Nima Hamidi", 87109956); $student->print_info ();
منابع
خیلی ممنون بابت مطلب مفیدتون.
ببخشید منبع فارسی زبانی هم میشناسید که به طور جامع تر این زبان رو یاد بده؟
راستی این زبان شباهت زیادی به php داره، درسته؟