LINUX.ORG.RU
ФорумTalks

Rust 1.21

 ,


1

4

Так как никто не хочет писать новость, то просто закину сюда.

https://blog.rust-lang.org/2017/10/12/Rust-1.21.html

The Rust team is happy to announce the latest version of Rust, 1.21.0. Rust is a systems programming language focused on safety, speed, and concurrency.

Главное

Изменено поведение литерала & в некоторых случаях:

use std::thread;

fn main() {
    let x = &5;
    
    thread::spawn(move || {
        println!("{}", x);
    }); 
    
}
Данный код не скомпилируется на предыдущих версиях из-за 'borrowed value doesn't live long enough'. Но в новой версии код успешно компилируется, потому что добавили еще немного сахара. Теперь код let x = &5 будет эквивалентен этому:
static FIVE: i32 = 5;

let x = &FIVE;

for_each теперь stable

// old
for i in 0..10 {
    println!("{}", i);
}

// new
(0..10).for_each(|i| println!("{}", i));
Ответ на: комментарий от Virtuos86

Способы бывают разные, но во всех других известных мне языках об этом заботится for, а внутри него уже доступен результат разыменования, как в примере с map.

Softwayer ★★
()
Ответ на: комментарий от Softwayer

Мне кажется речь была о:

    let v = [1, 2];
    let mut iter = v.iter();
    
    println!("{:?}", iter.next()); // Some(1)
    println!("{:?}", iter.next()); // Some(2)
    println!("{:?}", iter.next()); // None
    println!("{:?}", iter.next()); // None

RazrFalcon ★★★★★
()
Ответ на: комментарий от Softwayer

Способы бывают разные, но во всех других известных мне языках об этом заботится for, а внутри него уже доступен результат разыменования, как в примере с map.

Option::None замена null, nil, etc в других языках.

for i in 0..10 {
    println!("{}", i);
}

// for — сахар для следующего
let mut iter = 0..10;
while let Some(i) = iter.next() { // выполнять до тех пор, пока next не вернёт None
    println!("{}", i);
}

// while let — сахар для этого
let mut iter = 0..10;
loop {
    match iter.next() {
        Some(i) => println!("{}", i),
        None => break, // если next вернул None, то выйти из цикла
    }
}

// на C
iterator_t iter = iterator_create(0, 10);
int *i = iterator_next(iter);
while (i != NULL) {
    printf("%d\n", *i);
    i = iterator_next();
}
numas13
()
Ответ на: комментарий от numas13

Спасибо, я понимаю, что такое Option (и слабо представляю, как можно не понимать, ведь он нынче есть примерно в любом языке высокоуровневее С). Речь о том, что кусок кода, написанный выше Virtuos86, переписывается так:

let mut v = Vec::new();
for i in <Iterator> {
    v.push(func(i))
}
Что хоть и менее выразительно, чем с помощью map и collect, но не сказать чтобы сильно многословно, и «матчинг за нас» в любом случае выполняют.

Softwayer ★★
()
Ответ на: комментарий от Softwayer

Что хоть и менее выразительно, чем с помощью map и collect, но не сказать чтобы сильно многословно, и «матчинг за нас» в любом случае выполняют.

Всё же collect предпочтительнее, т. к. специализация. Для Vec аналог выглядит так, но кто знает, что надо сделать для др. коллекции?

let iter = <Iterator>;
let (size, _) = iter.size_hint();
let mut v = Vec::with_capacity(size);
for i in iter {
    v.push(i);
}
numas13
()
Ответ на: комментарий от Softwayer

Да, я сегодня ночь не спал, поэтому воспалённый разум родил нечто курьёзное. for также неявно match'ит выхлоп итератора. Уж сколько раз зарекался стараться не напрягать мозги на фоне усталости.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Crocodoom

Пили пример «усложнённой логики»

На мабиле трудновато примеры строчить, тем более когда в языке ехал скобка через скобка. Просто поверь на слово, что всегда проще запердолить цикл, чем корячиться с гирляндами лямбд. У императивных утят так по крайней мере.

bread
()
Ответ на: комментарий от Virtuos86

for также неявно match'ит выхлоп итератора.

То есть функциональный foreach не нужен. Запилили его какие-то рубироиды просто для крысоты.

bread
()

В толксы нельзя писать новости. Новости разрешено оформлять для главной страницы. В крайнем случае разрешено обсуждать технические подробности в технических разделах. А в толксах про новые релизы должна быть тишина.

saahriktu ★★★★★
()
Ответ на: комментарий от Crocodoom

а мы тебе постараемся в функциональном стиле это переписать

в том и соль, что постараетесь, да как бы не порвались

функциональщина хороша только в малых дозах. что вполне обосновывает её нужность, собственно

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

так зачем for_each, если с тем же успехом можно сделать map на лямбду, возвращающую ()?

map — ленивый, то есть не выполнится, пока не пройдёшь по всем итерациям.

numas13
()
Ответ на: комментарий от MyTrooName

а мы тебе постараемся в функциональном стиле это переписать

в том и соль, что постараетесь

Думаю, никакого продолжения этих слов (в виде конкретного кода) от тебя тоже ожидать не стоит?.. А ну да, это же толксы.

функциональщина хороша только в малых дозах

Хороша в малых дозах где? В системном программировании? Да, поэтому Rust не функциональный язык, там из полноценных ФП языков от силы 10% взято. Потому что ФП без сборщика мусора пока не изобрели.

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

Crocodoom ★★★★★
()
Ответ на: комментарий от Virtuos86

Конечно, не нужен. loop хватит всем.

Не совсем, но while точно хватит всем. Уже отцы сишки начали хипстовать с этим своим for. По сути классический for является классическим говнострочником, где все в одну кучу свалили. For как сахар для итераторов еще туда-сюда, хотя конечно тоже ненужно.

bread
()
Ответ на: комментарий от I60R

В чем, собственно, проблема этого кода?

Для начала там 10 скобок на 5 лексем. А главное этот мусор дублирует уже имеющиеся средства и никакого профита не приносит. Типичный кодерский онанизм.

bread
()
Ответ на: комментарий от Crocodoom

Думаю, никакого продолжения этих слов (в виде конкретного кода) от тебя тоже ожидать не стоит?.. А ну да, это же толксы.

ну напиши, например, &str.join функциональщиной

более частный пример:

краткий и эффективный &str join

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от MyTrooName

Попробую:

fn reverse_words(s: &str) -> String {
  s.split_whitespace().rev().fold(String::new(), |acc, s| acc + " " + s)
}
Если это плохо, то рассказывай, почему. Я не пишу на Rust, могут быть косяки. Но пишу на Python и Haskell, поэтому и вписался за ФП в споре против ИП. А синтаксис Rust на ходу подгуглил.

Crocodoom ★★★★★
()
Ответ на: комментарий от I60R
(0..10).forEach(::println)

Это не эквивалент.

fn println<T: Display>(x: T) {
    println!("{}", x);
}

(0..10).for_each(println); // так же передаётся функция, а не замыкание
numas13
()
Ответ на: комментарий от Crocodoom

Если это плохо, то рассказывай, почему

как минимум, у тебя в начале лишний пробел вылезет

Но пишу на Python и Haskell

напиши на python или haskell, меня устроит

MyTrooName ★★★★★
()
Ответ на: комментарий от numas13

Слабо написать inplace вариант? (:

Оставаясь при этом в функциональной парадигме? Естественно слабо, по определению функциональной парадигмы (:

Crocodoom ★★★★★
()
Ответ на: комментарий от MyTrooName

вообще-то это и есть inplace, если я правильно понимаю, что ты имеешь ввиду

Нет, он возвращает строку на куче, в которую записывает результат.

numas13
()
Ответ на: комментарий от numas13

Можно ещё так развернуть

(0..10).forEach({ i -> println(i) })
Вроде всё то же самое

I60R ★★
()
Ответ на: комментарий от numas13

аа, настолько инплейс...

я бы даже императивно не стал так делать) и все равно наверняка придется аллоцировать, хотя бы массив индексов

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

как минимум, у тебя в начале лишний пробел вылезет

напиши на python или haskell, меня устроит

Если в Rust есть fold без начального элемента (в Haskell и Python есть, код ниже), то получится и в Rust без лишнего пробела.

Haskell

reverse_words s = foldr1 (\a b -> a ++ " " ++ b) (reverse (words s))
λ> reverse_words "alpha beta gamma"
"gamma beta alpha"

Python

def reverse_words(s):                                                           
    return str(reduce(lambda a, b: a + " " + b, reversed(s.split(' ')))) 
>>> reverse_words('alpha beta gamma')
'gamma beta alpha'

Crocodoom ★★★★★
()
Ответ на: комментарий от MyTrooName

Пожалуйста:

def reverse_words(s):                                                           
    return str(reduce(lambda a, b: a + " " + b, reversed(s.split())))           

>>> reverse_words('alpha beta  gamma')
'gamma beta alpha'

Кстати, можно join вернуть, раз уж мы в Python перешли с Rust. Будет немного короче.

def reverse_words(s):                                                           
    return str(' '.join(reversed(s.split())))  

Crocodoom ★★★★★
()
Ответ на: комментарий от Crocodoom

первый вариант упадет на пустой строке

`join` в расте тоже отсутствует (т.е. он есть, но не на итераторе, а на векторе, который придется аллоцировать. в питоне, конечно, на спичках не экономят)

короче, проблема в наборе функциональных примитивов. в какой-то момент тебе придется тащить структуру состояния через цепочку вызовов, или крутить монады. первое читается ужасно, второе - императивщина для инвалидов^Wхаскелистов

MyTrooName ★★★★★
()
Ответ на: комментарий от Crocodoom

короче, решение с join я объявляю читерским и не принимаю) фикси эксепшн

MyTrooName ★★★★★
()
Ответ на: комментарий от Virtuos86

приведенных мною примерах map способствует сокращению кода

но не удобству прочтения

Joe_Bishop
()
Ответ на: комментарий от Crocodoom

полное тз было - краткий и эффективный join на расте. я надеялся на твое решение на питоне, которое можно было бы один-в-один перевести на раст так что код не раздуется и не будет тормозить на пустом месте.

альтернативное полное тз - составить контрпример тз (so meta), доказывающий, что на данном языке (скажем, питоне) функциональщина ущербна без императивщины (для тебя - опровергнуть, что, конечно, сложнее)

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

MyTrooName ★★★★★
()
Ответ на: комментарий от Crocodoom

Если это плохо, то рассказывай, почему.

Например, вполне возможно лучше определить суммарную длину результата и сразу выделить место под него, и только затем заполнить, дабы уменьшить число выделений памяти. По-хорошему, её (длину) можно найти ещё на этапе расщепления изначальной строки.

Joe_Bishop
()
Последнее исправление: Joe_Bishop (всего исправлений: 2)
Ответ на: комментарий от MyTrooName

полное тз было - краткий и эффективный join на расте. я надеялся на твое решение на питоне, которое можно было бы один-в-один перевести на раст так что код не раздуется и не будет тормозить на пустом месте.

Ну значит я делал не то ТЗ :) Я готов переписать небольшой императивный сниппет на функциональный, чтобы опровергнуть «ущербность ФП». При этом если в каком-то конкретном языке нет какого-то конкретного инструмента из ФП, то это не мои проблемы, и не проблемы ФП. Например оказалось, что в Rust не завезли фолды без начального значения, а это довольно базовая функция, поэтому я съехал на Haskell и Python. Сейчас ты начинаешь объявлять какие-то стандартные библиотечные функции Python читерскими - это ок, я понимаю, почему ты так говоришь. Но оставляю за собой право съехать и с Python, ибо в нём как раз недостаток встроенного функционального инструментария (3-4 функции + list comprehensions + итераторы, по сути всё) как раз компенсируется «читерской» библиотекой. Так что если в итоге это нельзя будет написать на Python, я напишу на Haskell. Но постараюсь остаться в рамках Python.

если я дам тебе реальный таск, ты попросишь денег

Смотря какой таск. Если это останется в рамках какого-то преобразования строки (с чего мы начинали), то не попрошу.

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

Короче while(true). Долбиться в стену мне не интересно, спасибо.

Crocodoom ★★★★★
()
Ответ на: комментарий от Crocodoom

При этом если в каком-то конкретном языке нет какого-то конкретного инструмента из ФП, то это не мои проблемы, и не проблемы ФП.

согласен

поэтому я съехал на Haskell и Python

это не ты съехал с раста на питон, а я тебе любезно позволил, т.к. свой код на расте ты даже запустить не попытался, иначе заметил бы, что он не работает

Так что если в итоге это нельзя будет написать на Python, я напишу на Haskell

крайне желательно на питоне, чтобы сравнить с равносильной императивщиной.

Смотря какой таск

вот следующая итерация: дан итератор по словам (в случае хаскеля - список, в случае питона сойдет `text.split()`). нужно их разбавить пробелами и \n, чтобы по ширине влезло в 80 символов

while(true)

предупреждаю, дальше по плану перенос внутри слов с упрощенными правилами разбиения на слоги

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 2)
Ответ на: комментарий от Aswed

вангую, что он имеет ввиду родную ленивость хаскеля, которая в питоне и расте заменена wrapperом, возвращаемым из map

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

это не ты съехал с раста на питон, а я тебе любезно позволил

И то, и то. Если бы ты «не позволил», я бы просто сказал, что в раст не завезли фолд без начального значения, поэтому элегантного кода в любом случае не будет, и умыл бы руки.

Я даже могу объяснить, почему здесь это принципиально важно, а не придирка: потому что операция «склеить два слова с пробелом между ними» тупо не имеет нейтрального элемента. Большинство нужных операций имеют нейтральный элемент, например обычная конкатенация строк, сумма или произведение чисел — это "", 0, 1 соответственно. Для операций с нейтральными элементам отдельный фолд без начального значения не нужен, можно обойтись общим фолдом. Но не в случае «конкатенации с пробелом». Как раз для таких случае в остальные языки завезли специальный фолд, но (пока) не в Rust.

свой код на расте ты даже запустить не попытался, иначе заметил бы, что он не работает

Ну почему. Запустил на первом попавшемся сайте, уж некомпиляющийся код я бы не стал выкладывать. Но лишний пробел в начале не заметил. Ну бывает.

вот следующая итерация: дан итератор по словам (в случае хаскеля - список, в случае питона сойдет `text.split()`). нужно их разбавить пробелами и \n, чтобы по ширине влезло в 80 символов

предупреждаю, дальше по плану перенос внутри слов с упрощенными правилами разбиения на слоги

Чтоб ты не халявил, я напомню, что я предлагал свои «услуги» по переписыванию (небольшого) императивного сниппета в функциональный стиль. Так что императивный код всего это добра в студию. Причём окончательный, без добавлений «а, ну на самом деле там надо было вот так».

Crocodoom ★★★★★
()
Ответ на: комментарий от Crocodoom
def tw(text, width=80, sep=' ', linesep='\n'):
    line = 0 # current line length
    result = []

    for word in text.split():
        if line + len(sep) + len(word) > width:
            result.append(linesep)
            line = 0
        if line > 0:
            result.append(sep)
            line += len(sep)
        result.append(word)
        line += len(word)
    return ''.join(result)
MyTrooName ★★★★★
()
Ответ на: комментарий от Crocodoom

Причём окончательный, без добавлений «а, ну на самом деле там надо было вот так».

не обещаю, что не без багов. никто такого в здравом уме не обещает

MyTrooName ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.