Fonksiyonların dinamik olarak oluşturulması ve çağrılması, Perl'in en esnek mekanizmalarından biridir, Lateks ve shell betiği geleneklerinden gelmektedir. Perl'in erken sürümlerinden itibaren, fonksiyonların dize ile (sembolik bağlantılar/globlardan) çağrılmasına, alt programlara referansların değişkenlerde ve ilişkilendirilmiş dizilerde saklanmasına ve AUTOLOAD yapısının anında fonksiyonlar üretmek için kullanılmasına izin verilmektedir.
Bu yaklaşımın en büyük sorunu güvenlik (istenmeyen bir fonksiyonun sahte bir dize ile çağrılması olasılığı) ve performanstır (sembolik ad çözümü, doğrudan çağrıdan daha yavaştır). Ayrıca, fonksiyonların görünürlük alanını kontrol etmek ve doğru argüman sayısını sağlamak önemlidir.
Çözüm - bir hash dispatcher kullanmak (dize/anahtar haritası ile coderef'e), kullanıcı kodunu çalıştırmak için eval'den kaçınmak ve çağırılmasına izin verilen fonksiyonların kesin listesini belirlemektir.
Anahtar ile (dispatch) örnek kod:
my %dispatch = ( add => sub { $_[0] + $_[1] }, sub => sub { $_[0] - $_[1] }, mult => sub { $_[0] * $_[1] }, ); my $key = 'add'; if (exists $dispatch{$key}) { print $dispatch{$key}->(2, 3); # 5 çıktı verir } else { die "Bilinmeyen eylem $key"; }
Anahtar özellikler:
Sadece bir dize kullanarak bir fonksiyonu adıyla çağırmak mümkün mü?
Cevap: Evet, ancak bu tehlikeli - $fn_name->() ile çağırmak veya doğrudan sembolik bağlantı ile &$fn_name(); kullanmak, dış (kullanıcı) verileri ile önerilmez, çünkü bu potansiyel zayıflıklara yol açar.
Perl'de kod referansı ile fonksiyon adı arasında fark var mı?
Cevap: Evet, fonksiyon adı her zaman küreseldir, oysa fonksiyon referansı (coderef) sözleksel, yerel olabilir, alt programlar arasında geçebilir ve anonim bir fonksiyonu saklayabilir.
my $coderef = sub { ... }; my $named = \&fn_name;
Bir hash dispatcher üzerinden mevcut olmayan bir fonksiyonu çağırırsak ne olur?
Cevap: Eğer anahtar yoksa, bir hata ortaya çıkacaktır. Bu nedenle her zaman çağrıdan önce exists kontrolü yapılması ve tanınmayan komutların işlenmesi gereklidir, aksi takdirde undef çağrısı yapılmaya çalışılacaktır (fatal error).
Web sitesindeki komut, GET parametresinden bir fonksiyon adı alır ve eval üzerinden çağrılır - herhangi bir kullanıcı system, unlink ve diğer tehlikeli fonksiyonları çağırabilir.
Artılar:
Eksiler:
Fonksiyonların beyaz listesini içeren bir hash kullanılıyor, tüm parametreler doğrulanıyor, eval kullanılmıyor, hatalar yakalanıyor ve kaydediliyor.
Artılar:
Eksiler: