Programação funcional - Guia rápido

Linguagens de programação funcional são especialmente projetadas para lidar com aplicativos de computação simbólica e processamento de listas. A programação funcional é baseada em funções matemáticas. Algumas das linguagens de programação funcional populares incluem: Lisp, Python, Erlang, Haskell, Clojure, etc.

Linguagens de programação funcional são categorizadas em dois grupos, ou seja -

  • Pure Functional Languages- Esses tipos de linguagens funcionais suportam apenas os paradigmas funcionais. Por exemplo - Haskell.

  • Impure Functional Languages- Esses tipos de linguagens funcionais suportam os paradigmas funcionais e a programação de estilo imperativo. Por exemplo - LISP.

Programação Funcional - Características

As características mais proeminentes da programação funcional são as seguintes -

  • Linguagens de programação funcional são projetadas no conceito de funções matemáticas que usam expressões condicionais e recursão para realizar cálculos.

  • Suporta programação funcional higher-order functions e lazy evaluation características.

  • Linguagens de programação funcional não oferecem suporte a controles de fluxo como instruções de loop e instruções condicionais como If-Else e Switch Statements. Eles usam diretamente as funções e chamadas funcionais.

  • Como OOP, as linguagens de programação funcional oferecem suporte a conceitos populares como Abstração, Encapsulamento, Herança e Polimorfismo.

Programação Funcional - Vantagens

A programação funcional oferece as seguintes vantagens -

  • Bugs-Free Code - A programação funcional não suporta state, portanto, não há resultados de efeitos colaterais e podemos escrever códigos sem erros.

  • Efficient Parallel Programming- Linguagens de programação funcional NÃO têm estado mutável, portanto, não há problemas de mudança de estado. Pode-se programar "Funções" para funcionar paralelamente como "instruções". Esses códigos oferecem fácil reutilização e testabilidade.

  • Efficiency- Os programas funcionais consistem em unidades independentes que podem ser executadas simultaneamente. Como resultado, esses programas são mais eficientes.

  • Supports Nested Functions - A programação funcional oferece suporte a funções aninhadas.

  • Lazy Evaluation - A programação funcional oferece suporte a construções funcionais preguiçosas, como listas preguiçosas, mapas preguiçosos, etc.

Como desvantagem, a programação funcional requer um grande espaço de memória. Como não tem estado, você precisa criar novos objetos a cada vez para realizar ações.

A Programação Funcional é usada em situações em que temos que realizar muitas operações diferentes no mesmo conjunto de dados.

  • Lisp é usado para aplicativos de inteligência artificial, como aprendizado de máquina, processamento de linguagem, modelagem de fala e visão, etc.

  • Os interpretadores Lisp incorporados adicionam programabilidade a alguns sistemas como o Emacs.

Programação Funcional vs. Programação Orientada a Objetos

A tabela a seguir destaca as principais diferenças entre a programação funcional e a programação orientada a objetos -

Programação Funcional OOP
Usa dados imutáveis. Usa dados mutáveis.
Segue o modelo de programação declarativo. Segue o modelo de programação imperativa.
O foco está em: “O que você está fazendo” O foco está em "Como você está indo"
Suporta Programação Paralela Não é adequado para programação paralela
Suas funções não têm efeitos colaterais Seus métodos podem produzir efeitos colaterais graves.
O controle de fluxo é feito usando chamadas de função e chamadas de função com recursão O controle de fluxo é feito usando loops e instruções condicionais.
Ele usa o conceito de "Recursão" para iterar os Dados de Coleta. Ele usa o conceito de "Loop" para iterar os Dados de Coleta. Por exemplo: For-each loop in Java
A ordem de execução das instruções não é tão importante. A ordem de execução das instruções é muito importante.
Suporta "Abstração sobre Dados" e "Abstração sobre Comportamento". Suporta apenas "Abstração sobre Dados".

Eficiência de um Código de Programa

A eficiência de um código de programação é diretamente proporcional à eficiência do algoritmo e à velocidade de execução. Boa eficiência garante maior desempenho.

Os fatores que afetam a eficiência de um programa incluem:

  • A velocidade da máquina
  • Velocidade do compilador
  • Sistema operacional
  • Escolhendo a linguagem de programação certa
  • A forma como os dados em um programa são organizados
  • Algoritmo usado para resolver o problema

A eficiência de uma linguagem de programação pode ser melhorada executando as seguintes tarefas -

  • Removendo o código desnecessário ou o código que vai para o processamento redundante.

  • Fazendo uso de memória ideal e armazenamento não volátil

  • Fazendo o uso de componentes reutilizáveis ​​sempre que aplicável.

  • Fazendo o uso do tratamento de erros e exceções em todas as camadas do programa.

  • Criando um código de programação que garante a integridade e consistência dos dados.

  • Desenvolvendo o código do programa compatível com a lógica e o fluxo do design.

Um código de programação eficiente pode reduzir o consumo de recursos e o tempo de conclusão tanto quanto possível, com risco mínimo para o ambiente operacional.

Em termos de programação, um functioné um bloco de instruções que executa uma tarefa específica. As funções aceitam dados, os processam e retornam um resultado. As funções são escritas principalmente para oferecer suporte ao conceito de reutilização. Depois que uma função é escrita, ela pode ser chamada facilmente, sem a necessidade de escrever o mesmo código repetidamente.

Diferentes linguagens funcionais usam diferentes sintaxes para escrever uma função.

Pré-requisitos para escrever uma função

Antes de escrever uma função, um programador deve saber os seguintes pontos -

  • O objetivo da função deve ser conhecido pelo programador.

  • O algoritmo da função deve ser conhecido do programador.

  • Variáveis ​​de dados de funções e seu objetivo devem ser conhecidos pelo programador.

  • Os dados da função devem ser conhecidos pelo programador que é chamado pelo usuário.

Controle de fluxo de uma função

Quando uma função é "chamada", o programa "transfere" o controle para executar a função e seu "fluxo de controle" é o seguinte -

  • O programa chega à instrução que contém uma "chamada de função".

  • A primeira linha dentro da função é executada.

  • Todas as instruções dentro da função são executadas de cima para baixo.

  • Quando a função é executada com sucesso, o controle volta para a instrução de onde começou.

  • Todos os dados calculados e retornados pela função são usados ​​no lugar da função na linha de código original.

Sintaxe de uma função

A sintaxe geral de uma função é a seguinte -

returnType functionName(type1 argument1, type2 argument2, . . . ) {     
   // function body 
}

Definindo uma função em C ++

Vamos dar um exemplo para entender como uma função pode ser definida em C ++, que é uma linguagem de programação orientada a objetos. O código a seguir tem uma função que adiciona dois números e fornece seu resultado como saída.

#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 
}

Ele produzirá a seguinte saída -

Sum = 11

Definindo uma função em Erlang

Vamos ver como a mesma função pode ser definida em Erlang, que é uma linguagem de programação funcional.

-module(helloworld).  
-export([add/2,start/0]).   

add(A,B) ->
   C = A + B,  
   io:fwrite("~w~n",[C]).  
start() ->  
   add(5,6).

Ele produzirá a seguinte saída -

11

Protótipo de Função

Um protótipo de função é uma declaração da função que inclui tipo de retorno, nome da função e lista de argumentos. É semelhante à definição de função sem corpo de função.

For Example - Algumas linguagens de programação suportam prototipagem de função e outras não.

Em C ++, podemos fazer o protótipo da função 'sum' assim -

int sum(int a, int b)

Note - Linguagens de programação como Python, Erlang, etc não suportam prototipagem de função, precisamos declarar a função completa.

Qual é o uso do protótipo de função?

O protótipo da função é usado pelo compilador quando a função é chamada. O compilador usa-o para garantir o tipo de retorno correto, a lista de argumentos adequada é passada e seu tipo de retorno está correto.

Assinatura de Função

Uma assinatura de função é semelhante ao protótipo de função em que o número de parâmetros, o tipo de dados dos parâmetros e a ordem de aparecimento devem estar em ordem semelhante. Por exemplo -

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

Function1 e Function2 têm assinaturas diferentes. Function2 e Function3 têm as mesmas assinaturas.

Note - A sobrecarga de função e a substituição de função, que discutiremos nos capítulos subsequentes, são baseadas no conceito de assinaturas de função.

  • A sobrecarga de função é possível quando uma classe tem várias funções com o mesmo nome, mas assinaturas diferentes.

  • A substituição de função é possível quando uma função de classe derivada tem o mesmo nome e assinatura de sua classe base.

As funções são de dois tipos -

  • Funções predefinidas
  • Funções definidas pelo usuário

Neste capítulo, discutiremos em detalhes sobre as funções.

Funções Predefinidas

Estas são as funções incorporadas ao Language para realizar operações e são armazenadas na Biblioteca de Funções Padrão.

For Example - 'Strcat' em C ++ e 'concat' em Haskell são usados ​​para anexar as duas strings, 'strlen' em C ++ e 'len' em Python são usados ​​para calcular o comprimento da string.

Programa para imprimir o comprimento da string em C ++

O programa a seguir mostra como você pode imprimir o comprimento de uma string usando 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; 
}

Ele produzirá a seguinte saída -

String length is: 11

Programa para imprimir o comprimento da string em Python

O programa a seguir mostra como imprimir o comprimento de uma string usando Python, que é uma linguagem de programação funcional -

str = "Hello World"; 
print("String length is: ", len(str))

Ele produzirá a seguinte saída -

('String length is: ', 11)

Funções definidas pelo usuário

As funções definidas pelo usuário são definidas pelo usuário para executar tarefas específicas. Existem quatro padrões diferentes para definir uma função -

  • Funções sem argumento e sem valor de retorno
  • Funções sem argumento, mas um valor de retorno
  • Funções com argumento, mas sem valor de retorno
  • Funções com argumento e um valor de retorno

Funções sem argumento e sem valor de retorno

O programa a seguir mostra como definir uma função sem argumento e sem valor de retorno em C++ -

#include <iostream> 
using namespace std; 

void function1() { 
   cout <<"Hello World"; 
}  
int main() { 
   function1(); 
   return 0; 
}

Ele produzirá a seguinte saída -

Hello World

O programa a seguir mostra como você pode definir uma função semelhante (sem argumento e sem valor de retorno) em Python -

def function1():    
   print ("Hello World") 
    
function1()

Ele produzirá a seguinte saída -

Hello World

Funções sem argumento, mas um valor de retorno

O programa a seguir mostra como definir uma função sem nenhum argumento, mas um valor de retorno em C++ -

#include <iostream> 
using namespace std; 
string function1() { 
   return("Hello World"); 
}  

int main() { 
   cout<<function1(); 
   return 0; 
}

Ele produzirá a seguinte saída -

Hello World

O programa a seguir mostra como você pode definir uma função semelhante (sem nenhum argumento, mas um valor de retorno) em Python -

def function1(): 
   return "Hello World" 
res = function1() 
print(res)

Ele produzirá a seguinte saída -

Hello World

Funções com argumento, mas sem valor de retorno

O programa a seguir mostra como definir uma função com argumento, mas sem valor de retorno em 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; 
}

Ele produzirá a seguinte saída -

Sum is: 9

O programa a seguir mostra como você pode definir uma função semelhante em Python -

def function1(x,y): 
   c = x + y 
   print("Sum is:",c) 
function1(4,5)

Ele produzirá a seguinte saída -

('Sum is:', 9)

Funções com argumento e um valor de retorno

O programa a seguir mostra como definir uma função em C ++ sem nenhum argumento, mas um valor de retorno -

#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; 
}

Ele produzirá a seguinte saída -

Sum is: 9

O programa a seguir mostra como definir uma função semelhante (com argumento e um valor de retorno) em Python -

def function1(x,y): 
   c = x + y 
   return c  

res = function1(4,5) 
print("Sum is ",res)

Ele produzirá a seguinte saída -

('Sum is ', 9)

Depois de definir uma função, precisamos passar argumentos para ela para obter a saída desejada. A maioria das linguagens de programação suportacall by value e call by reference métodos para passar argumentos para funções.

Neste capítulo, aprenderemos que "chamada por valor" funciona em uma linguagem de programação orientada a objetos como C ++ e em uma linguagem de programação funcional como Python.

No método Call by Value, o original value cannot be changed. Quando passamos um argumento para uma função, ele é armazenado localmente pelo parâmetro da função na memória da pilha. Portanto, os valores são alterados apenas dentro da função e não terão efeito fora da função.

Chamada por valor em C ++

O programa a seguir mostra como Call by Value funciona em 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;   
}

Ele produzirá a seguinte saída -

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

Chamada por valor em Python

O programa a seguir mostra como Call by Value funciona em Python -

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

Ele produzirá a seguinte saída -

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

Na chamada por referência, o original value is changedporque passamos o endereço de referência dos argumentos. Os argumentos reais e formais compartilham o mesmo espaço de endereço, portanto, qualquer alteração de valor dentro da função é refletida tanto dentro quanto fora da função.

Chamada por referência em C ++

O programa a seguir mostra como Call by Value funciona em 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;   
}

Ele produzirá a seguinte saída -

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

Chamada por referência em Python

O programa a seguir mostra como Call by Value funciona em Python -

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]

Ele produzirá a seguinte saída -

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

Quando temos várias funções com o mesmo nome, mas parâmetros diferentes, é dito que elas estão sobrecarregadas. Essa técnica é usada para melhorar a legibilidade do programa.

Existem duas maneiras de sobrecarregar uma função, ou seja -

  • Tendo um número diferente de argumentos
  • Tendo diferentes tipos de argumento

A sobrecarga de função normalmente é feita quando temos que realizar uma única operação com diferentes números ou tipos de argumentos.

Sobrecarga de função em C ++

O exemplo a seguir mostra como a sobrecarga de função é feita em C ++, que é uma linguagem de programação orientada a objetos -

#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; 
}

Ele produzirá a seguinte saída -

Integer number: 10 
Float number: 15

Sobrecarga de função em Erlang

O exemplo a seguir mostra como executar a sobrecarga de função em Erlang, que é uma linguagem de programação funcional -

-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).

Ele produzirá a seguinte saída -

10 
15

Quando a classe base e a classe derivada têm funções de membro com exatamente o mesmo nome, mesmo tipo de retorno e mesma lista de argumentos, então se diz que está substituindo a função.

Substituição de função usando C ++

O exemplo a seguir mostra como a substituição de função é feita em C ++, que é uma linguagem de programação orientada a objeto -

#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;  
}

Ele irá produzir a seguinte saída

Derived Class

Substituição de função usando Python

O exemplo a seguir mostra como realizar a substituição de funções em Python, que é uma linguagem de programação funcional -

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()

Ele produzirá a seguinte saída -

Base Class 
Derived Class

Uma função que chama a si mesma é conhecida como função recursiva e esta técnica é conhecida como recursão. Uma instrução de recursão continua até que outra instrução a impeça.

Recursão em C ++

O exemplo a seguir mostra como a recursão funciona em C ++, que é uma linguagem de programação orientada a objetos -

#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; 
}

Ele irá produzir a seguinte saída

Enter a positive integer: 5 
Factorial of 5 = 120

Recursão em Python

O exemplo a seguir mostra como funciona a recursão em Python, que é uma linguagem de programação funcional -

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)))

Ele produzirá a seguinte saída -

Enter a number: 6
The factorial of 6 is 720

Uma função de ordem superior (HOF) é uma função que segue pelo menos uma das seguintes condições -

  • Assume ou mais funções como argumento
  • Retorna uma função como resultado

HOF em PHP

O exemplo a seguir mostra como escrever uma função de ordem superior em PHP, que é uma linguagem de programação orientada a objetos -

<?php  
$twice = function($f, $v) { return $f($f($v)); 
};  

$f = function($v) { 
   return $v + 3; }; echo($twice($f, 7));

Ele produzirá a seguinte saída -

13

HOF em Python

O exemplo a seguir mostra como escrever uma função de ordem superior em Python, que é uma linguagem de programação orientada a objetos -

def twice(function): 
   return lambda x: function(function(x))  
def f(x): 
   return x + 3 
g = twice(f)
print g(7)

Ele produzirá a seguinte saída -

13

Um tipo de dados define o tipo de valor que um objeto pode ter e quais operações podem ser executadas nele. Um tipo de dados deve ser declarado antes de ser usado. Diferentes linguagens de programação oferecem suporte a diferentes tipos de dados. Por exemplo,

  • C suporta char, int, float, long, etc.
  • Python suporta string, lista, tupla, etc.

Em um sentido amplo, existem três tipos de tipos de dados -

  • Fundamental data types- Estes são os tipos de dados predefinidos que são usados ​​pelo programador diretamente para armazenar apenas um valor conforme o requisito, ou seja, tipo inteiro, tipo de caractere ou tipo flutuante. Por exemplo - int, char, float, etc.

  • Derived data types- Esses tipos de dados são derivados usando tipos de dados embutidos que são projetados pelo programador para armazenar vários valores do mesmo tipo de acordo com seus requisitos. Por exemplo - Array, Pointer, function, list, etc.

  • User-defined data types- Esses tipos de dados são derivados usando tipos de dados integrados que são agrupados em um único tipo de dados para armazenar vários valores do mesmo tipo ou de tipo diferente, ou ambos, conforme o requisito. Por exemplo - Classe, Estrutura, etc.

Tipos de dados suportados por C ++

A tabela a seguir lista os tipos de dados suportados por C ++ -

Tipo de dados Tamanho Alcance
Caracteres 1 byte -128 a 127 ou 0 a 255
caracter não identifcado 1 byte 0 a 255
char assinado 1 byte -128 a 127
int 4 bytes -2147483648 a 2147483647
int não assinado 4 bytes 0 a 4294967295
int assinado 4 bytes -2147483648 a 2147483647
curto int 2 bytes -32768 a 32767
int curto sem sinal 2 bytes 0 a 65.535
int curto assinado 2 bytes -32768 a 32767
longo int 4 bytes -2.147.483.648 a 2.147.483.647
assinado longo int 4 bytes -2.147.483.648 a 2.147.483.647
int longo sem sinal 4 bytes 0 a 4.294.967.295
flutuador 4 bytes +/- 3,4e +/- 38 (~ 7 dígitos)
em dobro 8 bytes +/- 1,7e +/- 308 (~ 15 dígitos)
longo duplo 8 bytes +/- 1,7e +/- 308 (~ 15 dígitos)

Tipos de dados suportados por Java

Os seguintes tipos de dados são suportados por Java -

Tipo de dados Tamanho Alcance
byte 1 byte -128 a 127
Caracteres 2 bytes 0 a 65.536
baixo 2 bytes -32.7688 a 32.767
int 4 bytes -2.147.483.648 a 2.147.483.647
grandes 8 bytes -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807
flutuador 4 bytes -2147483648 a 2147483647
em dobro 8 bytes + 9,223 * 1018
boleano 1 bit Verdadeiro ou falso

Tipos de dados suportados por Erlang

Nesta seção, discutiremos os tipos de dados suportados por Erlang, que é uma linguagem de programação funcional.

Número

Erlang suporta dois tipos de literais numéricos, ou seja, integer e float. Dê uma olhada no exemplo a seguir que mostra como adicionar dois valores inteiros -

-module(helloworld).
-export([start/0]). 
start() -> 
   io:fwrite("~w",[5+4]).

Ele produzirá a seguinte saída -

9

Átomo

A atomé uma string cujo valor não pode ser alterado. Deve começar com uma letra minúscula e pode conter quaisquer caracteres alfanuméricos e especiais. Quando um átomo contém caracteres especiais, ele deve ser colocado entre aspas simples ('). Dê uma olhada no exemplo a seguir para entender melhor.

-module(helloworld). 
-export([start/0]). 

start()-> 
   io:fwrite(monday).

Ele produzirá a seguinte saída -

monday

Note- Tente mudar o átomo para "segunda-feira" com "M" maiúsculo. O programa produzirá um erro.

boleano

Este tipo de dados é usado para exibir o resultado como true ou false. Dê uma olhada no exemplo a seguir. Mostra como comparar dois inteiros.

-module(helloworld). 
-export([start/0]). 

start() -> 
   io:fwrite(5 =< 9).

Ele produzirá a seguinte saída -

true

String de bits

Uma string de bits é usada para armazenar uma área de memória não digitada. Dê uma olhada no exemplo a seguir. Mostra como converter 2 bits de uma string de bits em uma lista.

-module(helloworld). 
-export([start/0]). 

start() -> 
   Bin2 = <<15,25>>, 
   P = binary_to_list(Bin2), 
   io:fwrite("~w",[P]).

Ele produzirá a seguinte saída -

[15,25]

Tupla

Uma tupla é um tipo de dados composto com um número fixo de termos. Cada termo de uma tupla é conhecido como umelement. O número de elementos é o tamanho da tupla. O exemplo a seguir mostra como definir uma tupla de 5 termos e imprime seu tamanho.

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} ,  
   io:fwrite("~w",[tuple_size(K)]).

Ele produzirá a seguinte saída -

5

Mapa

Um mapa é um tipo de dados composto com um número variável de associações de valores-chave. Cada associação de valor-chave no mapa é conhecida como umassociation-pair. okey e value partes do par são chamadas elements. O número de pares de associação é considerado o tamanho do mapa. O exemplo a seguir mostra como definir um mapa de 3 mapeamentos e imprimir seu tamanho.

-module(helloworld).  
-export([start/0]).  
 
start() ->  
   Map1 = #{name => 'abc',age => 40, gender => 'M'},  
   io:fwrite("~w",[map_size(Map1)]).

Ele produzirá a seguinte saída -

3

Lista

Uma lista é um tipo de dados composto com um número variável de termos. Cada termo da lista é chamado de elemento. Diz-se que o número de elementos é o comprimento da lista. O exemplo a seguir mostra como definir uma lista de 5 itens e imprimir seu tamanho.

-module(helloworld).  
-export([start/0]).  

start() ->  
   List1 = [10,15,20,25,30] ,  
   io:fwrite("~w",[length(List1)]).

Ele produzirá a seguinte saída -

5

Note - O tipo de dados 'String' não é definido em Erlang.

Polimorfismo, em termos de programação, significa reutilizar um único código várias vezes. Mais especificamente, é a capacidade de um programa de processar objetos de maneira diferente, dependendo de seu tipo ou classe de dados.

O polimorfismo é de dois tipos -

  • Compile-time Polymorphism - Este tipo de polimorfismo pode ser obtido usando a sobrecarga do método.

  • Run-time Polymorphism - Este tipo de polimorfismo pode ser obtido usando a substituição de métodos e funções virtuais.

Vantagens do polimorfismo

O polimorfismo oferece as seguintes vantagens -

  • Ajuda o programador a reutilizar os códigos, ou seja, as classes, uma vez escritas, testadas e implementadas, podem ser reutilizadas conforme necessário. Economiza muito tempo.

  • Uma única variável pode ser usada para armazenar vários tipos de dados.

  • Fácil de depurar os códigos.

Tipos de dados polimórficos

Os tipos de dados polimórficos podem ser implementados usando ponteiros genéricos que armazenam apenas um endereço de byte, sem o tipo de dados armazenado naquele endereço de memória. Por exemplo,

function1(void *p, void *q)

Onde p e q são indicadores genéricos que podem conter int, float (ou qualquer outro) valor como um argumento.

Função polimórfica em C ++

O programa a seguir mostra como usar funções polimórficas em C ++, que é uma linguagem de programação orientada a objetos.

#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; 
}

Ele produzirá a seguinte saída -

A class method is called 
B class method is called

Função polimórfica em Python

O programa a seguir mostra como usar funções polimórficas em Python, que é uma linguagem de programação funcional.

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)

Ele produzirá a seguinte saída -

A class method is called 
B class method is called

UMA stringé um grupo de personagens incluindo espaços. Podemos dizer que é uma matriz unidimensional de caracteres que termina com um caractere NULL ('\ 0'). Uma string também pode ser considerada uma classe predefinida que é suportada pela maioria das linguagens de programação, como C, C ++, Java, PHP, Erlang, Haskell, Lisp, etc.

A imagem a seguir mostra como a string "Tutorial" ficará na memória.

Crie uma string em C ++

O programa a seguir é um exemplo que mostra como criar uma string em C ++, que é uma linguagem de programação orientada a objetos.

#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; 
}

Ele produzirá a seguinte saída -

Today is: Holiday

String em Erlang

O programa a seguir é um exemplo que mostra como criar uma string em Erlang, que é uma linguagem de programação funcional.

-module(helloworld).  
-export([start/0]).   
start() -> 
   Str = "Today is: Holiday",  
   io:fwrite("~p~n",[Str]).

Ele produzirá a seguinte saída -

"Today is: Holiday"

Operações de string em C ++

Diferentes linguagens de programação oferecem suporte a diferentes métodos em strings. A tabela a seguir mostra alguns métodos de string predefinidos suportados pelo C ++.

S.No. Método e Descrição
1

Strcpy(s1,s2)

Ele copia a string s2 para a string s1

2

Strcat(s1,s2)

Ele adiciona a string s2 no final de s1

3

Strlen(s1)

Ele fornece o comprimento da string s1

4

Strcmp(s1,s2)

Ele retorna 0 quando as strings s1 e s2 são iguais

5

Strchr(s1,ch)

Ele retorna um ponteiro para a primeira ocorrência do caractere ch na string s1

6

Strstr(s1,s2)

Ele retorna um ponteiro para a primeira ocorrência da string s2 na string s1

O programa a seguir mostra como os métodos acima podem ser usados ​​em 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; 
}

Ele produzirá a seguinte saída -

strcpy(str3, str1)   :  Today is 
strcat(str1, str2)   :  Today is Monday 
strlen(str1)         :  15

Operações de cordas em Erlang

A tabela a seguir mostra uma lista de métodos de string predefinidos com suporte por Erlang.

S.No. Método e Descrição
1

len(s1)

Retorna o número de caracteres na string fornecida.

2

equal(s1,s2)

Retorna verdadeiro quando a string s1 e s2 são iguais, caso contrário, retorna falso

3

concat(s1,s2)

Ele adiciona a string s2 no final da string s1

4

str(s1,ch)

Ele retorna a posição do índice do caractere ch na string s1

5

str (s1,s2)

Ele retorna a posição do índice de s2 na string s1

6

substr(s1,s2,num)

Este método retorna a string s2 da string s1 com base na posição inicial e no número de caracteres da posição inicial

7

to_lower(s1)

Este método retorna string em minúsculas

O programa a seguir mostra como os métodos acima podem ser usados ​​em 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]).

Ele produzirá a seguinte saída -

"Today is Monday"

Listé o tipo de dados mais versátil disponível em linguagens de programação funcionais usadas para armazenar uma coleção de itens de dados semelhantes. O conceito é semelhante a matrizes na programação orientada a objetos. Os itens da lista podem ser escritos entre colchetes separados por vírgulas. A maneira de escrever dados em uma lista varia de idioma para idioma.

Programa para criar uma lista de números em Java

Lista não é um tipo de dados em Java / C / C ++, mas temos maneiras alternativas de criar uma lista em Java, ou seja, usando ArrayList e LinkedList.

O exemplo a seguir mostra como criar uma lista em Java. Aqui, estamos usando um método de lista vinculada para criar uma lista de números.

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); 
   } 
}

Ele produzirá a seguinte saída -

[1, 2, 3, 4, 5]

Programa para criar uma lista de números em Erlang

-module(helloworld).  
-export([start/0]).   

start() ->  
   Lst = [1,2,3,4,5],  
   io:fwrite("~w~n",[Lst]).

Ele produzirá a seguinte saída -

[1 2 3 4 5]

Listar operações em Java

Nesta seção, discutiremos algumas operações que podem ser feitas em listas em Java.

Adicionando Elementos a uma Lista

Os métodos add (Object), add (index, Object), addAll () são usados ​​para adicionar elementos a uma lista. Por exemplo,

ListStrings.add(3, “three”)

Removendo Elementos de uma Lista

Os métodos remove (index) ou removeobject () são usados ​​para remover elementos de uma lista. Por exemplo,

ListStrings.remove(3,”three”)

Note - Para remover todos os elementos da lista, o método clear () é usado.

Recuperando Elementos de uma Lista

O método get () é usado para recuperar elementos de uma lista em um local especificado. Os métodos getfirst () e getlast () podem ser usados ​​na classe LinkedList. Por exemplo,

String str = ListStrings.get(2)

Atualizando elementos em uma lista

O método set (índice, elemento) é usado para atualizar um elemento em um índice especificado com um elemento especificado. Por exemplo,

listStrings.set(2,”to”)

Classificando elementos em uma lista

Os métodos collection.sort () e collection.reverse () são usados ​​para classificar uma lista em ordem crescente ou decrescente. Por exemplo,

Collection.sort(listStrings)

Pesquisando Elementos em uma Lista

Os três métodos a seguir são usados ​​de acordo com o requisito -

Boolean contains(Object) método retorna true se a lista contém o elemento especificado, senão ele retorna false.

int indexOf(Object) método retorna o índice da primeira ocorrência de um elemento especificado em uma lista, caso contrário, retorna -1 quando o elemento não é encontrado.

int lastIndexOf(Object) retorna o índice da última ocorrência de um elemento especificado em uma lista, caso contrário, retorna -1 quando o elemento não é encontrado.

Listar operações em Erlang

Nesta seção, discutiremos algumas operações que podem ser feitas sobre listas em Erlang.

Adicionando duas listas

O método append (listfirst, listsecond) é usado para criar uma nova lista adicionando duas listas. Por exemplo,

append(list1,list2)

Excluindo um elemento

O método delete (element, listname) é usado para excluir o elemento especificado da lista e retorna a nova lista. Por exemplo,

delete(5,list1)

Excluindo o último elemento da lista

O método droplast (listname) é usado para excluir o último elemento de uma lista e retornar uma nova lista. Por exemplo,

droplast(list1)

Procurando um elemento

O método do membro (elemento, nome da lista) é usado para pesquisar o elemento na lista, se encontrado, retorna verdadeiro, caso contrário, retorna falso. Por exemplo,

member(5,list1)

Obtendo valor máximo e mínimo

Os métodos max (listname) e min (listname) são usados ​​para encontrar os valores máximo e mínimo em uma lista. Por exemplo,

max(list1)

Elementos da lista de classificação

Os métodos sort (listname) e reverse (listname) são usados ​​para ordenar uma lista em ordem crescente ou decrescente. Por exemplo,

sort(list1)

Adicionando elementos de lista

O método sum (listname) é usado para adicionar todos os elementos de uma lista e retornar sua soma. Por exemplo,

sum(list1)

Classifique uma lista em ordem crescente e decrescente usando Java

O programa a seguir mostra como classificar uma lista em ordem crescente e decrescente usando 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); 
   } 
}

Ele produzirá a seguinte saída -

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]

Classifique uma lista em ordem crescente usando Erlang

O programa a seguir mostra como classificar uma lista em ordem crescente e decrescente usando Erlang, que é uma linguagem de programação funcional -

-module(helloworld).  
-import(lists,[sort/1]).  
-export([start/0]).   

start() ->  
   List1 = [5,3,4,2,1],  
   io:fwrite("~p~n",[sort(List1)]),

Ele produzirá a seguinte saída -

[1,2,3,4,5]

Uma tupla é um tipo de dados composto com um número fixo de termos. Cada termo em uma tupla é conhecido como umelement. O número de elementos é o tamanho da tupla.

Programa para definir uma tupla em C #

O programa a seguir mostra como definir uma tupla de quatro termos e imprimi-los usando C #, que é uma linguagem de programação orientada a objetos.

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);    
   } 
}

Ele produzirá a seguinte saída -

Tuple :(1, 2, 3, (4, 5))

Programa para definir uma tupla em Erlang

O programa a seguir mostra como definir uma tupla de quatro termos e imprimi-los usando Erlang, que é uma linguagem de programação funcional.

-module(helloworld).  
-export([start/0]).   

start() -> 
   P = {1,2,3,{4,5}} ,  
   io:fwrite("~w",[P]).

Ele produzirá a seguinte saída -

{1, 2, 3, {4, 5}}

Vantagens da Tupla

As tuplas oferecem as seguintes vantagens -

  • As tuplas são de tamanho definido na natureza, ou seja, não podemos adicionar / deletar elementos de / para uma tupla.

  • Podemos pesquisar qualquer elemento em uma tupla.

  • Tuplas são mais rápidas do que listas, porque têm um conjunto constante de valores.

  • Tuplas podem ser usadas como chaves de dicionário, porque contêm valores imutáveis ​​como strings, números, etc.

Tuplas vs listas

Tupla Lista
Tuplas são immutable, ou seja, não podemos atualizar seus dados. Lista são mutable, ou seja, podemos atualizar seus dados.
Os elementos em uma tupla podem ser de tipos diferentes. Todos os elementos de uma lista são do mesmo tipo.
As tuplas são indicadas por parênteses arredondados ao redor dos elementos. As listas são denotadas por colchetes ao redor dos elementos.

Operações em tuplas

Nesta seção, discutiremos algumas operações que podem ser realizadas em uma tupla.

Verifique se um valor inserido é uma tupla ou não

O método is_tuple(tuplevalues)é usado para determinar se um valor inserido é uma tupla ou não. Retornatrue quando um valor inserido é uma tupla, senão ele retorna false. Por exemplo,

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} , io:fwrite("~w",[is_tuple(K)]).

Ele produzirá a seguinte saída -

True

Convertendo uma lista em uma tupla

O método list_to_tuple(listvalues)converte uma lista em uma tupla. Por exemplo,

-module(helloworld).  
-export([start/0]).  

start() ->  
   io:fwrite("~w",[list_to_tuple([1,2,3,4,5])]).

Ele produzirá a seguinte saída -

{1, 2, 3, 4, 5}

Converter uma tupla em uma lista

O método tuple_to_list(tuplevalues)converte uma tupla especificada em formato de lista. Por exemplo,

-module(helloworld).  
-export([start/0]).  

start() ->  
   io:fwrite("~w",[tuple_to_list({1,2,3,4,5})]).

Ele produzirá a seguinte saída -

[1, 2, 3, 4, 5]

Verifique o tamanho da tupla

O método tuple_size(tuplename)retorna o tamanho de uma tupla. Por exemplo,

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} ,  
   io:fwrite("~w",[tuple_size(K)]).

Ele produzirá a seguinte saída -

5

Um registro é uma estrutura de dados para armazenar um número fixo de elementos. É semelhante a uma estrutura em linguagem C. No momento da compilação, suas expressões são traduzidas em expressões de tupla.

Como criar um registro?

A palavra-chave 'registro' é usada para criar registros especificados com o nome do registro e seus campos. Sua sintaxe é a seguinte -

record(recodname, {field1, field2, . . fieldn})

A sintaxe para inserir valores no registro é -

#recordname {fieldName1 = value1, fieldName2 = value2 .. fieldNamen = valuen}

Programa para criar registros usando Erlang

No exemplo a seguir, criamos um registro de nome student tendo dois campos, ou seja, sname e sid.

-module(helloworld).  
-export([start/0]).  
-record(student, {sname = "", sid}).   

start() ->  
   S = #student{sname = "Sachin",sid = 5}.

Programa para criar registros usando C ++

O exemplo a seguir mostra como criar registros usando C ++, que é uma linguagem de programação orientada a objetos -

#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;  
}

Programa para acessar valores de registro usando Erlang

O programa a seguir mostra como acessar valores de registro usando Erlang, que é uma linguagem de programação funcional -

-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]).

Ele produzirá a seguinte saída -

5 
"Sachin"

Programa para acessar valores de registro usando C ++

O programa a seguir mostra como acessar valores de registro usando 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; 
}

Ele produzirá a seguinte saída -

5 
Sachin

Os valores do registro podem ser atualizados alterando o valor para um campo específico e, em seguida, atribuindo esse registro a um novo nome de variável. Dê uma olhada nos dois exemplos a seguir para entender como isso é feito usando linguagens de programação orientadas a objetos e funcionais.

Programa para atualizar valores de registro usando Erlang

O programa a seguir mostra como atualizar os valores de registro usando 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]).

Ele produzirá a seguinte saída -

5
"Jonny"

Programa para atualizar valores de registro usando C ++

O programa a seguir mostra como atualizar valores de registro usando 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; 
}

Ele produzirá a seguinte saída -

Jonny 
5 
value after updating 
Jonny 
10

Lambda calculus é uma estrutura desenvolvida por Alonzo Church em 1930 para estudar cálculos com funções.

  • Function creation - Church introduziu a notação λx.Epara denotar uma função em que 'x' é um argumento formal e 'E' é o corpo funcional. Essas funções podem ser sem nomes e argumentos únicos.

  • Function application - Church usou a notação E1.E2 para denotar a aplicação da função E1 para o argumento real E2. E todas as funções estão em um único argumento.

Sintaxe do cálculo lambda

O cálculo do Lamdba inclui três tipos diferentes de expressões, ou seja,

E :: = x (variáveis)

| E 1 E 2 (aplicação de função)

| λx.E (criação de função)

Onde λx.E é chamada de abstração Lambda e E é conhecida como expressões λ.

Avaliando Cálculo Lambda

O cálculo lambda puro não possui funções integradas. Vamos avaliar a seguinte expressão -

(+ (* 5 6) (* 8 3))

Aqui, não podemos começar com '+' porque ele opera apenas em números. Existem duas expressões redutíveis: (* 5 6) e (* 8 3).

Podemos reduzir qualquer um primeiro. Por exemplo -

(+ (* 5 6) (* 8 3)) 
(+ 30 (* 8 3)) 
(+ 30 24) 
= 54

Regra de redução β

Precisamos de uma regra de redução para lidar com λs

(λx . * 2 x) 4 
(* 2 4) 
= 8

Isso é chamado de redução β.

O parâmetro formal pode ser usado várias vezes -

(λx . + x x) 4 
(+ 4 4) 
= 8

Quando existem vários termos, podemos tratá-los da seguinte maneira -

(λx . (λx . + (− x 1)) x 3) 9

O interior x pertence ao interior λ e o x externo pertence ao externo.

(λx . + (− x 1)) 9 3 
+ (− 9 1) 3 
+ 8 3 
= 11

Variáveis ​​livres e limitadas

Em uma expressão, cada aparência de uma variável é "livre" (para λ) ou "limitada" (para λ).

β-redução de (λx . E) y substitui todos x que ocorre gratuitamente em E com y. Por exemplo -

Redução Alfa

A redução alfa é muito simples e pode ser feita sem alterar o significado de uma expressão lambda.

λx . (λx . x) (+ 1 x) ↔ α λx . (λy . y) (+ 1 x)

Por exemplo -

(λ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

Teorema de Church-Rosser

O Teorema de Church-Rosser afirma o seguinte -

  • Se E1 ↔ E2, então existe um E tal que E1 → E e E2 → E. “A redução de qualquer forma pode eventualmente produzir o mesmo resultado.”

  • Se E1 → E2 e E2 estiver na forma normal, haverá uma redução de ordem normal de E1 para E2. “A redução de ordem normal sempre produzirá uma forma normal, se houver.”

A avaliação preguiçosa é uma estratégia de avaliação que mantém a avaliação de uma expressão até que seu valor seja necessário. Isso evita avaliações repetidas.Haskell é um bom exemplo de uma linguagem de programação funcional cujos fundamentos são baseados na avaliação preguiçosa.

A avaliação preguiçosa é usada nas funções de mapa do Unix para melhorar seu desempenho carregando apenas as páginas necessárias do disco. Nenhuma memória será alocada para as páginas restantes.

Avaliação preguiçosa - vantagens

  • Ele permite que o tempo de execução da linguagem descarte subexpressões que não estão diretamente vinculadas ao resultado final da expressão.

  • Ele reduz a complexidade de tempo de um algoritmo descartando os cálculos temporários e condicionais.

  • Ele permite que o programador acesse componentes de estruturas de dados fora de ordem após inicializá-los, desde que estejam livres de quaisquer dependências circulares.

  • É mais adequado para carregar dados que serão acessados ​​com pouca frequência.

Avaliação preguiçosa - desvantagens

  • Ele força o tempo de execução da linguagem a manter a avaliação de subexpressões até que seja necessário no resultado final, criando thunks (objetos atrasados).

  • Às vezes, aumenta a complexidade do espaço de um algoritmo.

  • É muito difícil encontrar seu desempenho porque ele contém muitas expressões antes de sua execução.

Avaliação preguiçosa usando Python

o rangemétodo em Python segue o conceito de avaliação preguiçosa. Ele economiza o tempo de execução para intervalos maiores e nunca exigimos todos os valores de uma vez, portanto, também economiza o consumo de memória. Dê uma olhada no exemplo a seguir.

r = range(10) 
print(r) 
range(0, 10) 
print(r[3])

Ele produzirá a seguinte saída -

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
3

Precisamos de arquivos para armazenar a saída de um programa quando o programa termina. Usando arquivos, podemos acessar informações relacionadas usando vários comandos em diferentes idiomas.

Aqui está uma lista de algumas operações que podem ser realizadas em um arquivo -

  • Criação de um novo arquivo
  • Abrindo um arquivo existente
  • Lendo o conteúdo do arquivo
  • Pesquisando dados em um arquivo
  • Escrevendo em um novo arquivo
  • Atualizar o conteúdo para um arquivo existente
  • Excluindo um arquivo
  • Fechando um arquivo

Escrevendo em um arquivo

Para gravar o conteúdo em um arquivo, primeiro precisamos abrir o arquivo necessário. Se o arquivo especificado não existir, um novo arquivo será criado.

Vamos ver como escrever conteúdo em um arquivo usando C ++.

Exemplo

#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 é a classe de fluxo usada para controlar as operações de leitura / gravação de arquivos.

  • ofstream é a classe de fluxo usada para gravar o conteúdo no arquivo.

Vamos ver como escrever conteúdo em um arquivo usando Erlang, que é uma linguagem de programação funcional.

-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 -

  • Para abrir um arquivo, temos que usar, open(filename,mode).

  • Sintaxe para gravar o conteúdo no arquivo: write(filemode,file_content).

Output - Quando executamos este código, “Gravando o conteúdo no arquivo” será gravado no arquivo Tempfile.txt. Se o arquivo tiver algum conteúdo existente, ele será sobrescrito.

Lendo de um arquivo

Para ler um arquivo, primeiro temos que abrir o arquivo especificado em reading mode. Se o arquivo não existir, seu respectivo método retornará NULL.

O programa a seguir mostra como ler o conteúdo de um arquivo em 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; 
}

Ele produzirá a seguinte saída -

Writing contents to file

Note- Neste programa, abrimos um arquivo texto em modo de leitura usando “ios :: in” e depois imprimimos seu conteúdo na tela. Nós usamoswhile loop para ler o conteúdo do arquivo linha por linha usando o método “getline”.

O programa a seguir mostra como realizar a mesma operação usando Erlang. Aqui, vamos usar oread_file(filename) método para ler todo o conteúdo do arquivo especificado.

-module(helloworld).  
-export([start/0]).   

start() ->  
   rdfile = file:read_file("Tempfile.txt"),  
   io:fwrite("~p~n",[rdfile]).

Ele produzirá a seguinte saída -

ok, Writing contents to file

Excluir um arquivo existente

Podemos excluir um arquivo existente usando operações de arquivo. O programa a seguir mostra como excluir um arquivo existenteusing 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; 
}

Ele produzirá a seguinte saída -

file deleted successfully

O programa a seguir mostra como você pode realizar a mesma operação em Erlang. Aqui, vamos usar o métododelete(filename) para excluir um arquivo existente.

-module(helloworld).  
-export([start/0]).   

start() ->  
   file:delete("Tempfile.txt").

Output - Se o arquivo “Tempfile.txt” existir, ele será excluído.

Determinando o tamanho de um arquivo

O programa a seguir mostra como você pode determinar o tamanho de um arquivo usando C ++. Aqui, a funçãofseek define o indicador de posição associado ao fluxo para uma nova posição, enquanto ftell retorna a posição atual no fluxo.

#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 - Se o arquivo “Tempfile.txt” existe, então mostrará seu tamanho em bytes.

O programa a seguir mostra como você pode realizar a mesma operação em Erlang. Aqui, vamos usar o métodofile_size(filename) para determinar o tamanho do arquivo.

-module(helloworld).  
-export([start/0]).   

start() ->  
   io:fwrite("~w~n",[filelib:file_size("Tempfile.txt")]).

Output- Se o arquivo “Tempfile.txt” existe, então mostrará seu tamanho em bytes. Caso contrário, exibirá “0”.