WEB3DEV

Cover image for Explorando alguns conceitos do Cairo 1.0 (Parte 1/2).
Adriano P. Araujo
Adriano P. Araujo

Posted on • Atualizado em

Explorando alguns conceitos do Cairo 1.0 (Parte 1/2).

Image description

Foto de Markus Spiske em Unsplash

Neste artigo, exploraremos alguns dos novos recursos do Cairo 1.0 que foram introduzidos para tornar a programação mais fácil e eficiente, com foco no desenvolvimento de programas prováveis. Nosso objetivo é ajudá-lo a se familiarizar com esses novos recursos, para que você possa aproveitar ao máximo seus projetos. Seja você um desenvolvedor experiente ou iniciante, convidamos você a se juntar a nós enquanto nos aprofundamos no emocionante mundo do Cairo 1.0!

Tipos primitivos:

O Cairo 1.0 suporta vários tipos primitivos, incluindo valores booleanos, felt e números inteiros, como u8, u16, u32,   u64u128, e  u256. Além disso, as strings literais também são suportadas na linguagem.


Aprenda a converter tipos inteiros e felt.

// Execute `starklings hint primitive_types4` ou use o subcomando `hint` para  obter uma dica.

use traits::Into;

use traits::TryInto;

use option::OptionTrait;



fn sum_u8s(x: u8, y: u8) -> u8 {

  return  x + y;

}




//A FAZER: modificação dos tipos desta função para evitar um estouro ao somar grandes valores

fn sum_big_numbers(x: u16, y: u16) -> u16 {

  return  x + y;

}



fn convert_to_felt(x: u8) -> felt {



   /A FAZER: retorno x como um felt.

  return x.into();

}



fn convert_felt_to_u8(x: felt) -> u8 {



   /A FAZER retorno x como u8.

  let xy:u8 = x.try_into().unwrap();

    return xy;

}



Enter fullscreen mode Exit fullscreen mode

O código acima define várias funções para demonstrar a conversão entre diferentes tipos primitivos na linguagem de programação Cairo.

A função sum_u8s recebe dois argumentos u8 e retorna sua soma como um valor u8. A função sum_big_numbers recebe dois argumentos u16 e retorna sua soma como um valor u16. No entanto, o comentário no código sugere que os tipos de função devem ser modificados para evitar overflow ao somar grandes valores.

A função convert_to_felt recebe um único argumento u8 e o retorna como um tipo de felt usando o método into() fornecido pela característica "Into”. 

A função convert_felt_to_u8 pega um único argumento de entrada de felt e o retorna como um tipo u8  usando o método "try_into( )" fornecido pelo "TryInto”. Se a conversão falhar devido ao transbordamento, ela retornará um valor opcional vazio.

Variáveis

No Cairo, as variáveis são imutáveis por padrão, mas podem ser mutáveis adicionando mut na frente do nome da variável. No entanto, o Cairo usa um modelo de memória imutável; portanto, alterar o valor de uma variável cria um novo local de memória.

Vamos dar uma olhada em alguns exemplos:


fn main() {

    let x = 3;

    debug::print_felt(x);

    x = 5; // não mude esta linha

    debug::print_felt(x);

}

Enter fullscreen mode Exit fullscreen mode

O código acima define um função main na qual 3 é atribuído à uma variável x e a depuração :: print_felt ( x ) imprime o valor de x. A variável x é reatribuída para 5. O código acima não será compilado. Abaixo está o código correto:


fn main() {

    let mut x = 3;

    debug::print_felt(x);

    x = 5; // não mude esta linha

    debug::print_felt(x);

}

Enter fullscreen mode Exit fullscreen mode

O mut permite a reatribuição de um novo valor na variável x.

Operadores:

Os felts na programação aceitam os operadores de adição ( + ), subtração ( - ) e multiplicação ( * ), mas não divisão ( / ). Além disso, os felt podem ser comparados usando operadores como menor que ( < ), maior que ( >), maior ou igual a (≤ ), maior ou igual a (≥ ), e diferente de (!= ).




fn poly(x : felt, y: felt) ->  (felt) {

    // PREENCHA-ME

    let res = (x*x*x) + y - 2;

   return res;   

}



Enter fullscreen mode Exit fullscreen mode

A função poly recebe dois argumentos, ambos do tipo felt e retorna um único valor de tipo felt. A função calcula o resultado da expressão polinomial x^3 + y - 2, onde x e y são os argumentos de entrada. O resultado é armazenado em uma variável chamada "res", retornada como a saída da função.

Na versão anterior da linguagem de programação Cairo (Cairo0), a divisão era um pouco difícil de tentar. No entanto, na versão atual ( Cairo1 ), tipo inteiro nativo u8, u16, u32, u64, u128 , e u256, e usize são introduzidos, suportando mais operadores do que felts. Mesmo que eles confiem no tipo básico felt nos bastidores, é mais seguro usá-los se o contexto for apropriado.




fn modulus(x : u8, y: u8) ->  u8 {

    // calcula o módulo de x e y

    let res = x % y;

   return res;

}



fn floor_division(x: usize, y: usize) -> u32 {

  // calcula a divisão de piso de x e y

    let res = x/y;

  return  res;

}



fn multiplication(x: u64, y: u64) -> u64 {

     // calcula a multiplicação de x e y




    let res = x * y;

    return res;

}



Enter fullscreen mode Exit fullscreen mode
Funções:

Funções no Cairo 1.0 são definidas pela palavra-chave func. Como em rust, as funções têm duas maneiras de retornar valores. O primeiro é usando a expressão final da função. Nesse caso, o ; é omitido no final da linha. O segundo é usando a  palavra-chave return.

Exemplo:


Esta loja está fazendo uma venda `where if` (onde se)o preço é um número par, você recebe

 10 Cairobucks, mas se é um número ímpar, são 3 Cairobucks.




use traits::Into;



fn main() {

    let original_price = 51_u32;

    debug::print_felt(sale_price(original_price).into());

}



fn sale_price(price: u32) ->u32 {

    if is_even(price) {

        price - 10_u32

    } else {

        price - 3_u32

    }

}



fn is_even(num: u32) -> bool {

 return  num % 2_u32 == 0_u32

}

Enter fullscreen mode Exit fullscreen mode

O código inclui uma instrução “ use ” para importar a característica Into do módulo “traits”. Ele define uma função "principal" que declara uma variável "original_price" com um valor de 51 e depois chama a função sale_price com original_price como o argumento de entrada. O resultado de sale_price é impresso no console usando a instrução "debug :: print_felt", após primeiro convertê-lo em um tipo "felt" usando o método "into( )" fornecido pela "Into”.

A função sale_price pega um único argumento de entrada do tipo u32, e retorna um valor u32 representando o preço de venda descontado. A função verifica se o preço de entrada está usando a função is_even. Se o preço for par, a função subtrai 10 dele, caso contrário, subtrai 3.

A função  is_even pega um único argumento de entrada do tipo u32 e retorna um valor booleano indicando se a entrada é par ou ímpar, verificando se a entrada é divisível por 2 sem resto.

Declarações condicionais:

O Cairo 1.0 fornece as instruções “if”, “else if”, e “else” para execução condicional de código com base no valor de uma expressão booleana.




Complete essa função usando if, else if e /ou  blocos else.

    // Se é fizz,

   // 'fizz', retorne 'foo'

   // 'fuzz', retorne 'bar'

   // qualquer outra coisa, retorne 'baz'



fn foo_if_fizz(fizzish: felt) -> felt {

   // Conclua esta função usando if, else if / ou blocos else .

   // Se estiver com gás,

   // 'fizz', retorne 'foo'

   // 'fuzz', retorne 'bar'

   // qualquer outra coisa, retorne 'baz'

    if fizzish == 'fizz' {

       return 'foo';

    } else if fizzish == 'fuzz' {

        return 'bar';

    }

    return 'baz';

}

Enter fullscreen mode Exit fullscreen mode
Structs:

O Cairo possui um único tipo de struct que representa coleções nomeadas de dados relacionados armazenados em campos. Eles são declarados assim:


struct ColorStruct {

    red:felt,

    green:felt,

    blue:felt,

}

Enter fullscreen mode Exit fullscreen mode

Vamos ver como inicializar a estrutura acima:


#[derive(Copy, Drop)]

struct Order {

    name: felt,

    year: felt,

    made_by_phone: bool,

    made_by_mobile: bool,

    made_by_email: bool,

    item_number: felt,

    count: felt,

}



fn create_order_template() -> Order {

    Order {

        name: 'Bob',

        year: 2019,

        made_by_phone: false,

        made_by_mobile: false,

        made_by_email: true,

        item_number: 123,

        count: 0

    }

}

#[test]

fn test_your_order() {

    let order_template = create_order_template();

    // A FAZER: Desserializa seu pedido em várias variáveis para fazer passar as afirmações!



    let Order{name, year, made_by_phone, made_by_mobile, made_by_email,item_number, count} = order_template;



    assert(name == 'Bob', 'Wrong name');

    assert(year == order_template.year, 'Wrong year');

    assert(made_by_phone == order_template.made_by_phone, 'Wrong phone');

    assert(made_by_mobile == order_template.made_by_mobile, 'Wrong mobile');

    assert(made_by_email == order_template.made_by_email, 'Wrong email');

    assert(item_number == order_template.item_number, 'Wrong item number');

    assert(count == 0, 'Wrong count');

}

Enter fullscreen mode Exit fullscreen mode

O código que você forneceu define uma estrutura chamada Order que possui sete campos: nameyearmade_by_phonemade_by_mobilemade_by_emailitem_number,  e  count. O  nameyear, e  item_number são   campos do tipo felt, que é um tipo primitivo no Cairo que pode representar números inteiros assinados de até 256 bits. O made_by_phone, made_by_mobile, e made_by_email são campos do tipo booleano, que representa um valor booleano ( verdadeiro ou falso ). O campo count também é do tipo felt.

A função create_order_template() cria uma nova instância do struct Order com valores padrão para cada campo. O campo name é inicializado para o valor de felt 'Bob', o campo year é inicializado para o valor de felt 2019, os campos made_by_phone e made_by_mobile são inicializados para false, o campo made_by_email é inicializado como true, o campo item_number é inicializado para o valor de felt 123 e o campo count é inicializado para 0.

A função test_your_order() é um teste de unidade que verifica se a função create_order_template() retorna uma instância Order com os valores padrão corretos. Ele chama primeiro create_order_template() para criar uma instância do struct Order. Em seguida, usa a atribuição de desestruturação para atribuir cada campo da instância do Order para uma variável separada: name, year, made_by_phone, made_by_mobile, made_by_email, item_number, e count.

Finalmente, a função usa uma série de afirmações para verificar se cada campo tem o valor esperado. A função assert() usa dois argumentos: uma expressão booleana que é avaliada como true se o teste for aprovado, e uma mensagem de erro impressa se o teste falhar. Se todas as afirmações passarem, o teste passa. Se alguma das afirmações falhar, o teste falhará e imprimirá uma mensagem de erro indicando qual afirmação falhou e quais eram os valores esperados e reais.

No geral, esse código define uma struct que representa uma ordem com vários campos, fornece uma função para criar um modelo de ordem padrão, e inclui uma função de teste para verificar se o modelo de pedido possui os valores padrão corretos.

Para resumir este artigo, nos aprofundamos em conceitos importantes, como variáveis, operadores, funções, declarações condicionais e structs no Cairo 1.0. Esperamos que você o tenha achado esclarecedor. Na Parte 2 deste artigo(traduzido), mudaremos nosso foco para outros conceitos cruciais, como matrizes, opções, enums e muito mais. Fique ligado!


Este artigo foi escrito por  Starknet Africa e traduzido por Adriano P. de Araujo. O original em inglês pode ser encontrado aqui.

Latest comments (0)