Новость из категории: Информация

Язык программирования Rust: переменные, указатели, массивы и функции

Содержание:
1. История и установка;
2. Утилиты, документация, идеология и синтаксис;
3. Переменные, указатели, массивы и функции (Вы читаете данный раздел);
4. Объектно-ориентированное программирование;
5. Исключения и общие выводы.
Переменные

Язык программирования Rust: переменные, указатели, массивы и функции

Переменные в Rust объявляются ключевым словом let. Если тип переменной не указан, он определяется автоматически из контекста. По умолчанию все переменные неизменяемы (immutable), т.е. по сути константы. Ключевое слово mut позволяет создать изменяемое значение.
let hi = "hi";
let mut count = 0;

При желании можно определить тип явно «в стиле Pascal»:
let mut count: int = 0;

Указатели и их типы

По умолчанию все переменные и литералы в Rust размещаются статически в стеке. Для динамического выделения памяти используются указатели, но они отличаются от привычных в С/С++. Имеется три типа указателей: заимствованные (borrowed, задаются добавлением к переменной префикса «&»), принадлежащие (owned, префикс «~») и управляемые (managed, префикс «@»). Заимствованный указатель - это то же, что ссылка (reference) в С++; он является адресом уже соответствующей переменной:
let mut s = "Text"; // Текстовая переменная в стеке
let p = &s; // Ссылка на нее (адрес в памяти)
io::println(*p); // Разыменование ссылки и вывод на экран

Принадлежащий указатель, грубо говоря, эквивалентен классу unique_ptr<> в С++: при инициализации он выделяет память в куче и помещает туда переменную. Этот указатель уникален - никто другой не может ссылаться на ту же переменную:
let mut s1 = ~"Text"; // Переменная в куче
let mut s2 = s1; // Семантика перемещения - теперь s2 ссылается на выделенную
// память, а s1 не определен(произошло «перемещение»)
let p = &s1; // ОШИБКА! Ссылка s1 уже не определен!

Управляемый указатель похож на shared_ptr<> в С++, но он автоматически попадает в поле зрения сборщика мусора того потока, где он определен:
let mut s1 = @"Text"; // Переменная в куче потока
let mut s2 = s1; // s1 и s2 ссылаются на одну и ту же память

Массивы

В Rust имеются встроенные массивы (векторы) - как статические, так и динамические:
let a: [int,..3] = [1,5,10]; // Статический массив из 3 элементов
let mut b: @[int] = @[1,2,3]; // Динамический массив из 3 элементов
b += [4,5,6]; // добавляем еще три элемента

Функции, замыкания и основанные на них конструкции

Функции объявляются следующим образом:
fn f1(val: int) -> int { // Функция возвращает тип int return 42+val;
}
io::println(fmt!("%i",f1(1))) // Выводим форматированное значение 43

Функции не видят окружающего их контекста и могут общаться с «внешним миром» только через переменные в стиле функциональных языков программирования. В том же стиле в Rust определены замыкания (анонимные функции с захватом контекста):
// Функция принимает как аргумент другую функцию с сигнатурой fn(int)
// и вызывает ее с параметром 10
fn call_closure_with_ten(b: &fn(int)) { b(10); }
// Переменная в локальном контексте
let captured_var = 20;
// Объявляем замыкание; между || перечисляются аргументы // все переменные локального контекста видны!
let closure = |arg| println(fmt!("captured_var=%d, arg=%d", captured_var, arg));
// Передаем замыкание в функцию
call_closure_with_ten(closure);

Как и переменные замыкания бывают трех типов: стековые, управляемые и принадлежащие с разными накладными расходами и областями применения. Например, так можно определить максимальное число в массиве с помощью обычного (стекового) замыкания:
let mut max = 0;
[1, 2, 3].map(|x| if *x > max { max = *x });

Дух функционального программирования в Rust проник даже в управляющие конструкции. Например, нормального цикла for в Rust нет, но зато есть специальный синтаксис замыканий:
// Функция принимает массив чисел и другую функцию fn для их обработки
fn each(v: &[int], op: &fn(v: &int) -> bool) {
let mut n = 0; while n < v.len() {
if !op(&v[n]) { break;
}
n += 1;
}
}
// Вызываем нашу функцию а-ля управляющую конструкцию // Все, что находится в фигурных скобках, становится телом замыкания, // которое передается как второй аргумент в функцию each for each([2, 4, 8, 5, 16]) |n| { if *n % 2 != 0 {
println("found odd number!");
break;
}
}

Для людей, пришедших из императивных языков, это выглядит как тарабарщина, но зато адепты функционального стиля будут чувствовать себя как дома.

Рейтинг статьи

Оценка
2/5
голосов: 4
Ваша оценка статье по пятибальной шкале:
 
 
   

Поделиться

Похожие новости

Комментарии

^ Наверх