التهيئة الكسولة

في برمجة الحاسوب ، تُعرف عملية التهيئة الكسولة بأنها أسلوب لتأجيل إنشاء كائن ، أو حساب قيمة ، أو أي عملية أخرى مكلفة حتى الحاجة إليها لأول مرة. وهي نوع من التقييم الكسول الذي يشير تحديدًا إلى إنشاء الكائنات أو الموارد الأخرى.

يتم تحقيق ذلك عادةً عن طريق إضافة تعديل إلى دالة الوصول (أو دالة جلب الخاصية) للتحقق مما إذا كان عضو خاص، يعمل كذاكرة تخزين مؤقتة، قد تم تهيئته مسبقًا. إذا كان كذلك، يتم إرجاعه مباشرةً. وإذا لم يكن كذلك، يتم إنشاء نسخة جديدة منه، ووضعها في متغير العضو، وإعادتها إلى المستدعي في الوقت المناسب لاستخدامها لأول مرة.

إذا كانت للكائنات خصائص نادرة الاستخدام، فقد يُحسّن ذلك من سرعة بدء التشغيل. قد يكون متوسط ​​أداء البرنامج أسوأ قليلاً من حيث الذاكرة (لمتغيرات الحالة) ودورات التنفيذ (للتحقق منها)، ولكن تأثير إنشاء الكائنات يتوزع على مدار الوقت ("يُستهلك") بدلاً من أن يتركز في مرحلة بدء تشغيل النظام، وبالتالي يمكن تحسين متوسط ​​أوقات الاستجابة بشكل كبير.

في التعليمات البرمجية متعددة الخيوط ، يجب مزامنة الوصول إلى الكائنات/الحالة التي تم تهيئتها بشكل كسول للحماية من حالات التزامن .

"المصنع الكسول"

في منظور أنماط تصميم البرمجيات ، غالباً ما يُستخدم التهيئة الكسولة مع نمط طريقة المصنع . وهذا يجمع بين ثلاث أفكار:

  • استخدام أسلوب المصنع لإنشاء نسخ من فئة ( نمط أسلوب المصنع )
  • تخزين النسخ في خريطة ، وإعادة نفس النسخة لكل طلب للحصول على نسخة بنفس المعلمات ( نمط متعدد النسخ )
  • استخدام التهيئة الكسولة لإنشاء الكائن في المرة الأولى التي يُطلب فيها (نمط التهيئة الكسولة)

أمثلة

أكشن سكريبت 3

فيما يلي مثال على فئة تم تطبيق التهيئة الكسولة فيها باستخدام لغة ActionScript :

package examples.lazyinstantiation { public class Fruit { private var _typeName : String ; private static var instancesByTypeName : Dictionary = new Dictionary ( ) ; public function Fruit ( typeName : String ) : void { this._typeName = typeName ; } public function gettypeName ( ) : String { return _typeName ; } public static function getFruitByTypeName ( typeName : String ) : Fruit { return instancesByTypeName [ typeName ] ||= new Fruit ( typeName ) ; } public static function printCurrentTypes ( ) : void { for each ( var fruit : Fruit in instancesByTypeName ) { // iterates through each value trace ( fruit.typeName ) ; } } } }

الاستخدام الأساسي:

package { import examples.lazyinstantiation ; public class Main { public function Main ( ) : void { Fruit.getFruitByTypeName ( "Banana" ) ; Fruit.printCurrentTypes ( ) ; Fruit.getFruitByTypeName ( " Apple " ) ; Fruit.printCurrentTypes ( ) ; Fruit.getFruitByTypeName ( " Banana " ) ; Fruit.printCurrentTypes ( ) ; } } }

ج

في لغة C ، يتم عادةً تنفيذ التقييم الكسول داخل دالة واحدة، أو ملف مصدر واحد، باستخدام متغيرات ثابتة .

في دالة:

#include <stddef.h> #include <stdlib.h> #include <stdio.h> #include <string.h>typedef struct Fruit { char * name ; struct Fruit * next ; int number ; // أعضاء أخرى } Fruit ;Fruit * getFruit ( char * name ) { static Fruit * fruitList ; static int seq ; Fruit * f = fruitList ;بينما ( f ) { إذا ( ! strcmp ( name , f -> name )) { أرجع f ; } f = f -> next ; }إذا لم يتم تخصيص الذاكرة لمتغير من نوع Fruit ، فسيتم إرجاع قيمة فارغة ( NULL ) .إذا لم يكن اسم المتغير f مطابقًا لقيمة strdup ( name ) ، فسيتم تحرير المتغير f وإرجاع قيمة NULL .f -> number = ++ seq ; f -> next = fruitList ; fruitList = f ; return f ; }// مثال على الكودint main ( int argc , char * argv []) { Fruit * f ;إذا كان عدد الوسائط أقل من 2 ، فسيتم طباعة رسالة " الاستخدام: فواكه اسم الفاكهة [...] \n " على الخطأ القياسي ، ثم يتم إرجاع القيمة 1 .for ( int i = 1 ; i < argc ; i ++ ) { if ( f = getFruit ( argv [ i ])) { printf ( "Fruit %s: number %d \n " , argv [ i ], f- > number ); } }return 0 ; }

إن استخدام ملف مصدر واحد بدلاً من ذلك يسمح بمشاركة الحالة بين وظائف متعددة، مع إخفائها في الوقت نفسه عن الوظائف غير ذات الصلة.

Fruit.h :

دبراغما مرة واحدةtypedef struct Fruit { char * name ; struct Fruit * next ; int number ; // أعضاء أخرى } Fruit ;Fruit * getFruit ( char * name ); void printFruitList ( FILE * file );

Fruit.c :

#include <stddef.h> #include <stdlib.h> #include <stdio.h> #include <string.h>#include "Fruit.h"static Fruit * fruitList ; static int seq ;struct Fruit * getFruit ( char * name ) { Fruit * f = fruitList ;بينما ( f ) { إذا ( ! strcmp ( name , f -> name )) { أرجع f ; } f = f -> next ; }إذا لم يتم تخصيص الذاكرة لمتغير من نوع Fruit ، فسيتم إرجاع قيمة فارغة ( NULL ) .إذا لم يكن اسم المتغير f مطابقًا لقيمة strdup ( name ) ، فسيتم تحرير المتغير f وإرجاع قيمة NULL .f -> number = ++ seq ; f -> next = fruitList ; fruitList = f ; return f ; }void printFruitList ( FILE * file ) { Fruit * f = fruitList ; while ( f ) { fprintf ( file , "%4d %s \n " , f -> number , f -> name ); f = f -> next ; } }

Main.c :

#include <stdlib.h> #include <stdio.h>#include "Fruit.h"int main ( int argc , char * argv []) { Fruit * f ;إذا كان عدد الوسائط أقل من 2 ، فسيتم طباعة رسالة " الاستخدام: فواكه اسم الفاكهة [...] \n " على الخطأ القياسي ، ثم يتم إرجاع القيمة 1 .for ( int i = 1 ; i < argc ; i ++ ) { if ( f = getFruit ( argv [ i ])) { printf ( "Fruit %s: number %d \n " , argv [ i ], f- > number ); } }printf ( "تم إنتاج الثمار التالية: \n " ); printFruitList ( stdout ); return 0 ; }

سي شارب

في إطار عمل .NET 4.0، أضافت مايكروسوفت System.Lazyفئةً يمكن استخدامها للتحميل الكسول. فيما يلي بعض التعليمات البرمجية التجريبية التي تُطبّق التحميل الكسول لهذه الفئة.Fruit

باستخدام النظام ؛Lazy <Fruit> lazyFruit = new ( ) ; Fruit fruit = lazyFruit.Value ;

إليك مثال توضيحي بلغة C# .

Fruitلا يقوم الصنف نفسه بأي شيء هنا، متغير الصنف_typesDictionary عبارة عن قاموس/خريطة تُستخدم لتخزين Fruitالمثيلات بواسطة typeName.

namespace Wikipedia.Examples ;باستخدام System ؛ باستخدام System.Collections ؛ باستخدام System.Collections.Generic ؛class Fruit { private string _typeName ; private static IDictionary < string , Fruit > _typesDictionary = new Dictionary < string , Fruit > ();private Fruit ( string typeName ) { this . _typeName = typeName ; }public static Fruit GetFruitByTypeName ( string type ) { Fruit fruit ;إذا لم يكن بالإمكان الحصول على قيمة من النوع ` type` في قاموس الأنواع ، فسيتم إنشاء كائن ` fruit` جديد باستخدام النوع ` type` ._typesDictionary.Add ( type , fruit ) ; }أعد الفاكهة ؛ }public static void ShowAll ( ) { if ( _typesDictionary.Count > 0 ) { Console.WriteLine ( " عدد النسخ = {0}" , _typesDictionary.Count ) ; foreach ( KeyValuePair < string , Fruit > kvp in _typesDictionary ) { Console.WriteLine ( kvp.Key ) ; } Console.WriteLine ( ) ; } } public Fruit ( ) { // مطلوب لكي يتم تجميع المثال } }public class Program { static void Main ( string [] args ) { Fruit . GetFruitByTypeName ( "Banana" ); Fruit . ShowAll ();Fruit.GetFruitByTypeName ( "Apple " ) ; Fruit.ShowAll ( ) ;// يُعيد نسخة موجودة مسبقًا من أول مرة تم فيها إنشاء فاكهة باسم "موز" Fruit.GetFruitByTypeName ( "موز" ); Fruit.ShowAll ( );Console.ReadLine ( ) ; } }

مثال بسيط إلى حد ما لنمط تصميم التهيئة الكسولة، يعتمد على ملء الفراغات، باستثناء أنه يستخدم تعدادًا للنوع.

namespace Wikipedia.Examples ;باستخدام System ؛ باستخدام System.Collections.Generic ؛public class LazyFactoryObject { // مجموعة داخلية من العناصر // يضمن IDictionary أن تكون العناصر فريدة private IDictionary < LazyObjectSize , LazyObject > _LazyObjectList = new Dictionary < LazyObjectSize , LazyObject > ();// تعداد لتمرير اسم الحجم المطلوب // يتجنب تمرير السلاسل النصية وهو جزء من LazyObject المتقدم public enum LazyObjectSize { None , Small , Big , Bigger , Huge }// نوع الكائن القياسي الذي سيتم إنشاؤه public struct LazyObject { public LazyObjectSize Size ; public IList < int > Result ; }// يأخذ الحجم وينشئ قائمة " مكلفة " خاصة IList <int> Result ( LazyObjectSize size ) { IList <int> result = null ;switch ( size ) { case LazyObjectSize.Small : result = CreateSomeExpensiveList ( 1 , 100 ) ; break ; case LazyObjectSize.Big : result = CreateSomeExpensiveList ( 1 , 1000 ) ; break ; case LazyObjectSize.Bigger : result = CreateSomeExpensiveList ( 1 , 10000 ) ; break ; case LazyObjectSize.Huge : result = CreateSomeExpensiveList ( 1 , 100000 ) ; break ; case LazyObjectSize.None : result = null ; break ; default : result = null ; break ; }أعد النتيجة ؛ }// ليس عنصرًا مكلفًا للإنشاء، ولكن الفكرة واضحة // يؤجل إنشاء بعض الكائنات المكلفة حتى الحاجة إليها private IList <int> CreateSomeExpensiveList ( int start , int end ) { IList <int> result = new List <int> ( ) ;for ( int counter = 0 ; counter < ( end - start ) ; counter ++ ) { result.Add ( start + counter ) ; }أعد النتيجة ؛ }public LazyFactoryObject () { // مُنشئ فارغ }public LazyObject GetLazyFactoryObject ( LazyObjectSize size ) { // نعم، أعلم أنه غير واضح وغير دقيق LazyObject noGoodSomeOne ;// يسترجع LazyObjectSize من القائمة عبر out، وإلا يُنشئ واحدًا ويضيفه إلى القائمة إذا ( ! _LazyObjectList . TryGetValue ( size , out noGoodSomeOne )) { noGoodSomeOne = new LazyObject (); noGoodSomeOne . Size = size ; noGoodSomeOne . Result = this . Result ( size );_LazyObjectList.Add ( size , noGoodSomeOne ) ; }return noGoodSomeOne ; } }

لغة سي++

هذا المثال مكتوب بلغة C++ .

استيراد std ؛template < typename K , typename V > using HashMap = std :: unordered_map < K , V > ; template < typename T > using SharedPtr = std :: shared_ptr < T > ; using String = std :: string ;class Fruit { private : static HashMap < String , SharedPtr < Fruit >> types = {}; String type ;// ملاحظة: المُنشئ خاص، مما يُجبر على استخدام الدالة الثابتة getFruit. explicit Fruit ( const String & type ) : type { type } {} public : // دالة المصنع الكسولة، تحصل على نسخة Fruit المرتبطة بنوع معين. // تُنشئ نسخًا جديدة حسب الحاجة. static SharedPtr < Fruit > getFruit ( const String & type ) { auto [ it , inserted ] = types . emplace ( type , nullptr ); if ( inserted ) { it -> second = std :: make_shared < Fruit > ( type ); } return it -> second ; }// لأغراض التوضيح فقط، لرؤية النمط عمليًا. static void printCurrentTypes () { std :: println ( "عدد النسخ المُنشأة = {}" , types . size ()); for ( const auto & [ type , fruit ] : types ) { std :: println ({}, type ); } std :: println (); } };int main ( int argc , char * argv []) { Fruit :: getFruit ( "Banana" ); Fruit :: printCurrentTypes ();الفاكهة :: getFruit ( "Apple" ); الفاكهة :: printCurrentTypes ()؛// تُعيد هذه الدالة نسخةً موجودةً مسبقًا من أول مرة تم فيها إنشاء فاكهة من نوع "موز". Fruit :: getFruit ( "موز" ); Fruit :: printCurrentTypes (); }// المخرجات: // // عدد النسخ المُنشأة = 1 // موزة // // عدد النسخ المُنشأة = 2 // تفاحة // موزة // // عدد النسخ المُنشأة = 2 // تفاحة // موزة //

كريستال

صنف الفاكهة (Fruit) نوع الجلب الخاص : سلسلة نصية @@types = {} of String => Fruitdef initialize ( @type ) enddef self.get_fruit_by_type ( type : String ) @@ types [ type ] || = Fruit.new ( type ) enddef self.show_all puts " عدد النسخ المُنشأة : # { @@ types.size } " @@ types.each do | type , fruit | puts " # { type } " end puts enddef self.size @@ types.size end endFruit.get_fruit_by_type ( " Banana " ) Fruit.show_allFruit.get_fruit_by_type ( " Apple " ) Fruit.show_allFruit.get_fruit_by_type ( " Banana " ) Fruit.show_all

الناتج:

عدد الحالات التي تم إجراؤها: 1 موز عدد الحالات المسجلة: 2 موز تفاحة عدد الحالات المسجلة: 2 موز تفاحة 

هاكس

هذا المثال مكتوب بلغة هاكس . [ 1 ]

class Fruit { private static var _instances = new Map < String , Fruit >();public var name ( default , null ): String ;public function new ( name : String ) { this . name = name ; }public static function getFruitByName ( name : String ) : Fruit { if ( ! _instances.exists ( name ) ) { _instances.set ( name , new Fruit ( name ) ) ; } return _instances.get ( name ) ; }public static function printAllTypes ( ) { trace ([ for ( key in _instances.keys ()) key ] ); } }

الاستخدام

class Test { public static function main () { var banana = Fruit . getFruitByName ( "Banana" ); var apple = Fruit . getFruitByName ( "Apple" ); var banana2 = Fruit . getFruitByName ( "Banana" ); trace ( banana == banana2 ); // صحيح. نفس الموز Fruit . printAllTypes (); // ["Banana","Apple"] } }

جافا

هذا المثال مكتوب بلغة جافا .

package org.wikipedia.examples ;استيراد java.util.HashMap ؛ استيراد java.util.Map ؛التعداد FruitType { NONE , APPLE , BANANA , }class Fruit { private static Map < FruitType , Fruit > types = new HashMap <> (); /**  * استخدام مُنشئ خاص لفرض استخدام طريقة المصنع.  * @param type  */ private Fruit ( FruitType type ) {} /**  * دالة مصنع كسولة، تحصل على نسخة Fruit المرتبطة بنوع معين  . * تُنشئ نسخًا جديدة حسب الحاجة.  * @param type أي نوع فاكهة مسموح به، على سبيل المثال APPLE  * @return نسخة Fruit المرتبطة بهذا النوع.  */ public static Fruit getFruitByTypeName ( FruitType type ) { Fruit fruit ; // هذه الدالة بها مشاكل تزامن. هنا، القراءة من الأنواع غير متزامنة، // لذلك قد يتم استدعاء types.put و types.containsKey في نفس الوقت. // لا تستغرب إذا كانت البيانات تالفة. if ( ! types . containsKey ( type )) { // تهيئة كسولة fruit = new Fruit ( type ); types . put ( type , fruit ); } else { // حسنًا، إنها متاحة حاليًا fruit = types . get ( type ); } return fruit ; } /**  * دالة مصنع كسولة، تحصل على نسخة Fruit المرتبطة بنوع معين  . * تُنشئ نسخًا جديدة حسب الحاجة. تستخدم نمط قفل مزدوج التحقق  للاستخدام في بيئات متزامنة للغاية.  * @param type أي نوع فاكهة مسموح به، على سبيل المثال تفاحة  * @return كائن Fruit المرتبط بهذا النوع.  */ public static Fruit getFruitByTypeNameHighConcurrentVersion ( FruitType type ) { if ( ! types . containsKey ( type )) { synchronized ( types ) { // تحقق مرة أخرى، بعد الحصول على القفل للتأكد من // أن الكائن لم يتم إنشاؤه في هذه الأثناء بواسطة مؤشر ترابط آخر if ( ! types . containsKey ( type )) { // تهيئة كسولة types . put ( type , new Fruit ( type )); } } } return types . get( type ) ; } / ** *  يعرض جميع الفواكه المُدخلة. * / public static  void showAll ( ) { if ( types.size ( ) > 0 ) { System.out.printf ( " عدد النسخ = % d % n " , types.size ( ) ) ; for ( Map.Entry < FruitType , Fruit > entry : types.entrySet ( ) ) { String fruit = entry.getKey ( ) . toString ( ) ; fruit = Character.toUpperCase ( fruit.charAt ( 0 ) ) + fruit.substring ( 1 ) ; System.out.println ( fruit ) ; } System.out.println ( ) ; } } }public class Program {/**  * @param args  */ public static void main ( String [] args ) { Fruit . getFruitByTypeName ( FruitType . BANANA ); الفاكهة . showAll (); الفاكهة . getFruitByTypeName ( FruitType . APPLE ); الفاكهة . showAll (); الفاكهة . getFruitByTypeName ( FruitType . BANANA ); الفاكهة . showAll (); } }

الناتج

عدد الحالات التي تم إجراؤها = 1 موز عدد الحالات التي تم إجراؤها = 2 موز تفاحة عدد الحالات التي تم إجراؤها = 2 موز تفاحة 

جافا سكريبت

هذا المثال مكتوب بلغة جافا سكريبت .

var Fruit = ( function () { var types = {}; function Fruit () {};// دالة لحساب عدد الخصائص الخاصة بالكائن ( obj ) { return Object.keys ( obj ) .length ; }var _static = { getFruit : function ( type ) { if ( typeof types [ type ] == 'undefined' ) { types [ type ] = new Fruit ; } return types [ type ]; }, printCurrentTypes : function () { console . log ( 'عدد النسخ المُنشأة: ' + count ( types )); for ( var type in types ) { console . log ( type ); } } };return _static ;})();الفاكهة . getFruit ( 'Apple' ); الفاكهة . printCurrentTypes (); الفاكهة . getFruit ( 'الموز' ); الفاكهة . printCurrentTypes (); الفاكهة . getFruit ( 'Apple' ); الفاكهة . printCurrentTypes ();

الناتج

عدد الحالات التي تم إجراؤها: 1 تفاحة عدد الحالات المسجلة: 2 تفاحة موز عدد الحالات المسجلة: 2 تفاحة موز 

PHP

فيما يلي مثال على التهيئة الكسولة في PHP 7.4:

<?php header ( 'Content-Type: text/plain; charset=utf-8' );class Fruit { private string $type ; private static array $types = array ();private function __construct ( string $type ) { $this -> type = $type ; }public static function getFruit ( string $type ) : Fruit { // يتم هنا تهيئة الكائن عند الطلب if ( ! isset ( self :: $types [ $type ])) { self :: $types [ $type ] = new Fruit ( $type ); }return self :: $types [ $type ]; }public static function printCurrentTypes () : void { echo 'عدد النسخ المُنشأة: ' . count ( self :: $types ) . " \n " ; foreach ( array_keys ( self :: $types ) as $key ) { echo " $key \n " ; } echo " \n " ; } }الفاكهة :: getFruit ( 'Apple' ); الفاكهة :: printCurrentTypes ()؛الفاكهة :: getFruit ( 'Banana' ); الفاكهة :: printCurrentTypes ()؛الفاكهة :: getFruit ( 'Apple' ); الفاكهة :: printCurrentTypes ()؛/* الناتج:عدد الحالات المُسجلة: 1 أبلعدد الحالات: 2 تفاحة وموزةعدد مرات التكرار: 2 تفاحة وموز */

بايثون

هذا المثال مكتوب بلغة بايثون .

class Fruit : def __init__ ( self , item : str ) -> None : self . item = itemclass FruitCollection : def __init__ ( self ) -> None : self . items : dict [ str , Fruit ] = {}دالة get_fruit ( self , item : str ) -> Fruit : إذا لم يكن العنصر موجودًا في self . items : self . items [ item ] = Fruit ( item )أعد self.items [ item ]إذا كان __name__ يساوي " __main__ " : fruits : FruitCollection = FruitCollection () print ( fruits.get_fruit ( "Apple" )) print ( fruits.get_fruit ( " Lime " ))

روبي

هذا المثال مكتوب بلغة روبي ، ويُظهر كيفية تهيئة رمز المصادقة بشكل كسول من خدمة بعيدة مثل جوجل. كما أن طريقة تخزين @auth_token مؤقتًا تُعد مثالًا على التخزين المؤقت .

تتطلب مكتبة 'net/http' فئة Blogger دالة auth_token @auth_token ||= ( res = Net :: HTTP . post_form ( uri , params )) && get_token_from_http_response ( res ) نهاية# يتم تعريف get_token_from_http_response و uri و params لاحقًا في نهاية الفئةb = Blogger.new b.instance_variable_get ( : @ auth_token ) # تُرجع nil b.auth_token # تُرجع token b.instance_variable_get ( : @ auth_token ) # تُرجع token

الصدأ

Rust have std::cell::LazyCell. [ 2 ]

استخدم std :: cell :: LazyCell ؛let lazy : LazyCell = LazyCell :: new ( || 42 );

سكالا

تدعم لغة سكالا بشكل مدمج تهيئة المتغيرات الكسولة. [ 3 ]

scala > val x = { println ( "Hello" ); 99 } Hello x : Int = 99 scala > lazy val y = { println ( "Hello!!" ); 31 } y : Int = < lazy > scala > y Hello !! res2 : Int = 31 scala > y res3 : Int = 31

أحاديث قصيرة

هذا المثال مكتوب بلغة Smalltalk ، وهو عبارة عن طريقة وصول نموذجية لإرجاع قيمة متغير باستخدام التهيئة الكسولة.

الارتفاع ^ الارتفاع إذا كان فارغًا: [ الارتفاع := 2.0 ] .

البديل "غير الكسول" هو استخدام طريقة تهيئة يتم تشغيلها عند إنشاء الكائن ثم استخدام طريقة وصول أبسط لجلب القيمة.

تهيئة الارتفاع := 2.0الارتفاع ^ الارتفاع

لاحظ أنه يمكن استخدام التهيئة الكسولة أيضًا في اللغات غير الموجهة للكائنات .

علوم الحاسوب النظرية

في مجال علوم الحاسوب النظرية ، تُعدّ التهيئة الكسولة [ 4 ] (وتُسمى أيضًا المصفوفة الكسولة ) تقنيةً لتصميم هياكل بيانات تعمل مع ذاكرة لا تحتاج إلى تهيئة. على وجه التحديد، لنفترض أن لدينا جدولًا T يحتوي على n خلية ذاكرة غير مهيأة (مرقمة من 1 إلى n )، ونريد تعيين m خلية من هذا الجدول، على سبيل المثال، نريد تعيين T[ki] := vi للأزواج (k1, v1)، ...، (km, vm ) حيث تكون جميع  قيم ki مختلفة . تُمكّننا تقنية التهيئة الكسولة من القيام بذلك في O ( m) عملية فقط ، بدلًا من O ( m + n ) عملية لتهيئة جميع خلايا الجدول أولًا. ببساطة ، تقوم التقنية على تخصيص جدول V لتخزين الأزواج ( ki , vi ) بترتيب عشوائي، وكتابة موضع المفتاح ki في V لكل i في الخلية T [ ki ] ، مع ترك باقي خلايا T غير مهيأة. يمكن استخدام هذه الطريقة لمعالجة الاستعلامات على النحو التالي: عند البحث عن الخلية T [ k ] لقيمة معينة k ، نتحقق مما إذا كانت T [ k ] تقع ضمن النطاق {1، ...، m }: إذا لم تكن كذلك، فإن T [ k ] غير مهيأة. وإلا، نتحقق من V [ T [ k ]]، ونتأكد من أن العنصر الأول في هذا الزوج يساوي k . إذا لم يكن كذلك، فإن T [ k ] غير مهيأة (وقد وقعت مصادفةً ضمن النطاق {1، ...، m }). وإلا، نعلم أن T [ k ] هي بالفعل إحدى الخلايا المهيأة، وأن القيمة المقابلة هي العنصر الثاني في الزوج.

انظر أيضاً

مراجع

  1. "التهيئة الكسولة - أنماط التصميم - دليل لغة برمجة هاكس" . 11 يناير 2018. تم الاطلاع عليه بتاريخ 9 نوفمبر 2018 .
  2. "LazyCell in std::cell - Rust" . doc.rust-lang.org . تم الاطلاع عليه بتاريخ 18 يناير 2025 .
  3. بولاك، ديفيد (25-05-2009). مقدمة في لغة سكالا . دار نشر أبريس. رقم ISBN 9781430219897.
  4. موريت، بي إم إي؛ شابيرو، إتش دي (1991). الخوارزميات من P إلى NP، المجلد 1: التصميم والكفاءة . شركة بنجامين/كومينغز للنشر. الصفحات 191-192 . ISBN  0-8053-8008-6.