Rust

Jan. 14th, 2015 03:18 pm
thedeemon: (office)
[personal profile] thedeemon
На днях вышла 1.0.0.alpha, решил наконец приобщиться. Почитал онлайн книжку. Если она не слишком много скрывает, язык довольно маленький и простой, это хорошо. Для начала сделал вариант для недавнего микробенчмарка про маленький интерпретатор. В тот раз добрые люди помогли ускорить наивные решения, так что все времена опустились ниже 1 секунды, что делает замеры менее осмысленными. Тем не менее, вот текущие результаты:

D - 0.40 s (при использовании LDC)
Rust - 0.44 s
OCaml - 0.57 s
Haskell - 0.85 s
(с одной закавыкой - Rust тут 64-битный, все остальные 32-битные, так уж получилось)

Т.к. опыт с Rust'ом у меня пока минимальный, впечатления смутные. Одной фразой - "ML в руках плюсовиков". Видишь знакомый набор из алгебраиков, паттерн-матчинга, лямбд, expression-based syntax, начинаешь писать как на ML, и тут на тебя выпрыгивает наследие С++: а ты здесь это значение насовсем передал (у нас move-семантика по-умолчанию, уж больно нам эта фича из С++ понравилась) или хотел лишь по указателю? Ах по указателю, тогда так и напиши везде, и где принимаешь, и где передаешь. А еще и писать туда хотел? Тогда не забудь при передаче &mut дописать. И это же выскакивает при паттерн-матчинге: вот тут ты поле алгебраика заматчил, тебе его так отдать или по ссылке? А обращаться хорошо с ней будешь?
Причем как-то странно сделано, вот есть структуры и есть туплы, разница между ними довольно косметическая, так? Можем пару значений передать как тупл, а можем как структуру. Сделаем пару одинаковых функций, складывающих два поля:
#[derive(Show)]
struct S { x : i32, y : i32 }

fn eat_struct(s : S) -> i32 { 
  s.x + s.y 
}

fn eat_tuple(t : (i32, i32)) -> i32 { 
  let (x,y) = t;
  x + y
} 

Обе получают аргумент по значению.
Теперь попробуем их повызывать:
fn main() {
  let s = S { x: 1, y : 2 };
  let t = (1, 2);
  let rs = eat_struct(s);
  let rt = eat_tuple(t);
  println!("{} {} {:?} {:?}", rs, rt, s, t);
}

И получаем ошибку:
hi.rs:18:39: 18:40 error: use of moved value: `s`
hi.rs:18   println!("{} {} {:?} {:?}", rs, rt, s, t);
                                               ^

Оказывается, когда мы структуру передали в ту функцию, мы ее отдали насовсем, это был move. А вот тупл скопировался, передача по значению, оригинал остается у вызывающей ф-ии. Неожиданно.

Еще занятный момент. В растовском варианте, что по ссылке выше, есть такое выражение:
1 + (if a[i] > a[j] { evalBlock(a, b1) } else { evalBlock(a, b2) })
Казалось бы, его, как в ML вариантах, можно заменить более простым:
1 + evalBlock(a, if a[i] > a[j] { b1 } else { b2 })
Но не тут-то было. Rust считает, что в первом аргументе evalBlock происходит мутабельное заимствование массива а, а при вычислении второго аргумента имеет место иммутабельное заимствование этого же массива. И хотя аргументы должны быть вычислены до вызова функции, и по времени эти два использования массива не пересекаются никак, Rust считает, что тут два параллельных заимствования, одно из которых мутабельное, что недопустимо.

Буду продолжать наблюдения. В целом штука занятная.
Page 1 of 3 << [1] [2] [3] >>

Date: 2015-01-14 08:21 am (UTC)
From: [identity profile] macrop.livejournal.com
ммм.. как вводу. сижу голову над с++ перещениями ломаю. Как раз rust вспоминал вечером))

Date: 2015-01-14 08:24 am (UTC)
From: [identity profile] diam-2003.livejournal.com
Да-да, вот эти самые пляски с владением в Rust-е с теоретической стороны кажутся весьма привлекательными, особенно для программистов на С++, а на деле порой нетривиально замутняют код. К вопросу о том, почему не всё, что делает компилятор (например, escape-анализ) следует пихать в систему типов.

Date: 2015-01-14 09:18 am (UTC)
From: [identity profile] gds.livejournal.com
диагноз: невнятная хуита.

Date: 2015-01-14 10:36 am (UTC)
From: [identity profile] kodt-rsdn.livejournal.com

Стобы понять с++ные перемещения, надо знать предысторию. С их велосипедами народ трахался пятнадцать лет, пока не пришёл к пониманию ценности, цены, области применения и стандарта.


С передачей ссылок и значений, кстати, народ также натрахался вволю, но ещё в фортране.

Date: 2015-01-14 10:36 am (UTC)
From: [identity profile] macrop.livejournal.com
У меня раньше пляска со строками была.
Были адовы горы строк с подсчётом ссылок. Но при этом, иногда их надо было просто передавать куда-то для вывода или обработки, не дёргая попусту всю эту мишуру с механизмом подсчёта. Поэтому была какая-то припарка, вспомогательный объект, через который в функцию передавался объект, без пересчёта ссылок. Очень это геморно было, и от ошибок не защищёно.

Не понимаю как в си раньше до такого нужного механизма не додумались. В Rust, я так понимаю, он более развит, хотя не все проблемы решает.

Date: 2015-01-14 10:37 am (UTC)
From: [identity profile] kodt-rsdn.livejournal.com

Йес ыт ыз!
За углоскобки отдельное фи. На ровном месте усложнили жизнь парсеру.

Date: 2015-01-14 10:41 am (UTC)
From: [identity profile] diam-2003.livejournal.com
Классический вопрос для программиста на С++:
сколько классов строк было в вашем самом большом проекте?

Date: 2015-01-14 11:19 am (UTC)
From: [identity profile] v-l-a-d.livejournal.com
по сравнению с чем усложнили, и в каком месте?

Date: 2015-01-14 11:28 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Они наоборот шли на поводу у парсера, чтобы был быстрый и без длинных look-ahead'ов работал, порой усложняя жизнь человекам. Так получились штуки вроде f::<T>(v).

Date: 2015-01-14 11:32 am (UTC)
From: [identity profile] thedeemon.livejournal.com
Без помощи человека escape-анализ работает слишком долго и плохо. Остается выбор между ручной аннотацией всякого (Rust, ATS), полаганием на сборщик мусора, либо полаганием на авось (C/C++).

Date: 2015-01-14 11:35 am (UTC)
From: [identity profile] kodt-rsdn.livejournal.com

Тэг пропал, ахаха. < T > надо было.


А как в расте с двойной закрывающей скобкой, это одна лексема или две?

Date: 2015-01-14 11:39 am (UTC)
From: [identity profile] kodt-rsdn.livejournal.com

По сравнению с си без крестов.
В плюсах есть спецтанцы с бубном для устранения неоднозначностей, и жутко контекстнозависимый парсер. А двойную закрывающую скобку сколько лет фиксили, 15 или 18?

Date: 2015-01-14 11:45 am (UTC)
From: [identity profile] diam-2003.livejournal.com
Это ваше утверждение про "долго и плохо" как-нибудь можно подтвердить :) ?

Нормальный быстрый escape-анализ + сборщик мусора + арены для особо исключительных случаев.
Контроллеры с весьма маленькой (4М, например) памятью.
Всё хорошо.

Date: 2015-01-14 12:09 pm (UTC)
From: [identity profile] thedeemon.livejournal.com
Какой тэг? Ничего не пропало.

Плюсовых проблем с закрытием > в расте нет, пробел не нужен. Сколько лексем - не знаю.

Date: 2015-01-14 12:16 pm (UTC)
From: [identity profile] thedeemon.livejournal.com
>Нормальный быстрый escape-анализ + сборщик мусора

А если без сборщика?
Со сборщиком всегда можно быть довольно консервативным: не уверен, что можно положить на стек, - пихай в кучу. А вот чтобы без лишней консервативности, это надо или глобальный анализ делать по всей программе и библиотекам, или таки в типы пометки совать.

Date: 2015-01-14 12:30 pm (UTC)
From: [identity profile] kodt-rsdn.livejournal.com
А, похоже, это глюки ведроидклиента. Он сожрал (Т) как незакрытый тэг.
У жж движок разметки странноватый, часть неоднозначностей он исправляет, часть игнорирует.

Date: 2015-01-14 12:32 pm (UTC)
From: [identity profile] Денис Жамойдик (from livejournal.com)
а как насчёт переписать ещё на ним? (http://nim-lang.org/)

Date: 2015-01-14 12:33 pm (UTC)
From: [identity profile] v-l-a-d.livejournal.com
Так в расте как раз проблем с этим никаких нет, т.к. синтаксис f:: хоть и уродский, но однозначный http://www.reddit.com/r/rust/comments/2s7bnt/thoughts_about_rust_from_d_programmer/cnn03e0

Date: 2015-01-14 01:35 pm (UTC)
From: [identity profile] diam-2003.livejournal.com
А зачем без сборщика и без консервативности :) ?

Глобальный анализ по всей программе и библиотекам, с аннотациями и всем таким. Без поливариантных типов, поэтому достаточно быстро. Может не покрывать какой-нибудь специфический "декларативный" код, но мы за это и не боролись никогда. В кровавой эмбеддщине так никто не пишет.

Date: 2015-01-14 02:10 pm (UTC)
From: [identity profile] dmytrish.livejournal.com
Так вот откуда этот ужас.

Date: 2015-01-14 04:25 pm (UTC)
wizzard: (Default)
From: [personal profile] wizzard
Кажется, что тут нужен gradual typing. Типа, делаем какой-то best effort inference, а где компилятор не угадал - там ему хинтим, что, дескать, делать так-то и так-то.

Date: 2015-01-14 04:27 pm (UTC)
wizzard: (Default)
From: [personal profile] wizzard
> с весьма маленькой

О времена, о нравы!

В моем понимании, весьма маленькая память - это 128 байт (сим-карты) :)

Date: 2015-01-14 04:37 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Ну или ATtiny какие-нибудь ;-)
У них вообще от 32 байт памяти.

Date: 2015-01-14 05:07 pm (UTC)
From: [identity profile] thedeemon.livejournal.com
Можете попробовать, будет интересно сравнить.
Nim - тоже довольно занятный экземпляр, делающий успехи сейчас. Но я пока для него не созрел, чем-то он мне противен.

Date: 2015-01-14 08:32 pm (UTC)
From: [identity profile] swizard.livejournal.com
Оказывается, когда мы структуру передали в ту функцию, мы ее отдали насовсем, это был move. А вот тупл скопировался, передача по значению, оригинал остается у вызывающей ф-ии. Неожиданно.

Ещё буквально пару недель назад это было не так: структуры тоже обладали Copy, если нет деструктора, и все её члены Copy =) Теперь нужно либо явно указывать #[derive(Copy)], либо #[allow(missing_copy_implementations)] (иначе компилятор нервничает).
Page 1 of 3 << [1] [2] [3] >>

Profile

thedeemon: (Default)
Dmitry Popov

December 2025

S M T W T F S
 12 3456
789101112 13
14151617181920
21222324252627
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 28th, 2026 12:38 am
Powered by Dreamwidth Studios