වසා දැමීම යනු කුමක්ද?


157

සෑම විටම මම "වසා දැමීම්" සඳහන් කර ඇති බව දකිමි, මම එය සොයා බැලීමට උත්සාහ කළ නමුත් විකී මට තේරෙන පැහැදිලි කිරීමක් ලබා නොදේ. මට මෙතනින් උදව් කරන්න කාටහරි පුළුවන්ද?


ඔබ දන්නවා ජාවා / සී # මෙම සබැඳිය උපකාරී වනු ඇතැයි බලාපොරොත්තු වේ- http://www.developerfusion.com/article/8251/the-beauty-of-closures/
ගුල්ෂාන්

1
වසා දැමීම් තේරුම් ගැනීමට අපහසුය. එම විකිපීඩියා ලිපියේ පළමු වාක්‍යයේ ඇති සියලුම සබැඳි ක්ලික් කර එම ලිපි පළමුව තේරුම් ගැනීමට ඔබ උත්සාහ කළ යුතුය.
Zach


3
වසා දැමීමක් සහ පන්තියක් අතර මූලික වෙනස කුමක්ද? හරි, එක් පොදු ක්‍රමයක් පමණක් ඇති පන්තියක්.
biziclop

5
iz බිසික්ලොප්: ඔබට පන්තියක් සමඟ වසා දැමීමක් අනුකරණය කළ හැකිය (ජාවා ඩෙව්ස් කළ යුත්තේ එයයි). නමුත් ඒවා සාමාන්‍යයෙන් නිර්මාණය කිරීමට තරමක් අඩු වාචික වන අතර ඔබ අවට ඇති දේ අතින් කළමණාකරනය කළ යුතු නොවේ. (දෘ c තැටි ලිස්පර්ස් සමාන ප්‍රශ්නයක් අසයි, නමුත් අනෙක් නිගමනයට එළඹිය හැකිය - ඔබ වසා දැමූ විට භාෂා මට්ටමේ OO සහාය අනවශ්‍යය).

Answers:


141

(වියාචනය: මෙය මූලික පැහැදිලි කිරීමකි; අර්ථ දැක්වීම අනුව, මම ටිකක් සරල කරමි)

වසා දැමීමක් ගැන සිතීමට ඇති සරලම ක්‍රමය නම් විචල්‍යයක් ලෙස ගබඩා කළ හැකි ශ්‍රිතයකි (“පළමු පන්තියේ ශ්‍රිතයක්” ලෙස හැඳින්වේ), එය නිර්මාණය කරන ලද විෂය පථයට දේශීයව වෙනත් විචල්‍යයන්ට ප්‍රවේශ වීමේ විශේෂ හැකියාවක් ඇත.

උදාහරණය (ජාවාස්ක්‍රිප්ට්):

var setKeyPress = function(callback) {
    document.onkeypress = callback;
};

var initialize = function() {
    var black = false;

    document.onclick = function() {
        black = !black;
        document.body.style.backgroundColor = black ? "#000000" : "transparent";
    }

    var displayValOfBlack = function() {
        alert(black);
    }

    setKeyPress(displayValOfBlack);
};

initialize();

කාර්යයන් 1 පවරා document.onclickහා displayValOfBlackවසා දැමීම් වේ. ඔවුන් දෙදෙනාම බූලියන් විචල්‍යය යොමු කරන බව ඔබට පෙනෙනු ඇත black, නමුත් එම විචල්‍යය ශ්‍රිතයෙන් පිටත පවරා ඇත. නිසා blackශ්රිතය අර්ථ සිටි විෂය පථය දේශීය , මෙම විචල්ය පෙන්නුම් කරන්නක්, කල් තබා ගන්නා ඇත.

ඔබ මෙය HTML පිටුවක තැබුවහොත්:

  1. කළු බවට වෙනස් කිරීමට ක්ලික් කරන්න
  2. "සත්‍ය" බැලීමට [ඇතුල් කරන්න] ඔබන්න
  3. නැවත ක්ලික් කරන්න, නැවත සුදු පැහැයට වෙනස් වේ
  4. "අසත්‍යය" බැලීමට [ඇතුල් කරන්න] ඔබන්න

මෙයින් පෙන්නුම් කරන්නේ දෙදෙනාම එක black හා සමාන ප්‍රවේශයක් ඇති අතර කිසිදු ආවරණයක් නොමැතිව වස්තුව ගබඩා කිරීම සඳහා භාවිතා කළ හැකි බවයි .

ඇමතුම setKeyPressයනු ඕනෑම විචල්‍යයක් මෙන් ශ්‍රිතයක් සම්මත කළ හැකි ආකාරය නිරූපණය කිරීමයි. මෙම විෂය පථය වසා, කල් තබා ගන්නා තවමත් කාර්යයේ අර්ථ සිටි තැනැත්තා ය.

වසා දැමීම් සාමාන්‍යයෙන් සිදුවීම් හසුරුවන්නන් ලෙස භාවිතා කරයි, විශේෂයෙන් ජාවාස්ක්‍රිප්ට් සහ ඇක්ෂන් ස්ක්‍රිප්ට් වල. වසා දැමීම් හොඳින් භාවිතා කිරීම මඟින් වස්තු ආවරණයක් සෑදීමෙන් තොරව විචල්‍යයන් සිදුවීම් හසුරුවන්නන් සමඟ ව්‍යංගයෙන් බැඳීමට උපකාරී වේ. කෙසේ වෙතත්, නොසැලකිලිමත් ලෙස භාවිතා කිරීම මතක කාන්දුවීම් වලට තුඩු දෙනු ඇත (භාවිතයට නොගත් නමුත් සංරක්‍ෂිත සිදුවීම් හසුරුවන්නෙකු මතකයේ ඇති විශාල වස්තූන්, විශේෂයෙන් DOM වස්තූන් මත රඳවා තබා ගත හැකි එකම දෙය, කසළ එකතු කිරීම වැළැක්වීම වැනි).


1: ඇත්ත වශයෙන්ම, ජාවාස්ක්‍රිප්ට් හි සියලුම කාර්යයන් වසා දැමීම් වේ.


3
මම ඔබේ පිළිතුර කියවන විට මගේ සිතේ විදුලි බුබුලක් ක්‍රියාත්මක වන බවක් දැනුනි. බොහෝ අගය කළා! :)
ජේ

1
සිට black, විශාල උත්සවයක් තුළ ප්රකාශයට පත් කරන්නේ අඩුක්කුව unwinds ලෙස විනාශ කර ගැනීමට බව කළේ නැත ...?
ගැබ්ලින්

1
ඇග්බ්ලින්, වසා දැමීම් ඇති භාෂාවල අද්විතීය වන්නේ එයයි. කසළ එකතු කරන සියලුම භාෂාවන් එකම ආකාරයකින් ක්‍රියා කරයි - වස්තුවක් ගැන වැඩි සඳහනක් නොමැති විට එය විනාශ කළ හැකිය. JS හි ශ්‍රිතයක් නිර්මාණය කරන සෑම විටම, එම ශ්‍රිතය විනාශ වන තෙක් දේශීය විෂය පථය එම ශ්‍රිතයට බැඳී ඇත.
නිකොල්

3
ඇග්බ්ලින්, ඒක හොඳ ප්‍රශ්නයක්. මම ඔවුන් හිතන්නේ නැහැ බැහැ & mdash; නමුත් මම ගෙන ආවේ කසළ එකතු කිරීම පමණයි. JS භාවිතා කරන්නේ එයයි. ඔබ සඳහන් කළේ “ blackශ්‍රිතයක් තුළ ප්‍රකාශයට පත් කර ඇති බැවින් එය විනාශ නොවනු ඇත” යනුවෙනි. ඔබ ශ්‍රිතයක වස්තුවක් ප්‍රකාශයට පත් කර වෙනත් තැනක ජීවත්වන විචල්‍යයකට එය පවරන්නේ නම්, එම වස්තුව සංරක්ෂණය වන්නේ එයට වෙනත් යොමු කිරීම් ඇති බැවිනි.
නිකොල්

1
වෛෂයික-සී (සහ සී යටතේ ක්ලැන්ග්) කුණු එකතු කිරීමකින් තොරව අත්‍යවශ්‍යයෙන්ම වසා දැමිය හැකි කුට්ටි සඳහා සහාය වේ. එයට ධාවන කාල සහාය සහ මතක කළමනාකරණය වටා යම් අතින් මැදිහත් වීමක් අවශ්‍ය වේ.
බෙන් සොටෝ

69

වසා දැමීම මූලික වශයෙන් වස්තුවක් දෙස බැලීමේ වෙනස් ආකාරයකි. වස්තුවක් යනු එයට එකක් හෝ වැඩි ගණනක් බැඳී ඇති දත්ත ය. වසා දැමීම යනු විචල්‍යයන් එකක් හෝ වැඩි ගණනක් බැඳී ඇති ශ්‍රිතයකි. අවම වශයෙන් ක්‍රියාත්මක කිරීමේ මට්ටමින් මේ දෙක මූලික වශයෙන් සමාන වේ. සැබෑ වෙනස වන්නේ ඔවුන් පැමිණෙන්නේ කොතැනින්ද යන්නයි.

වස්තු-නැඹුරු වැඩසටහන්කරණයේදී, ඔබ වස්තු පන්තියක් ප්‍රකාශයට පත් කරන්නේ එහි සාමාජික විචල්‍යයන් සහ එහි ක්‍රම (සාමාජික ක්‍රියාකාරකම්) ඉහළට නිර්වචනය කරමිනි, ඉන්පසු ඔබ එම පන්තියේ අවස්ථා නිර්මාණය කරයි. සෑම අවස්ථාවක්ම සාමාජිකයාගේ දත්ත පිටපතක් සමඟ එන අතර එය ඉදිකිරීම්කරු විසින් ආරම්භ කරනු ලැබේ. එවිට ඔබට වස්තු වර්ගයක විචල්‍යයක් ඇති අතර එය දත්ත කැබැල්ලක් ලෙස සම්මත කරන්න, මන්ද අවධානය යොමු වන්නේ එහි ස්වභාවය දත්ත ලෙස ය.

වසා දැමීමේදී, අනෙක් අතට, වස්තුව වස්තු පන්තියක් මෙන් ඉහළට නිර්වචනය කර නැත, නැතහොත් ඔබේ කේතයේ ඉදිකිරීම්කරු ඇමතුමක් හරහා ක්ෂණිකව සකසා ඇත. ඒ වෙනුවට, ඔබ වසා දැමීම වෙනත් ශ්‍රිතයක ඇතුළත ශ්‍රිතයක් ලෙස ලියයි. වසා දැමීමෙන් බාහිර ශ්‍රිතයේ ඕනෑම දේශීය විචල්‍යයකට යොමු විය හැකි අතර, සම්පාදකයා එය හඳුනාගෙන මෙම විචල්‍යයන් බාහිර ශ්‍රිතයේ සිරස් අවකාශයේ සිට වසා දැමීමේ සැඟවුණු වස්තු ප්‍රකාශනය දක්වා ගෙන යයි. එවිට ඔබට වසා දැමීමේ වර්ගයක විචල්‍යයක් ඇති අතර, එය මූලික වශයෙන් කබාය යට වස්තුවක් වුවද, ඔබ එය ශ්‍රිත යොමු කිරීමක් ලෙස එය පසුකර යයි, මන්දයත් එහි ස්වභාවය ශ්‍රිතයක් ලෙස අවධානය යොමු කර ඇති බැවිනි.


3
+1: හොඳ පිළිතුරක්. වසා දැමීම එක් ක්‍රමයක් පමණක් ඇති වස්තුවක් ලෙසත්, අත්තනෝමතික වස්තුවක් සමහර පොදු යටින් පවතින දත්ත (වස්තුවේ සාමාජික විචල්‍යයන්) හරහා වසා දැමීමේ එකතුවක් ලෙසත් ඔබට දැකිය හැකිය. මම හිතන්නේ මේ අදහස් දෙක තරමක් සමමිතිකයි.
ජෝජියෝ

3
ඉතා හොඳ පිළිතුරක්. එය සැබවින්ම වසා දැමීමේ තීක්ෂ්ණ බුද්ධිය පැහැදිලි කරයි.
රොබෝ ඇලෙක්ස්

1
Ason මේසන් වීලර්: වසා දැමීමේ දත්ත ගබඩා වන්නේ කොහේද? ශ්‍රිතයක් මෙන් සිරස්ව තිබේද? නැත්නම් වස්තුවක් මෙන් ගොඩවල් වලද?
රොබෝ ඇලෙක්ස්

1
@RoboAlex: ගොඩේ, එය ශ්‍රිතයක් මෙන් පෙනෙන වස්තුවක් වන නිසා .
මේසන් රෝද රථය

1
O රොබෝ ඇලෙක්ස්: වසා දැමීමක් සහ එහි ග්‍රහණය කරගත් දත්ත ගබඩා කර ඇති ස්ථානය ක්‍රියාත්මක කිරීම මත රඳා පවතී. C ++ හි එය ගොඩවල හෝ තොගයේ ගබඩා කළ හැකිය.
ජෝර්ජියෝ

29

වසා දැමීම යන පදය පැමිණෙන්නේ කේත කැබැල්ලකට (වාරණය, ශ්‍රිතය) කේත වාරණය අර්ථ දක්වා ඇති පරිසරය විසින් වසා ඇති (එනම් අගයකට බැඳී ඇති) නිදහස් විචල්‍යයන් තිබිය හැකි බැවිනි.

Scala ශ්‍රිත අර්ථ දැක්වීම උදාහරණයක් ලෙස ගන්න:

def addConstant(v: Int): Int = v + k

මෙම උත්සවයට සිරුරේ නම් (විචල්යයන්) දෙකක් ඇත vහා kපූර්ණ සංඛ්යාමය අගයන් දෙකක් පෙන්නුම්. නම vබැඳී ඇත්තේ එය ශ්‍රිතයේ තර්කයක් ලෙස ප්‍රකාශයට පත් කර ඇති බැවිනි addConstant(ශ්‍රිතය ප්‍රකාශ කිරීම දෙස බැලීමෙන් vශ්‍රිතය ආයාචනා කරන විට එය අගයක් පවරනු ඇත). kශ්‍රිතයට නම නිදහස් වේ. ශ්‍රිතයට addConstantකුමන අගයකට kබැඳී ඇත්ද යන්න පිළිබඳ කිසිදු හෝඩුවාවක් නොමැති නිසා (සහ කෙසේද).

වැනි ඇමතුමක් ඇගයීම සඳහා:

val n = addConstant(10)

අපට kඅගයක් පැවරිය යුතුය, එය සිදුවිය හැක්කේ kඅර්ථ දක්වා ඇති සන්දර්භය තුළ addConstantනම අර්ථ දැක්වුවහොත් පමණි. උදාහරණයක් වශයෙන්:

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  def addConstant(v: Int): Int = v + k

  values.map(addConstant)
}

දැන් අපි අර්ථ ඇති බව addConstantද, සන්ධර්භයක, kඅර්ථ දක්වා ඇත, addConstantඑය බවට පත් වී තිබේ වසා එහි සියලු නිදහස් විචල්ය දැන් නිසා වසා (අ අගය කිරීමට බැඳී): addConstantඑය කාර්යය නම් ලෙස ආයාචනා සහ ඒ අවට සම්මත කළ හැක. මෙම නිදහස් විචල්ය සටහන kවසා විට අගය කිරීමට බැඳී ඇත අර්ථ තර්කය විචල්ය ඇති ෙහයින්ද, vවසා දැමීම විට බැඳී පළ කළහ .

එබැවින් වසා දැමීම මූලික වශයෙන් ශ්‍රිතයක් හෝ කේත වාරණයක් වන අතර එමඟින් සන්දර්භය මගින් බැඳී ඇති පසු එහි නිදහස් විචල්‍යයන් හරහා දේශීය නොවන අගයන්ට ප්‍රවේශ විය හැකිය.

බොහෝ භාෂාවලින්, ඔබ වසා දැමීමක් භාවිතා කරන්නේ එක් වරක් පමණක් නම්, ඔබට එය නිර්නාමික කළ හැකිය , උදා

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  values.map(v => v + k)
}

නිදහස් විචල්‍යයන් නොමැති ශ්‍රිතයක් වසා දැමීමේ විශේෂ අවස්ථාවක් බව සලකන්න (හිස් නිදහස් විචල්‍ය සමූහයක් සමඟ). ප්‍රතිසමයට අනුව, නිර්නාමික ශ්‍රිතයක් යනු නිර්නාමික වසා දැමීමේ විශේෂ අවස්ථාවකි , එනම් නිර්නාමික ශ්‍රිතයක් යනු නිදහස් විචල්‍යයන් නොමැති නිර්නාමික වසා දැමීමකි.


මෙය තර්කනයේ සංවෘත හා විවෘත සූත්‍ර සමඟ හොඳින් ගැලපේ. ඔබගේ පිළිතුරට ස්තුතියි.
RainDoctor

AinRainDoctor: නිදහස් විචල්‍යයන් තාර්කික සූත්‍රවල සහ ලැම්බඩා කැල්කියුලස් ප්‍රකාශනවල සමාන ආකාරයකින් අර්ථ දක්වා ඇත: ලැම්බඩා ප්‍රකාශනයක ඇති ලැම්බඩා තාර්කික සූත්‍රවල ප්‍රමාණාත්මකකරණය මෙන් ක්‍රියා කරයි නිදහස් / බැඳී ඇති විචල්‍යයන්.
ජෝර්ජියෝ

9

JavaScript හි සරල පැහැදිලි කිරීමක්:

var closure_example = function() {
    var closure = 0;
    // after first iteration the value will not be erased from the memory
    // because it is bound with the returned alertValue function.
    return {
        alertValue : function() {
            closure++;
            alert(closure);
        }
    };
};
closure_example();

alert(closure)හි කලින් සාදන ලද අගය භාවිතා කරයි closure. ආපසු ලබා දුන් alertValueශ්‍රිතයේ නාම අවකාශය closureවිචල්‍යය වාසය කරන නාම අවකාශයට සම්බන්ධ වේ . ඔබ සම්පූර්ණ ශ්‍රිතය closureමකා දැමූ විට, විචල්‍යයේ අගය මකා දැමෙනු ඇත, නමුත් එතෙක් alertValueශ්‍රිතයට විචල්‍යයේ අගය කියවීමට / ලිවීමට හැකි closureවේ.

ඔබ මෙම කේතය ක්‍රියාත්මක කරන්නේ නම්, පළමු ක්‍රියාවලිය closureවිචල්‍යයට 0 අගයක් ලබා දී ශ්‍රිතය නැවත ලියන්නේ:

var closure_example = function(){
    alertValue : function(){
        closure++;
        alert(closure);
    }       
}

ශ්‍රිතය ක්‍රියාත්මක කිරීම alertValueසඳහා දේශීය විචල්‍යය අවශ්‍ය වන හෙයින් closure, එය කලින් පවරා ඇති දේශීය විචල්‍යයේ අගය සමඟ බැඳී පවතී closure.

දැන් ඔබ closure_exampleශ්‍රිතය අමතන සෑම අවස්ථාවකම එය closureවිචල්‍යයේ වැඩි කළ අගය ලියා තබනු ඇත alert(closure).

closure_example.alertValue()//alerts value 1 
closure_example.alertValue()//alerts value 2 
closure_example.alertValue()//alerts value 3
//etc. 

ස්තූතියි, මම කේතය පරීක්ෂා කළේ නැත =) දැන් සියල්ල හොඳින් පෙනේ.
මුහා

5

“වසා දැමීම” යනු සාරාංශයක් ලෙස සමහර ප්‍රාදේශීය රාජ්‍ය සහ සමහර කේත පැකේජයකට ඒකාබද්ධ කිරීමයි. සාමාන්‍යයෙන්, ප්‍රාදේශීය රාජ්‍යය පැමිණෙන්නේ අවට ඇති (ශබ්දකෝෂ) විෂය පථයකින් වන අතර කේතය (අත්‍යවශ්‍යයෙන්ම) අභ්‍යන්තර ශ්‍රිතයක් වන අතර එය නැවත පිටතට යවනු ලැබේ. වසා දැමීම යනු අභ්‍යන්තර ශ්‍රිතය දකින ග්‍රහිත විචල්‍යයන්ගේ එකතුවක් සහ අභ්‍යන්තර ශ්‍රිතයේ කේතයයි.

නුහුරු නුපුරුදු නිසා අවාසනාවකට එය පැහැදිලි කිරීමට ටිකක් අපහසු වන එකකි.

අතීතයේ දී මම සාර්ථකව භාවිතා කළ එක් ප්‍රතිසමයක් නම්, “අපට පොත” යනුවෙන් යමක් ඇතැයි සිතන්න, කාමරය වසා දැමීමේදී, “පොත” යනු එහි පිටපතක්, කෙළවරේ, TAOCP හි පිටපතක්, නමුත් මේසය වැසීම මත ය. , එය ඩ්‍රෙස්ඩන් ලිපිගොනු පොතක පිටපතකි. එබැවින් ඔබ සිටින්නේ කුමන සංවෘතද යන්න මත පදනම්ව, 'මට පොත දෙන්න' යන කේතය විවිධ දේ සිදුවීමට හේතු වේ. "


ඔබට මෙය අමතක විය: en.wikipedia.org/wiki/Closure_(computer_programming) ඔබේ පිළිතුරේ.
එස්.ලොට්

3
නැත, මම එම පිටුව වසා නොදැමීමට කැමැත්තෙන් තෝරා ගත්තෙමි.
Vatine

"තත්වය සහ ක්‍රියාකාරිත්වය.": staticදේශීය විචල්‍යයක් සහිත සී ශ්‍රිතයක් වසා දැමීමක් ලෙස සැලකිය හැකිද? හස්කල් හි වසා දැමීම්වලට රාජ්‍ය සම්බන්ධ වේද?
ජෝජියෝ

2
Ask හස්කල්හි ජෝජියෝ වසා දැමීම් (ඔවුන් විශ්වාස කරන පරිදි) ඔවුන් අර්ථ දක්වා ඇති ශබ්දකෝෂ විෂය පථයේ තර්ක වසා දමයි, එබැවින් මම "ඔව්" යැයි කියමි (මට හැස්කෙල් ගැන එතරම් නුහුරු වුවත්). ස්ථිතික විචල්‍යයක් සහිත AC ශ්‍රිතය, ඉතා සීමිත වසා දැමීමකි (ඔබට ඇත්ත වශයෙන්ම අවශ්‍ය වන්නේ තනි ශ්‍රිතයකින් බහුවිධ වසා දැමීම් නිර්මාණය කිරීමට හැකිවීමයි, staticදේශීය විචල්‍යයක් සමඟ, ඔබට හරියටම එකක් තිබේ).
Vatine

මම මෙම ප්‍රශ්නය ඇසුවේ ස්ථිතික විචල්‍යයක් සහිත සී ශ්‍රිතයක් වසා දැමීමක් නොවන බව මා සිතන බැවිනි: ස්ථිතික විචල්‍යය දේශීයව අර්ථ දක්වා ඇති අතර එය වසා දැමීමේදී පමණක් දන්නා අතර එය පරිසරයට ප්‍රවේශ නොවේ. එසේම, මට 100% ක් විශ්වාස නැත, නමුත් මම ඔබේ ප්‍රකාශය වෙනත් ආකාරයකින් සකස් කරමි: ඔබ විවිධ කාර්යයන් නිර්මාණය කිරීම සඳහා වසා දැමීමේ යාන්ත්‍රණය භාවිතා කරයි (ශ්‍රිතයක් යනු සංවෘත අර්ථ දැක්වීමකි + එහි නිදහස් විචල්‍යයන් සඳහා බන්ධනයකි).
ජෝජියෝ

5

'රාජ්‍යය' යන සංකල්පය නිර්වචනය නොකර වසා දැමීම යනු කුමක්ද යන්න නිර්වචනය කිරීම දුෂ්කර ය.

මූලික වශයෙන්, කාර්යයන් පළමු පන්තියේ අගයන් ලෙස සලකන පූර්ණ ශබ්ද කෝෂ සහිත භාෂාවක, විශේෂ දෙයක් සිදු වේ. මම මේ වගේ දෙයක් කරනවා නම්:

function foo(x)
return x
end

x = foo

විචල්‍යය xයොමු කිරීම් function foo()පමණක් නොව fooඑය නැවත පැමිණෙන විට තත්වය ඉතිරිව ඇති බව ද සඳහන් කරයි . සැබෑ මැජික් සිදුවන්නේ fooවෙනත් කාර්යයන් එහි විෂය පථය තුළ තවදුරටත් අර්ථ දක්වා ඇති විට ය; එය තමන්ගේම කුඩා පරිසරයක් හා සමානයි ('සාමාන්‍යයෙන්' අපි ගෝලීය පරිසරයක කාර්යයන් නිර්වචනය කරනවා සේම).

ක්‍රියාකාරීව එයට C ++ (C?) හි ස්ථිතික මූලපදය හා සමාන බොහෝ ගැටලු විසඳිය හැකි අතර එය බහු ක්‍රියාකාරී ඇමතුම් පුරා දේශීය විචල්‍ය තත්වයක් රඳවා ගනී; කෙසේ වෙතත් එය ශ්‍රිතයකට එකම මූලධර්මය (ස්ථිතික විචල්‍යය) යෙදීම හා සමාන වේ. වසා දැමීම මඟින් සමස්ත ශ්‍රිතයේම සුරැකීමට සහය එක් කරයි (C ++ හි ස්ථිතික ශ්‍රිත සමඟ කිසිදු සම්බන්ධයක් නැත).

කාර්යයන් පළමු පන්තියේ අගයන් ලෙස සැලකීම සහ වසා දැමීම් සඳහා ආධාරක එකතු කිරීම යන්නෙන් අදහස් කරන්නේ ඔබට එකම ශ්‍රිතයේ අවස්ථා එකකට වඩා වැඩි ප්‍රමාණයක් මතකයේ තිබිය හැකි බවයි (පන්ති වලට සමාන). මෙයින් අදහස් කරන්නේ ශ්‍රිතයක් තුළ C ++ ස්ථිතික විචල්‍යයන් සමඟ කටයුතු කිරීමේදී අවශ්‍ය වන පරිදි ශ්‍රිතයේ තත්වය නැවත සැකසීමකින් තොරව ඔබට එකම කේතය නැවත භාවිතා කළ හැකිය (මේ පිළිබඳව වැරදි විය හැකිද?).

මෙන්න ලුආගේ වසා දැමීමේ සහාය පිළිබඳ පරීක්ෂණ කිහිපයක්.

--Closure testing
--By Trae Barlow
--

function myclosure()
    print(pvalue)--nil
    local pvalue = pvalue or 10
    return function()
        pvalue = pvalue + 10 --20, 31, 42, 53(53 never printed)
        print(pvalue)
        pvalue = pvalue + 1 --21, 32, 43(pvalue state saved through multiple calls)
        return pvalue
    end
end

x = myclosure() --x now references anonymous function inside myclosure()

x()--nil, 20
x() --21, 31
x() --32, 42
    --43, 53 -- if we iterated x() again

ප්රතිපල:

nil
20
31
42

එය උපක්‍රමශීලී විය හැකි අතර, එය බොහෝ විට භාෂාවෙන් භාෂාවට වෙනස් විය හැකි නමුත්, ශ්‍රිතයක් ක්‍රියාත්මක වන සෑම විටම එහි තත්වය යළි පිහිටුවන බව ලුවා හි පෙනේ. මා එසේ කියන්නේ අප විසින් myclosureශ්‍රිතයට / තත්වයට කෙලින්ම ප්‍රවේශ වන්නේ නම් (එය නැවත පැමිණෙන නිර්නාමික ශ්‍රිතය හරහා නොව) ඉහත කේතයේ ප්‍රති results ල වෙනස් pvalueවනු ඇති නිසා ය. නමුත් අපි x (නිර්නාමික ශ්‍රිතය) හරහා මයික්ලෝසර් තත්වයට පිවිසෙන්නේ නම් pvalueඑය සජීවීව හා මතකයේ කොතැනක හෝ ඇති බව ඔබට දැක ගත හැකිය . එයට තව ටිකක් ඇති බව මම සැක කරමි, සමහර විට ක්‍රියාත්මක කිරීමේ ස්වභාවය වඩා හොඳින් යමෙකුට පැහැදිලි කළ හැකිය.

PS: මම C ++ 11 (පෙර සංස්කරණවල ඇති දේ හැර) ලෙවකෑමක් නොදනිමි, එබැවින් මෙය C ++ 11 සහ Lua හි වසා දැමීම් අතර සංසන්දනයක් නොවන බව සලකන්න. එසේම, ලුවා සිට සී ++ දක්වා ඇති සියලුම 'රේඛා' ස්ථිතික විචල්‍යයන් හා සමාන කිරීම් වන අතර වසා දැමීම් 100% සමාන නොවේ; සමහර විට ඒවා සමාන ගැටළු විසඳීමට භාවිතා කළත්.

මට විශ්වාස නැති දෙය නම්, ඉහත කේත උදාහරණයේ දී, නිර්නාමික ශ්‍රිතය හෝ ඉහළ පෙළේ ශ්‍රිතය වසා දැමීමක් ලෙස සලකන්නේ ද?


4

වසා දැමීම යනු රාජ්‍යයට සම්බන්ධ වූ ශ්‍රිතයකි:

පර්ල් වලදී ඔබ මේ වගේ වසා දැමීම් නිර්මාණය කරයි:

#!/usr/bin/perl

# This function creates a closure.
sub getHelloPrint
{
    # Bind state for the function we are returning.
    my ($first) = @_;a

    # The function returned will have access to the variable $first
    return sub { my ($second) = @_; print  "$first $second\n"; };
}

my $hw = getHelloPrint("Hello");
my $gw = getHelloPrint("Goodby");

&$hw("World"); // Print Hello World
&$gw("World"); // PRint Goodby World

C ++ සමඟ සපයා ඇති නව ක්‍රියාකාරිත්වය දෙස බැලුවහොත්.
වත්මන් තත්වය වස්තුවට බැඳීමට ද එය ඔබට ඉඩ දෙයි:

#include <string>
#include <iostream>
#include <functional>


std::function<void(std::string const&)> getLambda(std::string const& first)
{
    // Here we bind `first` to the function
    // The second parameter will be passed when we call the function
    return [first](std::string const& second) -> void
    {   std::cout << first << " " << second << "\n";
    };
}

int main(int argc, char* argv[])
{
    auto hw = getLambda("Hello");
    auto gw = getLambda("GoodBye");

    hw("World");
    gw("World");
}

2

සරල කාර්යයක් සලකා බලමු:

function f1(x) {
    // ... something
}

මෙම ශ්‍රිතය වෙනත් මට්ටමේ ශ්‍රිතයක් තුළ කූඩු කර නොමැති නිසා එය ඉහළ මට්ටමේ ශ්‍රිතයක් ලෙස හැඳින්වේ. සෑම ජාවාස්ක්‍රිප්ට් ශ්‍රිතයක්ම “විෂය පථය” යනුවෙන් හැඳින්වෙන වස්තු ලැයිස්තුවක් සමඟ සම්බන්ධ වේ . මෙම විෂය පථය ඇණවුම් කරන ලද වස්තු ලැයිස්තුවකි. මෙම සෑම වස්තුවක්ම සමහර විචල්යයන් අර්ථ දක්වයි.

ඉහළ මට්ටමේ කාර්යයන් වලදී, විෂය පථය තනි වස්තුවක් වන ගෝලීය වස්තුවකින් සමන්විත වේ. උදාහරණයක් ලෙස, f1ඉහත ශ්‍රිතයට විෂය පථ දාමයක් ඇති අතර එහි තනි වස්තුවක් ඇති අතර එය සියලු ගෝලීය විචල්‍යයන් අර්ථ දක්වයි. .

මෙම ශ්‍රිතය ආයාචනා කළ විට, ජාවාස්ක්‍රිප්ට් “සක්‍රිය වස්තුවක්” ලෙස යමක් නිර්මාණය කර එය විෂය පථයේ ඉහළින් තබයි. මෙම වස්තුවෙහි සියලුම දේශීය විචල්‍යයන් අඩංගු වේ (උදාහරණයක් ලෙස xමෙහි). එබැවින් දැන් අපට විෂය පථයේ වස්තු දෙකක් ඇත: පළමුවැන්න සක්‍රීය වස්තුව වන අතර ඊට යටින් ගෝලීය වස්තුව වේ.

විවිධ වේලාවන්හිදී වස්තූන් දෙක විෂය පථයට ඇතුළත් කර ඇති බව ඉතා ප්‍රවේශමෙන් සලකන්න. ශ්‍රිතය අර්ථ දක්වන විට ගෝලීය වස්තුව දමනු ලැබේ (එනම්, ජාවාස්ක්‍රිප්ට් ශ්‍රිතය විග්‍රහ කොට ශ්‍රිත වස්තුව නිර්මාණය කළ විට), සහ ක්‍රියාකාරී වස්තුව ඇතුළු වන විට සක්‍රිය වස්තුව ඇතුල් වේ.

ඉතින්, අපි දැන් මෙය දනිමු:

  • සෑම ශ්‍රිතයක්ම ඒ හා සම්බන්ධ විෂය පථ දාමයක් ඇත
  • ශ්‍රිතය අර්ථ දක්වන විට (ශ්‍රිත වස්තුව නිර්මාණය කළ විට), ජාවාස්ක්‍රිප්ට් එම ශ්‍රිතය සමඟ විෂය පථයක් සුරකිනු ඇත
  • ඉහළ මට්ටමේ කාර්යයන් සඳහා, විෂය පථයේ දාමයේ ක්‍රියාකාරී අර්ථ දැක්වීමේ වේලාවේ ගෝලීය වස්තුව පමණක් අඩංගු වන අතර ආයාචන වේලාවේදී අතිරේක සක්‍රීය වස්තුවක් එක් කරයි

අපි කැදැලි කාර්යයන් සමඟ කටයුතු කරන විට තත්වය සිත්ගන්නාසුළු වේ. ඉතින්, අපි එකක් නිර්මාණය කරමු:

function f1(x) {

    function f2(y) {
        // ... something
    }

}

f1නිර්වචනය කළ විට අපට ගෝලීය වස්තුව පමණක් අඩංගු විෂය පථයක් ලැබේ.

දැන් f1ඇමතූ විට , විෂය පථයේ දාමය f1සක්‍රීය වස්තුව ලබා ගනී. මෙම සක්‍රිය වස්තුවෙහි ශ්‍රිතය වන විචල්‍යය xසහ විචල්‍යය අඩංගු වේ f2. තවද, f2එය අර්ථ දක්වා ඇති බව සලකන්න . එබැවින්, මෙම අවස්ථාවෙහිදී, ජාවාස්ක්‍රිප්ට් සඳහා නව විෂය පථයක් ද ඉතිරි කරයි f2. මෙම අභ්‍යන්තර ශ්‍රිතය සඳහා සුරකින ලද විෂය පථය දැනට ක්‍රියාත්මක වන විෂය පථ දාමයයි. වත්මන් විෂය පථය දාමය වේ f1. ඒ නිසා f2ගේ විෂය පථය දාම වේ f1ගේ වත්මන් සකී්රය වස්තුව අඩංගු - විෂය පථය දාම f1හා ගෝලීය වස්තුව.

f2එය හැඳින්වූ විට , එය සක්‍රීය කිරීමේ වස්තුව අඩංගු yවන අතර එහි විෂය පථයට එකතු කර ඇති අතර එය දැනටමත් සක්‍රිය වස්තුව f1සහ ගෝලීය වස්තුව අඩංගු වේ .

තවත් කැදැලි ශ්‍රිතයක් නිර්වචනය කර ඇත්නම් f2, එහි විෂය පථයේ අර්ථ දැක්වීමේ වේලාවට වස්තු තුනක් (බාහිර ශ්‍රිත දෙකක සක්‍රීය වස්තු 2 ක් සහ ගෝලීය වස්තුව) අඩංගු වන අතර ඉන්වොයිසි වේලාවේදී 4 ක් අඩංගු වේ.

ඉතින්, දැන් අපට තේරෙනවා විෂය පථය ක්‍රියා කරන ආකාරය නමුත් අපි තවමත් වසා දැමීම් ගැන කතා කර නැත.

ශ්‍රිතයේ විචල්‍යයන් නිරාකරණය කර ඇති ශ්‍රිත වස්තුවක් සහ විෂය පථයක් (විචල්‍ය බන්ධන සමූහයක්) සංයෝජනය පරිගණක විද්‍යා සාහිත්‍යයේ වසා දැමීමක් ලෙස හැඳින්වේ - ජාවාස්ක්‍රිප්ට් ඩේවිඩ් ෆ්ලැනගන් විසින් නිශ්චිත මාර්ගෝපදේශය

බොහෝ ශ්‍රිතයන් ආයාචනය කරනු ලබන්නේ ශ්‍රිතය නිර්වචනය කරන විට ක්‍රියාත්මක වූ එකම විෂය පථ දාමය භාවිතා කර වන අතර එය වසා දැමීමක් සිදුවීම ඇත්තෙන්ම වැදගත් නොවේ. ඒවා නිර්වචනය කරන විට බලපැවැත්වූ ඒවාට වඩා වෙනස් විෂය පථයක් යටතේ ආයාචනා කරන විට වසා දැමීම් සිත්ගන්නාසුළු වේ. මෙය වඩාත් සුලභව සිදුවන්නේ කැදැලි ශ්‍රිත වස්තුවක් අර්ථ දක්වා ඇති ශ්‍රිතයෙන් ආපසු ලබා දෙන විටය .

ශ්‍රිතය නැවත පැමිණි විට, එම සක්‍රිය වස්තුව විෂය පථයෙන් ඉවත් කරනු ලැබේ. කැදැලි කාර්යයන් නොතිබුනේ නම්, සක්‍රීය වස්තුව පිළිබඳ වැඩි සඳහනක් නොමැති අතර එය කසළ එකතු වේ. කැදැලි ශ්‍රිත නිර්වචනය කර ඇත්නම්, එම එක් එක් ශ්‍රිතයට විෂය පථ දාමය ගැන සඳහනක් ඇති අතර, එම විෂය පථය සක්‍රීය වස්තුවට යොමු වේ.

කෙසේ වෙතත්, එම කැදැලි ශ්‍රිත වස්තූන් ඒවායේ බාහිර ක්‍රියාකාරිත්වය තුළ පවතින්නේ නම්, ඒවාම කුණු කසළ එකතු කරනු ලැබේ. නමුත් ශ්‍රිතය කැදැලි ශ්‍රිතයක් නිර්වචනය කර එය නැවත ලබා දෙන්නේ නම් හෝ එය කොතැනක හෝ දේපලක් තුළ ගබඩා කරන්නේ නම්, එවිට කූඩු කළ ශ්‍රිතයට බාහිර සඳහනක් ඇත. එය කසළ එකතු නොවන අතර එය සඳහන් කරන සක්‍රිය වස්තුව කසළ එකතු නොකෙරේ.

අපගේ ඉහත උදාහරණය, අපි ආපසු හැරී එන්නේ නැහැ f2සිට f1ඒ නිසා,, ඇමතුමක් විට f1ප්රතිලාභ, එහි සක්රිය වස්තුව එහි විෂය පථය දාම හා කුණු කසළ එකතු ඉවත් කරනු ඇත. නමුත් අපට මේ වගේ දෙයක් තිබුණා නම්:

function f1(x) {

    function f2(y) {
        // ... something
    }

    return f2;
}

මෙන්න, ආපසු පැමිණීමේ f2විෂය පථය සක්‍රීය කිරීමේ වස්තුව අඩංගු වන f1අතර එම නිසා එය කසළ එකතු නොවේ. මෙම අවස්ථාවෙහිදී, අප අමතන්නේ නම්, අප පිටත සිටියද එයට විචල්‍යයට f2ප්‍රවේශ විය හැකිය.f1xf1

එබැවින් ශ්‍රිතයක් මඟින් එහි විෂය පථය එය සමඟ තබා ගන්නා අතර විෂය පථ දාමය සමඟ බාහිර ශ්‍රිතවල සියලුම සක්‍රීය වස්තු පැමිණේ. වසා දැමීමේ සාරය මෙයයි. ජාවාස්ක්‍රිප්ට් හි කාර්යයන් “ශබ්දකෝෂයෙන් පරිහරණය කර ඇති බව අපි කියමු , එයින් අදහස් කරන්නේ ඒවා ඇමතූ විට ක්‍රියාකාරී වූ විෂය පථයට පටහැනිව අර්ථ දැක්වීමේදී ක්‍රියාකාරී වූ විෂය පථය සුරකිනු ඇති බවයි.

පුද්ගලික විචල්‍යයන් ආසන්න වශයෙන් ගණනය කිරීම, සිදුවීම් මත පදනම් වූ ක්‍රමලේඛනය, අර්ධ යෙදුම වැනි වසා දැමීම් ඇතුළත් ප්‍රබල ක්‍රමලේඛන ක්‍රම ගණනාවක් තිබේ .

වසා දැමීමට සහාය වන සියලුම භාෂාවන්ට මේ සියල්ල අදාළ වන බව සලකන්න. උදාහරණයක් ලෙස PHP (5.3+), පයිතන්, රූබි ආදිය.


-1

වසා දැමීම යනු සම්පාදක ප්‍රශස්තිකරණයකි (සින්ටැක්ටික් සීනි?). සමහර අය මෙය දුප්පත් මිනිසාගේ වස්තුව ලෙසද හැඳින්වේ.

එරික් ලිපර්ට්ගේ පිළිතුර බලන්න : (පහත උපුටා ගැනීම)

සම්පාදකයා මෙවැනි කේත ජනනය කරයි:

private class Locals
{
  public int count;
  public void Anonymous()
  {
    this.count++;
  }
}

public Action Counter()
{
  Locals locals = new Locals();
  locals.count = 0;
  Action counter = new Action(locals.Anonymous);
  return counter;
}

තේරුමක් තිබේද?
එසේම, ඔබ සැසඳීම් ඉල්ලා සිටියේය. VB සහ JScript යන දෙකම එකම ආකාරයකින් වසා දැමීම් නිර්මාණය කරයි.


මෙම පිළිතුර සීඩබ්ලිව් ය. එරික්ගේ විශිෂ්ට පිළිතුර සඳහා මට ලකුණු සුදුසු නොවේ. ඔබට සුදුසු යැයි පෙනෙන පරිදි කරුණාකර එය ඉහළට ඔසවන්න. HTH
goodguys_activate

3
-1: ඔබේ පැහැදිලි කිරීම C # හි මුල් බැස ඇත. වසා දැමීම බොහෝ භාෂාවල භාවිතා වන අතර මෙම භාෂාවල සින්ටැක්ටික් සීනි වලට වඩා බොහෝ සෙයින් වැඩි වන අතර එහි ක්‍රියාකාරිත්වය සහ තත්වය යන දෙකම ඇතුළත් වේ.
මාටින් යෝක්

1
නැත, වසා දැමීම යනු හුදෙක් “සම්පාදක ප්‍රශස්තිකරණය” හෝ සින්ටැක්ටික් සීනි නොවේ. -1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.