LINUX.ORG.RU

Привычки и Rust

 , ,


0

4

На сишке привык циклы с предусловием писать так:

while(k--) {
   ...
}

В Rust это превращается (насколько я понимаю) в

while k > 0 {
    k -= 1;
    ...
}

Что не совсем красиво и неочевидно, с первого взгляда.
Как принято в Rust записывать циклы с предусловием, чтобы красиво и понятно?

★★★★★

for k in (0..k).rev() {
    // ...
}
anonymous
()

Лучше от while переходить к for, если знаешь заранее количество итераций, это в любых языках.

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

Счётчик внутри цикла - это правильно, с while придётся счётчик объявлять в другой области видимости, с while возможны баги по этой причине; while хорош для всяких рекурсий и т.п.

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

Ну это понятно: там где счетчик нужен, конечно for.

это неправда. Часто while намного очевидней. while(i++)while(i < 100), зачем тут for городить? К тому же while хорошо имитирует loop в языках где его нетwhile(true). for — вообще самый уродская и ненужная конструкция.

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

ага, вначале к фору придумали синтаксический сахар в виде while, потом стали коллективно думать как бы for искоренить совсем и оставить один while дабы быстрей уходить от императивной записи, и тут ВНЕЗАПНО оказывается что вайл не_нужен! Прямо санта-барбара какая-то :)

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

интересно, зачем топикстартеру вообще сдался счётчик. В первую очередь нужно избавиться от него. Если там нужно посчитать количество элементов списка, то намного лучше дернуть .count() у стандартной коллекции (в этом вашем расте ведь есть коллекции в стандартной библиотеке?)

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)

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

    let mut v = vec![10,9,8,7,6,5,4,3,2,1,0];
    for (i,x) in v.iter_mut().enumerate() {
        *x = i;
    }
Если нужно пробежаться по значениям от n до единицы, то
    let n=10;
    for i in (1..n+1).rev() {
        print!("{} ", i);
    }

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

А что,циклы и счетчики используются только для списков?

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

Если нужно пробежаться по значениям от n до единицы, то

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

#![feature(inclusive_range_syntax)]

fn main() {
    let n=10;
    for i in (1...n).rev() { // inclusive_range_syntax
        print!("{} ", i); // 10 9 8 7 6 5 4 3 2 1 
    }

    for i in (1..n+1).rev() {
        print!("{} ", i); // 10 9 8 7 6 5 4 3 2 1 
    }
}
anonymous
()
Ответ на: комментарий от filequest

Часто while намного очевидней. while(i++)while(i < 100)

тонко

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

Речь о случаях, где он не нужен.

Зачем ты тогда выкатил пример со счетчиком?

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

Почему?

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

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

Скоро будем путаться в точках.

А ты из тех, кто в трёх точках заблудится?

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

Там вычисляется длина и цикл надо выполнить ровно len раз. Алгоритм Брезенхэма.
Сейчас вот так сделал:

for _ in 0..len {
   ...
}

mersinvald ★★★★★
() автор топика

Кстати, раз уж такая пьянка. Можно ли в Rust, Swift или другом современном ЯП при помощи for-in итерироваться через массив при том, что иногда в зависимости от содержимого элемента нужно взять следующий и обработать его по-особенному?

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

Можно ли в Rust, Swift или другом современном ЯП при помощи for-in итерироваться через массив при том, что иногда в зависимости от содержимого элемента нужно взять следующий и обработать его по-особенному?

for (elem, next_elem) in array.iter().zip(array[1..].iter()) {
    if should_work_with_next(elem) {
        work_with(next_elem);
    }
}
anonymous
()
Ответ на: комментарий от mersinvald

и на каждой итерации надо сделать что? Это выражается в логике фильтров, или map-reduce? Я к тому, чтобы помедетировать над

let names = vec!["Jane", "Jill", "Jack", "John"];
    
let total_bytes = names
    .iter()
    .map(|name: &&str| name.len())
    .fold(0, |acc, len| acc + len );
stevejobs ★★★★☆
()
Ответ на: комментарий от anonymous

Кстати в ночных сборках есть расширение

Кстати, а есть ли где-нибудь полный список фичегейтов в текущем найтли?

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

Это выражается в логике фильтров, или map-reduce?

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

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

В каких, говоришь, эффектах, в побочных?

Haskell

module Bitmap.Line(line) where
 
import Bitmap
import Control.Monad
import Control.Monad.ST
import qualified Data.STRef
 
var = Data.STRef.newSTRef
get = Data.STRef.readSTRef
mutate = Data.STRef.modifySTRef
 
line :: Color c => Image s c -> Pixel -> Pixel -> c -> ST s ()
line i (Pixel (xa, ya)) (Pixel (xb, yb)) c = do
    yV <- var y1
    errorV <- var $ deltax `div` 2
    forM_ [x1 .. x2] (\x -> do
        y <- get yV
        setPix i (Pixel $ if steep then (y, x) else (x, y)) c
        mutate errorV $ subtract deltay
        error <- get errorV
        when (error < 0) (do
            mutate yV (+ ystep)
            mutate errorV (+ deltax)))
  where steep = abs (yb - ya) > abs (xb - xa)
        (xa', ya', xb', yb') = if steep
          then (ya, xa, yb, xb)
          else (xa, ya, xb, yb)
        (x1, y1, x2, y2) = if xa' > xb'
          then (xb', yb', xa', ya')
          else (xa', ya', xb', yb')
        deltax = x2 - x1
        deltay = abs $ y2 - y1
        ystep = if y1 < y2 then 1 else -1

Clojure:

(defn draw-line
  "Draw a line from x1,y1 to x2,y2 using Bresenham's, to a java BufferedImage in the colour of pixel." 
  [buffer x1 y1 x2 y2 pixel]
  (let [dist-x (Math/abs (- x1 x2))
   dist-y (Math/abs (- y1 y2))
   steep (> dist-y dist-x)]
    (let [[x1 y1 x2 y2] (if steep [y1 x1 y2 x2] [x1 y1 x2 y2])]
      (let [[x1 y1 x2 y2] (if (> x1 x2) [x2 y2 x1 y1] [x1 y1 x2 y2])]
  (let  [delta-x (- x2 x1)
     delta-y (Math/abs (- y1 y2))
     y-step (if (< y1 y2) 1 -1)]
 
    (let [plot (if steep 
       #(.setRGB buffer (int %1) (int %2) pixel) 
       #(.setRGB buffer (int %2) (int %1) pixel))]
 
      (loop [x x1 y y1 error (Math/floor (/ delta-x 2)) ]
        (plot x y)
        (if (< x x2)
    ; Rather then rebind error, test that it is less than delta-y rather than zero
    (if (< error delta-y) 
      (recur (inc x) (+ y y-step) (+ error (- delta-x delta-y)))
      (recur (inc x) y            (- error delta-y)))))))))))

http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm

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

Во, хашкел и колоша, как всегда слили, JS

function bline(x0, y0, x1, y1) {
 
  var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
  var dy = Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1; 
  var err = (dx>dy ? dx : -dy)/2;
 
  while (true) {
    setPixel(x0,y0);
    if (x0 === x1 && y0 === y1) break;
    var e2 = err;
    if (e2 > -dx) { err -= dy; x0 += sx; }
    if (e2 < dy) { err += dx; y0 += sy; }
  }
}
Кстати, у тебя там скорей всего тоже без сайд эффектов не обошлось, уж слишком подозрительно вот это вот выглядит

mutate errorV $ subtract deltay

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

о! анонiмус. Как всегда чужим кодом размахиваешь? Сказать то что хотел? что кто-то осилил это на язычке для браузеров написать? молодца, чо

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

JS

А теперь окончательно слепи это в одну строчку, чтобы всем было ясно, какой JS лаконичный.

уж слишком подозрительно вот это вот выглядит

Это как раз нормально, оно останется в функции и наружу не вылезет.

без сайд эффектов не обошлось

Таки да, там image модифицируется вместо того, чтобы возвращать новый. Вот я и недоумеваю, что чувак хотел этим сказать. Там явно не мапредьюс, и побочные эффекты есть. Или он типа считает, что если на цацкеле написано - значит никаких побочных эффектов?

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

я обычно своим размахиваю. Просто тут чужой кстати подвернулся. Кстати, я отвечал на пост где тоже был чужой. А вот история, как я своим попустил

Крестики-нолики на Хацкеле. (комментарий)

наслаждайся

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

Ба! Крестики-нолики, которые в любой книге «Уэб для домохозяек» в первых главах пишут, ты считаешь достижением. Ох лол. Какой же ты ... никакой

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

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

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

Я кстати из головы писал. Я книги по JS вообще не читаю. А у тебя, кстати, попаболь, это видно, и это приятно

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

Решение на Rust =)

macro_rules! full_while (
    ($e:expr; $body:block )
        => (
            let mut x = true;
            loop {
                x = $e;                  
                if (true != x) { break; }
                $body;                                  
            }
        );
);

fn post_decrement(r: &mut i32) -> i32 {
    let temp = *r;
    *r = *r - 1;
    return temp;
}

fn main() {
    let mut i = 10;   
    full_while!(post_decrement(&mut i) > 0; {         
        println!("{}", i);
    });
}

На самом деле работает и просто вот так:

fn post_decrement(r: &mut i32) -> i32 {
    let temp = *r;
    *r = *r - 1;
    return temp;
}

fn main() {
    let mut i = 10;   
    while (post_decrement(&mut i) > 0) {         
        println!("{}", i);
    }
}

Но полная версия выше показывает, что нужно делать нытикам, когда они уже не в силах «жрать что дают» xDDD

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

Побочные эффекты там есть, мапредьюса там нет. Никаких твоих слов оно не подтверждает, никаких моих - не опровергает.

ожидаемо

Что ожидаемо? Что ты выкатишь левую цацкельную пасту с розеточки, и у тебя спросят, нахера ты это сделал? Ожидаемо, да.

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

Спецолимпиада вроде еще не скоро, а вы так усердно тренируетесь. Отдохните, успеете еще.

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

Через for-in нельзя. Разве что continue дергать. Однако можно итераторы дергать вручную

let mut iter = vec_of_some.iter();
loop {
  let head = iter.next();
  match head {
    None => break,
    Some(obj) => ...
  }
}
Вот тут можно по желанию дернуть iter.next несколько раз

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

Однако можно итераторы дергать вручную

Ппц изврат. Твой цикл записать можно проще:

let mut iter = vec_of_some.iter();
while let Some(obj) = iter.next() {
    ...
}
anonymous
()

Как справедливо отметил анонимус, ты зачем-то написал цикл while со счетчиком, который красиво и очевидно записывается через for.

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

for вообще пишут одни лишь ретрограды типо меня, хипстота придумала лямбды и функциональщину, мапы там всякие, пердусы...

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