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
, u64
, u128
, 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;
}
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);
}
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);
}
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;
}
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;
}
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
}
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';
}
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,
}
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');
}
O código que você forneceu define uma estrutura chamada Order
que possui sete campos: name
, year
, made_by_phone
, made_by_mobile
, made_by_email
, item_number
, e count
. O name
, year
, 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.
Top comments (0)