Обновить
231
0
Всеволод @torkve

Пользователь

Отправить сообщение
В том, что вы ставите вопрос, что же делать, если команда подсела на какой-нибудь viber или skype, но отвечаете на какой-то другой: «некоторые запрещают, некоторые игнорируют, но это всё плохо, а вот у нас можно логиниться через ldap!».
Задаёте вопрос: «Почему не на нашем сервере, у нас важная приватная информация», и сами же в ответ рассказываете о чём-то совершенно другом: «а вот мы посвящаем разработке нашего продукта всё рабочее время, поэтому вы должны доверять эту информацию нам!». И где приватность, где гарантии безопасности? Я молчу уж о том, что сейчас все вменяемые поставщики таких SaaS-решений постепенно осваивают такие удивительные способы, как дать покупателю docker-контейнер с инсталляцией, чтобы он получил систему под собственным контролем.
У Вас написано довольно много ереси и глупостей:
1. Любые данные в Python это об<ъекты.
2. Если объекты «одинаковы», то они хранятся по одному адресу в памяти. Иными словами, a == b и id(a) == id(b) это эквивалентные утверждения.

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> id(a) == id(b)
False

Касательно именно чисел Вам надо почитать, что такое free list.
Первое правило составления паролей: никому не говорить о своих правилах составления паролей.
Урок окончен.
Существует два основных режима работы в редакторе. В первом он пищит, а во втором — всё портит. Для продвинутых пользователей имеется нулевой режим, который был единственным в полумифическом предшественнике vi, который, по легенде, назывался v. В нулевом режиме редактор управляется смайликами. Попробуйте, например, ввести команду :%s).):)g

В соответствии с некоторыми апокрифами, существует легендарный Третий режим, в котором редактор делает всё за пользователя сам. Вызывать третий режим, согласно преданию, могут джедаи не ниже третьего уровня.
©

И это уже четыре!
Хм, попробовал vimchat, пришлось патчить python-xmpp, который иначе не заводился, плюс ростер выглядит примерно вот так:
image
Как Вы им пользуетесь?
Там всё-таки избыточные режимы есть, вроде того же operator-pending, который суть normal посреди команды.
Опять же, можно спорить, имеет ли смысл объединять visual, line-visual, block-visual в один режим или нет. Поэтому и «примерно 8» :)
текстовый редактор Vim, обладает двумя режимами работы

На самом деле примерно восемью :)
Не хочу рассказывать Вам про широкоиспользуемый telnet, но…
А ещё в эти управляющие символы входят перенос строки \n, любимый в windows возврат каретки \r, знак табуляции \t — это только то, что постоянно встречается любому пользователю, про стандартные терминальные escape, EOT, и прочие bell и backspace даже говорить не хочу (хоть и можно придумать какую-нибудь увлекательную систему, где они не должны быть вводимыми, а должны распознаваться и обрабатываться непосредственно средой).
Уберите в моём втором варианте последний unwrap, будет как раз то, что надо.
А чего я, простите, должен добиться? В оригинальном коде используется проверка с вызовом удалённого сейчас макроса fail!, заменой которого в данной ситуации и является panic!, поэтому unwrap делает ровно то, что нужно.
Вообще вся эта конструкция на расте записывается так:
let ratio = checked::div(x, y).unwrap();
let ln = checked::ln(ratio).unwrap();
let sqrt = checked::sqrt(ln).unwrap();

Либо, если хочется именно пайпа, то делается примерно как в хаскелле:
checked::div(x, y).and_then(|ratio| checked::ln(ratio).and_then(|ln| checked::sqrt(ln).unwrap()))
Мне кажется, что для таких вещей вообще надо заимствовать синтаксис перла, который, как правильно пишут комментом ниже, отчасти спародировали в питоне:
doSomething() if x == 3;
doOtherThings() unless x == 4;

Для тернарного оператора, емнип, в перле как раз аналога нет, но подобная реверсивная запись для чтения достаточно удобна.
Это всё-таки не вариант тернарного оператора, а популярная в функциональных языках идея, что каждое выражение возвращает какое-то значение. Например:
let y = if x == 5 then 10 else 15 in (* ocaml *)
let y = match x with | 5 -> 10 | _ -> 15 (* то же самое, только pattern matching *)

auto y = [x](){if (x == 5) return 10 else return 15;}(); // аналог из C++
Просто, чтобы цифра с пятью нулями Вас не очень пугала. Посмотрите, сколько стоит заявка на регистрацию доменной зоны первого уровня. Гарантии, что выдачу домена одобрят, при этом нет.
Ну, в современных нормальных дистрибутивах это не проблема.
Вот вам в помощь: github.com/rust-lang/rust/wiki/Doc-building-for-ios
Для линуксового ARM в качестве target я указывал arm-unknown-linux-gnueabi.
Насколько мне известно, раст успешно собирается кросскомпиляцией под арм и дальше отлично работает (собственно, движок Servo предназначен в первую очередь для мобильных платформ). Самому мне правда собрать не удалось, памяти не хватает.
Освобождать память надо отдельно, да.
В моём случае строка раскручивалась для передачи в exec(), поэтому об утечке речи не шло :)
Я когда-то как раз практически по мотивам пропаганды Стёпы попробовал покоммитить в живой проект и делился во внутренних обсуждениях впечатлениями в жанре «поток сознания». Возможно, Вам будет интересно:
Неоднократно воспетые лайфтаймы и референсы. Это прикольно, но очень непривычно. Реально приходится что-то перестраивать в мозгах, чтобы нормально это воспринимать. Сначала кажется, что «ну, всё просто, есть owned pointer, есть мутабельная ссылка, есть иммутабельная, я про всё это читал, всё просто». Потом оказывается, что есть мутабельные строки вида String и иммутабельные вида &str, которые суть всем знакомый StringView. Потом ты начинаешь их складывать в массив и понимаешь, что массивов бывает тоже два вида — мутабельный вектор Vec и лёгкий слайс вида &[T]. При этом, решив в какой-то момент использовать где-то для простоты слайс, выясняешь, что пустых слайсов не бывает. Может, я их так и не нашёл, не знаю. Но нельзя просто так взять и написать возвращающую слайс функцию, если в какой-то из её веток ты хочешь вернуть пустой список.

С указателями всё тоже не так легко, как хотелось бы. В какой-то момент мне потребовалось оперировать не конкретными типами, а интерфейсами (trait в расте). Их совершенно закономерно нужно, как и в C++, хранить исключительно в виде указателей — Box, где Box — аналог std::unique_ptr. И вот в этом месте лично я проклял всё, потому что обнаружил синтаксис, весьма схожий со всякими const char const *, только более запутанный. Если вы хотите принимать в своей функции, скажем, Box (который, напоминаю, сам по себе умный указатель), вы можете написать:

fn fun(dgst: Box<Digest>) // immutable owned variable
fn fun(dgst: &Box<Digest>) // immutable reference to variable
fn fun(dgst: &mut Box<Digest>) // mutable reference to variable
fn fun(mut dgst: Box<Digest>) // mutable owned variable
fn fun(mut dgst: &Box<Digest>) // mutable variable with immutable reference
fn fun(mut dgst: &mut Box<Digest>) // mutable variable with mutable reference


Но это я сейчас такой умный, а поначалу я без всякой задней мысли заиспользовал первый вариант и, будучи уверенным, что я сделал move данных в свою функцию и могу дальше делать с ними всё, что душа пожелает, попытался передать mut-ссылку на этот указатель дальше. А оказалось, что хрен. Целый час убитого выходного открыл мне, что хоть я в этой функции и единоличный обладатель данных, это всё равно не значит, что они мутабельны — мутабельную ссылку на них взять нельзя. Я конечно сам виноват, но это очень большая разница с C++, где наоборот, надо специально говорить const для неизменяемости. Функциональным задротам будет проще, у них в языках обычно тоже всё иммутабельно по умолчанию, как в расте.

Зато сами trait'ы офигенны. Это вот очень круто, что можно придать любому типу желаемую функциональность, не редактируя сам тип. По большому счёту это работает, как всякие визиторы с перегрузками из C++, только намного читаемее и удобнее в написании и использовании. Ну и концепты, так и не попавшие в плюсовый стандарт, есть из коробки.

Есть всякая удобная информация, предоставляемая компилятором, которая удобнее и понятнее, чем традиционные ifdef'ы:

#[cfg(target_os = "linux")]
fn myfun() {
  ... 
}
#[cfg(target_os = "macos")]
fn myfun() {
  ...
}


С другой стороны что-то пока прямо просит его поюзать, но пока недоступно: заголовок, идентифицирующий при компиляции библиотеку и её версию, — #![crate_id = «chroot#1.0.0»] — достать из кода нельзя, информацию приходится дублировать.

Взаимодействие с сишными функциями не так удобно, как было обещано. Нет, FFI есть и с ним всё хорошо (а функции libc по умолчанию прокинуты в стандартную библиотеку в забавном виде: libc::funcs::posix88::unistd::execvp), но при этом строки в Rust хранятся без \0, что несколько огорчает libc. Несмотря на то, что метод преобразовании строки строки существует, это, во-первых, явно вызывает реаллокацию памяти, а во-вторых, чтобы передать строку из argv (который имеет тип Vec) в libc-функцию, надо написать вот так:

argv.get(1).as_slice().to_c_str().unwrap() // Vec<String> -> String -> &str -> CString -> *c_char
А не логичнее ли поднять тор-прокси и научить свой днс отдавать .onion-адреса? Кажется, в такой ситуации апач и кастомные скрипты под каждый сайт будут не нужны.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность