Jump to content

Ընդհանրացված ծրագրավորում

Վիքիպեդիայից՝ ազատ հանրագիտարանից

Ընդհանրացված ծրագրավորումը (անգլ.՝ generic programming) ծրագրավորման պարադիգմ է, որը բաղկացած է տվյալների և ալգորիթմների նկարագրությունից, որոնք կարող են կիրառվել տարբեր տեսակի տվյալների վրա՝ առանց այդ նկարագրությունը փոխելու։ Այն այս կամ այն ​​ձևով աջակցվում է տարբեր ծրագրավորման լեզուներով: Ընդհանրացված ծրագրավորման հնարավորությունները առաջին անգամ հայտնվեցին ջեներիկների(ընդհանրացված ֆունկցիաների) տեսքով 1970-ականներին Clu-ում և Ada-ում, այնուհետև պարամետրային պոլիմորֆիզմի տեսքով ML-ում և նրա հետնորդներում, այնուհետև շատ օբյեկտ կողմնորոշված լեզուներում, ինչպիսիք են C++, Python[1], Java, Object Pascal[2], D, Eiffel, լեզուներ .NET պլատֆորմի համար և այլն:

Մեթոդաբանություն

[խմբագրել | խմբագրել կոդը]

Ընդհանրացված ծրագրավորումը դիտարկվում է որպես ծրագրավորման մեթոդաբանություն, որը հիմնված է տվյալների կառուցվածքների և ալգորիթմների տարանջատման վրա՝ պահանջների աբստրակտ նկարագրությունների կիրառմամբ[3]: Աբստրակտ պահանջների նկարագրությունները աբստրակտ տվյալների տիպի հասկացության ընդլայնումն են: Մեկ տեսակ նկարագրելու փոխարեն ընդհանրացված ծրագրավորման մեջ օգտագործվում է տիպերի ընտանիքի նկարագրությունը, որոնք ունեն ընդհանուր ինտերֆեյս և իմաստային վարքագիծ (անգլ.՝ semantic behavior)։ Պահանջների ամբողջությունը, որոնք նկարագրում են ինտերֆեյսը և իմաստային վարքագիծը, կոչվում է կոնցեպցիա (concept): Այսպիսով, ընդհանրացված ոճով գրված ալգորիթմը կարող է օգտագործվել ցանկացած տիպի համար։ Այդպիսի հատկանիշը կոչվում է պոլիմորֆիզմ։

Ասում են, որ տիպը մոդելավորում է կոնցեպցիան (կոնցեպցիայի մոդել է), եթե այն բավարարում է դրա պահանջներին: Կոնցեպցիանը մեկ այլ կոնցեպցիայի հստակեցումն է, եթե այն լրացնում է վերջինս: Կոնցեպցիայի պահանջները պարունակում են հետևյալ տեղեկությունները

  • Թույլատրելի արտահայտությունները (անգլ.՝ valid expressions) ծրագրավորման լեզուների արտահայտություններ են, որոնք պետք է հաջողությամբ կոմպիլյացվեն կոնցեպցիան մոդելավորող տիպերի համար:
  • Ասոցիացված տիպեր (associated types) օժանդակ տիպեր են, որոնք որոշակի կապ ունեն կոնցեպցիան մոդելավորող տիպի հետ:
  • Ինվարիանտները(invariants) տիպերի բնութագրիչներ են, որոնք միշտ պետք է ճշմարիտ լինեն կատարման ժամանակ: Սովորաբար արտահայտվում է նախապայմանների և հետպայմանների տեսքով։ Նախապայմանին չբավարարելը հանգեցնում է համապատասխան գործողության անկանխատեսելիության և կարող է հանգեցնել սխալների:
  • Բարդության երաշխիքներ(complexity guarantees) թույլատրելի արտահայտության առավելագույն կատարման ժամանակն է

C++ լեզվում օբյեկտ կողմնորոշված ծրագրավորումը (ՕԿԾ) իրականացվում է վիրտուալ ֆունկցիաների և ժառանգման միջոցով, մինչդեռ ընդհանրացված ծրագրավորումը իրականացվում է դասի շաբլոնների և ֆունկցիաների միջոցով: Այնուամենայնիվ, երկու մեթոդաբանությունների էությունը միայն անուղղակիորեն է կապված կոնկրետ իրականացման տեխնոլոգիաների հետ: ՕԿԾ-ն հիմնված է ենթատիպային պոլիմորֆիզմի վրա, մինչդեռ ընդհանրացված ծրագրավորումը հիմնված է պարամետրային պոլիմորֆիզմի վրա: Այլ լեզուներում երկուսն էլ կարող են այլ կերպ իրականացվել: Օրինակ, CLOS-ում մուլտիմեթոդներն ունեն պարամետրային պոլիմորֆիզմի նման իմաստ։

Մասերը և Ստեպանովը առանձնացնում են ընդհանրացված ծրագրավորման մեթոդաբանության խնդրի լուծման հետևյալ փուլերը:

  1. Գտնել օգտակար և արդյունավետ ալգորիթմ:
  2. Սահմանել ընդհանրացված ներկայացում (պարամետրացնել ալգորիթմը ՝ նվազագույնի հասցնելով մշակվող տվյալների պահանջները:
  3. Նկարագրել մի շարք (նվազագույն) պահանջներ, որոնք բավարարելով, դուք դեռ կարող եք ստանալ արդյունավետ ալգորիթմներ:
  4. Ստեղծեք շրջանակ՝ հիմնված դասակարգված պահանջների վրա:

Նվազագույնի հասցնելը և շրջանակի ստեղծումը նպատակ ունեն ստեղծել այնպիսի կառուցվածք, որում ալգորիթմները կախված չեն տվյալների հատուկ տիպերից:Այս մոտեցումը արտացոլված է STL գրադարանի կառուցվածքում։

Ընդհանրացված ծրագրավորման սահմանման այլընտրանքային մոտեցում է՝ տվյալների տիպի ընդհանրացված ծրագրավորումը (անգլ. datatype generic programming), որն առաջարկվել է Ռիչարդ Բիրդի և Լամբերտ Մերտենսի կողմից։ Դրանում տվյալների տիպի կառուցվածքները ընդհանրացված ծրագրերի պարամետրեր են: Դրա համար ծրագրավորման լեզվում ներդրվում է աբստրակցիայի նոր մակարդակ, այն է՝ պարամետրացում՝ կապված փոփոխականի գրելաձևով հանրահաշվական դասերի հետ։ Թեև երկու մոտեցումների տեսությունները կախված չեն ծրագրավորման լեզվից, Մասեր-Ստեպանովի մոտեցումը, որը շեշտը դնում է կոնցեպցիայի վերլուծության վրա, C++ ծրագրավորման լեզուն դարձրել է իր հիմնական հարթակը, մինչդեռ ընդհանրացված տվյալների տիպի ծրագրավորումն օգտագործում է գրեթե բացառապես Haskell-ը և դրա տարբերակները։

Ընդհանուր մեխանիզմ

[խմբագրել | խմբագրել կոդը]

Ընդհանրացված ծրագրավորման գործիքներն իրականացվում են ծրագրավորման լեզուներում որոշակի շարահյուսական միջոցների տեսքով, որոնք հնարավորություն են տալիս նկարագրել տվյալները(տվյալների տեսակները) և ալգորիթմները (կոնցեպցիաներ, ֆունկցիաներ, մեթոդներ), որոնք պարամետրացվում են տվյալների տիպերի կողմից: Ֆունկցիան կամ տվյալների տիպը հստակ նկարագրում են ֆորմալ պարամետրերը՝ տիպերը: Այս նկարագրությունը ընդհանրացված է և չի կարող ուղղակիորեն օգտագործվել իր սկզբնական տեսքով:

Ծրագրի այն վայրերում, որտեղ օգտագործվում է ընդհանրացված տիպը կամ ֆունկցիան, ծրագրավորողը պետք է հստակ նշի իրական պարամետրը՝ նկարագրությունը բնութագրող տիպը: Օրինակ, երկու արժեքների վերադասավորման ընդհանրացված ֆունկցիան կարող է ունենալ պարամետր-տիպ, որը սահմանում է այն արժեքների տիպը, որը այն փոխում է: Երբ ծրագրավորողը պետք է փոխի երկու ամբողջ արժեք, նա կանչում է «ամբողջ թիվ» տիպի պարամետրով ֆունկցիան և երկու պարամետրով՝ ամբողջ թվեր, երբ երկու տող՝ «տող» տիպի պարամետրով և երկու պարամետրով՝ տողերով: Տվյալների դեպքում ծրագրավորողը կարող է, օրինակ, նկարագրել «ցուցակ» ընդհանրացված տեսակը՝ տիպ պարամետրով, որը սահմանում է ցուցակում պահվող արժեքների տիպը: Այնուհետև իրական ցուցակները նկարագրելիս ծրագրավորողը պետք է նշի ընդհանրացված տիպը և պարամետր-տեսակը ՝ այդպիսով ստանալով ցանկացած ցանկալի ցուցակ ՝ օգտագործելով նույն նկարագրությունը:

Կոմպիլյատորը, հանդիպելով ընդհանրացված տիպին կամ ֆունկցիայի կանչին, կատարում է ստատիկ տիպի ստուգման անհրաժեշտ վերահսկողությունները, գնահատում է տվյալի կոնկրետացման հնարավորությունը և դրական գնահատման դեպքում գեներացնում է կոդ՝ փոխարինելով իրական տիպի պարամետրը ֆորմալ տիպի պարամետրին ընդհանրացված նկարագրության մեջ: Բնականաբար, ընդհանրացված նկարագրությունները հաջողությամբ օգտագործելու համար պետք է իրական պարամետրերի տիպերը բավարարեն որոշակի պայմաններին: Եթե ​​ընդհանրացված ֆունկցիան համեմատում է պարամետրի տիպի արժեքները, ապա դրա մեջ օգտագործվող ցանկացած տիպ պետք է աջակցի համեմատման ​​գործողություններին, եթե այն վերագրում է պարամետր-տիպի արժեքները փոփոխականներին, այն պետք է իրականացնի ճիշտ վերագրում:

Ընդհանրացված ծրագրավորումը լեզուներում

[խմբագրել | խմբագրել կոդը]

C++ լեզվում ընդհանրացված ծրագրավորումը հիմնված է «շաբլոն» հասկացողության վրա, որը սկսվում է template բանալի բառով։ Լայնորեն կիրառվում է C++ շաբլոնների ստանդարտ գրադարանում, ինչպես նաև կողմնակի boost, Loki գրադարաններում։ Ալեքսանդր Ստեպանովը մեծ ներդրում ունեցավ C++ ծրագրավորման լեզվում ընդհանրացված ծրագրավորման զարգացման գործում։

Որպես օրինակ՝ բերենք ֆունկցիայի շաբլոն (ընդհանրացում), որը վերադարձնում է երկու արժեքներից մեծագույնը։

// Շաբլոն ֆունկցիայի նկարագրություն
template <typename T> T max(T x, T y)
{
    if (x < y)
        return y;
    else
        return x;
}
...
// Շաբլոնով տրված ֆունկցիայի կիրառում

int a = max(10,15);
...
double f = max(123.11, 123.12);
...

կամ կապակցված ցուցակի դասի շաբլոն (ընդհանրացում).

template <class T>
 class List
 {
 /* ... */
 public:
   void Add( const T& Element );
   bool Find( const T& Element );
 /* ... */
 };

Haskell լեզուն ապահովում է տվյալների տիպերի ընդհանրացված ծրագրավորում: Հետևյալ օրինակում a-ն պարամետրային տիպի փոփոխական է:

data List a = Nil | Cons a (List a)
length :: List a -> Int
length Nil = 0
length (Cons _ tl) = 1 + length tl

Հաշվարկի օրինակ․

length (Cons 1 (Cons 2 Nil)) == 2

Java-ն տրամադրում է ընդհանրացված ծրագրավորման գործիքներ, որոնք շարահյուսորեն հիմնված են C++ լեզվի վրա՝ սկսած J2SE 5.0 տարբերակից։ Այս լեզվում կան generics կամ «T տիպի կոնտեյներներ»՝ ընդհանրացված ծրագրավորման ենթաբազմություն։

. Net պլատֆորմում ընդհանրացված ծրագրավորման գործիքները հայտնվել են 2.0 տարբերակում։

 // Ընդհանրացված դասի հայտարարում
 public class GenericList<T>
 {
     void Add(T input) { }
 }
 class TestGenericList
 {
     private class ExampleClass { }
     static void Main()
     {
         GenericList<int> list1 = new GenericList<int>();
         GenericList<string> list2 = new GenericList<string>();
         GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
     }
 }
interface IPerson 
{
  string GetFirstName();
  string GetLastName();
}

class Speaker 
{
  public void SpeakTo<T>(T person) where T : IPerson 
  {
    string name = person.GetFirstName();
    this.say("Hello, " + name);
  }
}

D լեզվի շաբլոնների վրա հիմնված ռեկուրսիվ գեներացիայի օրինակ.

// http://digitalmars.com/d/2.0/template.html
template Foo(T, R...) // T - тип, R - набор типов
{
    void Foo(T t, R r)
    {
	writeln(t);
	static if (r.length)	// if more arguments
	    Foo(r);		// do the rest of the arguments
    }
}

void main()
{
    Foo(1, 'a', 6.8);
}

/+++++++++++++++
 prints:
 1
 a
 6.8
 +++++++++++++++/

Free Pascal կոմպիլյատորում ընդհանրացված ծրագրավորման աջակցությունը հայտնվել է 2007 թվականի 2.2 տարբերակից սկսած[4]: Դելֆիում՝ 2008 թվականի հոկտեմբերից։ Ընդհանրացված դասի աջակցությունն առաջին անգամ հայտնվեց Delphi 2007 .NET-ում 2006 թվականին, բայց այն ազդեց միայն .NET Framework-ի վրա: Ավելի ամբողջական աջակցություն ընդհանրացված ծրագրավորմանը ավելացվել է Delphi 2009-ում։ Ընդհանրացված դասերը նույնպես աջակցվում են Object Pascal-ում PascalABC.NET համակարգում:

import typetraits

proc getType[T](x: T): string =
  return x.type.name

echo getType(21)       # կարտածի int
echo getType(21.12)    # կարտածի float64
echo getType("string") # կարտածի string

Ծանոթագրություններ

[խմբագրել | խմբագրել կոդը]
  1. «Python Generic». Արխիվացված է օրիգինալից 2021-02-09-ին. Վերցված է 2020-05-28-ին. {{cite web}}: Unknown parameter |deadurl= ignored (|url-status= suggested) (օգնություն)
  2. В Delphi и PascalABC.NET
  3. Сик, Ли, Ламсдэйн, 2006, էջ 47—48
  4. «Freepascal.Generics». Արխիվացված է օրիգինալից 2010-12-15-ին. Վերցված է 2011-02-01-ին. {{cite web}}: Unknown parameter |deadurl= ignored (|url-status= suggested) (օգնություն)

Գրականություն

[խմբագրել | խմբագրել կոդը]
  • Джереми Сик, Лай-Кван Ли, Эндрю Ламсдэйн. C++ Boost Graph Library. — Питер, 2006. — 304 с. — ISBN 5-469-00352-3
  • Степанов Александр А., Роуз Дэниэл Э. От математики к обобщённому программированию. — ДМК Пресс, 2016. — 264 с. — ISBN 978-5-97060-379-6