uy - Internetni sozlash
Dasturlashda funksiya nomi nima. Dasturlash funktsiyalari

Ishning maqsadi: 1) funktsiyalarni tavsiflash qoidalarini o'rganish; 2) C++ tilida dasturlar yozishda funksiyalardan foydalanish ko‘nikmalarini egallash.

Nazariy ma'lumotlar

C++ tilidagi dasturlarning asosiy moduli funksiya hisoblanadi.

Funktsiya- nomga ega bo'lgan dasturning mantiqiy to'ldirilgan, aniq ishlab chiqilgan qismi. Funktsiyalar katta hisoblash vazifalarini kichikroqlarga bo'lish imkonini beradi.

Har bir C++ dasturida, albatta, dasturning asosiy qismi bo'lgan main nomli funksiya mavjud. Boshqa barcha funktsiyalar uchun, agar dasturda mavjud bo'lsa, prototiplar e'lon qilinishi kerak - kompilyatorga dasturdagi har bir funktsiyaning nomi va shaklini aytib beradigan sxematik belgilar.

Parametrli funksiya prototipi sintaksisi:

qaytish_qiymati_turi funksiya_nomi (turi_ko'rsatilgan parametrlar_ro'yxati);

C++ tilidagi funksiyalar standart (kutubxona) va foydalanuvchi tomonidan dasturlashtiriladi.

Standart xususiyatlar

Standart funksiyalarning tavsiflari #include direktivasi yordamida dasturga kiritilgan fayllarda mavjud. Bunday fayllar sarlavhali fayllar deb ataladi; ular h kengaytmasiga ega.

Asosiy dasturda funksiya nomiga murojaat qilish funksiya chaqiruvi deyiladi.

Funksiyalarni chaqirish natijasida ba'zi amallar bajariladi yoki qaysidir qiymat hisoblab chiqiladi, keyinchalik u dasturda qo'llaniladi.

y = sin(x); //sinusni hisoblash funksiyasi

Funktsiya ta'rifi

Umuman olganda, funktsiyalar quyidagicha tavsiflanadi:

qaytish_qiymati_turi funksiya_nomi (parametr_nomini yozing,..., parametr_nomini yozing)

tana_funktsiyasi

Dasturlashtiriladigan xususiyatlar

Dasturchining o'zi yaratadigan funktsiyalari dasturlarni yozish jarayonini soddalashtiradi, chunki ular:

    takroriy dasturlashni oldini olishga yordam beradi, chunki bir xil funktsiya turli dasturlarda ishlatilishi mumkin;

    dasturning modullilik darajasini oshirish, shuning uchun uni o'qish, o'zgartirishlar kiritish va xatolarni tuzatishni osonlashtiradi.

Misol9 .1. 65 ta "*" belgilarni ketma-ket chop etadigan funksiya yarataylik. Ushbu funktsiyani ba'zi kontekstda ishlashi uchun u blanka chop etish dasturiga kiritilgan. Dastur funksiyalardan iborat: main() va stars().

// Firma blankasi

#o'z ichiga oladi

const int Limit=65;

bo'sh yulduzlar (bo'sh); // stars() funktsiyasi prototipi

cout<<"Moscow Institute of Electronic Engineering"<

// stars() funksiyasining ta'rifi

uchun (hisoblash = 1; hisoblash<=Limit; count++)

Biz argumentlarga ega bo'lmagan va hech qanday qiymat qaytarmaydigan oddiy funksiya misolini ko'rib chiqdik.

Funktsiya parametrlari

Funktsiya parametrlaridan foydalanish misolini ko'rib chiqamiz.

Misol9. 2. Bo'shliq(), funksiyasini yozamiz. Kimning argumenti bu funksiya chop etishi kerak bo'lgan bo'shliqlar soni bo'ladi.

#"Zelenograd" manzilini aniqlang

# nomini aniqlang "Moskva elektron muhandislik instituti"

#aniqlash "Informatika va dasturlash" kafedrasi

const int LIMIT=65;

#o'z ichiga oladi

bo'sh joy (int raqami);

cout<

bo'shliqlar=(LIMIT - strlen(ism))/2; // Qanchaligini hisoblang

// bo'sh joy kerak

cout<

kosmik((LIMIT - strlen(bo'lim))/2); // argument - ifoda

cout<

//stars() funksiyasining ta'rifi

uchun (hisoblash = 1; hisoblash<=LIMIT; count++)

// space() funksiyasining ta'rifi

bo'sh joy (int raqami)

uchun (hisoblash = 1; hisoblash<=number; count++)

Raqam o'zgaruvchisi rasmiy argument deb ataladi. Ushbu o'zgaruvchi funktsiya chaqirilganda haqiqiy argumentning qiymatini oladi. Boshqa so'z bilan, rasmiy dalil chaqirilgan pastki dasturning ta'rifidagi o'zgaruvchidir va haqiqiy argument chaqiruvchi dastur tomonidan ushbu o'zgaruvchiga tayinlangan o'ziga xos qiymatdir.

Agar funktsiya bilan bog'lanish uchun bir nechta argument kerak bo'lsa, funktsiya nomi bilan birga vergul bilan ajratilgan argumentlar ro'yxatini belgilashingiz mumkin:

void printnum (int i, int j)

(kout<<"Координаты точек”<< i << j <

Funktsiyaning kirish qiymati mavjudligi tufayli qayta ishlanishi mumkin dalil; Chiqish qiymati return kalit so'zi yordamida qaytariladi.

Printsipial jihatdan dasturlashdan uzoq bo'lgan foydalanuvchilar funktsiyalar va protseduralar tushunchalariga kamdan-kam duch kelishadi va ular matematik va byurokratik-tibbiy narsa bilan bog'liq. Dasturlashda ko'plab tillar ushbu tushunchalar bilan ishlaydi, ammo ba'zida hatto mutaxassislar ham funktsiya va protsedura o'rtasidagi farqni aniq tushuna olmaydilar. Xuddi o'sha gopher kabi: u erda, lekin uni hech kim ko'rmaydi. Keling, farqlar shunchalik ko'rinmasmi yoki yo'qligini ko'rib chiqaylik.

Funktsiya va protsedura atamalari nimani anglatadi?

  • Funktsiya dasturlashda, boshqa kichik dasturlardan kerakli ko'p marta chaqirilgan kichik dastur.
  • Jarayon- dasturning keyingi qismlaridan kerakli ko'p marta qayta-qayta chaqiriladigan dasturning nomlangan qismi (kichik dastur).

Funktsiya va protsedurani taqqoslash

Funksiya va protsedura o'rtasidagi asosiy farq uning qaytaradigan natijasidir. Haqiqatdan ham funksiyalar ham, protseduralar ham dastur kodini tashkil etuvchi mantiqiy bo‘linmas bloklardir. Funktsiya qiymatni qaytaradi, ko'pgina dasturlash tillarida protsedura qaytarmaydi yoki (masalan, C tilida) bo'sh qiymatni qaytaradi. Oxirgi holatda (C da) protsedura funksiyaning subordinatsiyali versiyasi hisoblanadi.

Funktsiya sarlavhasida "funktsiya" so'zi, identifikator (funktsiyaning to'g'ri nomi), ixtiyoriy ravishda parametrlar ro'yxati va, albatta, natija turi mavjud. Funktsiya tanasida funktsiya nomiga qiymat beradigan operator bo'lishi kerak, natijada u qaytaradi. Jarayon sarlavhasi "protsedura" so'zini, identifikatorni (protsedura nomi) va ixtiyoriy ravishda parametrlar ro'yxatini o'z ichiga oladi.

Funktsiya chaqiruvi ushbu ifodalar qo'llaniladigan iboralarning bir qismi sifatida amalga oshiriladi; protsedura chaqiruvi alohida bayonotni talab qiladi.

Protsedura faqat nom bilan chaqiriladi, funksiya nomi esa uning qiymati bilan bog'lanadi. Algoritm diagrammalarida funksiya chaqiruvi chiqish blokida yoki jarayon blokida, protsedura chaqiruvi maxsus “oldindan belgilangan jarayon” blokida tasvirlangan.

Dasturlashda funktsiya va protsedura o'rtasidagi farq quyidagicha:

  • Funktsiya qiymatni qaytaradi, protsedura esa qaytarmaydi.
  • Funktsiya sarlavhasi natija turini o'z ichiga olishi kerak.
  • Funktsiya tanasi funktsiya nomiga qiymat beradigan bayonotni o'z ichiga olishi kerak.
  • Protsedurani chaqirish alohida bayonotni talab qiladi; funktsiyani chaqirish ifodaning bir qismi sifatida mumkin.
  • Protsedura nomi uni chaqirish uchun, funksiya nomi esa qiymat berish uchun kerak.
  • Algoritm diagrammalarida protsedura chaqiruvi alohida blokda, funksiya chaqiruvi jarayon yoki chiqish blokida tasvirlangan.

Har qanday kompyuter dasturining asosini buyruqlar shaklida ifodalangan algoritmlar tashkil etadi. Kodni yozgan odam: buni ol, buni, buni va buni qil, keyin natijani u yerga chiqarib, dam ol, deydi. Shunday qilib, dasturlardagi buyruqlar bitta tartibsizlikka qo'shilmasligi va bir-biri bilan o'zaro ta'sir qilishi uchun ular funktsiyalar va protseduralar deb ataladigan guruhlarga birlashtirilgan. Biz bu tushunchalar bilan tanishamiz.

Funktsiya nima

Funksiya nomlaridan foydalaniladi: 1) hujjatlarni yaratish uchun; 2) API uchun, ya'ni har qanday dasturning dastur yoki butun operatsion tizimiga ulanish uchun interfeys. Shuning uchun, bu nomlar tushunarli va iloji bo'lsa, bajarilayotgan harakatlarga mos kelishi kerakligini yana bir bor eslatish mantiqan.

Keling, xulosa qilaylik

Demak, funksiyalar algoritmlarni guruhlash uchun konteyner turidir. Ular:

  1. muayyan vazifalar uchun javobgar;
  2. boshqa ob'ektlar bilan aloqa qilish;
  3. Qanchalik ayanchli tuyulmasin, zamonaviy dasturlashning kontseptual asosidir.

Protseduralar aslida bir xil funktsiyalardir, garchi "bo'sh" bo'lsa ham, hech narsa qaytarmaydi (bu ularning asosiy farqidir). Bu muntazam harakatlarni bajarish, shuningdek, joy, kuch va vaqtni tejash uchun mo'ljallangan yordamchi vositalardir.

Oldingi nashrlar:

Men ushbu maqolani "Funksiyalar dasturlashning ajralmas qismi sifatida" deb bejiz ataganim yo'q, chunki ularsiz, mening fikrimcha, hech qanday til mavjud bo'lishga haqli emas. Bu nima? Funktsiya yaxshi yozilgan dasturning asosiy komponentidir. Bu nafaqat kodni o'qishni osonlashtiradi, balki tizimli dasturlash g'oyasini tubdan o'zgartiradi. Funktsiyalar yordamida siz dasturning alohida qismlarini istalgan parametrlarni o'tkazish orqali qayta ishlatishingiz mumkin. Hech qanday jiddiy dasturni dasturlash elementining ushbu mo''jizasisiz tasavvur qilib bo'lmaydi.

Bu qanday ishlashini sizga qisqacha aytib beraman. Funktsiya - bu sizning dasturingiz chaqirishi mumkin bo'lgan ko'rsatmalar blokidir. Ushbu blokning sarlavhasiga (funksiya nomi) kirganda, u bajariladi va dasturchi tomonidan belgilangan ba'zi amallarni bajaradi. Shundan so'ng, bu blok qabul qilingan qiymatni qaytaradi va uni asosiy dasturga o'tkazadi. Amalda tushuntiraman.

Qo'pol qilib aytganda, shunday ko'rinadi. Qisqacha tushuntirib beraman. Biz qandaydir o'zgaruvchini yaratamiz va unga myfunc funksiyasini bajarish natijasini tayinlaymiz, bu esa o'z navbatida qandaydir sonni kvadratga solish qiymatini hisoblab chiqadi. Funktsiyalar dastur ishga tushganda darhol bajarilmaydi, faqat ular chaqirilganda bajariladi. Bu biroz chalkash bo'lishi mumkin, lekin bu shunday.

Funktsiyani qanday chaqirish mumkin?

Funktsiyani chaqirish uchun uni yaratish kerak. Garchi o'rnatilgan funktsiyalar ham mavjud. Masalan, bu: cos, sin, md5, count, abs va hokazo. Ularni chaqirish uchun o'zgaruvchiga kerakli qiymatni belgilash kifoya.

Funktsiya argumenti bu siz uni chaqirganingizda unga o'tadigan qiymatdir. Funksiya argumentlari qavslar ichida joylashtirilgan. Funktsiyani yaratishda siz argumentlar uchun shartli nomlarni ko'rsatasiz. Keyin bu nomlar funktsiya tanasida mahalliy o'zgaruvchilar sifatida ishlatilishi mumkin. Keling, foydalanuvchining o'zi yaratadigan funktsiyalarga qaytaylik. Bu juda oson amalga oshiriladi. Birinchidan, funktsiya tanasi yaratiladi:

Hello() funktsiyasi ("Salom, dunyo!"; ) aks-sadosi

Keyin uni chaqiramiz. Bundan tashqari, agar uning parametrlari bo'lmasa, biz oddiygina qavs qo'yamiz. Ushbu funktsiyani chaqirish uchun biz faqat qatordan foydalanamiz: Salom();. Har qanday funktsiya zaxiralangan so'z yordamida qiymatni ham qaytarishi mumkin qaytish. Ushbu bayonot funktsiyani bajarishni to'xtatadi va qaytariladigan qiymatni chaqiruvchi dasturga yuboradi. funktsiya summasi($first, $second) ($r=$first + $second; qaytish $r;) echo summa(2,5); dasturni bajarish natijasi 7 ga teng bo'ladi. Lokal va global o'zgaruvchilar

Boshqa har qanday dasturlash tilida bo'lgani kabi, faqat funktsiya ichida mavjud bo'lgan o'zgaruvchilar va dasturning kodida mavjud bo'lgan o'zgaruvchilar mavjud. Bunday o'zgaruvchilar mos ravishda mahalliy va global deb ataladi. Funktsiya ichida siz funktsiyadan tashqarida yaratilgan o'zgaruvchiga oddiygina kira olmaysiz. Agar siz buni qilishga harakat qilsangiz, xuddi shu nomli, lekin ushbu funktsiya uchun mahalliy bo'lgan yangi o'zgaruvchi yaratasiz.

$per = "Dima"; funktsiya primer() // Bajaradi: mahalliy o'zgaruvchini ko'rsatish ( echo "Mening ismim ".$per; ) echo primer();

Bunday holda, ekranda "Mening ismim" iborasi paydo bo'ladi. Bu shuni anglatadiki, $per o'zgaruvchisi primer funktsiyasi ichida yaratilgan va sukut bo'yicha nol qiymatga ega bo'lgan. Bunday murabbolarning oldini olish uchun siz operatordan foydalanishingiz kerak global. Yuqoridagi kodni mos ravishda tuzatamiz:

$per = "Dima"; funktsiya primer() // Bajaradi: global o'zgaruvchini ko'rsatish ( global $per; echo "Mening ismim ".$per; ) echo primer();

Hozir hamma narsa yaxshi bo'lishi kerak - muammo hal qilindi. Shuni unutmangki, agar funktsiya tashqi o'zgaruvchining qiymatini o'zgartirsa, unda bunday o'zgarish butun dasturga ta'sir qiladi, shuning uchun siz ushbu operatordan ehtiyotkorlik bilan foydalanishingiz kerak!

Ikki yoki undan ortiq argumentlarning funktsiyalari

Funksiyaga berilgan argumentlarning ba'zilari ixtiyoriy bo'lishi mumkin, bu funksiyani kamroq talab qiladi. Quyidagi misol buni aniq ko'rsatib turibdi:

… funktsiya shrifti ($matn, $size=5) // Bajarilishi: shrift hajmini chiqarish ( echo " ".$matn.""; ) font("Salom
",1); shrift ("Salom
",2); shrift ("Salom
",3); shrift ("Salom
",4); shrift ("Salom
",5); shrift ("Salom
",6); shrift ("Salom
");

Odatiy bo'lib, shrift o'lchami 5. Agar funktsiyaning ikkinchi parametrini o'tkazib yuborsak, u ushbu qiymatga teng bo'ladi.

Xulosa

Xayrlashishdan oldin bir maslahatga e'tiboringizni qaratmoqchiman. Bu siz yozgan barcha funksiyalarni bitta faylga joylashtirishdan iborat (masalan, function.php). Va keyin, funktsiyani chaqirishingiz kerak bo'lgan faylda siz faqat function.php ni kiritishingiz kerak va hamma narsa foydalanishga tayyor bo'ladi. Bu sizning dasturingizdagi mantiqni tushunishni ancha osonlashtiradi. Ulanish uchun foydalaning:

include_once("function.php");

require_once("function.php");

Agar siz ushbu maqolada muhokama qilingan masalaning mohiyatini tushunsangiz, unda dasturlaringizdagi funktsiyalardan osongina foydalanishingiz mumkinligiga aminman. Yana bir bor ta'kidlaymizki, bu ularni yanada moslashuvchan va qayta foydalanishga yaroqli holga keltirishdir.

Bu “Dasturchilar uchun toifalar nazariyasi” turkumidagi uchinchi maqola bo’lgan maqola yangiliklar.net saytiga kiritilgan.

Turlar kimga kerak?

Jamiyatda statik va dinamik yozish va kuchli va kuchsiz yozishning afzalliklari haqida bir oz kelishmovchilik mavjud. Menga yozishni tanlashni fikrlash tajribasi bilan tasvirlab beraman. Klaviaturali millionlab maymunlarni tasodifiy tugmachalarni quvonch bilan bosib, dasturlarni yozish, kompilyatsiya qilish va ishga tushirishni tasavvur qiling.

Mashina tili bilan maymunlar tomonidan ishlab chiqarilgan baytlarning har qanday kombinatsiyasi qabul qilinadi va bajariladi. Ammo yuqori darajadagi tillarda kompilyatorning leksik va grammatik xatolarni aniqlay olishi juda qadrlanadi. Ko'pgina dasturlar shunchaki rad etiladi va maymunlar banansiz qoladilar, ammo qolganlari mazmunli bo'lish imkoniyatiga ega bo'ladi. Turni tekshirish bema'ni dasturlarga qarshi yana bir to'siqni ta'minlaydi. Bundan tashqari, dinamik tarzda terilgan tillarda turdagi nomuvofiqliklar faqat ish vaqtida aniqlansa, qattiq terilgan statik tekshirilgan tillarda turdagi nomuvofiqliklar kompilyatsiya vaqtida aniqlanadi, bu esa ko'plab noto'g'ri dasturlarni bajarish imkoniyatiga ega bo'lgunga qadar yo'q qiladi.

Demak, savol shundaki, biz maymunlarning baxtli bo'lishini xohlaymizmi yoki to'g'ri dasturlarni yaratishni xohlaymizmi?
(tarjimonning eslatmasi: xafa bo'lishning hojati yo'q, muallif RNG va "baytlarning tasodifiy ketma-ketligi" ga qaraganda kamroq zerikarli metaforalarni yaxshi ko'radi va dasturchilarni maymun deb atamaydi).

Odatda, maymuncha fikrlash tajribasining maqsadi Shekspirning to'liq asarlarini yaratishdir. (tarjimonning eslatmasi: yoki Tolstoyning "Urush va tinchlik"). Imlo va grammatikani bir tsiklda tekshirish muvaffaqiyatga erishish imkoniyatingizni sezilarli darajada oshiradi. Turni tekshirish analogi bundan ham uzoqroq: Romeo inson deb e'lon qilingandan so'ng, tip tekshiruvi uning barglari o'smasligiga va kuchli tortishish maydoni bilan fotonlarni tutmasligiga ishonch hosil qiladi.

Kompozitsiya uchun turlar kerak

Kategoriyalar nazariyasi strelkalar tarkibini o'rganadi. Faqat ikkita o'qni birlashtirish mumkin emas: bitta o'qning maqsadli ob'ekti keyingisining manba ob'ektiga mos kelishi kerak. Dasturlashda biz natijalarni bir funktsiyadan boshqasiga o'tkazamiz. Agar ikkinchi funktsiya birinchisi tomonidan olingan ma'lumotlarni to'g'ri talqin qila olmasa, dastur ishlamaydi. Tarkibi ishlashi uchun ikkala funktsiya bir-biriga mos kelishi kerak. Tilning tip tizimi qanchalik kuchli bo'lsa, bu moslikni yaxshiroq tasvirlash va avtomatik tekshirish mumkin.

Kuchli statik yozishga qarshi eshitadigan yagona jiddiy dalil shundaki, u semantik jihatdan to'g'ri bo'lgan ba'zi dasturlarni rad etishi mumkin. Amalda bu juda kam uchraydi (tarjimonning eslatmasi: chalkashmaslik uchun shuni ta'kidlaymanki, muallif ko'plab uslublar mavjudligini hisobga olmagan yoki rozi emas va skript tillarida dasturchilarga tanish bo'lgan o'rdak terish ham yashash huquqiga ega. Boshqa tomondan, qattiq tipdagi tizimda shablonlar, belgilar, tip sinflari, interfeyslar orqali o'rdak terish mumkin, ko'plab texnologiyalar mavjud, shuning uchun muallifning fikrini mutlaqo noto'g'ri deb hisoblash mumkin emas.) va har qanday holatda ham, har bir til, albatta, kerak bo'lganda, turdagi tizimni chetlab o'tish uchun qandaydir orqa eshikni o'z ichiga oladi. Hatto Xaskellda unsafeCoerce mavjud. Ammo bunday dizaynlardan oqilona foydalanish kerak. Frants Kafkaning qahramoni Gregor Samsa ulkan qo'ng'izga aylanganda tip tizimini buzadi va bu qanday tugashini hammamiz bilamiz. (tarjimonning eslatmasi: yomon :).

Men tez-tez eshitadigan yana bir dalil shundaki, kuchli matn terish dasturchiga juda ko'p yuk beradi. Men C++ da bir nechta iterator deklaratsiyasini yozganim uchun bu muammoga hamdard bo'lishim mumkin, bundan tashqari, kompilyatorga ko'pgina turlarni ular qo'llanilgan kontekstdan xulosa chiqarish imkonini beruvchi texnologiya, turdagi xulosalar mavjud. C++ da siz auto oʻzgaruvchisini eʼlon qilishingiz mumkin va kompilyator siz uchun turni aniqlaydi.

Haskellda, kamdan-kam holatlar bundan mustasno, turdagi izohlar ixtiyoriy. Dasturchilar baribir ulardan foydalanadilar, chunki turlar sizning kodingiz semantikasi haqida ko'p narsalarni aytib berishi mumkin va turdagi deklaratsiyalar kompilyatsiya xatolarini tushunishga yordam beradi. Xaskellda keng tarqalgan amaliyot bu turlarni ishlab chiqish orqali loyihani boshlashdir. Keyinchalik, turdagi izohlar amalga oshirishning asosini tashkil qiladi va kompilyator tomonidan kafolatlangan sharhlarga aylanadi.

Kuchli statik yozish ko'pincha kodni sinab ko'rmaslik uchun bahona sifatida ishlatiladi. Ba'zan Haskell dasturchilarining "Agar kod tuzilsa, u to'g'ri" degan gaplarini eshitasiz. Albatta, turi to'g'ri bo'lgan dastur to'g'ri natijani ishlab chiqarish ma'nosida to'g'ri ekanligiga kafolat yo'q. Bunday munosabat natijasida, bir qator tadqiqotlarda Xaskell, kutilgandek, kod sifati bo'yicha boshqa tillardan sezilarli darajada oshib ketmadi. Ko'rinishidan, tijorat sharoitida xatolarni tuzatish zarurati faqat ma'lum bir sifat darajasiga qadar mavjud bo'lib, bu asosan dasturiy ta'minotni ishlab chiqish iqtisodiyoti va oxirgi foydalanuvchining bag'rikengligi bilan bog'liq va dasturlash tili yoki ishlanmasi bilan juda kam aloqasi bor. metodologiyasi. Qancha loyiha rejadan ortda qolganini yoki funksionalligi sezilarli darajada pasaygan holda topshirilganligini o'lchash yaxshiroq chora bo'ladi.

Endi, birlik testi kuchli yozishni almashtirishi mumkinligi haqidagi da'voga kelsak. Qattiq terilgan tillarda keng tarqalgan refaktoring amaliyotini ko'rib chiqamiz: argument turini funktsiyaga o'zgartirish. Kuchli yozilgan tillarda ushbu funktsiya deklaratsiyasini o'zgartirish va keyin har qanday qurilish xatolarini tuzatish kifoya. Zaif terilgan tillarda funktsiya endi boshqa ma'lumotlarni kutayotganligini qo'ng'iroq qiluvchiga bog'lab bo'lmaydi.

Birlik testi ba'zi nomuvofiqliklarni aniqlashi mumkin, ammo test deyarli har doim deterministik jarayon emas, balki ehtimollikdir. (tarjimonning eslatmasi: ehtimol ular testlar to'plamini nazarda tutgandir: siz barcha mumkin bo'lgan kirishlarni emas, balki ma'lum bir vakillik namunasini qamrab olasiz.) Sinov to'g'rilikni isbotlashning yomon o'rnini bosadi.

Turlari nima?

Turlarning eng oddiy tavsifi shundaki, ular qiymatlar to'plamidir. Bool turi (esda tuting, konkret turlar Haskellda bosh harf bilan boshlanadi) ikkita element to'plamiga mos keladi: True va False. Char tipi - "a" yoki "ą" kabi barcha Unicode belgilar to'plami.

To'plamlar chekli yoki cheksiz bo'lishi mumkin. Char ro'yxatining sinonimi bo'lgan String turi cheksiz to'plamga misoldir.

Biz x ni butun son deb e'lon qilganimizda:
x::Integer
butun sonlar to‘plamining elementi deymiz. Haskelldagi butun son cheksiz to'plam bo'lib, har qanday aniqlikdagi arifmetika uchun ishlatilishi mumkin. C++ da int kabi mashina turiga mos keladigan Int ning chekli to'plami ham mavjud.

Turlarni to'plamlar bilan tenglashtirishni qiyinlashtiradigan ba'zi nozikliklar mavjud. Tsiklik ta'riflarga ega bo'lgan polimorf funktsiyalar bilan, shuningdek, barcha to'plamlar to'plamiga ega bo'lolmaslik bilan bog'liq muammolar mavjud; lekin, va'da qilganimdek, men qattiq matematik bo'lmayman. Muhimi, Set deb nomlangan to'plamlar toifasi mavjud va biz u bilan ishlaymiz.
To'plamda ob'ektlar to'plamlar va morfizmlar (strelkalar) funksiyalardir.

To'plam alohida toifadir, chunki biz uning ob'ektlarini ko'rishimiz mumkin va bu bizga ko'p narsalarni intuitiv tushunishga yordam beradi. Misol uchun, biz bilamizki, bo'sh to'plam hech qanday elementga ega emas. Biz bilamizki, bitta elementning maxsus to'plamlari mavjud. Biz bilamizki, funktsiyalar bir to'plamning elementlarini boshqasining elementlariga moslashtiradi. Ular ikkita elementni bittaga solishtirishlari mumkin, lekin bitta elementni ikkitaga emas. Bizga ma'lumki, identifikatsiya funktsiyasi to'plamning har bir elementini o'ziga moslashtiradi va hokazo. Men bu ma'lumotlarni asta-sekin unutib, o'rniga bu tushunchalarning barchasini sof kategorik shaklda, ya'ni ob'ektlar va o'qlar nuqtai nazaridan ifodalashni rejalashtirmoqdaman.

Ideal dunyoda biz shunchaki aytishimiz mumkinki, Haskelldagi turlar to'plamlar, Haskelldagi funktsiyalar esa ularning orasidagi matematik funktsiyalardir. Bitta kichik muammo bor: matematik funktsiya hech qanday kodni bajarmaydi - u faqat javobni biladi. Haskelldagi funksiya javobni hisoblashi kerak. Agar javob qanchalik katta bo'lishidan qat'i nazar, cheklangan miqdordagi qadamlarda olinishi mumkin bo'lsa, bu muammo emas. Ammo rekursiyani o'z ichiga olgan ba'zi hisoblar mavjud va ular hech qachon tugamasligi mumkin. Biz Haskellda tugatmaydigan funksiyalarga oddiygina ruxsat bera olmaymiz, chunki funktsiyaning tugashi yoki tugatmasligini farqlash - mashhur to'xtatish muammosi - hal qilib bo'lmaydi. Shuning uchun kompyuter olimlari har bir turni pastki deb nomlangan maxsus qiymat bilan kengaytirish uchun sizning nuqtai nazaringizga qarab ajoyib g'oya yoki iflos hack bilan chiqdilar. (tarjimonning eslatmasi: bu atama (pastki) rus tilida ahmoqona tuyuladi, agar kimdir yaxshi variantni bilsa, taklif qiling.), bu _|_ yoki Unicode ⊥ bilan belgilanadi. Bu "qiymat" to'liq bo'lmagan hisob-kitobga mos keladi. Shunday qilib, funktsiya quyidagicha e'lon qilinadi:
f::Bool -> Bool
True, False yoki _|_ ni qaytarishi mumkin; ikkinchisi funksiya hech qachon tugallanmaganligini bildiradi.

Qizig'i shundaki, siz tur tizimiga pastki qismni qabul qilganingizdan so'ng, har bir ish vaqti xatosini pastki deb hisoblash va hatto funktsiyaga aniq pastga qaytishga ruxsat berish qulay. Ikkinchisi odatda aniqlanmagan ifoda yordamida amalga oshiriladi:
f::Bool -> Bool f x = aniqlanmagan
Bu ta'rif turni tekshirishdan o'tadi, chunki undefined barcha turlarga, shu jumladan Boolga ham kiritilgan pastga qarab baholanadi. Siz hatto yozishingiz mumkin:
f::Bool -> Bool f = aniqlanmagan
(x holda) chunki pastki ham Bool -> Bool tipidagi a'zodir.

Barcha mumkin bo'lgan argumentlar uchun to'g'ri natijalarni qaytaradigan oddiy funktsiyalardan farqli o'laroq, pastki qismni qaytarishi mumkin bo'lgan funktsiyalar qisman deb ataladi.

Pastki qismi tufayli Haskell turlari va funktsiyalari toifasi Set emas, Hask deb ataladi. Nazariy nuqtai nazardan, bu cheksiz asoratlar manbai, shuning uchun bu vaqtda men qassob pichog'imni ishlataman va uni bir kun deb atayman. Pragmatik nuqtai nazardan, siz tugatmaydigan funktsiyalarni va pastki qismini e'tiborsiz qoldirishingiz va Haskga xuddi to'g'ri to'plam kabi munosabatda bo'lishingiz mumkin.

Nima uchun bizga matematik model kerak?

Dasturchi sifatida siz dasturlash tilining sintaksisi va grammatikasini yaxshi bilasiz. Tilning bu jihatlari odatda til spetsifikatsiyasining boshida rasmiy ravishda tasvirlangan. Ammo tilning ma'nosi va semantikasini tasvirlash ancha qiyin; bu tavsif yana ko'p sahifalarni egallaydi, kamdan-kam hollarda etarli darajada rasmiy va deyarli to'liq bo'lmaydi. Shu sababli, til yuristlari o'rtasida tugamaydigan munozaralar va butun yozgi kitoblar sohasi til me'yorlarining nozik tomonlarini sharhlashga bag'ishlangan.

Til semantikasini tavsiflash uchun rasmiy vositalar mavjud, ammo ularning murakkabligi tufayli ular sanoat dasturlashning haqiqiy gigantlari uchun emas, balki asosan soddalashtirilgan, akademik tillar uchun ishlatiladi. Bu vositalardan biri operativ semantika deb ataladi va dasturni bajarish mexanikasini tavsiflaydi. U rasmiylashtirilgan, ideallashtirilgan tarjimonni belgilaydi. C++ kabi sanoat tillarining semantikasi odatda norasmiy mulohazalar yordamida, ko'pincha "mavhum mashina" nuqtai nazaridan tasvirlanadi.

Muammo shundaki, operatsion semantikadan foydalanadigan dasturlar haqida biror narsani isbotlash juda qiyin. Dasturning xususiyatini ko'rsatish uchun uni ideallashtirilgan tarjimon orqali "ishlatish" kerak.

Dasturchilar hech qachon to'g'riligini rasman isbotlamasligi muhim emas. Biz har doim to'g'ri dasturlarni yozyapmiz deb "o'ylaymiz". Hech kim klaviaturada o'tirmaydi: "Oh, men bir necha qator kod yozaman va nima bo'lishini ko'raman". (tarjimonning eslatmasi: oh, faqat ...) Biz yozgan kod kerakli natijalarni beradigan muayyan harakatlarni amalga oshirishiga ishonamiz. Agar bunday bo'lmasa, biz odatda juda hayron qolamiz. Bu shuni anglatadiki, biz yozgan dasturlar haqida o'ylaymiz va biz buni odatda tarjimonni boshimizda ishga tushirish orqali qilamiz. Bu shunchaki, barcha o'zgaruvchilarni kuzatib borish juda qiyin. Kompyuterlar dasturlarni bajarishda yaxshi, odamlar emas! Agar biz bo'lganimizda, bizga kompyuter kerak emas edi.

Ammo alternativa bor. U denotatsion semantika deb ataladi va matematikaga asoslanadi. Denotatsion semantikada har bir lingvistik konstruktsiya uchun matematik talqin tavsiflanadi. Shunday qilib, agar siz dasturning xususiyatini isbotlamoqchi bo'lsangiz, shunchaki matematik teoremani isbotlaysiz. Siz teoremalarni isbotlash qiyin deb o'ylaysiz, lekin aslida biz insonlar ming yillar davomida matematik usullarni quramiz, shuning uchun foydalanish mumkin bo'lgan juda ko'p to'plangan bilimlar mavjud. Bundan tashqari, professional matematiklar isbotlagan teoremalarga qaraganda, biz dasturlashda duch keladigan muammolar juda oddiy, agar ahamiyatsiz bo'lsa. (tarjimonning eslatmasi: dalil sifatida muallif dasturchilarni xafa qilmoqchi emas.)

Denotatsion semantikaga osonlikcha mos keladigan Xaskell tilidagi omil funksiyasining ta'rifini ko'rib chiqing:
fakt n = mahsulot
Ifoda 1 dan n gacha bo‘lgan butun sonlar ro‘yxatidir. Mahsulot funktsiyasi ro'yxatning barcha elementlarini ko'paytiradi. Darslikdan olingan faktorial ta'rifi kabi. Buni C bilan solishtiring:
int fakt(int n) ( int i; int natija = 1; uchun (i = 2; i)<= n; ++i) result *= i; return result; }
Davom etishim kerakmi? (tarjimonning eslatmasi: muallif Haskellda kutubxona vazifasini olib, biroz aldagan. Aslida, aldashning hojati yo'q edi; halol tavsif, ta'rifiga ko'ra, bundan qiyin emas):
fakt 0 = 1 fakt n = n * fakt (n - 1)
Yaxshi, men darhol tan olaman, bu arzon zarba edi! Faktorial aniq matematik ta'rifga ega. Aqlli o'quvchi savol berishi mumkin: klaviaturadan belgilarni o'qish yoki tarmoq orqali paket yuborishning matematik modeli nima? Uzoq vaqt davomida bu juda chalkash tushuntirishlarga olib keladigan noqulay savol bo'ladi. Denotatsion semantika foydali dasturlarni yozish uchun zarur bo'lgan va operativ semantika bilan osongina echilishi mumkin bo'lgan muhim muammolarni hal qilish uchun yaroqsiz bo'lib tuyuldi. Yutuq toifalar nazariyasidan kelib chiqdi. Eugenio Moggi hisoblash effektlarini monadlarga aylantirish mumkinligini aniqladi. Bu nafaqat denotatsion semantikaga yangi hayot bag'ishlagan va sof funktsional dasturlarni qulayroq qilgan, balki an'anaviy dasturlash haqida yangi ma'lumotlarni taqdim etgan muhim kuzatuv bo'ldi. Keyinchalik kategoriyali vositalarni ishlab chiqqanimizda monadlar haqida gapiraman.

Dasturlash uchun matematik modelga ega bo'lishning muhim afzalliklaridan biri bu dasturiy ta'minotning to'g'riligini rasmiy isbotlash qobiliyatidir. Iste'molchi dasturiy ta'minotini yozayotganingizda bu unchalik muhim bo'lmasligi mumkin, ammo dasturlashning bunday sohalari borki, bu erda muvaffaqiyatsizlik narxi juda katta bo'lishi mumkin yoki inson hayoti xavf ostida. Ammo sog'liqni saqlash tizimi uchun veb-ilovalarni yozayotganda ham, Haskell standart kutubxonasi funktsiyalari va algoritmlari to'g'riligini tasdiqlovchi dalillar bilan to'ldirilgan degan fikrni qadrlashingiz mumkin.

Toza va iflos funktsiyalari

Biz C++ yoki boshqa imperativ tilda funksiyalar deb ataydigan narsa matematiklar funksiya deb ataydigan narsa bilan bir xil emas. Matematik funktsiya shunchaki qiymatlardan qiymatlarga xaritalashdir.

Biz dasturlash tilida matematik funktsiyani amalga oshirishimiz mumkin: kirish qiymati berilgan bunday funktsiya chiqish qiymatini hisoblab chiqadi. Raqamni kvadratga aylantirish funksiyasi, ehtimol, kiritilgan qiymatni o'ziga ko'paytiradi. U har safar chaqirilganda buni amalga oshiradi va har safar bir xil argument bilan chaqirilganda bir xil natijani berishi kafolatlanadi. Raqamning kvadrati oyning fazalari bilan o'zgarmaydi.

Bundan tashqari, raqamning kvadratini hisoblash sizning itingizga mazali taom berishning yon ta'siriga ega bo'lmasligi kerak. Buni bajaradigan "funksiya" ni matematik funktsiya bilan osongina modellash mumkin emas.

Dasturlash tillarida har doim bir xil argumentlar bo'yicha bir xil natija beradigan va hech qanday nojo'ya ta'sir ko'rsatmaydigan funksiyalar sof deyiladi. Haskell kabi sof funktsional tilda barcha funktsiyalar sof bo'ladi. Bu ushbu tillarning denotatsion semantikasini aniqlash va toifalar nazariyasi yordamida ularni modellashtirishni osonlashtiradi. Boshqa tillar uchun siz har doim o'zingizni sof kichik to'plam bilan cheklashingiz yoki yon ta'siri haqida alohida o'ylashingiz mumkin. Keyinchalik biz monadlar faqat sof funktsiyalardan foydalangan holda barcha turdagi effektlarni modellashtirishga qanday imkon berishini ko'rib chiqamiz. Natijada, biz o'zimizni matematik funktsiyalar bilan cheklab, hech narsani yo'qotmaymiz.

Turlarga misollar

Turlar to'plam ekanligiga qaror qilganingizdan so'ng, siz juda ekzotik misollar bilan tanishishingiz mumkin. Masalan, bo'sh to'plamga qaysi tur mos keladi? Yo'q, u C++ da bekor emas, garchi bu tur Haskellda Void deb ataladi. Bu hech qanday qiymat bilan to'ldirilmagan tur. Siz Voidni qabul qiladigan funktsiyani belgilashingiz mumkin, lekin uni hech qachon chaqira olmaysiz. Unga qo'ng'iroq qilish uchun siz Void turidagi qiymatni kiritishingiz kerak va u shunchaki yo'q. Ushbu funktsiya nimani qaytarishi mumkinligiga kelsak, hech qanday cheklovlar yo'q. U har qanday turni qaytarishi mumkin (garchi bu hech qachon sodir bo'lmaydi, chunki uni chaqirib bo'lmaydi). Boshqacha qilib aytadigan bo'lsak, bu o'zining qaytish turiga ko'ra polimorf bo'lgan funksiyadir. Xaskellerlar buni shunday deb atashgan:
absurd::Void -> a
(tarjimonning eslatmasi: C++ da bunday funktsiyani aniqlash mumkin emas: C++ da har bir turda kamida bitta qiymat mavjud.)

(Yodda tutingki, a har qanday turdagi bo'lishi mumkin bo'lgan turdagi o'zgaruvchidir.) Bu nom tasodifiy emas. Turlar va funksiyalarning mantiqiy nuqtai nazardan chuqurroq talqini bor, bu Karri-Xovard izomorfizmi deb ataladi. Void turi yolg‘onni, absurd funksiyasi esa lotincha “ex falso sequitur quodlibet” iborasida bo‘lgani kabi, yolg‘ondan nimadir kelib chiqishi haqidagi tasdiqni ifodalaydi. (tarjimonning eslatmasi: har qanday narsa yolg'ondan kelib chiqadi.)

Keyinchalik singleton to'plamiga mos keladigan tur keladi. Bu faqat bitta mumkin bo'lgan qiymatga ega bo'lgan tur. Bu shunchaki "bor" degan ma'noni anglatadi. Siz uni darhol tanimasligingiz mumkin, lekin C++ da u bekor. Ushbu turdan boshlab va ushbu turdagi funktsiyalar haqida o'ylab ko'ring. Void funksiyasi har doim chaqirilishi mumkin. Agar bu sof funktsiya bo'lsa, u har doim bir xil natijani qaytaradi. Mana shunday funktsiyaga misol:
int f44() (qaytish 44; )
Siz bu funksiya "hech narsa" ni qabul qilmaydi deb o'ylashingiz mumkin, lekin biz ko'rganimizdek, "hech narsa" ni qabul qiladigan funktsiyani chaqirib bo'lmaydi, chunki "hech narsa" turini ifodalovchi qiymat yo'q. Xo'sh, bu funktsiya nimani qabul qiladi? Kontseptual ravishda, u faqat bitta misolga ega bo'lgan soxta qiymatni oladi, shuning uchun biz uni kodda aniq ko'rsatishimiz shart emas. Biroq, Haskell bu ma'noning belgisiga ega: bo'sh qavslar (). Shunday qilib, kulgili tasodif tufayli (yoki tasodif emasmi?), Voiddan funktsiyani chaqirish C++ va Haskellda bir xil ko'rinadi. Bundan tashqari, Xaskell qisqalikni yaxshi ko'rganligi sababli, bir xil belgi () bir xil to'plamga mos keladigan tur, konstruktor va yagona qiymat uchun ishlatiladi. Mana Haskelldagi funksiya:
f44::() -> Butun son f44() = 44
Birinchi satr f44 "birlik" deb nomlangan () turini Integer turiga o'zgartirishini e'lon qiladi. Ikkinchi qator f44 bitta konstruktorni, ya'ni () ni 44 raqamiga aylantirish uchun naqsh moslashuvidan foydalanishini bildiradi. Siz bu funktsiyani (() qiymatini berish orqali chaqirasiz:
f44()
E'tibor bering, birining har bir funktsiyasi maqsadli turdan bitta elementni tanlashga teng (bu erda Integer 44 tanlangan). Aslida, f44 ni 44 raqamining yana bir ko'rinishi sifatida tasavvur qilishingiz mumkin. Bu to'plam elementlariga to'g'ridan-to'g'ri havolani qanday qilib funktsiya (o'q) bilan almashtirishimiz mumkinligiga misoldir. Birdan ma'lum A turiga bo'lgan funktsiyalar A to'plam elementlari bilan birma-bir mos keladi.

Voidni qaytaradigan yoki Haskellda bittasini qaytaradigan funktsiyalar haqida nima deyish mumkin? C++ da bunday funksiyalar yon ta'sirlar uchun ishlatiladi, lekin biz bilamizki, bunday funktsiyalar so'zning matematik ma'nosida real funktsiyalar emas. Birini qaytaradigan sof funktsiya hech narsa qilmaydi: u o'z argumentini bekor qiladi.

Matematik jihatdan, A to'plamidan bitta to'plamgacha bo'lgan funktsiya har bir elementni ushbu to'plamning bitta elementiga moslashtiradi. Har bir A uchun aynan bitta shunday funksiya mavjud. Bu Integer uchun:
fInt::Integer -> () fInt x = ()
Siz unga istalgan butun sonni berasiz va u bittasini qaytaradi. Qisqalik ruhida Haskell argument sifatida pastki chiziqdan foydalanishga ruxsat beradi, bu esa bekor qilinadi. Shunday qilib, uning nomini o'ylab topishning hojati yo'q. Yuqoridagi kodni quyidagicha qayta yozish mumkin:
fInt::Integer -> () fInt_ = ()
E'tibor bering, bu funktsiyaning bajarilishi nafaqat unga berilgan qiymatdan, balki argument turiga ham bog'liq emas.

Har qanday tur uchun bir xil formula bilan aniqlanishi mumkin bo'lgan funktsiyalar parametrik polimorfik deyiladi. Siz ma'lum bir turdagi o'rniga parametrdan foydalanib, bitta tenglama bilan bunday funktsiyalarning butun oilasini amalga oshirishingiz mumkin. Polimorf funksiyani har qanday turdan bittaga qanday chaqirish mumkin? Albatta, biz uni birlik deb ataymiz:
birlik::a -> () birlik _ = ()
C++ da siz buni shunday amalga oshirasiz:
shablon bekor birligi (T) ()
(tarjimonning eslatmasi: kompilyatorga uni noopda optimallashtirishga yordam berish uchun shunday qilish yaxshidir):
shablon bekor birligi (T&&) ()
Keyingi "turlar tipologiyasi" da ikkita elementdan iborat to'plam mavjud. C++ da u bool deb ataladi, Haskellda esa Bool, ajablanarli emas. Farqi shundaki, C++ da bool o'rnatilgan tur, Haskellda esa uni quyidagicha aniqlash mumkin:
data Bool = rost | Yolg'on
(Ushbu ta'rifni quyidagicha o'qish kerak: Bool True yoki False bo'lishi mumkin.) Asosan, C++ da bu turni tavsiflash mumkin edi:
enum bool(to'g'ri, noto'g'ri);
Lekin C++ enum aslida butun sondir. C++ 11 "sinf enum" dan foydalanish mumkin, ammo keyin qiymatni sinf nomi bilan belgilash kerak bo'ladi: bool:: true yoki bool:: false, har bir faylga mos keladigan sarlavhani kiritish zarurati haqida gapirmaslik kerak. bu uni ishlatadi.

Pure Bool funktsiyalari oddiygina maqsadli turdan ikkita qiymatni tanlaydi, ulardan biri Truega, ikkinchisi Falsega mos keladi.

Booldagi funksiyalar predikatlar deb ataladi. Masalan, Xaskelldagi Data.Char kutubxonasida IsAlpha yoki isDigit kabi ko'plab predikatlar mavjud. C++ da shunga o'xshash kutubxona mavjud , bu boshqa narsalar qatori isalpha va isdigit funktsiyalarini e'lon qiladi, lekin ular mantiqiy qiymatdan ko'ra intni qaytaradi. Hozirgi predikatlar ichida belgilangan va ctype::is(alfa, c) va ctype::is(raqam, c) deb ataladi.



 


O'qing:



Sotib olgandan keyin iPhone-ni sozlash Sotib olgandan keyin iPhone se-ni qanday sozlash mumkin

Sotib olgandan keyin iPhone-ni sozlash Sotib olgandan keyin iPhone se-ni qanday sozlash mumkin

Apple gadjetlari butun sayyorani to'ldirgandek tuyulganiga qaramay, yangi iPhone foydalanuvchilari soni kundan-kunga ortib bormoqda. Shunga qaramay...

YouTube kanalingiz uchun chiroyli fon yaratishning eng yaxshi usullari

YouTube kanalingiz uchun chiroyli fon yaratishning eng yaxshi usullari

Siz qiziqarli video kontent yaratyapsizmi? Kanalingizni chiroyli loyihalashni unutmang! Kanalni loyihalashda eng muhim rolni sarlavha deb ataladigan narsa o'ynaydi...

Samsung smartfonlarini zavod sozlamalariga qaytaring

Samsung smartfonlarini zavod sozlamalariga qaytaring

Ko'pincha Android telefoningizni qayta o'rnatishga ehtiyoj bor. Ushbu protsedura juda oddiy. Bir necha marta ekranga teging...

Power BI nima va u bilan qanday ishlash kerak?

Power BI nima va u bilan qanday ishlash kerak?

Assalomu alaykum, aziz do'stlar, Anton Buduev siz bilan. Ushbu maqola bilan men har birimiz uchun juda chuqur va muhim mavzuni ko'rib chiqishni boshlayman ...

tasma tasviri RSS