Как стать автором
Обновить
32
0.5
Николай Меркин @nickolaym

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

Отправить сообщение

Это уже отмазки пошли. Я сказал, зачем нужно делать new const T, вы сказали, что чаще бывает static T, я привёл сценарии - более чем рабочие! - а вы отделываетесь какой-то совершенно пустой фразой "главное, чтобы программист знал..."

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

Это читерство и антипаттерны.

Если некий тип задуман как состоящий из константной (ключевой) и неконстантной частей, то лучше эти неконстантные части объявить как mutable.

Или вообще переделать дизайн программы, а то начинается "в этом контексте мы можем ломать константность только для этих полей, в другом контексте - только для тех полей, а в третьем ломать константность нельзя вовсе..." - и потом где-нибудь что-нибудь напутать и сломать.

const_cast, снимающий константность - это всегда звонкий колокол.

Плохая статья.

В ней просто названы несколько взятых наобум мусорных языков и показаны случайные примеры на них.

Что мы видим? Что это write-only языки, код на которых больно читать. И больше ничего не видим.

Какие идеи заложены в эти языки, помимо минимального синтаксиса и нечитаемости? Можете рассказать?

Давайте-ка я сделаю это за вас. Начну с "традиционных" вырвиглазок.

  1. Старый добрый брейнфак. Это - разновидность машины Тьюринга. (В которую добавили бесконечное количество состояний ячеек и откуда убрали goto).

  2. Unlambda. Комбинаторная логика на традиционном базисе SKI.

  3. Йот. Довели КЛ до абсурда-и-предела, базис из единственного комбинатора i.

  4. APL, J, K, Q. Это промышленные языки, которые работают с произвольными тензорами, а синтаксис упрощён в пользу тацитной (безымянной) нотации. Упор там сделан на очень быстрый парсер и очень быстрый интерпретатор.

  5. Лисп. Лямбда-исчисление, код-как-данные, сам себя интерпретатор.

  6. Форт. Стековая машина, ПОЛИЗ, и опять же сам себя интерпретатор.

А теперь посмотрим на то, что в статье.

  1. Malbolge. Просто упоротая машина Тьюринга. (Но не брейнфак).

  2. Whitespace. Брейнфакнутая версия форта.

  3. Chef. Коболизированная версия форта с множеством стеков.

  4. INTERCAL. Коболизированная версия бейсика.

  5. Коболизированная версия брейнфака.

Скушно! Просто потрахать мозг. Никакой красивой математической идеи за ними не стоит.

А ещё есть const_cast и его помощники - функции std::move и std::as_const.

Большое количество больших константных объектов в принципе не создают в статической памяти.

А если эти константы времени исполнения?

Например, строки. Например, содержимое конфиг-файла.

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

1 клетка принимает 3 состояния и влезает в 2 разряда.

2 клетки - 3^2 = 9 состояний, 4 разряда.

3 клетки - 3^3 = 27 состояний, 5 разрядов.

Это значит, мы можем построить функции

using table = unsigned short;  // 15 bit
using row = unsigned char;  // 5 bit
using cell = unsigned char;  // 2 bit

row encode_row(cell c0, cell c1, cell c2) {
  return c0 + (c1 + c1*2) + (c2 + c2*8);
  // на сдвигах, если хочется умножения экономить
}

const cell decode_row[27][3] = {
  {0,0,0},{1,0,0},{2,0,0},
  {0,1,0},...............,
  ...............,{2,2,2},
};
// что-то сходу лень думать, можно ли арифметическим колдовством
// обойтись без деления и при этом - без таблицы

В общем, дальше лень писать :)

Что будет быстрее работать, - деления или нудная работа с таблицами, - хз. Бенчмарки тоже лень писать.

В функции set_cell ошибка, там сигнатура должна быть `void set_cell(state* s, .....)`

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

Элементарно! Если объект достаточно велик, чтобы жить на стеке.

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

Интегральные схемы - это не совсем рассыпуха :))

У светодиодов нет инерции, надо бы её добавить - чтобы было какое-никакое послесвечение. Может быть, rc-цепочки на каждый столбец?

  • Кодировка UTF-16: он состоит из двух байтов (то есть 16 бит). Это означает что один символ весит 16 бит. В данную кодировку вмещается 2 ^ 16 = 65536 различных символов.

Ну вот нет. UTF-16 и UCS-2 - это разные кодировки. И та и другая используют двухбайтные слова, только у UCS-2 - на один символ ровно одно слово, поэтому она вмещает 65536 символов, а UTF-16 - это кодировка переменной длины! Почитайте про суррогатные пары самостоятельно, пожалуйста.

До кучи, ещё есть UTF-7.

Практический смысл разных UTF-n в том, что для ASCII (наиболее расхожий набор символов) UTF-8 кодируется 1 байтом, и для европейских алфавитов и всякой популярной графики UTF-16 кодируется одним словом (но китайцы уже страдают!), а UTF-32 хватит для всего UCS-4 - и вот это уже кодировка фиксированной длины.

Этак при желании можно ломануть и зеркало дистрибутива, и даже сам дистрибутив. Потом будет скандал, но это когда ещё будет...

Кроме того, сторонний софт на то и сторонний, что в дистрибутив не вошёл. И что теперь, исповедовать подход эппла, "чего нет в нашем апсторе, то вам и не нужно!"

Пользователи линукса - это не исключительно красноглазики, у которых всё труъ из сырцов и потрошёные дебы.

А практика ставить недостающий софт (которого не положили в репу дистрибутива) из сторонних реп - это нормально. Репа производителя - куда уж официальнее-то?

И сырцы не панацея. Автор прекрасно может насрать в свои собственные сырцы - на гитхабе такие истории уже были.

Вы каждый пакет вычитываете и верифицируете? Вам делать больше нечего?

Вы ради браузера поднимаете докер? Ну вы-то, допустим, можете...

Осталось главной интригой - какие люди-Х и как инфицировали сайт FDM? Засланные казачки, или извне ломанули?

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

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

Я привёл чисто декларативный код: "первый (или любой) элемент из последовательности многократных применений f к x, такой, что удовлетворяет заданному условию".

Причём эта формулировка позволяет делать всякие улучшения.

Например, обнаруживать зацикливание. Хоть самое простое, когда функция попала в неподвижную точку, fx = x. Хоть когда попала в цикл произвольной длины, f^n(x) = x.

Или обнаруживать ошибки в коде. Мы утверждаем, что функция монотонная (на каждом шаге мы уточняем игровое поле). То есть, x <= fx. И из этого следует, что возможны только циклы длиной 1 - неподвижные точки. Но если это не так, то пара смежных элементов x1, x2 с нарушением порядка, x1>x2, говорит, что ой всё.

Потому что мы исследуем последовательности как структуры данных.

А код "вызывать функцию и проверять условие, вызывать и проверять..." - это та самая императивность. Записанная посредством функционального языка. На языке с переменными и циклами это просто контракт - постусловие. "Если программа останавливается, то из этого следует, что постусловие выполнено". Очень даже декларативно, не? Если не накрутить макарон внутри цикла. Ну так макароны и в функциональном коде можно накрутить.

Сидящий в кофейне разработчик вполне может подключиться к интрасети своей конторы через VPN своей конторы. И это будет то же самое, что сидеть непосредственно в конторе. Всякая там жира, почта, панели управления... которые наружу в принципе не торчат.

И всё было бы хорошо, но у него оказывается есть кейлоггер в лице любимого хромчика или ёжика.

"Мы вставили абстракцию цикл Ц-слово, но мы не хотим, чтобы про неё думали, как про Ц-слово, поэтому давайте напишем на концевой рекурсии, расскажем сказку про контракт (процедурщики и так знают, что такое постусловие Ц-слова), а чтобы уж наверняка, назовём нашу функцию высшего порядка Ц-словом! чтоб никто не догадался"

Цикл он и есть цикл.

Хотелось бы функциональщины, - ввели бы

1) генератор многократных применений функции: проекция типа T на T* (бесконечный список)

2) фильтр по предикату

iterate f x = x : iterate f (f x)
filter p xs = [x | x <- xs, p x]

until p f x = head (filter p (iterate f x))

и вуаля, мы тут мыслим в терминах данных (бесконечный ленивый список и его элементы), а не в терминах процессов (вызывать f раз за разом)

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

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

Не просто и не всё. Утечка из браузера происходит мимо роботса.

Это уже потом ИБшники будут удивляться, какого фига гугловский паукан пытается обращаться по внутренним урлам (и ему за это иногда дают по хелицерам).

И натравление паукана на внутренние сайты - лишь одна из проблем. Пример другой проблемы показан в статье. Где там роботс? Нигде.

Информация

В рейтинге
1 580-й
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Зарегистрирован
Активность