Programowanie funkcjonalne - szybki przewodnik
Funkcjonalne języki programowania są specjalnie zaprojektowane do obsługi obliczeń symbolicznych i aplikacji do przetwarzania list. Programowanie funkcjonalne opiera się na funkcjach matematycznych. Niektóre z popularnych funkcjonalnych języków programowania to: Lisp, Python, Erlang, Haskell, Clojure itp.
Funkcjonalne języki programowania są podzielone na dwie grupy, tj.
Pure Functional Languages- Te typy języków funkcyjnych obsługują tylko paradygmaty funkcjonalne. Na przykład - Haskell.
Impure Functional Languages- Te typy języków funkcyjnych wspierają paradygmaty funkcjonalne i imperatywny styl programowania. Na przykład - LISP.
Programowanie funkcjonalne - charakterystyka
Najważniejsze cechy programowania funkcjonalnego są następujące -
Funkcjonalne języki programowania są zaprojektowane w oparciu o koncepcję funkcji matematycznych, które używają wyrażeń warunkowych i rekurencji do wykonywania obliczeń.
Programowanie funkcjonalne obsługuje higher-order functions i lazy evaluation funkcje.
Funkcjonalne języki programowania nie obsługują kontrolek przepływu, takich jak instrukcje pętli i instrukcje warunkowe, takie jak instrukcje If-Else i Switch. Bezpośrednio używają funkcji i wywołań funkcyjnych.
Podobnie jak OOP, funkcjonalne języki programowania obsługują popularne koncepcje, takie jak abstrakcja, enkapsulacja, dziedziczenie i polimorfizm.
Programowanie funkcjonalne - zalety
Programowanie funkcjonalne oferuje następujące korzyści -
Bugs-Free Code - Programowanie funkcjonalne nie obsługuje state, więc nie ma skutków ubocznych i możemy pisać bezbłędne kody.
Efficient Parallel Programming- Funkcjonalne języki programowania nie mają stanu Mutable, więc nie ma problemów ze zmianą stanu. Można zaprogramować „Funkcje”, aby działały równolegle jako „instrukcje”. Takie kody zapewniają łatwość ponownego użycia i testowalności.
Efficiency- Programy funkcjonalne składają się z niezależnych jednostek, które mogą działać równolegle. W rezultacie takie programy są bardziej wydajne.
Supports Nested Functions - Programowanie funkcjonalne obsługuje funkcje zagnieżdżone.
Lazy Evaluation - Programowanie funkcjonalne obsługuje leniwe konstrukcje funkcjonalne, takie jak leniwe listy, leniwe mapy itp.
Wadą programowania funkcjonalnego jest duża ilość pamięci. Ponieważ nie ma stanu, za każdym razem musisz tworzyć nowe obiekty, aby wykonywać akcje.
Programowanie funkcjonalne jest używane w sytuacjach, gdy musimy wykonać wiele różnych operacji na tym samym zestawie danych.
Lisp jest używany w aplikacjach sztucznej inteligencji, takich jak uczenie maszynowe, przetwarzanie języka, modelowanie mowy i widzenia itp.
Wbudowane interpretery Lisp dodają programowalność do niektórych systemów, takich jak Emacs.
Programowanie funkcjonalne a programowanie obiektowe
Poniższa tabela przedstawia główne różnice między programowaniem funkcjonalnym a programowaniem obiektowym -
Programowanie funkcjonalne | OOP |
---|---|
Używa niezmiennych danych. | Używa mutowalnych danych. |
Podąża za deklaratywnym modelem programowania. | Podąża za imperatywnym modelem programowania. |
Skupiamy się na: „Co robisz” | Skoncentruj się na „Jak się masz” |
Obsługuje programowanie równoległe | Nie nadaje się do programowania równoległego |
Jego funkcje nie mają skutków ubocznych | Jej metody mogą powodować poważne skutki uboczne. |
Sterowanie przepływem odbywa się za pomocą wywołań funkcji i wywołań funkcji z rekurencją | Sterowanie przepływem odbywa się za pomocą pętli i instrukcji warunkowych. |
Wykorzystuje koncepcję „rekurencji” do iteracji danych kolekcji. | Wykorzystuje koncepcję „pętli” do iteracji danych kolekcji. Na przykład: pętla For-each w Javie |
Kolejność wykonywania instrukcji nie jest tak ważna. | Kolejność wykonywania instrukcji jest bardzo ważna. |
Obsługuje zarówno „Abstrakcję na podstawie danych”, jak i „Abstrakcję na podstawie zachowania”. | Obsługuje tylko „Abstrakcję na podstawie danych”. |
Efektywność kodu programu
Wydajność kodu programistycznego jest wprost proporcjonalna do wydajności algorytmicznej i szybkości wykonywania. Dobra wydajność zapewnia wyższą wydajność.
Czynniki wpływające na skuteczność programu obejmują:
- Prędkość maszyny
- Szybkość kompilatora
- System operacyjny
- Wybór odpowiedniego języka programowania
- Sposób danych w programie jest zorganizowany
- Algorytm zastosowany do rozwiązania problemu
Wydajność języka programowania można poprawić, wykonując następujące zadania -
Usuwając niepotrzebny kod lub kod, który trafia do nadmiarowego przetwarzania.
Korzystając z optymalnej pamięci i nieulotnej pamięci masowej
Wykorzystując wszędzie tam, gdzie ma to zastosowanie, elementy wielokrotnego użytku.
Wykorzystując obsługę błędów i wyjątków na wszystkich warstwach programu.
Tworząc kod programistyczny zapewniający integralność i spójność danych.
Opracowując kod programu zgodny z logiką projektowania i przepływem.
Wydajny kod programistyczny może maksymalnie zredukować zużycie zasobów i czas realizacji przy minimalnym ryzyku dla środowiska operacyjnego.
Pod względem programowania a functionto blok instrukcji, który wykonuje określone zadanie. Funkcje akceptują dane, przetwarzają je i zwracają wynik. Funkcje zostały napisane przede wszystkim w celu wspierania koncepcji ponownego wykorzystania. Po napisaniu funkcji można ją łatwo wywołać, bez konieczności wielokrotnego pisania tego samego kodu.
Różne języki funkcyjne używają różnej składni do pisania funkcji.
Wymagania wstępne dotyczące pisania funkcji
Przed napisaniem funkcji programista musi znać następujące punkty -
Cel funkcji powinien być znany programiście.
Algorytm funkcji powinien być znany programiście.
Zmienne danych funkcji i ich cel powinny być znane programiście.
Dane funkcji powinny być znane programiście wywoływanemu przez użytkownika.
Sterowanie przepływem funkcji
Gdy funkcja jest „wywoływana”, program „przekazuje” sterowanie w celu wykonania funkcji, a jej „przepływ sterowania” jest następujący:
Program sięga do instrukcji zawierającej „wywołanie funkcji”.
Wykonywana jest pierwsza linia wewnątrz funkcji.
Wszystkie instrukcje wewnątrz funkcji są wykonywane od góry do dołu.
Gdy funkcja zostanie wykonana pomyślnie, sterowanie wraca do instrukcji, od której została rozpoczęta.
Wszelkie dane obliczone i zwrócone przez funkcję są używane zamiast funkcji w oryginalnym wierszu kodu.
Składnia funkcji
Ogólna składnia funkcji wygląda następująco -
returnType functionName(type1 argument1, type2 argument2, . . . ) {
// function body
}
Definiowanie funkcji w C ++
Weźmy przykład, aby zrozumieć, jak można zdefiniować funkcję w C ++, który jest językiem programowania obiektowego. Poniższy kod zawiera funkcję, która dodaje dwie liczby i podaje wynik jako dane wyjściowe.
#include <stdio.h>
int addNum(int a, int b); // function prototype
int main() {
int sum;
sum = addNum(5,6); // function call
printf("sum = %d",sum);
return 0;
}
int addNum (int a,int b) { // function definition
int result;
result = a + b;
return result; // return statement
}
Wytworzy następujący wynik -
Sum = 11
Definiowanie funkcji w Erlang
Zobaczmy, jak można zdefiniować tę samą funkcję w Erlangu, który jest funkcjonalnym językiem programowania.
-module(helloworld).
-export([add/2,start/0]).
add(A,B) ->
C = A + B,
io:fwrite("~w~n",[C]).
start() ->
add(5,6).
Wytworzy następujący wynik -
11
Prototyp funkcji
Prototyp funkcji to deklaracja funkcji, która zawiera typ zwracany, nazwę funkcji i listę argumentów. Jest to podobne do definicji funkcji bez ciała funkcji.
For Example - Niektóre języki programowania obsługują prototypowanie funkcji, a inne nie.
W C ++ możemy stworzyć prototyp funkcji funkcji „sum” w ten sposób -
int sum(int a, int b)
Note - Języki programowania takie jak Python, Erlang itp. Nie obsługują prototypowania funkcji, musimy zadeklarować całą funkcję.
Jaki jest pożytek z prototypu funkcji?
Prototyp funkcji jest używany przez kompilator podczas wywoływania funkcji. Kompilator używa go, aby upewnić się, że zwracany typ jest prawidłowy, przekazywana jest właściwa lista argumentów, a ich zwracany typ jest poprawny.
Podpis funkcji
Sygnatura funkcji jest podobna do prototypu funkcji, w którym liczba parametrów, typ danych parametrów i kolejność pojawiania się powinny być w podobnej kolejności. Na przykład -
void Sum(int a, int b, int c); // function 1
void Sum(float a, float b, float c); // function 2
void Sum(float a, float b, float c); // function 3
Funkcja 1 i Funkcja 2 mają różne sygnatury. Funkcja 2 i Funkcja 3 mają takie same podpisy.
Note - Przeciążanie funkcji i nadpisywanie funkcji, które omówimy w kolejnych rozdziałach, oparte są na koncepcji sygnatur funkcji.
Przeciążanie funkcji jest możliwe, gdy klasa ma wiele funkcji o tej samej nazwie, ale różnych podpisach.
Zastępowanie funkcji jest możliwe, gdy funkcja klasy pochodnej ma taką samą nazwę i podpis jak jej klasa bazowa.
Funkcje są dwojakiego rodzaju -
- Predefiniowane funkcje
- Funkcje zdefiniowane przez użytkownika
W tym rozdziale omówimy szczegółowo funkcje.
Predefiniowane funkcje
Są to funkcje wbudowane w język w celu wykonywania operacji i są przechowywane w standardowej bibliotece funkcji.
For Example - „Strcat” w C ++ i „concat” w Haskell są używane do dołączania dwóch ciągów, „strlen” w C ++ i „len” w Pythonie są używane do obliczenia długości łańcucha.
Program do drukowania długości łańcucha w C ++
Poniższy program pokazuje, jak można wydrukować długość łańcucha przy użyciu C ++ -
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main() {
char str[20] = "Hello World";
int len;
len = strlen(str);
cout<<"String length is: "<<len;
return 0;
}
Wytworzy następujący wynik -
String length is: 11
Program do drukowania długości łańcucha w Pythonie
Poniższy program pokazuje, jak wydrukować długość łańcucha za pomocą Pythona, który jest funkcjonalnym językiem programowania -
str = "Hello World";
print("String length is: ", len(str))
Wytworzy następujący wynik -
('String length is: ', 11)
Funkcje zdefiniowane przez użytkownika
Funkcje zdefiniowane przez użytkownika są definiowane przez użytkownika w celu wykonywania określonych zadań. Istnieją cztery różne wzorce definiowania funkcji -
- Funkcje bez argumentu i wartości zwracanej
- Funkcje bez argumentu, ale zwracana wartość
- Funkcje z argumentem, ale bez wartości zwracanej
- Funkcje z argumentem i wartością zwracaną
Funkcje bez argumentu i wartości zwracanej
Poniższy program pokazuje, jak zdefiniować funkcję bez argumentu i wartości zwracanej w C++ -
#include <iostream>
using namespace std;
void function1() {
cout <<"Hello World";
}
int main() {
function1();
return 0;
}
Wytworzy następujący wynik -
Hello World
Poniższy program pokazuje, jak można zdefiniować podobną funkcję (bez argumentu i bez wartości zwracanej) w Python -
def function1():
print ("Hello World")
function1()
Wytworzy następujący wynik -
Hello World
Funkcje bez argumentu, ale zwracana wartość
Poniższy program pokazuje, jak zdefiniować funkcję bez argumentu, ale wartość zwracaną w C++ -
#include <iostream>
using namespace std;
string function1() {
return("Hello World");
}
int main() {
cout<<function1();
return 0;
}
Wytworzy następujący wynik -
Hello World
Poniższy program pokazuje, jak można zdefiniować podobną funkcję (bez argumentu, ale wartość zwracaną) w Python -
def function1():
return "Hello World"
res = function1()
print(res)
Wytworzy następujący wynik -
Hello World
Funkcje z argumentem, ale bez wartości zwracanej
Poniższy program pokazuje, jak zdefiniować funkcję z argumentem, ale bez wartości zwracanej w C++ -
#include <iostream>
using namespace std;
void function1(int x, int y) {
int c;
c = x+y;
cout<<"Sum is: "<<c;
}
int main() {
function1(4,5);
return 0;
}
Wytworzy następujący wynik -
Sum is: 9
Poniższy program pokazuje, jak zdefiniować podobną funkcję w Python -
def function1(x,y):
c = x + y
print("Sum is:",c)
function1(4,5)
Wytworzy następujący wynik -
('Sum is:', 9)
Funkcje z argumentem i wartością zwracaną
Poniższy program pokazuje, jak zdefiniować funkcję w C ++ bez argumentu, ale wartość zwracaną -
#include <iostream>
using namespace std;
int function1(int x, int y) {
int c;
c = x + y;
return c;
}
int main() {
int res;
res = function1(4,5);
cout<<"Sum is: "<<res;
return 0;
}
Wytworzy następujący wynik -
Sum is: 9
Poniższy program pokazuje, jak zdefiniować podobną funkcję (z argumentem i wartością zwracaną) w Python -
def function1(x,y):
c = x + y
return c
res = function1(4,5)
print("Sum is ",res)
Wytworzy następujący wynik -
('Sum is ', 9)
Po zdefiniowaniu funkcji musimy przekazać do niej argumenty, aby uzyskać pożądane wyjście. Obsługuje większość języków programowaniacall by value i call by reference metody przekazywania argumentów do funkcji.
W tym rozdziale nauczymy się, jak „wywołanie według wartości” działa w języku programowania obiektowego, takim jak C ++, oraz funkcjonalnym języku programowania, takim jak Python.
W metodzie Call by Value original value cannot be changed. Kiedy przekazujemy argument do funkcji, jest on przechowywany lokalnie przez parametr funkcji w pamięci stosu. W związku z tym wartości są zmieniane tylko w funkcji i nie będzie to miało wpływu poza funkcją.
Wywołaj według wartości w C ++
Poniższy program pokazuje, jak działa Call by Value w C ++ -
#include <iostream>
using namespace std;
void swap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
cout<<"\n"<<"value of a inside the function: "<<a;
cout<<"\n"<<"value of b inside the function: "<<b;
}
int main() {
int a = 50, b = 70;
cout<<"value of a before sending to function: "<<a;
cout<<"\n"<<"value of b before sending to function: "<<b;
swap(a, b); // passing value to function
cout<<"\n"<<"value of a after sending to function: "<<a;
cout<<"\n"<<"value of b after sending to function: "<<b;
return 0;
}
Wytworzy następujący wynik -
value of a before sending to function: 50
value of b before sending to function: 70
value of a inside the function: 70
value of b inside the function: 50
value of a after sending to function: 50
value of b after sending to function: 70
Wywołaj według wartości w Pythonie
Poniższy program pokazuje, jak działa Call by Value w Pythonie -
def swap(a,b):
t = a;
a = b;
b = t;
print "value of a inside the function: :",a
print "value of b inside the function: ",b
# Now we can call the swap function
a = 50
b = 75
print "value of a before sending to function: ",a
print "value of b before sending to function: ",b
swap(a,b)
print "value of a after sending to function: ", a
print "value of b after sending to function: ",b
Wytworzy następujący wynik -
value of a before sending to function: 50
value of b before sending to function: 75
value of a inside the function: : 75
value of b inside the function: 50
value of a after sending to function: 50
value of b after sending to function: 75
W Call by Reference, original value is changedponieważ przekazujemy adresy referencyjne argumentów. Faktyczne i formalne argumenty mają tę samą przestrzeń adresową, więc każda zmiana wartości wewnątrz funkcji jest odzwierciedlana zarówno wewnątrz, jak i na zewnątrz funkcji.
Wywołaj przez odniesienie w C ++
Poniższy program pokazuje, jak działa Call by Value w C ++ -
#include <iostream>
using namespace std;
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
cout<<"\n"<<"value of a inside the function: "<<*a;
cout<<"\n"<<"value of b inside the function: "<<*b;
}
int main() {
int a = 50, b = 75;
cout<<"\n"<<"value of a before sending to function: "<<a;
cout<<"\n"<<"value of b before sending to function: "<<b;
swap(&a, &b); // passing value to function
cout<<"\n"<<"value of a after sending to function: "<<a;
cout<<"\n"<<"value of b after sending to function: "<<b;
return 0;
}
Wytworzy następujący wynik -
value of a before sending to function: 50
value of b before sending to function: 75
value of a inside the function: 75
value of b inside the function: 50
value of a after sending to function: 75
value of b after sending to function: 50
Wywołaj przez odniesienie w Pythonie
Poniższy program pokazuje, jak działa Call by Value w Pythonie -
def swap(a,b):
t = a;
a = b;
b = t;
print "value of a inside the function: :",a
print "value of b inside the function: ",b
return(a,b)
# Now we can call swap function
a = 50
b =75
print "value of a before sending to function: ",a
print "value of b before sending to function: ",b
x = swap(a,b)
print "value of a after sending to function: ", x[0]
print "value of b after sending to function: ",x[1]
Wytworzy następujący wynik -
value of a before sending to function: 50
value of b before sending to function: 75
value of a inside the function: 75
value of b inside the function: 50
value of a after sending to function: 75
value of b after sending to function: 50
Kiedy mamy wiele funkcji o tej samej nazwie, ale różnych parametrach, mówi się, że są one przeciążone. Technika ta służy do zwiększenia czytelności programu.
Istnieją dwa sposoby na przeciążenie funkcji, tj.
- Mając różną liczbę argumentów
- Posiadanie różnych typów argumentów
Przeciążanie funkcji jest zwykle wykonywane, gdy musimy wykonać jedną operację z różną liczbą lub typami argumentów.
Przeciążanie funkcji w C ++
Poniższy przykład pokazuje, jak przeciążanie funkcji odbywa się w C ++, który jest językiem programowania obiektowego -
#include <iostream>
using namespace std;
void addnum(int,int);
void addnum(int,int,int);
int main() {
addnum (5,5);
addnum (5,2,8);
return 0;
}
void addnum (int x, int y) {
cout<<"Integer number: "<<x+y<<endl;
}
void addnum (int x, int y, int z) {
cout<<"Float number: "<<x+y+z<<endl;
}
Wytworzy następujący wynik -
Integer number: 10
Float number: 15
Przeciążanie funkcji w Erlangu
Poniższy przykład pokazuje, jak wykonać przeciążenie funkcji w Erlangu, który jest funkcjonalnym językiem programowania -
-module(helloworld).
-export([addnum/2,addnum/3,start/0]).
addnum(X,Y) ->
Z = X+Y,
io:fwrite("~w~n",[Z]).
addnum(X,Y,Z) ->
A = X+Y+Z,
io:fwrite("~w~n",[A]).
start() ->
addnum(5,5), addnum(5,2,8).
Wytworzy następujący wynik -
10
15
Gdy klasa bazowa i klasa pochodna mają funkcje składowe o dokładnie takiej samej nazwie, tym samym typie zwracanym i tej samej liście argumentów, wówczas mówi się, że jest to funkcja przesłaniająca.
Zastępowanie funkcji przy użyciu C ++
Poniższy przykład pokazuje, jak nadpisywanie funkcji jest wykonywane w C ++, który jest językiem programowania zorientowanym obiektowo -
#include <iostream>
using namespace std;
class A {
public:
void display() {
cout<<"Base class";
}
};
class B:public A {
public:
void display() {
cout<<"Derived Class";
}
};
int main() {
B obj;
obj.display();
return 0;
}
Wytworzy następujący wynik
Derived Class
Przesłanianie funkcji za pomocą Pythona
Poniższy przykład pokazuje, jak wykonać przesłanianie funkcji w Pythonie, który jest funkcjonalnym językiem programowania -
class A(object):
def disp(self):
print "Base Class"
class B(A):
def disp(self):
print "Derived Class"
x = A()
y = B()
x.disp()
y.disp()
Wytworzy następujący wynik -
Base Class
Derived Class
Funkcja, która wywołuje samą siebie, jest znana jako funkcja rekurencyjna, a ta technika jest znana jako rekurencja. Instrukcja rekursji jest kontynuowana, dopóki inna instrukcja jej nie uniemożliwi.
Rekursja w C ++
Poniższy przykład pokazuje, jak działa rekurencja w C ++, który jest zorientowanym obiektowo językiem programowania -
#include <stdio.h>
long int fact(int n);
int main() {
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
printf("Factorial of %d = %ld", n, fact(n));
return 0;
}
long int fact(int n) {
if (n >= 1)
return n*fact(n-1);
else
return 1;
}
Wytworzy następujący wynik
Enter a positive integer: 5
Factorial of 5 = 120
Rekursja w Pythonie
Poniższy przykład pokazuje, jak działa rekurencja w Pythonie, który jest funkcjonalnym językiem programowania -
def fact(n):
if n == 1:
return n
else:
return n* fact (n-1)
# accepts input from user
num = int(input("Enter a number: "))
# check whether number is positive or not
if num < 0:
print("Sorry, factorial does not exist for negative numbers")
else:
print("The factorial of " + str(num) + " is " + str(fact(num)))
Wytworzy następujący wynik -
Enter a number: 6
The factorial of 6 is 720
Funkcja wyższego rzędu (HOF) to funkcja spełniająca co najmniej jeden z następujących warunków -
- Przyjmuje lub więcej funkcji jako argument
- Zwraca funkcję jako wynik
HOF w PHP
Poniższy przykład pokazuje, jak napisać funkcję wyższego rzędu w PHP, który jest językiem programowania obiektowego -
<?php
$twice = function($f, $v) { return $f($f($v));
};
$f = function($v) {
return $v + 3; }; echo($twice($f, 7));
Wytworzy następujący wynik -
13
HOF w Pythonie
Poniższy przykład pokazuje, jak napisać funkcję wyższego rzędu w Pythonie, który jest językiem programowania obiektowego -
def twice(function):
return lambda x: function(function(x))
def f(x):
return x + 3
g = twice(f)
print g(7)
Wytworzy następujący wynik -
13
Typ danych definiuje typ wartości, jaką obiekt może mieć i jakie operacje można na nim wykonać. Przed użyciem należy najpierw zadeklarować typ danych. Różne języki programowania obsługują różne typy danych. Na przykład,
- C obsługuje znaki char, int, float, long itp.
- Python obsługuje ciągi, listy, krotki itp.
W szerokim sensie istnieją trzy typy typów danych -
Fundamental data types- Są to predefiniowane typy danych, które są używane przez programistę bezpośrednio do przechowywania tylko jednej wartości zgodnie z wymaganiami, tj. Typ całkowity, typ znakowy lub typ zmiennoprzecinkowy. Na przykład - int, char, float itp.
Derived data types- Te typy danych są wyprowadzane przy użyciu wbudowanych typów danych, które zostały zaprojektowane przez programistę do przechowywania wielu wartości tego samego typu zgodnie z ich wymaganiami. Na przykład - tablica, wskaźnik, funkcja, lista itp.
User-defined data types- Te typy danych są wyprowadzane przy użyciu wbudowanych typów danych, które są opakowane w jeden typ danych, aby przechowywać wiele wartości tego samego lub innego typu lub obu, zgodnie z wymaganiami. Na przykład - klasa, struktura itp.
Typy danych obsługiwane przez C ++
W poniższej tabeli wymieniono typy danych obsługiwane przez C ++ -
Typ danych | Rozmiar | Zasięg |
---|---|---|
zwęglać | 1 bajt | -128 do 127 lub 0 do 255 |
unsigned char | 1 bajt | Od 0 do 255 |
podpisany char | 1 bajt | -128 do 127 |
int | 4 bajty | Od -2147483648 do 2147483647 |
unsigned int | 4 bajty | 0 do 4294967295 |
podpisany int | 4 bajty | Od -2147483648 do 2147483647 |
krótki int | 2 bajty | -32768 do 32767 |
unsigned short int | 2 bajty | 0 do 65 535 |
podpisany krótki int | 2 bajty | -32768 do 32767 |
długi int | 4 bajty | -2 147 483 648 do 2 147 483 647 |
podpisany długi int | 4 bajty | -2 147 483 648 do 2 147 483 647 |
unsigned long int | 4 bajty | Od 0 do 4 294 967 295 |
pływak | 4 bajty | +/- 3,4e +/- 38 (~ 7 cyfr) |
podwójnie | 8 bajtów | +/- 1,7e +/- 308 (~ 15 cyfr) |
długie podwójne | 8 bajtów | +/- 1,7e +/- 308 (~ 15 cyfr) |
Typy danych obsługiwane przez Javę
Java obsługuje następujące typy danych -
Typ danych | Rozmiar | Zasięg |
---|---|---|
bajt | 1 bajt | -128 do 127 |
zwęglać | 2 bajty | Od 0 do 65 536 |
krótki | 2 bajty | -32,7688 do 32767 |
int | 4 bajty | -2 147 483 648 do 2 147 483 647 |
długo | 8 bajtów | -9 223 372 036 854 775 808 do 9 223 372 036 854 775 807 |
pływak | 4 bajty | Od -2147483648 do 2147483647 |
podwójnie | 8 bajtów | + 9,223 * 1018 |
Boolean | 1 bit | Prawda czy fałsz |
Typy danych obsługiwane przez Erlang
W tej sekcji omówimy typy danych obsługiwane przez Erlang, który jest funkcjonalnym językiem programowania.
Numer
Erlang obsługuje dwa typy literałów numerycznych, tj integer i float. Spójrz na poniższy przykład, który pokazuje, jak dodać dwie wartości całkowite -
-module(helloworld).
-export([start/0]).
start() ->
io:fwrite("~w",[5+4]).
Wytworzy następujące dane wyjściowe -
9
Atom
Na atomto ciąg, którego wartości nie można zmienić. Musi zaczynać się od małej litery i może zawierać dowolne znaki alfanumeryczne i specjalne. Kiedy atom zawiera znaki specjalne, powinien być ujęty w pojedyncze cudzysłowy ('). Spójrz na poniższy przykład, aby lepiej zrozumieć.
-module(helloworld).
-export([start/0]).
start()->
io:fwrite(monday).
Wytworzy następujący wynik -
monday
Note- Spróbuj zmienić atom na „poniedziałek” przez duże „M”. Program wyświetli błąd.
Boolean
Ten typ danych służy do wyświetlania wyniku jako albo true lub false. Spójrz na poniższy przykład. Pokazuje, jak porównać dwie liczby całkowite.
-module(helloworld).
-export([start/0]).
start() ->
io:fwrite(5 =< 9).
Wytworzy następujący wynik -
true
Ciąg bitów
Ciąg bitowy jest używany do przechowywania obszaru pamięci bez typu. Spójrz na poniższy przykład. Pokazuje, jak przekonwertować 2 bity ciągu bitowego na listę.
-module(helloworld).
-export([start/0]).
start() ->
Bin2 = <<15,25>>,
P = binary_to_list(Bin2),
io:fwrite("~w",[P]).
Wytworzy następujący wynik -
[15,25]
Tuple
Krotka to złożony typ danych, który ma stałą liczbę terminów. Każdy termin krotki jest znany jakoelement. Liczba elementów to rozmiar krotki. Poniższy przykład pokazuje, jak zdefiniować krotkę 5 terminów i wydrukować jej rozmiar.
-module(helloworld).
-export([start/0]).
start() ->
K = {abc,50,pqr,60,{xyz,75}} ,
io:fwrite("~w",[tuple_size(K)]).
Wytworzy następujący wynik -
5
Mapa
Mapa to złożony typ danych ze zmienną liczbą skojarzeń klucz-wartość. Każde skojarzenie klucz-wartość na mapie jest znane jakoassociation-pair. Plikkey i value nazywane są części pary elements. Mówi się, że liczba par asocjacji jest wielkością mapy. Poniższy przykład pokazuje, jak zdefiniować mapę 3 mapowań i wydrukować jej rozmiar.
-module(helloworld).
-export([start/0]).
start() ->
Map1 = #{name => 'abc',age => 40, gender => 'M'},
io:fwrite("~w",[map_size(Map1)]).
Wytworzy następujący wynik -
3
Lista
Lista to złożony typ danych zawierający zmienną liczbę terminów. Każdy termin na liście nazywany jest elementem. O liczbie elementów mówi się, że jest długością listy. Poniższy przykład pokazuje, jak zdefiniować listę 5 pozycji i wydrukować jej rozmiar.
-module(helloworld).
-export([start/0]).
start() ->
List1 = [10,15,20,25,30] ,
io:fwrite("~w",[length(List1)]).
Wytworzy następujący wynik -
5
Note - Typ danych „String” nie jest zdefiniowany w Erlang.
Polimorfizm z punktu widzenia programowania oznacza wielokrotne używanie jednego kodu. Mówiąc dokładniej, jest to zdolność programu do przetwarzania obiektów w różny sposób w zależności od ich typu lub klasy danych.
Polimorfizm jest dwojakiego rodzaju -
Compile-time Polymorphism - Ten typ polimorfizmu można osiągnąć stosując metodę przeciążania.
Run-time Polymorphism - Ten typ polimorfizmu można uzyskać za pomocą nadpisywania metod i funkcji wirtualnych.
Zalety polimorfizmu
Polimorfizm ma następujące zalety -
Pomaga programiście w ponownym wykorzystaniu kodów, tj. Klasy raz napisane, przetestowane i zaimplementowane mogą być ponownie użyte w razie potrzeby. Oszczędza dużo czasu.
Pojedyncza zmienna może służyć do przechowywania wielu typów danych.
Łatwe debugowanie kodów.
Polimorficzne typy danych
Polimorficzne typy danych można zaimplementować za pomocą ogólnych wskaźników, które przechowują tylko adres bajtowy, bez typu danych przechowywanych pod tym adresem pamięci. Na przykład,
function1(void *p, void *q)
gdzie p i q to ogólne wskaźniki, które mogą się trzymać int, float (lub dowolną inną) wartość jako argument.
Funkcja polimorficzna w C ++
Poniższy program pokazuje, jak używać funkcji polimorficznych w C ++, który jest językiem programowania obiektowego.
#include <iostream>
Using namespace std:
class A {
public:
void show() {
cout << "A class method is called/n";
}
};
class B:public A {
public:
void show() {
cout << "B class method is called/n";
}
};
int main() {
A x; // Base class object
B y; // Derived class object
x.show(); // A class method is called
y.show(); // B class method is called
return 0;
}
Wytworzy następujący wynik -
A class method is called
B class method is called
Funkcja polimorficzna w Pythonie
Poniższy program pokazuje, jak używać funkcji polimorficznych w Pythonie, który jest funkcjonalnym językiem programowania.
class A(object):
def show(self):
print "A class method is called"
class B(A):
def show(self):
print "B class method is called"
def checkmethod(clasmethod):
clasmethod.show()
AObj = A()
BObj = B()
checkmethod(AObj)
checkmethod(BObj)
Wytworzy następujący wynik -
A class method is called
B class method is called
ZA stringto grupa znaków ze spacjami. Można powiedzieć, że jest to jednowymiarowa tablica znaków zakończona znakiem NULL („\ 0”). Ciąg może być również traktowany jako predefiniowana klasa, która jest obsługiwana przez większość języków programowania, takich jak C, C ++, Java, PHP, Erlang, Haskell, Lisp itp.
Poniższy obraz pokazuje, jak ciąg „Tutorial” będzie wyglądał w pamięci.
Utwórz ciąg w C ++
Poniższy program jest przykładem, który pokazuje, jak utworzyć ciąg w C ++, który jest językiem programowania zorientowanym obiektowo.
#include <iostream>
using namespace std;
int main () {
char greeting[20] = {'H', 'o', 'l', 'i', 'd', 'a', 'y', '\0'};
cout << "Today is: ";
cout << greeting << endl;
return 0;
}
Wytworzy następujący wynik -
Today is: Holiday
String w Erlang
Poniższy program jest przykładem, który pokazuje, jak utworzyć ciąg w Erlang, który jest funkcjonalnym językiem programowania.
-module(helloworld).
-export([start/0]).
start() ->
Str = "Today is: Holiday",
io:fwrite("~p~n",[Str]).
Wytworzy następujący wynik -
"Today is: Holiday"
Operacje na ciągach znaków w C ++
Różne języki programowania obsługują różne metody na łańcuchach. W poniższej tabeli przedstawiono kilka wstępnie zdefiniowanych metod ciągów obsługiwanych przez C ++.
S.No. | Metoda i opis |
---|---|
1 | Strcpy(s1,s2) Kopiuje ciąg s2 do łańcucha s1 |
2 | Strcat(s1,s2) Dodaje ciąg s2 na końcu s1 |
3 | Strlen(s1) Zapewnia długość łańcucha s1 |
4 | Strcmp(s1,s2) Zwraca 0, gdy ciąg s1 i s2 są takie same |
5 | Strchr(s1,ch) Zwraca wskaźnik do pierwszego wystąpienia znaku ch w ciągu s1 |
6 | Strstr(s1,s2) Zwraca wskaźnik do pierwszego wystąpienia ciągu s2 w ciągu s1 |
Poniższy program pokazuje, jak powyższe metody mogą być używane w C ++ -
#include <iostream>
#include <cstring>
using namespace std;
int main () {
char str1[20] = "Today is ";
char str2[20] = "Monday";
char str3[20];
int len ;
strcpy( str3, str1); // copy str1 into str3
cout << "strcpy( str3, str1) : " << str3 << endl;
strcat( str1, str2); // concatenates str1 and str2
cout << "strcat( str1, str2): " << str1 << endl;
len = strlen(str1); // String length after concatenation
cout << "strlen(str1) : " << len << endl;
return 0;
}
Wytworzy następujący wynik -
strcpy(str3, str1) : Today is
strcat(str1, str2) : Today is Monday
strlen(str1) : 15
Operacje na łańcuchach w Erlangu
W poniższej tabeli przedstawiono listę wstępnie zdefiniowanych metod ciągów obsługiwanych przez Erlang.
S.No. | Metoda i opis |
---|---|
1 | len(s1) Zwraca liczbę znaków w podanym ciągu. |
2 | equal(s1,s2) Zwraca prawdę, gdy ciąg s1 i s2 są równe, w przeciwnym razie zwraca fałsz |
3 | concat(s1,s2) Dodaje ciąg s2 na końcu łańcucha s1 |
4 | str(s1,ch) Zwraca pozycję indeksu znaku ch w łańcuchu s1 |
5 | str (s1,s2) Zwraca pozycję indeksu s2 w ciągu s1 |
6 | substr(s1,s2,num) Ta metoda zwraca ciąg s2 z ciągu s1 na podstawie pozycji początkowej i liczby znaków z pozycji początkowej |
7 | to_lower(s1) Ta metoda zwraca ciąg małymi literami |
Poniższy program pokazuje, jak powyższe metody mogą być użyte w Erlang.
-module(helloworld).
-import(string,[concat/2]).
-export([start/0]).
start() ->
S1 = "Today is ",
S2 = "Monday",
S3 = concat(S1,S2),
io:fwrite("~p~n",[S3]).
Wytworzy następujący wynik -
"Today is Monday"
Listjest najbardziej wszechstronnym typem danych dostępnym w funkcjonalnych językach programowania, używanym do przechowywania zbioru podobnych elementów danych. Koncepcja jest podobna do tablic w programowaniu obiektowym. Elementy listy można zapisać w nawiasach kwadratowych oddzielonych przecinkami. Sposób zapisywania danych na liście różni się w zależności od języka.
Program do tworzenia listy numerów w Javie
Lista nie jest typem danych w Javie / C / C ++, ale mamy alternatywne sposoby tworzenia listy w Javie, np. ArrayList i LinkedList.
Poniższy przykład pokazuje, jak utworzyć listę w języku Java. Tutaj używamy metody listy połączonej, aby utworzyć listę numerów.
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
public class HelloWorld {
public static void main (String[] args) throws java.lang.Exception {
List<String> listStrings = new LinkedList<String>();
listStrings.add("1");
listStrings.add("2");
listStrings.add("3");
listStrings.add("4");
listStrings.add("5");
System.out.println(listStrings);
}
}
Wytworzy następujący wynik -
[1, 2, 3, 4, 5]
Program do tworzenia listy numerów w Erlang
-module(helloworld).
-export([start/0]).
start() ->
Lst = [1,2,3,4,5],
io:fwrite("~w~n",[Lst]).
Wytworzy następujący wynik -
[1 2 3 4 5]
Operacje na listach w Javie
W tej sekcji omówimy niektóre operacje, które można wykonać na listach w Javie.
Dodawanie elementów do listy
Metody add (Object), add (index, Object), addAll () służą do dodawania elementów do listy. Na przykład,
ListStrings.add(3, “three”)
Usuwanie elementów z listy
Metody remove (index) lub removeobject () służą do usuwania elementów z listy. Na przykład,
ListStrings.remove(3,”three”)
Note - Do usunięcia wszystkich elementów z listy używana jest metoda clear ().
Pobieranie elementów z listy
Metoda get () służy do pobierania elementów z listy w określonej lokalizacji. Metody getfirst () i getlast () mogą być używane w klasie LinkedList. Na przykład,
String str = ListStrings.get(2)
Aktualizacja elementów na liście
Metoda set (index, element) służy do aktualizowania elementu o określonym indeksie za pomocą określonego elementu. Na przykład,
listStrings.set(2,”to”)
Sortowanie elementów na liście
Metody collection.sort () i collection.reverse () służą do sortowania listy w porządku rosnącym lub malejącym. Na przykład,
Collection.sort(listStrings)
Wyszukiwanie elementów na liście
Następujące trzy metody są używane zgodnie z wymaganiami -
Boolean contains(Object) metoda zwraca true jeśli lista zawiera określony element, w przeciwnym razie zwraca false.
int indexOf(Object) metoda zwraca indeks pierwszego wystąpienia określonego elementu na liście, w przeciwnym razie zwraca wartość -1, gdy element nie zostanie znaleziony.
int lastIndexOf(Object) zwraca indeks ostatniego wystąpienia określonego elementu na liście, w przeciwnym razie zwraca wartość -1, gdy element nie zostanie znaleziony.
Lista operacji w Erlang
W tej sekcji omówimy niektóre operacje, które można wykonać na listach w Erlang.
Dodanie dwóch list
Metoda append (listfirst, listsecond) służy do tworzenia nowej listy poprzez dodanie dwóch list. Na przykład,
append(list1,list2)
Usuwanie elementu
Metoda delete (element, listname) służy do usunięcia określonego elementu z listy i zwraca nową listę. Na przykład,
delete(5,list1)
Usunięcie ostatniego elementu z listy
Metoda droplast (listname) służy do usuwania ostatniego elementu z listy i zwracania nowej listy. Na przykład,
droplast(list1)
Wyszukiwanie elementu
Metoda member (element, listname) służy do przeszukiwania elementu na liście, jeśli zostanie znaleziona, zwraca true, w przeciwnym razie zwraca false. Na przykład,
member(5,list1)
Uzyskanie wartości maksymalnej i minimalnej
Metody max (nazwa_listy) i min (nazwa_listy) służą do znalezienia wartości maksymalnych i minimalnych na liście. Na przykład,
max(list1)
Sortowanie elementów listy
Metody sort (nazwa_listy) i reverse (nazwa_listy) są używane do sortowania listy w porządku rosnącym lub malejącym. Na przykład,
sort(list1)
Dodawanie elementów listy
Metoda sum (nazwa listy) służy do dodawania wszystkich elementów listy i zwracania ich sumy. Na przykład,
sum(list1)
Posortuj listę rosnąco i malejąco za pomocą języka Java
Poniższy program pokazuje, jak posortować listę w porządku rosnącym i malejącym za pomocą języka Java -
import java.util.*;
import java.lang.*;
import java.io.*;
public class SortList {
public static void main (String[] args) throws java.lang.Exception {
List<String> list1 = new ArrayList<String>();
list1.add("5");
list1.add("3");
list1.add("1");
list1.add("4");
list1.add("2");
System.out.println("list before sorting: " + list1);
Collections.sort(list1);
System.out.println("list in ascending order: " + list1);
Collections.reverse(list1);
System.out.println("list in dsending order: " + list1);
}
}
Wytworzy następujący wynik -
list before sorting : [5, 3, 1, 4, 2]
list in ascending order : [1, 2, 3, 4, 5]
list in dsending order : [5, 4, 3, 2, 1]
Sortuj listę w porządku rosnącym za pomocą Erlang
Poniższy program pokazuje, jak posortować listę w porządku rosnącym i malejącym za pomocą Erlanga, który jest funkcjonalnym językiem programowania -
-module(helloworld).
-import(lists,[sort/1]).
-export([start/0]).
start() ->
List1 = [5,3,4,2,1],
io:fwrite("~p~n",[sort(List1)]),
Wytworzy następujący wynik -
[1,2,3,4,5]
Krotka to złożony typ danych, który ma stałą liczbę terminów. Każdy termin w krotce jest znany jakoelement. Liczba elementów to rozmiar krotki.
Program do definiowania krotki w C #
Poniższy program pokazuje, jak zdefiniować krotkę czterech terminów i wydrukować je przy użyciu języka C #, który jest zorientowanym obiektowo językiem programowania.
using System;
public class Test {
public static void Main() {
var t1 = Tuple.Create(1, 2, 3, new Tuple<int, int>(4, 5));
Console.WriteLine("Tuple:" + t1);
}
}
Wytworzy następujący wynik -
Tuple :(1, 2, 3, (4, 5))
Program do definiowania krotki w Erlang
Poniższy program pokazuje, jak zdefiniować krotkę czterech terminów i wydrukować je za pomocą Erlang, który jest funkcjonalnym językiem programowania.
-module(helloworld).
-export([start/0]).
start() ->
P = {1,2,3,{4,5}} ,
io:fwrite("~w",[P]).
Wytworzy następujący wynik -
{1, 2, 3, {4, 5}}
Zalety Tuple
Krotki mają następujące zalety -
Krotki mają z natury określony rozmiar, tzn. Nie możemy dodawać / usuwać elementów do / z krotki.
Możemy przeszukać dowolny element w krotce.
Krotki są szybsze niż listy, ponieważ mają stały zestaw wartości.
Krotki mogą być używane jako klucze słownikowe, ponieważ zawierają niezmienne wartości, takie jak łańcuchy, liczby itp.
Krotki a listy
Tuple | Lista |
---|---|
Krotki są immutabletj. nie możemy zaktualizować jego danych. | Lista jest mutableczyli możemy aktualizować jego dane. |
Elementy w krotce mogą być różnego typu. | Wszystkie elementy na liście są tego samego typu. |
Krotki są oznaczone okrągłymi nawiasami wokół elementów. | Listy są oznaczone nawiasami kwadratowymi wokół elementów. |
Operacje na krotkach
W tej sekcji omówimy kilka operacji, które można wykonać na krotce.
Sprawdź, czy wstawiona wartość jest krotką, czy nie
Metoda is_tuple(tuplevalues)służy do określenia, czy wstawiona wartość jest krotką, czy nie. Wracatrue gdy wstawiana wartość jest krotką, w przeciwnym razie zwraca false. Na przykład,
-module(helloworld).
-export([start/0]).
start() ->
K = {abc,50,pqr,60,{xyz,75}} , io:fwrite("~w",[is_tuple(K)]).
Wytworzy następujący wynik -
True
Konwersja listy na krotkę
Metoda list_to_tuple(listvalues)konwertuje listę na krotkę. Na przykład,
-module(helloworld).
-export([start/0]).
start() ->
io:fwrite("~w",[list_to_tuple([1,2,3,4,5])]).
Wytworzy następujący wynik -
{1, 2, 3, 4, 5}
Konwersja krotki na listę
Metoda tuple_to_list(tuplevalues)konwertuje określoną krotkę na format listy. Na przykład,
-module(helloworld).
-export([start/0]).
start() ->
io:fwrite("~w",[tuple_to_list({1,2,3,4,5})]).
Wytworzy następujący wynik -
[1, 2, 3, 4, 5]
Sprawdź rozmiar krotki
Metoda tuple_size(tuplename)zwraca rozmiar krotki. Na przykład,
-module(helloworld).
-export([start/0]).
start() ->
K = {abc,50,pqr,60,{xyz,75}} ,
io:fwrite("~w",[tuple_size(K)]).
Wytworzy następujący wynik -
5
Rekord to struktura danych służąca do przechowywania określonej liczby elementów. Jest podobna do struktury w języku C. W momencie kompilacji jego wyrażenia są tłumaczone na wyrażenia krotki.
Jak stworzyć rekord?
Słowo kluczowe „rekord” służy do tworzenia rekordów określonych nazwą rekordu i jego polami. Jego składnia jest następująca -
record(recodname, {field1, field2, . . fieldn})
Składnia wstawiania wartości do rekordu to -
#recordname {fieldName1 = value1, fieldName2 = value2 .. fieldNamen = valuen}
Program do tworzenia rekordów za pomocą Erlang
W poniższym przykładzie utworzyliśmy rekord imienia student posiadające dwa pola, tj. sname i sid.
-module(helloworld).
-export([start/0]).
-record(student, {sname = "", sid}).
start() ->
S = #student{sname = "Sachin",sid = 5}.
Program do tworzenia rekordów w C ++
Poniższy przykład pokazuje, jak tworzyć rekordy przy użyciu C ++, który jest językiem programowania obiektowego -
#include<iostream>
#include<string>
using namespace std;
class student {
public:
string sname;
int sid;
15
};
int main() {
student S;
S.sname = "Sachin";
S.sid = 5;
return 0;
}
Program do uzyskiwania dostępu do wartości rekordów za pomocą Erlang
Poniższy program pokazuje, jak uzyskać dostęp do wartości rekordów za pomocą Erlang, który jest funkcjonalnym językiem programowania -
-module(helloworld).
-export([start/0]).
-record(student, {sname = "", sid}).
start() ->
S = #student{sname = "Sachin",sid = 5},
io:fwrite("~p~n",[S#student.sid]),
io:fwrite("~p~n",[S#student.sname]).
Wytworzy następujący wynik -
5
"Sachin"
Program do uzyskiwania dostępu do wartości rekordów przy użyciu C ++
Poniższy program pokazuje, jak uzyskać dostęp do wartości rekordów za pomocą C ++ -
#include<iostream>
#include<string>
using namespace std;
class student {
public:
string sname;
int sid;
};
int main() {
student S;
S.sname = "Sachin";
S.sid = 5;
cout<<S.sid<<"\n"<<S.sname;
return 0;
}
Wytworzy następujący wynik -
5
Sachin
Wartości rekordów można zaktualizować, zmieniając wartość w określonym polu, a następnie przypisując ten rekord do nowej nazwy zmiennej. Przyjrzyj się dwóm poniższym przykładom, aby zrozumieć, jak to się robi za pomocą języków programowania obiektowego i funkcjonalnego.
Program do aktualizacji wartości rekordów za pomocą Erlang
Poniższy program pokazuje, jak zaktualizować wartości rekordów za pomocą Erlang -
-module(helloworld).
-export([start/0]).
-record(student, {sname = "", sid}).
start() ->
S = #student{sname = "Sachin",sid = 5},
S1 = S#student{sname = "Jonny"},
io:fwrite("~p~n",[S1#student.sid]),
io:fwrite("~p~n",[S1#student.sname]).
Wytworzy następujący wynik -
5
"Jonny"
Program do aktualizacji wartości rekordów za pomocą C ++
Poniższy program pokazuje, jak zaktualizować wartości rekordów za pomocą C ++ -
#include<iostream>
#include<string>
using namespace std;
class student {
public:
string sname;
int sid;
};
int main() {
student S;
S.sname = "Jonny";
S.sid = 5;
cout<<S.sname<<"\n"<<S.sid;
cout<<"\n"<< "value after updating"<<"\n";
S.sid = 10;
cout<<S.sname<<"\n"<<S.sid;
return 0;
}
Wytworzy następujący wynik -
Jonny
5
value after updating
Jonny
10
Rachunek lambda to struktura opracowana przez Alonzo Churcha w latach trzydziestych XX wieku w celu badania obliczeń z funkcjami.
Function creation - Kościół wprowadził notację λx.Edo oznaczenia funkcji, w której „x” jest argumentem formalnym, a „E” jest ciałem funkcjonalnym. Te funkcje mogą być bez nazw i pojedynczych argumentów.
Function application - Kościół użył notacji E1.E2 na oznaczenie zastosowania funkcji E1 do rzeczywistego argumentu E2. Wszystkie funkcje są na jednym argumencie.
Składnia rachunku Lambda
Rachunek Lamdby obejmuje trzy różne typy wyrażeń, tj.
E :: = x (zmienne)
| E 1 E 2 (zastosowanie funkcji)
| λx.E (tworzenie funkcji)
Gdzie λx.E nazywa się abstrakcją Lambda, a E jest znane jako wyrażenia λ.
Obliczanie rachunku lambda
Czysty rachunek lambda nie ma wbudowanych funkcji. Przeanalizujmy następujące wyrażenie -
(+ (* 5 6) (* 8 3))
Tutaj nie możemy zacząć od „+”, ponieważ operuje tylko na liczbach. Istnieją dwa redukowalne wyrażenia: (* 5 6) i (* 8 3).
Najpierw możemy zredukować jeden z nich. Na przykład -
(+ (* 5 6) (* 8 3))
(+ 30 (* 8 3))
(+ 30 24)
= 54
Reguła β-redukcji
Potrzebujemy reguły redukcji do obsługi λ
(λx . * 2 x) 4
(* 2 4)
= 8
Nazywa się to β-redukcją.
Parametr formalny może być używany wielokrotnie -
(λx . + x x) 4
(+ 4 4)
= 8
W przypadku wielu terminów możemy obsługiwać je w następujący sposób -
(λx . (λx . + (− x 1)) x 3) 9
Wewnętrzny x należy do wewnętrznego λ a zewnętrzne x należy do zewnętrznego.
(λx . + (− x 1)) 9 3
+ (− 9 1) 3
+ 8 3
= 11
Zmienne wolne i związane
W wyrażeniu każde pojawienie się zmiennej jest „wolne” (do λ) lub „związane” (do λ).
β-redukcja (λx . E) y zastępuje każdy x który występuje za darmo w E z y. Na przykład -
Redukcja alfa
Redukcja alfa jest bardzo prosta i można ją przeprowadzić bez zmiany znaczenia wyrażenia lambda.
λx . (λx . x) (+ 1 x) ↔ α λx . (λy . y) (+ 1 x)
Na przykład -
(λx . (λx . + (− x 1)) x 3) 9
(λx . (λy . + (− y 1)) x 3) 9
(λy . + (− y 1)) 9 3
+ (− 9 1) 3
+ 8 3
11
Twierdzenie Churcha-Rossera
Twierdzenie Churcha-Rossera stwierdza, co następuje -
Jeśli E1 ↔ E2, to istnieje E takie, że E1 → E i E2 → E. „Redukcja w jakikolwiek sposób może ostatecznie przynieść ten sam wynik”.
Jeśli E1 → E2 i E2 jest postacią normalną, to istnieje redukcja E1 do E2 w porządku normalnym. „Redukcja porządku normalnego zawsze da normalną formę, jeśli taka istnieje”.
Leniwa ocena to strategia oceny, która przechowuje ocenę wyrażenia do momentu, gdy będzie potrzebna jego wartość. Pozwala uniknąć wielokrotnej oceny.Haskell jest dobrym przykładem takiego funkcjonalnego języka programowania, którego podstawy są oparte na Lazy Evaluation.
Leniwe ocenianie jest używane w funkcjach map systemu Unix w celu poprawy ich wydajności przez ładowanie tylko wymaganych stron z dysku. Żadna pamięć nie zostanie przydzielona dla pozostałych stron.
Leniwa ocena - zalety
Umożliwia środowisku wykonawczemu języka odrzucanie wyrażeń podrzędnych, które nie są bezpośrednio powiązane z końcowym wynikiem wyrażenia.
Zmniejsza złożoność czasową algorytmu poprzez odrzucenie tymczasowych obliczeń i warunków.
Pozwala programiście na dostęp do nieuporządkowanych komponentów struktur danych po ich zainicjowaniu, o ile są one wolne od jakichkolwiek zależności cyklicznych.
Najlepiej nadaje się do ładowania danych, które będą rzadko używane.
Leniwa ocena - wady
Wymusza na środowisku wykonawczym języka wstrzymanie oceny wyrażeń podrzędnych, dopóki nie będzie to wymagane w wyniku końcowym przez utworzenie thunks (obiekty opóźnione).
Czasami zwiększa złożoność przestrzenną algorytmu.
Bardzo trudno jest znaleźć jego wykonanie, ponieważ zawiera bzdury wyrażeń przed ich wykonaniem.
Leniwa ocena przy użyciu języka Python
Plik rangemetoda w Pythonie jest zgodna z koncepcją Lazy Evaluation. Oszczędza czas wykonywania dla większych zakresów i nigdy nie wymagamy wszystkich wartości naraz, więc oszczędza również zużycie pamięci. Spójrz na poniższy przykład.
r = range(10)
print(r)
range(0, 10)
print(r[3])
Wytworzy następujący wynik -
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3
Potrzebujemy plików do przechowywania danych wyjściowych programu po jego zakończeniu. Korzystając z plików, możemy uzyskać dostęp do powiązanych informacji za pomocą różnych poleceń w różnych językach.
Oto lista niektórych operacji, które można wykonać na pliku -
- Tworzenie nowego pliku
- Otwieranie istniejącego pliku
- Czytanie zawartości pliku
- Wyszukiwanie danych w pliku
- Zapisywanie do nowego pliku
- Aktualizacja zawartości do istniejącego pliku
- Usuwanie pliku
- Zamknięcie pliku
Zapisywanie do pliku
Aby zapisać zawartość do pliku, musimy najpierw otworzyć wymagany plik. Jeśli określony plik nie istnieje, zostanie utworzony nowy plik.
Zobaczmy, jak zapisać zawartość do pliku za pomocą C ++.
Przykład
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("Tempfile.txt", ios::out);
myfile << "Writing Contents to file.\n";
cout << "Data inserted into file";
myfile.close();
return 0;
}
Note -
fstream jest klasą strumienia używaną do sterowania operacjami odczytu / zapisu plików.
ofstream jest klasą strumienia używaną do zapisywania zawartości do pliku.
Zobaczmy, jak zapisać zawartość do pliku za pomocą Erlang, który jest funkcjonalnym językiem programowania.
-module(helloworld).
-export([start/0]).
start() ->
{ok, File1} = file:open("Tempfile.txt", [write]),
file:write(File1,"Writting contents to file"),
io:fwrite("Data inserted into file\n").
Note -
Aby otworzyć plik, którego musimy użyć, open(filename,mode).
Składnia zapisu zawartości do pliku: write(filemode,file_content).
Output - Kiedy uruchomimy ten kod, do pliku zostanie zapisane „Zapisywanie zawartości do pliku” Tempfile.txt. Jeśli plik ma jakąkolwiek istniejącą zawartość, zostanie nadpisany.
Czytanie z pliku
Aby odczytać z pliku, najpierw musimy otworzyć określony plik w reading mode. Jeśli plik nie istnieje, odpowiednia metoda zwraca wartość NULL.
Poniższy program pokazuje, jak odczytać zawartość pliku w formacie C++ -
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string readfile;
ifstream myfile ("Tempfile.txt",ios::in);
if (myfile.is_open()) {
while ( getline (myfile,readfile) ) {
cout << readfile << '\n';
}
myfile.close();
} else
cout << "file doesn't exist";
return 0;
}
Wytworzy następujący wynik -
Writing contents to file
Note- W tym programie otworzyliśmy plik tekstowy w trybie odczytu za pomocą „ios :: in”, a następnie wydrukowaliśmy jego zawartość na ekranie. Użyliśmywhile pętla, aby odczytać zawartość pliku wiersz po wierszu przy użyciu metody „getline”.
Poniższy program pokazuje, jak wykonać tę samą operację przy użyciu Erlang. Tutaj użyjemyread_file(filename) metoda, aby odczytać całą zawartość z określonego pliku.
-module(helloworld).
-export([start/0]).
start() ->
rdfile = file:read_file("Tempfile.txt"),
io:fwrite("~p~n",[rdfile]).
Wytworzy następujący wynik -
ok, Writing contents to file
Usuń istniejący plik
Możemy usunąć istniejący plik za pomocą operacji na plikach. Poniższy program pokazuje, jak usunąć istniejący plikusing C++ -
#include <stdio.h>
int main () {
if(remove( "Tempfile.txt" ) != 0 )
perror( "File doesn’t exist, can’t delete" );
else
puts( "file deleted successfully " );
return 0;
}
Wytworzy następujący wynik -
file deleted successfully
Poniższy program pokazuje, jak można wykonać tę samą operację w programie Erlang. Tutaj użyjemy metodydelete(filename) aby usunąć istniejący plik.
-module(helloworld).
-export([start/0]).
start() ->
file:delete("Tempfile.txt").
Output - Jeśli plik „Tempfile.txt” istnieje, zostanie usunięty.
Określanie rozmiaru pliku
Poniższy program pokazuje, jak określić rozmiar pliku za pomocą języka C ++. Tutaj funkcjafseek ustawia wskaźnik pozycji powiązany ze strumieniem na nową pozycję, natomiast ftell zwraca bieżącą pozycję w strumieniu.
#include <stdio.h>
int main () {
FILE * checkfile;
long size;
checkfile = fopen ("Tempfile.txt","rb");
if (checkfile == NULL)
perror ("file can’t open");
else {
fseek (checkfile, 0, SEEK_END); // non-portable
size = ftell (checkfile);
fclose (checkfile);
printf ("Size of Tempfile.txt: %ld bytes.\n",size);
}
return 0;
}
Output - Jeśli plik „Tempfile.txt” istnieje, to pokaże swój rozmiar w bajtach.
Poniższy program pokazuje, jak wykonać tę samą operację w Erlang. Tutaj użyjemy metodyfile_size(filename) aby określić rozmiar pliku.
-module(helloworld).
-export([start/0]).
start() ->
io:fwrite("~w~n",[filelib:file_size("Tempfile.txt")]).
Output- Jeśli plik „Tempfile.txt” istnieje, to pokaże swój rozmiar w bajtach. W przeciwnym razie wyświetli „0”.