আমি বুঝতে পারি যে কোনও শ্রেণীর "নতুন" পদ্ধতির অভ্যন্তরে পার্লে "আশীর্বাদ" কীওয়ার্ডটি ব্যবহার করা হয়েছে:
sub new {
my $self = bless { };
return $self;
}
তবে হ্যাশ রেফারেন্সটিতে "আশীর্বাদ" ঠিক কী করছে?
আমি বুঝতে পারি যে কোনও শ্রেণীর "নতুন" পদ্ধতির অভ্যন্তরে পার্লে "আশীর্বাদ" কীওয়ার্ডটি ব্যবহার করা হয়েছে:
sub new {
my $self = bless { };
return $self;
}
তবে হ্যাশ রেফারেন্সটিতে "আশীর্বাদ" ঠিক কী করছে?
উত্তর:
সাধারণভাবে, bless
একটি শ্রেণীর সাথে কোনও বস্তুকে যুক্ত করে।
package MyClass;
my $object = { };
bless $object, "MyClass";
এখন আপনি যখন কোনও পদ্ধতি চালু করেন $object
, তখন পার্ল জানেন যে পদ্ধতিটির জন্য কোন প্যাকেজটি অনুসন্ধান করতে হবে।
যদি দ্বিতীয় যুক্তি বাদ দেওয়া হয়, যেমন আপনার উদাহরণ হিসাবে, বর্তমান প্যাকেজ / শ্রেণি ব্যবহৃত হয়।
স্পষ্টতার স্বার্থে, আপনার উদাহরণটি নিম্নরূপ লিখিত হতে পারে:
sub new {
my $class = shift;
my $self = { };
bless $self, $class;
}
সম্পাদনা: আরও বিস্তারিত জানার জন্য কিক্সক্সের ভাল উত্তর দেখুন।
bless
একটি প্যাকেজের সাথে একটি রেফারেন্স যুক্ত করে।
রেফারেন্সটি কী তা বিবেচনাধীন নয় , এটি একটি নিয়মিত অভিব্যক্তিতে হ্যাশ (সর্বাধিক সাধারণ ক্ষেত্রে), কোনও অ্যারের (এত সাধারণ নয়), একটি স্কেলারের (সাধারণত এটি অভ্যন্তরীণ কোনও বস্তু নির্দেশ করে ) হতে পারে matter , সাব্রুটিন বা টিওয়াইপেইলওগ ( দরকারী উদাহরণগুলির জন্য দামিয়ান কনওয়ের দ্বারা ধারণাগুলি এবং প্রোগ্রামিং কৌশলগুলির একটি বিস্তৃত গাইড ) বা অবজেক্ট ওরিয়েন্টেড পার্ল বইটি দেখুন বা কোনও ফাইল বা ডিরেক্টরি হ্যান্ডেলের একটি উল্লেখ (কমপক্ষে সাধারণ ক্ষেত্রে)।
প্রভাবটি bless
হ'ল এটি আপনাকে আশীর্বাদযুক্ত রেফারেন্সে বিশেষ সিনট্যাক্স প্রয়োগ করতে দেয়।
উদাহরণস্বরূপ, যদি কোনও আশীর্বাদযুক্ত রেফারেন্স $obj
( bless
প্যাকেজ "ক্লাস" এর সাথে যুক্ত ) সঞ্চিত থাকে , তবে $obj->foo(@args)
একটি সাব্রুটাইন কল করবে foo
এবং প্রথম আর্গুমেন্ট হিসাবে $obj
বাকী আর্গুমেন্টগুলি অনুসরণ করবে ( @args
)। সাব্রোটিন প্যাকেজ "ক্লাস" এ সংজ্ঞায়িত করা উচিত। foo
"ক্লাস" প্যাকেজে সাব্রুটিন না থাকলে, অন্যান্য প্যাকেজগুলির একটি তালিকা ( @ISA
প্যাকেজ "ক্লাস" এ অ্যারে রূপে গৃহীত হয়েছে ) অনুসন্ধান করা হবে এবং foo
পাওয়া প্রথম সাবরোটাইনকে ডাকা হবে।
এই ফাংশনটি REF দ্বারা রেফারেন্সিত সত্তাকে বলে যে এটি এখন CLASSNAME প্যাকেজে কোনও বস্তু, বা CLASSNAME বাদ দিলে বর্তমান প্যাকেজ। আশীর্বাদ দ্বি-যুক্তি রূপ ব্যবহার করার পরামর্শ দেওয়া হয়।
উদাহরণ :
bless REF, CLASSNAME
bless REF
ফেরত মূল্য
এই ফাংশনটি CLASSNAME এ আশীর্বাদ করা কোনও সামগ্রীর রেফারেন্স প্রদান করে।
উদাহরণ :
নীচে তার মৌলিক ব্যবহার দেখানো উদাহরণ কোডটি রয়েছে, প্যাকেজের শ্রেণিতে একটি রেফারেন্সকে আশীর্বাদ করে বস্তুটি রেফারেন্স তৈরি করা হয়েছে -
#!/usr/bin/perl
package Person;
sub new
{
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# Print all the values just for clarification.
print "First Name is $self->{_firstName}\n";
print "Last Name is $self->{_lastName}\n";
print "SSN is $self->{_ssn}\n";
bless $self, $class;
return $self;
}
আমি এখানে একটি উত্তর সরবরাহ করব যেহেতু এখানে যেগুলি আমার পক্ষে বেশিরভাগ ক্লিক করে নি।
পার্লের আশীর্বাদ ফাংশন কোনও প্যাকেজের ভিতরে সমস্ত ফাংশনের কোনও রেফারেন্সকে যুক্ত করে।
কেন আমাদের এটির প্রয়োজন হবে?
আসুন জাভাস্ক্রিপ্টে একটি উদাহরণ প্রকাশ করে শুরু করি:
(() => {
'use strict';
class Animal {
constructor(args) {
this.name = args.name;
this.sound = args.sound;
}
}
/* [WRONG] (global scope corruption)
* var animal = Animal({
* 'name': 'Jeff',
* 'sound': 'bark'
* });
* console.log(animal.name + ', ' + animal.sound); // seems good
* console.log(window.name); // my window's name is Jeff?
*/
// new is important!
var animal = new Animal(
'name': 'Jeff',
'sound': 'bark'
);
console.log(animal.name + ', ' + animal.sound); // still fine.
console.log(window.name); // undefined
})();
এখন ক্লাসের নির্মাণগুলি কেটে ফেলা যাক এবং এটি না করেই করুন:
(() => {
'use strict';
var Animal = function(args) {
this.name = args.name;
this.sound = args.sound;
return this; // implicit context hashmap
};
// the "new" causes the Animal to be unbound from global context, and
// rebinds it to an empty hash map before being constructed. The state is
// now bound to animal, not the global scope.
var animal = new Animal({
'name': 'Jeff',
'sound': 'bark'
});
console.log(animal.sound);
})();
ফাংশনটি সীমানাবিহীন বৈশিষ্ট্যের একটি হ্যাশ টেবিল নেয় (যেহেতু এটি 2016 সালে গতিশীল ভাষাগুলিতে একটি নির্দিষ্ট ক্রমে বৈশিষ্ট্যগুলি লেখার কোনও ধারণা নেই) এবং সেই বৈশিষ্ট্যগুলির সাথে একটি হ্যাশ টেবিল ফেরত দেয়, বা আপনি যদি নতুন কীওয়ার্ডটি রাখতে ভুলে যান তবে এটি পুরো বিশ্বব্যাপী প্রেক্ষাপট (যেমন ব্রাউজারের উইন্ডো বা নোডজে গ্লোবাল) ফিরিয়ে দেবে।
পার্লের কোনও "এই" বা "নতুন" বা "শ্রেণি" নেই, তবে এর এখনও একইরকম আচরণ করে এমন একটি ফাংশন থাকতে পারে। আমাদের কাছে কোনও নির্মাণকারী বা প্রোটোটাইপ নেই, তবে আমরা ইচ্ছামত নতুন প্রাণী তৈরি করতে এবং তাদের পৃথক বৈশিষ্ট্যগুলি সংশোধন করতে সক্ষম হব।
# self contained scope
(sub {
my $Animal = (sub {
return {
'name' => $_[0]{'name'},
'sound' => $_[0]{'sound'}
};
});
my $animal = $Animal->({
'name' => 'Jeff',
'sound' => 'bark'
});
print $animal->{sound};
})->();
এখন, আমাদের একটি সমস্যা আছে: আমরা যদি প্রাণীটি তাদের ভয়েস কী তা ছাপানোর পরিবর্তে নিজেরাই শব্দগুলি সম্পাদন করতে চাই What এটি হ'ল আমরা একটি ফাংশন পারফর্ম সাউন্ড চাই যা প্রাণীর নিজস্ব শব্দ মুদ্রণ করে।
এটি করার একটি উপায় হ'ল প্রতিটি প্রাণীকে কীভাবে এটি করা উচিত তা শেখানো। এর অর্থ হ'ল প্রতিটি বিড়ালের পারফরম্যান্স সাউন্ডের নিজস্ব ডুপ্লিকেট ফাংশন রয়েছে।
# self contained scope
(sub {
my $Animal = (sub {
$name = $_[0]{'name'};
$sound = $_[0]{'sound'};
return {
'name' => $name,
'sound' => $sound,
'performSound' => sub {
print $sound . "\n";
}
};
});
my $animal = $Animal->({
'name' => 'Jeff',
'sound' => 'bark'
});
$animal->{'performSound'}();
})->();
এটি খারাপ কারণ প্রতিবার প্রাণী তৈরির সময় পারফেক্টসাউন্ডটিকে সম্পূর্ণ নতুন ফাংশন অবজেক্ট হিসাবে রাখা হয়। 10000 প্রাণী মানে 10000 পারফরম্যান্স সাউন্ড। আমরা একটি একক ক্রিয়াকলাপ সম্পাদন করতে চাই যা সমস্ত প্রাণীর দ্বারা ব্যবহৃত হয় যা তাদের নিজস্ব শব্দ দেখে এবং এটি মুদ্রণ করে।
(() => {
'use strict';
/* a function that creates an Animal constructor which can be used to create animals */
var Animal = (() => {
/* function is important, as fat arrow does not have "this" and will not be bound to Animal. */
var InnerAnimal = function(args) {
this.name = args.name;
this.sound = args.sound;
};
/* defined once and all animals use the same single function call */
InnerAnimal.prototype.performSound = function() {
console.log(this.name);
};
return InnerAnimal;
})();
/* we're gonna create an animal with arguments in different order
because we want to be edgy. */
var animal = new Animal({
'sound': 'bark',
'name': 'Jeff'
});
animal.performSound(); // Jeff
})();
পার্ল কিন্ডার সমান্তরালটি এখানেই থামে।
জাভাস্ক্রিপ্টের নতুন অপারেটর optionচ্ছিক নয়, এগুলি ব্যতীত "এই" অবজেক্টের পদ্ধতিগুলি বিশ্বব্যাপী সুযোগকে কলুষিত করে:
(() => {
// 'use strict'; // uncommenting this prevents corruption and raises an error instead.
var Person = function() {
this.name = "Sam";
};
// var wrong = Person(); // oops! we have overwritten window.name or global.main.
// console.log(window.name); // my window's name is Sam?
var correct = new Person; // person's name is actually stored in the person now.
})();
আমরা প্রতিটি প্রাণীর জন্য একটি ফাংশন রাখতে চাই যা এটি নির্মাণে হার্ডকোডিংয়ের চেয়ে প্রাণীর নিজের শব্দটিকে সন্ধান করে।
আশীর্বাদ আমাদের প্যাকেজগুলি অবজেক্টের প্রোটোটাইপ হিসাবে ব্যবহার করতে দেয়। এইভাবে, অবজেক্টটি "প্যাকেজ" সম্পর্কে "এটি" রেফারেন্সযুক্ত "সম্পর্কে অবগত এবং এর পরিবর্তে প্যাকেজটির ফাংশনগুলি" প্যাকেজ অবজেক্ট "এর নির্মাণকারী থেকে তৈরি হওয়া নির্দিষ্ট দৃষ্টান্তগুলিতে" পৌঁছন "করতে পারে:
package Animal;
sub new {
my $packageRef = $_[0];
my $name = $_[1]->{'name'};
my $sound = $_[1]->{'sound'};
my $this = {
'name' => $name,
'sound' => $sound
};
bless($this, $packageRef);
return $this;
}
# all animals use the same performSound to look up their sound.
sub performSound {
my $this = shift;
my $sound = $this->{'sound'};
print $sound . "\n";
}
package main;
my $animal = Animal->new({
'name' => 'Cat',
'sound' => 'meow'
});
$animal->performSound();
সংক্ষিপ্তসার / টিএল; ডিআর :
পার্লের কোনও "এই", "শ্রেণি", বা "নতুন" নেই। কোনও প্যাকেজে কোনও বস্তুর আশীর্বাদ করলে সেই বস্তুটি প্যাকেজটির জন্য একটি রেফারেন্স দেয় এবং যখন এটি প্যাকেজে ফাংশন কল করে, তখন তাদের আর্গুমেন্টগুলি 1 স্লট দ্বারা অফসেট করা হবে এবং প্রথম যুক্তি ($ _ [0] বা শিফট) এর সমতুল্য হবে জাভাস্ক্রিপ্ট এর "এই"। পরিবর্তে, আপনি কিছুটা জাভাস্ক্রিপ্টের প্রোটোটাইপ মডেল অনুকরণ করতে পারেন।
দুর্ভাগ্যক্রমে রানটাইমে "নতুন ক্লাস" তৈরি করা অসম্ভব (আমার বোঝার কাছে) করে তোলে, যেমন আপনার প্রতিটি প্যাকেজটির নিজস্ব প্যাকেজ থাকতে প্রয়োজন, যেখানে জাভাস্ক্রিপ্টে আপনার "নতুন" কীওয়ার্ড হিসাবে কোনও প্যাকেজ দরকার নেই রানটাইমের সময় আপনার প্যাকেজ হিসাবে ব্যবহার করার জন্য একটি বেনামে হ্যাশম্যাপ তৈরি করে যাতে আপনি নতুন ফাংশন যুক্ত করতে এবং ফ্লাইতে ফাংশনগুলি সরিয়ে নিতে পারেন।
কিছু পার্ল গ্রন্থাগার রয়েছে যা মুস মত প্রকাশের মাধ্যমে এই সীমাবদ্ধতাটি সরিয়ে দেওয়ার নিজস্ব উপায় তৈরি করে।
বিভ্রান্তি কেন? :
প্যাকেজ কারণ। আমাদের অন্তর্নিহিততা আমাদের অবজেক্টটিকে তার 'প্রোটোটাইপযুক্ত হ্যাশম্যাপে আবদ্ধ করতে বলে। এটি আমাদের জাভাস্ক্রিপ্টের মতো রানটাইমে "প্যাকেজগুলি" তৈরি করতে দেয়। পার্লের তেমন নমনীয়তা নেই (কমপক্ষে অন্তর্নির্মিত নয়, আপনাকে এটি আবিষ্কার করতে হবে বা এটি অন্যান্য মডিউল থেকে পেতে হবে) এবং ফলস্বরূপ আপনার রানটাইম এক্সপ্রেসনেস বাধা হয়ে দাঁড়ায়। এটিকে "আশীর্বাদ" বলা খুব বেশি সুবিধা দেয় না।
আমরা কী করতে চাই :
এর মতো কিছু, তবে প্রোটোটাইপ মানচিত্রের পুনরাবৃত্তির সাথে আবদ্ধ হওয়া এবং স্পষ্টভাবে এটি করার চেয়ে প্রোটোটাইপের সাথে আবদ্ধ থাকুন।
এখানে এটির একটি নির্দোষ প্রচেষ্টা: সমস্যাটি হ'ল "কল" "" এটি কী বলে "জানে না, সুতরাং এটি একটি সর্বজনীন পার্ল ফাংশন" অবজেক্টআইভোকমেথড (অবজেক্ট, পদ্ধতি) "ও হতে পারে যা পরীক্ষা করে যে বস্তুটির পদ্ধতি আছে কিনা? , বা এর প্রোটোটাইপটিতে এটি রয়েছে, বা এটির প্রোটোটাইপ এটি রয়েছে, যতক্ষণ না এটি শেষের দিকে পৌঁছে যায় এবং এটি খুঁজে পায় না বা না (প্রোটোটাইপিক উত্তরাধিকার)। পার্ল এটি করার জন্য দুর্দান্ত ইওল ম্যাজিক রয়েছে তবে আমি পরে যা করার চেষ্টা করতে পারি তার জন্য ছেড়ে দেব।
যাইহোক এখানে ধারণা:
(sub {
my $Animal = (sub {
my $AnimalPrototype = {
'performSound' => sub {
return $_[0]->{'sound'};
}
};
my $call = sub {
my $this = $_[0];
my $proc = $_[1];
if (exists $this->{$proc}) {
return $this->{$proc}->();
} else {
return $this->{prototype}->{$proc}->($this, $proc);
}
};
return sub {
my $name = $_[0]->{name};
my $sound = $_[0]->{sound};
my $this = {
'this' => $this,
'name' => $name,
'sound' => $sound,
'prototype' => $AnimalPrototype,
'call' => $call
};
};
})->();
my $animal = $Animal->({
'name' => 'Jeff',
'sound'=> 'bark'
});
print($animal->{call}($animal, 'performSound'));
})->();
যাইহোক আশা করি কেউ এই পোস্টকে দরকারী বলে মনে করবেন।
my $o = bless {}, $anything;
একটি বস্তু আশীর্বাদ করবে $anything
। একইভাবে, {no strict 'refs'; *{$anything . '::somesub'} = sub {my $self = shift; return $self->{count}++};
একটি পদ্ধতি নাম ক্লাসে 'somesub' নামক তৈরি করবে $anything
। রানটাইম এ সব সম্ভব। "সম্ভাব্য" তবে, প্রতিদিনের কোডটি চালানো দুর্দান্ত অনুশীলন করে না। তবে এটি মুজ বা মু এর মতো অবজেক্ট ওভারলে সিস্টেম তৈরিতে কার্যকর।
unfortunately it makes it impossible(to my understanding) to create "new classes" at runtime
দাবিটি বাতিল করে দেয় । আমি অনুমান করি যে আমার উদ্বেগটি শেষ পর্যন্ত এটি প্যাকেজ সিস্টেমটি রানটাইম / এন্ডোস্পেক্টেপ করার জন্য উল্লেখযোগ্যভাবে কম স্বজ্ঞাত হয়ে উঠেছে, তবে আমি এখনও এটিকে অন্তর্নিহিতভাবে করতে পারি না এমন কিছুই দেখাতে ব্যর্থ হয়েছি। প্যাকেজ সিস্টেম রানটাইমে নিজেকে যুক্ত / অপসারণ / পরিদর্শন / সংশোধন করার জন্য প্রয়োজনীয় সমস্ত সরঞ্জামকে সমর্থন করে বলে মনে হচ্ছে।
বেশ কয়েকটি ভাল উত্তরের পাশাপাশি, কীভাবে একটি bless
এডের রেফারেন্সকে বিশেষত পৃথক করে তা হ'ল SV
এটির জন্য অতিরিক্ত FLAGS
( OBJECT
) এবং একটিSTASH
perl -MDevel::Peek -wE'
package Pack { sub func { return { a=>1 } } };
package Class { sub new { return bless { A=>10 } } };
$vp = Pack::func(); print Dump $vp; say"---";
$obj = Class->new; print Dump $obj'
একই (এবং এর জন্য অপ্রাসঙ্গিক) অংশগুলি সহ মুদ্রণগুলি
এসভি = আইভি (0x12d5530) 0x12d5540 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (আরওকে) আরভি = 0x12a5a68 এসভি = পিভিএইচভি (0x12ab980) 0x12a5a68 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (শেয়ারগুলি) ... এসভি = আইভি (0x12a5ce0) 0x12a5cf0 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (আইওকে, পিআইওকে) চতুর্থ = 1 --- এসভি = আইভি (0x12cb8b8) 0x12cb8c8 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (প্যাডমি, আরকে) আরভি = 0x12c26b0 এসভি = পিভিএইচভি (0x12aba00) 0x12c26b0 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (ওবিজেইসিটি, শ্যারকিইস) STASH = 0x12d5300 "শ্রেণি" ... এসভি = IV (0x12c26b8) 0x12c26c8 এ আরএফসিএনটি = 1 ফ্ল্যাগস = (আইওকে, পিআইওকে) চতুর্থ = 10
এটির সাথে এটি জানা যায় যে 1) এটি একটি অবজেক্ট 2) এটি কোন প্যাকেজের সাথে সম্পর্কিত এবং এটি তার ব্যবহারকে অবহিত করে।
উদাহরণস্বরূপ, যখন সেই ভেরিয়েবলটির ডিফারেন্সিংয়ের মুখোমুখি হয় ( $obj->name
), তখন সেই নামের একটি উপ প্যাকেজ (বা হায়ারার্কি) এ সন্ধান করা হয়, বস্তুটি প্রথম আর্গুমেন্ট, ইত্যাদি হিসাবে পাস করা হয় etc.
আমি উন্নয়ন চিন্তাধারা-ভিত্তিক পার্লকে গাইড করার জন্য এই চিন্তাকে অনুসরণ করছি।
ক্লাসের সাথে কোনও ডেটা স্ট্রাকচার রেফারেন্স যুক্ত করে আশীর্বাদ করুন। পার্ল কীভাবে উত্তরাধিকার কাঠামো তৈরি করে তা দেওয়া (এক ধরণের গাছের মধ্যে) কম্পোজিশনের জন্য অবজেক্ট তৈরি করতে অবজেক্ট মডেলের সুবিধা নেওয়া সহজ।
এই সংঘের জন্য আমরা অবজেক্টকে বলেছিলাম, বিকাশের জন্য সর্বদা মনে রাখবেন যে বস্তুর অভ্যন্তরীণ অবস্থা এবং শ্রেণি আচরণগুলি পৃথক। এবং আপনি কোনও প্যাকেজ / শ্রেণি আচরণ ব্যবহার করার জন্য কোনও ডেটা রেফারেন্সকে আশীর্বাদ / অনুমতি দিতে পারেন। যেহেতু প্যাকেজটি বস্তুর "সংবেদনশীল" অবস্থা বুঝতে পারে।
উদাহরণস্বরূপ, আপনি যদি আত্মবিশ্বাসী হতে পারেন যে কোনও বাগ বস্তু আশীর্বাদযুক্ত হ্যাশ হতে চলেছে, আপনি বাগ (মুদ্রণ_আমি) পদ্ধতিতে হারিয়ে যাওয়া কোডটি পূরণ করতে পারবেন (শেষ পর্যন্ত!):
package Bug;
sub print_me
{
my ($self) = @_;
print "ID: $self->{id}\n";
print "$self->{descr}\n";
print "(Note: problem is fatal)\n" if $self->{type} eq "fatal";
}
এখন, যখনই মুদ্রণ_ম পদ্ধতিটি বাগ শ্রেণীর জন্য আশীর্বাদযুক্ত কোনও হ্যাশের রেফারেন্সের মাধ্যমে কল করা হয়, তখন $ স্ব পরিবর্তনশীল রেফারেন্সটি প্রথম আর্গুমেন্ট হিসাবে পাস করা হয়েছে এবং তারপরে মুদ্রণ বিবরণী আশীর্বাদী হ্যাশের বিভিন্ন এন্ট্রিগুলিতে অ্যাক্সেস করে।