LeshaInc
Пользователи-
Публикации
777 -
Зарегистрирован
-
Посещение
-
Победитель дней
68
Тип публикации
Блоги
Профили
Форум
Багтрекер
Магазин
Все публикации пользователя LeshaInc
-
MoonJam — джем с привкусом луны // завершён
LeshaInc прокомментировал Fingercomp запись в блоге в Fingercomp's Playground
Я тоже, к слову, участвую, идейка есть, по мне прикольная. Удачи всем! :P -
54 duovigintillion 308 unvigintillion 428 vigintillion 790 novemdecillion 203 octodecillion 478 septendecillion 762 sexdecillion 340 quindecillion 52 quattuordecillion 723 tredecillion 346 duodecillion 983 undecillion 453 decillion 487 nonillion 23 octillion 489 septillion 987 sextillion 231 quintillion 275 quadrillion 412 trillion 390 billion 872 million 348 thousand 475
-
Ржавеем по полному! #3. Функции и указатели.
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
В каком смысле новый? 4 часть раста сегодня. -
Ржавеем по полному! #3. Функции и указатели.
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
Сегодня. -
Эта "эмуляция" ни капли не похожа на многопоточность. :/
- 12 ответов
-
- математика
- программирование
- (и ещё 4 )
-
Где многопоточность? Может я плохо вижу, к окулисту пора сходить?
- 12 ответов
-
- 1
-
-
- математика
- программирование
- (и ещё 4 )
-
Если вы когда нибудь сталкивались с созданием серверов под OpenOS, вам знакома проблема блокирования всего компьютера. Его нельзя использовать, пока сервер не выключится. Некоторые придумывали свои велосипеды, которые запускали event.listen или event.ignore. Но не то это! Для таких вещей существует rc, в OpenOS. Сейчас я расскажу вам, что это за зверь, где он живет и зачем он нам. Немного теории Итак, все скрипты для rc хранятся в папочке /etc/rc.d/. Любой файл с расширением .lua, который находится там, является rc-скриптом. У такого скрипта все глобальные функции это команды. Запустить такую команду можно командой rc <имя скрипта, без расширения> <имя команды>. Например если мы создадим глобальную функцию start в файлике /etc/rc.d/test.lua, то запустив команду rc test start эта команда выполнится. Все просто. Получить список команд определенного скрипта можно при помощи команды rc <имя скрипта, без расширения>. Например так: rc test. RC сам создает некоторые команды, хотя мы их можем переопределить: enable/disable. Соответственно включают/выключают скрипт. Все включенные скрипты получат команду start при запуске компьютера. restart если есть start и stop. Перезапускает скрипт, то есть поочередно запускает stop и start. Каждый скрипт можно конфигурировать. Конфиг находится в /etc/rc.cfg. Формат файла прост: <имя скрипта> = <конфиг: все что угодно, таблица, текст, число> По сути это обычный луа-файл, все глобальные значения из которого считаются полями. Каждый скрипт может получить доступ к своему конфигу. Конфиг записывается в переменную args. С теорией покончено, приступим к практике! Практика Я предлагаю написать простой эхо-сервер. Он будет слушать определенный порт (из конфига), и отвечать на любое сообщение эхом. Начнем! Создадим файл /etc/rc,d/echo.lua, и начнем писать в нем код. Нам понадобятся некоторые переменные -- нам понадобятся библиотека event -- что бы установить свой обработчик событий local event = require("event") -- еще нам нужна библиотека computer -- что бы подключить компонент `modem` local component = require("component") -- будем считать количество ответов -- зачем? для диванных аналитиков конечно! local count = 0 -- будем хранить текущее положение -- что б никто не запустил случайно сервер два раза local started = false -- сюда запишем прокси модема, когда убедимся что он есть local modem -- а сюда запишем рабочий порт local port Создадим обработчик события modem_message. Он будет вызываться при каждом сообщении по сетевой карте. -- функция ниже будет запускаться -- при каждом сообщении по сетевой плате local function onModemMessage(_, _, snd, prt, _, ...) -- `_` в нашем понимании - неиспользуемый аргумент -- если порт сообщения не совпадает с портом -- из конфига, выходим print(prt) if prt ~= port then return end -- добавим еденицу к счетчику count = count + 1 -- здесь мы уверены, что modem существует -- так как обработчик поставится только если у нас есть модем modem.send(snd, prt, ...) -- / | \ -- получатель, порт, данные -- просто напросто пересылаем отправителю то что он -- отправил нам =) end Теперь мы добавим команду start, которая запустит наш сервер. -- функция ниже глобальная, `local` нет. -- потому _rc_ ее будет смело считать командой -- а команда эта будет запускать наш сервер function start() -- мы должны проверить, есть ли у нашего сервера -- сетевая карта if not component.isAvailable("modem") then -- если ее нет, мы выводим ошибку и выходим io.stderr:write("Сетевая карта не найдена!") return end -- еще нам нужно проверить, выключены ли мы -- если это не так, снова ошибка if started then io.stderr:write("Сервер уже запущен!") return end count = 0 -- сбросим счетчик started = true -- теперь мы знаем, что с этого момента -- сервер включен. port = args or 666 -- args это переменная, в которую _rc_ запишет данные из конфига -- конфиг находится в /etc/rc.cfg -- но если в конфиге порт не настроен, используем дефолтный modem = component.modem -- мы проверили, что модем существует, -- поэтому смело его подключаем -- откроем порт modem.open(port) -- нам нужно сделать так, что бы все сообщения -- по сетевой карте обслуживались нашей функцией event.listen("modem_message", onModemMessage) -- ну а теперь мы точно включились! end Куда без команды stop? Добавим ее! -- эта функция тоже глобальная, поэтому считаем ее командой -- эта команда остановит сервер function stop() -- мы должны проверить, включен ли вообще сервер -- если он не включен, какой толк его выключать, верно? if not started then -- если он не включен, выводим ошибку и выходим io.stderr:write("Сервер уже выключен!") return end count = 0 -- опять же сбрасываем счетчик started = false -- запоминаем, что теперь -- сервер выключен -- теперь нам нужно по-настоящему выключить сервер event.ignore("modem_message", onModemMessage) -- все! с этого момента сервер выключен, и не принимает сообщение end Еще самая малость, добавим команду printCount, которая будет отображать количество полученных сообщений. -- и это тоже команда, думаю вы понимаете -- а эта команда напишет количество отправленных сообщений function printCount() -- выводить информацию будем только если сервер не запущен -- поэтому выведем ошибку, если он не включен if not started then io.stderr:write("Сервер выключен!") return end print(count) -- пишем количество подключений -- диванные аналитики ликуют! end Ну вот и все, программа сделана, диванные аналитики ликуют, инженеры недоумевают. Полный код: Время QA! Симулируем Васю Пупкина... А вот уже на другом компьютере отправлено сообщение на работающий сервер. Счетчик тоже работает. Установим значение в конфиге. Проверим... Все работает, инженеры ликуют! Такую систему очень удобно использовать для всяческих серверов. Сервер может спокойно работать в фоне, а в главном потоке спокойно можно запускать консоль сервера, интерпретатор луа, rm -rf / ... Enjoy!
-
Ржавеем по полному! #3. Функции и указатели.
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
Если что то непонятно, вопросы пишите в ирку! Выслушаем всех! -
Rust Сегодня познакомимся с функциями и указателями, а также по мелочи: зоны видимости. Функции Функции в расте похожи на функции в Си, Jawa, луа. Для создания функции используется ключевое слово fn. fn add(a: i32, b: usize) -> usize { a + b} После ключевого слова fn идет имя функции, далее в скобках указываются аргументы через запятую, и опционально, стрелочка -> и возвращаемый тип. Указывая аргументы нужно указывать тип аргумента после символа :. Функции в которых не указано возвращаемое значение, возвращают () Ключевое слово return возвращает значение из функции. fn answer() -> i32 { return 42;} return не всегда обязателен, позже разберемся где он нужен, а где не нужен. Указатели Указатели в расте гораздо безопаснее чем указатели в Си. Создать указатель на неизменяемые данные можно при помощи &. let a = 10;let pa = &a; Получить значение из указателя можно при помощи символа *. let a = 10;let pa = &a;println!("a = {}; *pa = {}; a + a = {}; *pa + *pa = {}", a, *pa, a + a, *pa + *pa);// \--> a = 10; *pa = 10; a + a = 20; *pa + *pa = 20 Но в некоторых случаях писать * не обязательно. let a = 10;let pa = &a;println!("a = {}; pa = {}; a + a = {}; pa + pa = {}", a, pa, a + a, pa + pa);// \--> a = 10; pa = 10; a + a = 20; pa + pa = 20 Раст сам все поймет, за что ему спасибо. Иногда мы хотим создать изменяемую ссылку. Для этого используется &mut. let mut a = 10;let pa = &mut a;*pa += 1; // здесь * обязателен println!("{}", pa); //--> 11 Если мы хотим изменить значение на которое указывает наш указатель, * обязателен. Без него раст не может понять, мы хотим присвоить новый указатель, или значение. В расте используется концепция "либо один писатель, либо много читателей". В примере выше, переменную a прочитать мы уже не сможем, и писать в нее тоже не сможем, так как она передана указателю pa. pa – писатель. Бывают случаи когда мы хотим присвоить указателю новое значение, то есть сделать так, что бы указатель указывал на другие данные. Это тоже предусмотрено. let mut a = 10;let mut b = 20;let mut pa = &mut a; println!("{}", pa); // --> 10 pa = &mut b; println!("{}", pa); // --> 20 println!("{}", a); // --> 10// ^ ошибка, a уже имеет писателя, читателя не создать. println!("{}", &a); // --> 10// ^- ошибка, a уже имеет писателя, читателя не создать. println!("{}", &mut a); // --> 10// ^----- ошибка, a уже имеет писателя, еще одного не создать. Как видите, все правила про "либо один писатель, либо много читателей" работают даже если на a уже не указывает ничего. Зоны видимости Зоны видимости в расте ничем не отличаются от тех же в Луа. fn main() { let a = 10; { let b = 20; println!("{}", a); // --> 10 println!("{}", b); // --> 10 } println!("{}", a); // --> 10 println!("{}", b); // --> 10 // ^ ошибка, b нет.} Хочу отметить только, что в расте все переменные удаляются когда уйдут из зоны видимости. Исключением являются только значения которые возвращаются в функциях. Хозяйке на заметку: { и ) это аналог do и end в Луа. На сегодня все. Извините что запоздал с 3 частью, так уж вышло. В следующий раз познакомимся с перечеслениями (enum) и структурами (struct). =)
-
Значит оптимизировать поиск путей, или вообще обойтись без поиска пути и использовать дорожки из специальных блоков. А андроид пусть идет по этой дорожке только
-
Не любишь сложности?...
-
Я вижу только одну проблему: Кто это все реализует
-
Ржавеем по полному! #2. Переменные. Литералы и операторы.
LeshaInc добавил запись в блоге в IncluderWorld
Rust Сегодня как я и говорил познакомимся с переменными и типами данных. Ну и еще по мелочи: операторы и литералы =) Учимся считать (переменные) Для создания переменной в расте используется ключевое слово let. let a = 10; // тип i32 Таким образом будет создана переменная a с типом i32 (подробнее о типах позже). Тип выведен автоматически. Например, если вместо числа 10 мы напишем строку, то тип будет выведен строковый. let a = "hello!"; // тип &str. да-да, вы угадали // будем говорить о нем позже =) Мы можем также сами указать тип через символ двоеточия : let a: char = "hello"; // ошибка, "hello" это не charlet b: u8 = 99; // ок, b теперь типа u8. Как видите компилятор проверяет типы. Теперь попробуем изменить нашу переменную. let a = 10;a = 20; // ошибкаa += 1; // ошибка ... И у нас ничего не выходит! Дело в том что по умолчанию переменные непеременные (но они не константы!) . Если мы хотим что бы наши переменные изменялись нужно использовать ключевое слово mut. let mut a = 10;// ^-- что бы наша переменная могла изменятьсяa = 20; // окa += 1; // ок// a = 21 Хозяйке на заметку: Константы в расте встраиваются прямо в исходный код программы, как если бы мы создали константу используя язык ассемблера. Переменные же (даже если они вовсе не меняются) создаются во время работы программы по умолчанию на стеке (об этом поговорим еще когда нибудь). Типы данных Раст предоставляет большой выбор примитивных типов: Целые: i8, i16, i32, i64, isize (размер указателя, на 32 битных машинах 32, на 64 битных - 64). Натуральные: u8, u16, u32, u64, usize (размер указателя). Рациональные: f32, f64. char Юникод символ, каждый 4 байта. bool Буля, true или false. () Юнит. (Используется как "ничего"). Массивы вроде [T; N]. Пример: [1, 2, 3, 4] тип: [i32; 4]. Кортежи вроде (A, B, ...). Пример: (true, false, 3) тип: (bool, bool, i32). Литералы Существуют литералы: целые числа 123, дробные числа 123.123, символы 'У', строки "RUST FOREVER!", були true, и юнит (). Целые числа могут быть также представлены двоичными, шестнадцатеричными и восьмеричными используя соответственно следующие префиксы: 0b, 0x, 0o. Например: 0b101 будет равно 5. В числа можно вставлять любое количество нижних подчеркиваний, дабы улучшить читаемость. 1_000_000 = 1000000, 0.000_000_1 = 0.0000001. Операторы В расте операторы похожи на операторы в Си-подобных языках. + плюс. - минус. * умножить. / разделить. % остаток от деления. ! логическое НЕ[/il] - унарный минус. ^ исключающее ИЛИ. | побитовое ИЛИ. & побитовое И. && логическое И. || логическое ИЛИ. << побитовый сдвиг влево. >> побитовый сдвиг вправо. А также соединенные с присваиванием операции, например a >>= 3 равносильно a = a >> 3. На этом все. В следующей части познакомимся с функциями и указателями. =) -
Ржавеем по полному! #0. Что за зверь Rust этот?
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
Мое субъективное мнение: -
Ржавеем по полному! #0. Что за зверь Rust этот?
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
@NEO, @Totoro, хватит тут разборки устраивать. Вам сюда. -
Rust Сегодня продолжим знакомство с языком программирования Rust. Научимся говорить как истинные джентльмены. Хозяйке на заметку: Комментарии в расте похожи на комментарии в большинства языках. От // до конца строки – комментарий: // Комментарий От /* до */ – комментарий: /* Большущий комментарий =) */ Учимся говорить В расте для вывода текста на консоль используется println! и соответственно print! fn main() { println!("Hello, world!"); // --> Hello, world! print!("Hello, "); // -\ print!("world!\n"); // --> Hello, world! // ^- это нужно что бы весь следующий // текст в консоли был на новой строке} Выводом такой программы будут две строки "Hello, world!". Отличия println! от print! заключаются в том, что print! не ставит в конце строки перенос на новую строку. Это очень удобно, когда мы хотим вывести две надписи в одну строку. Раст поддерживает форматирование текста. Но оно не такое как в Lua и Си. println!("Rust forever! {}", 42); // -> Rust forever! 42print!("Rust forever! {}\n", 42); // -> Rust forever! 42 println! и print! автоматически форматируют текст. Первый аргумент в таком случае – строка, которую будем форматировать, остальные аргументы – данные которые мы будем подставлять в {...} Мы также можем самостоятельно позиционировать аргументы. println!("{0}: Привет, я {0}. {1}: Привет! А я {1}! Приятно познакомиться.", "Маша", "Боб");// |--> Маша: Привет, я Маша. Боб: Привет! А я Боб! Приятно познакомиться. Фактически, {} {} {}... означает {0} {1} {2}.... Также можем давать имя аргументам. println!("{subject} {verb} {object}!", subject="Петя", verb="съел", object="печеньку"); // --> Петя съел печеньку! Специальное форматирование может быть указано после :. println!("{0} + {0} = {1:b}, и никак иначе!", 1, 1 + 1); // --> 1 + 1 = 10, и никак иначе!// ^ это означает *напиши число в двоичном формате (нулями и единицами)// подробнее о возможных можно узнать в документации. Можно выровнять строку по правому краю. println!("{0:>06}", 42); // --> 00042println!("{0:>01$}", 42, 7) // --> 000042println!("{0:>0width$}", 42, width=7) // --> 0000042println!("{str:>width$}", str="Петя", width=10) // --> Петя// Замените > на < и выравнивание будет по левому краю. На этом с форматированием все. В следующей части поговорим о переменных и типах данных. =)
-
Ржавеем по полному! #0. Что за зверь Rust этот?
LeshaInc прокомментировал LeshaInc запись в блоге в IncluderWorld
Все просто, Си появился в 1972, 44 года назад. Раст же в 2010, 6 лет назад. В общем то за такое время у Си набралось много учебных материалов, вакансий, примерных проектов. Что у раста за 6? Мощное сообщество (Mozilla), немного проектов, большинство из которых еще на ранних стадиях. Вакансий нет. Стоит подождать лет эдак 10 раст станет более популярным, не то что скала (привет, @Totoro), которая за 13 лет набрала 276 контрибьюторов всего. Для сравнения, в гитхабе раста 1427 контрибьюторов. -
Rust Не так давно появился язык программирования Rust. В этой записи я расскажу вам, чем так примечателен Rust (раст) и почему всем стоит на него переходить. На главной странице раста написано, что он – системный язык программирования, который работает быстро, предотвращает вылеты и гарантирует безопасность. Не стоит прямо сейчас закрывать страницу из-за непонятных слов. Сейчас во всем разберемся. Rust – системный ЯП Это значит что на нем можно писать программы любой сложности и их можно будет запустить везде, от тостера до компьютера Васи Пупкина, без необходимости скачивать интерпретаторы/виртуальные машины (как в случае с Java и Lua). Например, Си – системный, а Java – нет. :P Попробуйте написать на Java ядро ОС. У вас ничего не выйдет, так как что бы запустить Java нужна виртуальная машина (да-да, то самое "скачать жаву" это и есть "скачать виртуальную машину Java =) ) Совсем другое дело обстоит с Си. Например, следующий код можно запустить абсолютно на любом компьютере. int main() { int a = 1; a++; return 0;} Эквивалентный код на расте тоже будет работать везде. Вот он: fn main() { let mut a = 1; a += 1;} Эта фича позволит нам писать на расте программы любой сложности, от hello-world'ов, до операционных систем. Пойдем дальше. Rust – быстрый ЯП Раст – быстрый ЯП, и с этим не поспоришь. Он компилируется в машинный код что позволяет ему так быстро работать. Работает не хуже Си. Rust – безопасный ЯП Безопасность раста проявляется во всем. От I/O до потоков, от указателей до типов данных. В этом можно убедиться самому. Например следующий код на Си int main(){ int x = 10; int *px = &x; px = 0; *px = 3;} Вполне скомпилируется, но работать не будет. Программа с подобным кодом упадет. Дебаг таких программ всегда сложен. Аналогичный код на расте: fn main() { let ref mut p = 10; p = 0; *p = 3;} Компилироваться он не будет, следовательно программист заметит (скорее всего) ошибку и исправит ее. Убедитесь сами. Это не единственный пример такого поведения компилятора раста. Он всегда сообщит вам о небезопасности кода, чего не скажешь о других компиляторах. Из фич этого языка я бы выделил: "Бесплатные" абстракции. Когда в Java абстракции достигаются путем уменьшения качества выходного кода, в расте все бесплатно, как и в C++. Гарантированная безопасность. Когда в других языках гарантия безопасности обеспечивается программистом, в расте компилятор сам позаботится о безопасности кода. Он делает это всегда, но мы вполне можем попросить его не проверять код. Для этого используются unsafe блоки кода (поговорим еще о них). Многопоточность без гонок (англ. data-race). Все кто писал многопоточный код на языках вроде C++ или Java знают как не просто достигнуть безопасности таких потоков. В расте же такой код делается очень просто, сам убеждался не раз. Трэйты. Разработчики раста решили отказаться от стандартной концепции классов и интерфейсов. Но на расте вполне можно писать в объектном стиле (поговорим еще об этом). Все решать вам. Фич куда больше, это только малая часть. О самой работе с растом будет написано в следующей серии. =) Да Здравствует Rust!
-
setmetatable(_G, { __index = function (self, k) if k == "_" then return nil else return rawget(self, k) end end}) print(_) --> nil _ = 22 print(_) --> nil это было просто
- 14 ответов
-
- 3
-
-
- event
- opencomputers
-
(и ещё 1 )
Теги:
-
event.pull([eventName: string], [timeout: number])
- 14 ответов
-
- 2
-
-
- event
- opencomputers
-
(и ещё 1 )
Теги:
-
noExit = not noExit
