−96
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
#include <stdio.h>
#include <inttypes.h>
int main() {
int arr[] = {34, 12, 24, 65, 63, 22};
size_t arraySize = (sizeof(arr) / sizeof(*arr));
size_t i;
startloop1:;
void * loop1val = &&endloop1;
i = 0;
startloop2:
goto *( (void *[]){&&noexchange, &&exchange}[arr[i] >= arr[i+1]]);
exchange:;
int tmp;
tmp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=tmp;
loop1val = &&startloop1;
noexchange:
i++;
goto *( (void *[]){&&startloop2, &&endloop2}[i >= arraySize-1]);
endloop2:
goto *loop1val;
endloop1:
i = 0;
startloop3:
printf("%i ", arr[i]);
i++;
goto *( (void *[]){&&startloop3, &&endloop3}[i >= arraySize]);
endloop3:
return 0;
}
На говнохабре http://habrahabr.ru/post/269875/ очередная хуита написана, вот типа напишите сортировку не используя if. Но в том коде есть циклы, любой настоящий программист знает, что циклы это по сути то же самое, что и if(условие) goto куда-тотам. Как написано в одном фундаментальном труде http://www.lib.ru/ANEKDOTY/non_pas.txt
- поскольку в Фортране отсутствуют структурные операторы IF,
REPEAT ... UNTIL или CASE, настоящим программистам не
нужно беспокоиться, что они их не используют; кроме того
эти операторы можно при необходимости симулировать с
помощью присваиваемых GOTO.
Пользуясь этой вселенской мудростью, а так же зная про наличие присваиваемых goto в gcc, решил я сей код написать.
Запостил:
j123123,
28 Ноября 2015
Тернарники тоже нельзя? И short-circuit && и || ?
cond && thenAction;
cond || elseAction;
Но вот функции лучше.
Во-1 это законченные блоки кода, с неймспейсом и стеком.
Во-2 рекурсивной вложенности можно избежать передав функции адрес тела (указатель на функцию) и условия выхода.
Это плохо. Если вызывать функцию по указателю, она отжирает стек. Даже если нет рекурсивной вложенности, все равно на эти создания стека для функции тратится время. Да еще при call пишется адрес возврата, который потом по ret из стека вытаскивается. Неймспейс я могу сам запросто сделать, завернув куски кода в {} чтобы ограничить область видимости, и через goto передавать туда управление. А потом в конце этого {} обратно сделать goto на кусок кода, занимающийся обработкой этого самого шитого кода.
http://habrahabr.ru/company/intel/blog/261665/ вот кстати статья на хабре про интерпретаторы, там эта фича с присваиваемыми goto используется. Кроме того, там используется еще вот эта вот https://gcc.gnu.org/onlinedocs/gcc/Global-Register-Variables.html замечательная GCC фича. Настоящие программисты должны оценить
А на графики ты посмотрел? Это говно с вычисляемыми goto, внезапно, отработало медленнее процедур :)
http://www.agner.org/optimize/microarchitecture.pdf page 34
The P1 has no return stack buffer, but uses the same method for returns as for indirect jumps. Later processors have a return stack buffer. The size of this buffer is 4 in the PMMX, 8 in Atom, 12 in AMD k8, 16 in PPro, P2, P3, P4, P4E, PM, Core2 and Nehalem, and 24 in AMD k10. This size may seem rather small, but it is sufficient in most cases because only the innermost subroutines matter in terms of execution time. The return stack buffer may be insufficient, though, in the case of a deeply nesting recursive function. In order to make this mechanism work, you must make sure that all calls are matched with returns. Never jump out of a subroutine without a return and never use a return as an indirect jump.
И я подозреваю, что именно благодаря этому, там эти вызовы процедур оказались быстрее. На каком-нибудь древнем интель-проце или на дохлом арме ситуация может оказаться прямо противоположной
По какой-нибудь формуле вычисляем индекс массива — это и будет ветвлением.
итп
Операторы нинужны.
А слабо сделать бесшовные операторы через макросы и лямбду? Чтоб не писать постоянно [&]()
IF x < 10 THEN
...
ELSE
...
ENDIF
Интересно, а паттерн-матчинг или нормальный свищ с диапазонами запилить сложно?
У меня вложенность была какой-то дико маленькой. емнип 16.
Тогда max(x, y) = y + (x - y) * θ(x - y); min(x, y) = y + (x - y) * θ(y - x).
http://graphics.stanford.edu/~seander/bithacks.html
{
return (a > b) * a + (a <= b) * b;
}
Совсем не то.
Доклад интересный, но не сильно глубокий. Облом в том что у него `One + One` не возвращает `Two`. И все остальное обламывается в этом же подобном духе. И не сильно ново/оригинально - это более или менее переложение мат. языка на язык программирования. Lambda calculus уже слишком высокоурвнево.
Я думаю что тот чудак про формальные языки не слышал, потому что это именно то что он переизобретает, углубляясь в доисторические уровнии ОО, когда оно было теоретической моделью для экспертных систем ИИ.
Ну и пофиг. Оно же возвращает объект, эквивалентный Two. Этого достаточно.
В жабе вон Integer.valueOf(100500) и Integer.valueOf(100500) могут быть разными объектами. Но всем похуй, т.к. они эквивалентны.
> Ну и пофиг. Оно же возвращает объект, эквивалентный Two. Этого достаточно.
Достаточно, но криво. Потому что Two это не класс, а объект. Потому что Two не знает что оно Two.
С буквами он догадался что не возможно - а вот с числами не догадался. Концепция чисел настолько примитивна, что семантика и синтакс у большинства в голове перемешаны. А вот кодировки и чар-сеты тема более высокоуровневая и там он как бы и споткнулся. Но на самом деле концептуальная проблема та же самая что и с числами: двойка не знает что она двойка, двойка есть двойка потому что это то семантика которую люди приписывают слову "два".
ЗЫ Extreme OO как оно там излагается на самом деле большее Extreme O, потому что там "объектно-ориентированость" отсутствует, и используется почти исключительно "объектность".
Твоя фантазия недостаточно извращена, чтобы реализовать всё это вообще без циклов, условий, свичей, тернарников и short-circuit операторов, guest?
P.S. Да и вместо флагоёбства можно было просто break сделать.
Генерируем в зависимости от условий имя функции, запрашиваем его у либы, вызываем -> profit
> Как все настоящие программисты знают, единственной полезной структурой данных является массив.
> Если вы не можете выполнить эти работы на Фортране, выполните их на ассемблере. Если же их нельзя выполнить на ассемблере, их не стоит делать вообще.
/s/Фортран/Сишк/
MAXIMUM TSAR!!!
Вообще конечно он прав.
If you ignore the fact that it's structured, even C programming can be appreciated by the Real Programmer: after all, there's no type checking, variable names are seven (ten? eight?) characters long, and the added bonus of the Pointer data type is thrown in. It's like having the best parts of FORTRAN and assembly language in one place. (Not to mention some of the more creative uses for #define.)
Давно читал крео, это помню там за сишку было.
Вообще он прав. Фортран — охуенный язык, из которого произошёл бейсик. алгол и кобол — сакс.
Еще доставляет пассаж про правки двоичного кода
Из-за этого настоящие программисты неохотно редактируют уже работающие программы. Они считают более простым непосредственно латать двоичный объектный код, используя прекрасную программу под названием SuperZap (или ее эквивалент на не-IBM машинах).
Этот метод настолько хорош, что многие программы, работающие на ЭВМ фирмы ИБМ, не имеют ничего общего со своим собственным текстом на Фортране. В большом количестве случаев первоначальный символьный текст программы вообще не существует. Когда наступает время подправить такого рода программу, никакой администратор даже не думает послать на эту работу кого-либо, кроме настоящего программиста - никакой сосунок (структурный программист) не будут знать даже с чего начать. Это называется защита от несанкционированного доступа.
Разница с java том что однажды пропатчив слинкованный бинарник получается невосстановимый пиздец, который уже никак не декомпилировать в ЯВУ. После этого просто необходимо иметь в штате такого гения, который будет его сопровождать.
Означает ли это, что неструктурированные ассемблероподобные языки лучше?
Эммм. Самое ключевое их отличие было статическая тупизация vs динамическая. Это раз. Ну и компилятор vs интерпретатор — два.
Сишка всё-таки где-то посередине, ближе к алголу (точки с запятой, какие-никакие типы, компилируемость).
Ключевые отличия алгола от фортрана: точки с запятой, типы, структуры данных.
Идейными последователями фортрана я считаю: Бейсик, Питон, Js.
Хоть это и на первый взгляд абсурдно звучит. Но речь именно об идее. И тут они родственны фортрану: в отношении к типам, краткости, простоте, порогу вхождения и отсутствию точек с запятой (js может без них). И все изначально были интерпретируемыми.
Вот все кто пёрлись в своё время от фортрана и бейсика сейчас котируют js и питон.
Хотя лет 15-20 назад на JS и пытались писать, как на Фортране (вспомним сайты с document.writeln).
В Питоне тоже на первом месте структурированность кода, хотя там и отступы вместо фигурных скобок. Плюс функциональщина, без которой программиста питонистом считать не будут.
Остаётся только Бейсик.
Так в Фортране тоже отступы! 6 пробелов.
Идентация и структурированность!
Но вертикальной структурированности в классическом Фортране нет! В Фортране 66, как и в классическом Бейсике, не было этих всяких end if, а ветки разруливали с помощью меток и GOTO.
Когда в Фортране 90 вместо DO <метка конца цикла> ... ввели DO ... END DO, вместо PRINT <метка строки с форматом>, ... ввели PRINT "строковая константа", ..., добавили модульность (в том смысле, как в Модуле), а в реализациях Фортрана при вызове подпрограмм стал использоваться стек (как в Си и в Паскале), что наконец-то позволило совершать рекурсивный вызов, старые фортранщики это посчитали предательством.
*****
Но вообще в Фортране было что-то, что в Паскале и в Си долгие годы было недоступным. Это, например, неявные циклы (когда в некоторые выражения на вход вместо скаляра подаётся массив), «арифметический» IF с тремя ветками (это вам не тернарник с двумя!), а с Фортрана 90 ещё и стандартные функции над массивами. А ещё работа с комплексными числами из коробки!!!11адын-адын-адын
https://en.wikipedia.org/wiki/List_of_quantum_chemistry_and_solid-state_physics_software
http://stackoverflow.com/questions/7588079/how-to-computed-goto-and-longjmp-in-c
(рекомендую читать доставляющий срач в комментах)
Кстати, у нас есть две крайности:
1. С одной стороны, Царь, который считает, что никакие структуры, кроме одномерного массива не нужны, потому что оперативка представляет собой одномерный массив.
2. С другой стороны, математик-теоретик wxv (не помню, как дальше), который считает, что с помощью массивов можно решить далеко не любую задачу (а факт, что все эти списки, деревья, очереди, стеки, множества и прочие объекты в конце концов в библиотеке языка реализуются с помощью массивов, игнорирует).
Интересно было бы найти то же самое, но наоборот, в wxv-стиле, чтобы сравнить ощущения.
Чушь же. Все структуры — это просто сахар над одномерным массивом.
>Интересно было бы найти то же самое, но наоборот, в wxv-стиле, чтобы сравнить ощущения.
При всём уважении к wvxvw наоборот вряд ли получится.
Там речь о том, что Real Programmer настолько гениален что ему не нужны проверки типов для написания безошибочных программ.
Ну разве что обратная херня: не поближе к машинной реализации. А наоборот абсурдно далёко от неё и запредельно абстрактно.
Где так: настоящий программист пишет программы только на Лиспе и только в EMacs, транслируя их в нумералы Чёрча, которые он потом правит руками.
Проблему пока вижу в общении с внешним миром - линуксовое ядро эти нумералы в syscall'аъ не принимает :(
линукс пропатчить, чтобы он указатель на функцию вместо чисел принимал, и применял бы эту функцию к обычному инкременту
вот кусок кода ввода-вывода одной VM, которая поддерживает только комбинаторы и один примитивный тип RealWorld
как видно, мы лифтим хаскельные инкремент, (.), ($) и 0 в VM, а потом позволяем ей доделать всё остальное согласно обычной семантике
как-то так можно
пердолиться с остальной арифметикой на крестах мне сегодня лень
http://ideone.com/J9hZ4k
> надо
эти два слова могут встречаться в одном предложении только при условии, что третье и последнее слово в нём -- "закопать"
http://maxim.livejournal.com/352305.html
Иногда получается хаскелъ.
А как одну пропустил -- так сразу Хуанос застрелил Альберто, Мария беременна, Чиполлино объелся чеснока, а Чёрч - так вообще s (Â :. n :. ψ @ (Ψ {})) = Â' :. (n :. F (+1) :. N 0) :. ψ.
И оперативка это не массив, просто оь вас ласеров это скрыто контроллером памяти
И тролль лжец wwxw не знает что все выражаетс через моссив
А вот это, внезапно, уже вполне соответствует новым веяниям...
http://imgur.com/TutXNrT
t. clueless
P.S. А С++ стал такой няшей после С++11 (включительно)
Из собственного опыта, я думаю, можно смело сказать, что будущее прекрасно для настоящих программистов. Ни Linux, ни Сишка не высказывают ни каких признаков отмирания, несмотря на усилия программистов на С++. Даже такие изощренные уловки, как добавление RAII, конструкций объекто-ориентированного и функционального программирования в Сишку, провалились. Да, конечно, некоторые выпустили компиляторы С++, но каждый из них
оставил возможность перейти в режим компилятора С89 с помощью добавления одного флага — чтобы управлять памятью как предписано Богом.
а. остается написанный на ней актуальный код
б. остаются упрямые кодеры, которым легче всю жизнь вручную гонять байты, чем освоить ооп и шаблоны
Итого, сишка будет жить вечно, потому что кодеры из (б) будут писать код из (а), называя всех с++-кодеров крестоблядьми
Вот https://ideone.com/RHz5vW С++ (если б не было говношаблонов(например в чистом Си), я мог бы нагерить код функций через genfunctadd). А вот пример на языке D http://melpon.org/wandbox/permlink/22k35NmuFvFuVGKu где это делается одним единственным кодом.
Приведенные вами примеры генерации кода намного хуже, чем шаблоны.
Проблема известна, и недавнее введение в язык constexpr направлено как раз на её частичное устранение.
В лиспе, к примеру, компилятор может использовать в компайл-тайме встроенную или пользовательскую функцию, работающую со списками, для трансформации AST.
Этот пример даже не я сочинил, а спорящий со мной @j123123. Просто сравните читабельность двух процедур. А если надо написать что-то сложное?
Как зачем? Нужны конкретные примеры? Ну хорошо, допустим я хочу сделать некую хеш-таблицу
{"Петр Петрович", "$200", hash1}
{"Петр Иллич", "$1488", hash1}
{"Иван Петрович", "$400", hash2}
{"Петр Иванович", "$700", hash3}
{"Владимир Владимирович", "$10000000", hash2}
"hash?" это некое числовое значение(корзина), и у меня есть еще некая функция, которой если передать "Петр Петрович" то оно вернет число hash1, и потом я могу быстро найти. В начале у меня есть просто набор:
"Петр Петрович", "$200"
"Петр Иллич", "$1488"
"Иван Петрович", "$400"
"Петр Иванович", "$700"
"Владимир Владимирович", "$10000000"
без всяких хешей. Я хочу в компилтайме получить уже инициализированную хеш-таблицу. Я могу сделать это на этих гребаных шаблонах в компилтайме, но если я хочу еще в процессе работы править эту хеш-таблицу, например добавлять новых людей, то разве мне этот компилтайм-код поможет? Мне придется писать код для работы в рантайме, который дублирует функционал шаблонного кода. А нафиг мне вообще эти самые шаблоны, если я своим рантайм кодом могу накодогенерировать что мне надо, и просто заинклудить это в нужное место?
Хотя шаблоны в этом плане еще хуже
Вот что получилось: http://goo.gl/bhmKTO
Это
.L16:
test r8d, r8d
jne .L15
test r13b, r13b
jne .L80
.L18:
cmp BYTE PTR [rsp+15], 0
je .L19
mov DWORD PTR [rsp+64], ebx
.L19:
cmp BYTE PTR [rsp+7], 0
je .L20
mov DWORD PTR [rsp+72], edi
.L20:
cmp BYTE PTR [rsp+6], 0
je .L21
mov DWORD PTR [rsp+76], r10d
.L21:
cmp BYTE PTR [rsp+5], 0
je .L22
mov DWORD PTR [rsp+80], esi
.L22:
cmp BYTE PTR [rsp+12], 0
je .L23
mov DWORD PTR [rsp+84], ecx
нихрена не компилтайм, это говно какое-то
Плюс к тому, в вашем примере bubble_sort - процедура, а не функция, со всеми вытекающими.
Пример о том, как вам достичь желаемого и не только. Правда, использовать придется с++14. А написать один раз, чтобы сразу двух зайцев - ну, мб, дефайны помогут, хотя проще будет написать два куска для разных случаев
Послушайте, просто послушайте, что Вам говорит j123123, подумайте над этим.
1. В языке C++ есть возможность писать код, который работает во время компиляции и код, который работает во время исполнения
2. В принципе, на шаблонах можно написать всё то же самое (тьюрингова питушня и всё такое) за исключением ввода-вывода и с ограничением на вложенность шаблонов (Простого -ftemplate-depth хватает GCC для решения проблемы останова, над которой Тьюриг, CHayT и их апостолы бьются в математических спорах вот уже тысячелетия), но заново, что в нашем мире библиотек и переиспользования неприемлемо.
3. C++ и шаблоны C++ - это не python и lisp, это не два языка, это один язык, поэтому логично было бы желать иметь единообразное описание программ.
При правильном использовании, функция, результат которой будет вычисляем на этапе компиляции, будет отличаться от обычной функции только словом constexpr. Логично? Да. Человек приводит пример НАМЕРЕННОЕ нарушение требований constexpr и вообще банальной человеческой логики (constexpr void не несёт смысловой нагрузки) как аргумент против его использования. Логично? Нет. Это как жаловаться на язык потому что компилятор не умеет разбирать заведомо некорректную конструкцию.
Последнее: шаблоны - прослойка поверх синтаксиса плюсов, отвечающая за метапрограммирование. Логично? Да. И это лучше, чем запихивать код в строки и редактировать его вручную.
Не объясняет. Речь об ограниченности шаблонов в C++ и проблемах C++.
> Человек приводит пример НАМЕРЕННОЕ нарушение <...> банальной человеческой логики
Знаете, вот есть "по закону", а есть "по совести". Есть банальная человеческая логика, а есть здравый смысл.
Логика часто надеется на то, что программа выполнится за конечное и крайне малое время. В реальности же возникает бюрократия. Справка о том, что нужна справка, с подтверждением личности по паспорту, удостоверениям и кипе документов - понятие логичное, но крайне бессмысленное.
Кто-то логичный сказал: "Давайте я решу на песке уравнение и пойму, кто из людей более ценный, чтобы его спасти", а кто-то здравомыслящий успел спасти, из-за него кто-то не утонул.
Также логика точна, а здравый смысл работает с вероятностными величинами. Можно долго спорить о иррациональных числах и бесконечное количество времени вычислять число Пи, это логично, но можно работать с погрешностью. 3.14+-0.01 - всё то же старое Пи, заданное корректно с погрешностью, уместной в нашей задаче.
Вы смотрите на проблему с точки зрения логики, посмотрите на неё с точки зрения здравого смысла.
Они бы тогда убили и программистов, и пользователей.
В общем-то затем и нужен программист, чтобы аппроксимировать здравый смысл в бинарную логику.
Если здравый смысл противоречит логике, значит эта модель (логика) здесь неприменима или недостаточна, нужно придумать логику получше.
Вообще, очень показательный пример. Предположим что уже есть некая готовая кем-то написанная обычным способом функция на С/C++(уверен что есть), делающая разбор выражений вида "(4^2-9)/8+2/3". НО использовать ее в этих constexpr нельзя, и надо заново это все переписывать с учетом ограничений. Так почему бы вместо того чтобы переписывать, не сделать генерацию через эту функцию? Притом этот код на constexpr будет ТРУДНЕЕ для понимания, чем код, написанный в обычном стиле на тех же плюсах.
Там даже нет никакого malloc
О масштабах изменений судите сами. Challenged? Check. Delivered? Check.
Я уж не говорю о таких "мелочах", как то, что этот constexpr-код сортировки в компилтайме отрабатывает очень долго по сравнению с тем, как если эту сортировку скомпилировать обычным образом и передать ей на вход массив, который надо отсортировать. При сортировке больших массивов он отрабатывает так долго, что clang начитает предполагать что там бесконечный цикл, и прекращает сортировку компиляцию, а gcc падает с internal compiler error(судя по всему от нехватки памяти).
С++ код в общем случае не является С кодом. Но С код почти всегда можно собрать С++ компилятором(есть конечно пара-тройка несовместимостей, но это мелочи, можно поправить) и он будет корректно работать. Таким образом, очень большое количество С кода является С++ кодом.
>Я не менял сигнатуру ФУНКЦИИ, я менял сигнатуру ПРОЦЕДУРЫ
В языке СИ нет деления на процедуры, подпрограммы и функции, здесь вся программа строится только из функций. Есть понятие функции, возвращающей void.
>а процедура не может иметь смысл как constexpr, и это потому что это логично, а не потому что язык говно.
А меня не волнует. Допустим у меня есть работающий код из функций(или процедур если угодно), написанных в обычном Си стиле. Когда писался этот код, никаких constexpr-ов в плюсах не было, и естественно код писался в обычном стиле, а не так, чтобы потом если вдруг в плюсах появятся constexpr-ы то чтобы оно на них легко портанулось. Очевидно, что этот код просто так не засовывается в этот constexpr, и чтобы его туда засунуть, надо очень много переписывать, а заниматься такой ерундой никто не собирается. Так что если я вдруг захочу использовать этот код в компилтайме для генерации неких данных, я просто скомпилирую этот код обычным образом, прикрутив к нему вывод через printf или std::cout <<, запущу его и потом просто использую этот полученный вывод.
2. Функция, которая ничего не возвращает назвыается процедурой. void - это как раз таки "ничто".
3.
> >а процедура не может иметь смысл как constexpr
> А меня не волнует.
"Я хочу чтобы void в компайлтайме пересчитался в отсортированный массив" - это финиш
Почему же другой? Если он корректно компилируется С++ компилятором и корректно(так же, как если бы его компилировали С компилятором) выполняется, то этого разве недостаточно?
>Функция, которая ничего не возвращает назвыается процедурой. void - это как раз таки "ничто".
Хорошо, если вам такая терминология больше нравится, будем называть функцию, возвращающую void процедурой. В СИ это всего лишь частный случай функции, не более.
>"Я хочу чтобы void в компайлтайме пересчитался в отсортированный массив" - это финиш
А что не так? По-вашему, сделать это не представляется возможным? Или это как-то "методологически неправильно" ?
Сколько информации может нести переменная типа void? 0, черт подери, 0!, КАРЛ! Мы говорим о языке со СТАТИЧЕСКОЙ типизацией, где, в отличие всяких лиспов/питонов/жабаскриптов нельзя вместо true/false засунуть хеш или обратиться к 10-му элементу null-а и не получить ошибки.
Речь вообще была о с++. В с++ есть интересующий вас функционал? Да. Неумение им пользоваться - ваш личный геморрой. Всё. Вопрос закрыт.
Функция, меняющая состояние окружения в принципе не может являться выражением времени компиляции, т.к. логика работы программы зависит от времени вызова такой функции. И это правильно. То, с чем вы сравниваете, можно сделать хоть на си - написать препроцессор, который будет компилироваться на основе тех же файлов и заменять код основной программы перед её компиляцией.
Это теоретические вопросы. На практике как нечто полезное используется не состояние программы, а её результат. Нужно лишь попросить программиста предоставить какой-то результат.
Можно определить некоторые переменные, которые будут экспортированы.
Например, обозвать их compiletime:
Во время компиляции исполняется ct_main, после этого при запуске в compiletime-переменных хранится то, что было в них в момент завершения ct_main.
Возможно, malloc/free/конструкторы/деструкторы патчатся, чтобы сохранить структуру экспортируемого объекта. Возможно, malloc и конструкторы должны выполняться при исполнении. Т.е. если есть динамический compiletime массив с посчитанными на этапе компиляции знаками пи, во время исполнения создаётся int*/std::vector с вызовами malloc/new/конструкторов и заполняется посчитанными знаками.
Т.е. осуществляется сериализация/десериализация объектов.
Если, скажем, статические поля класса как-то изменялись, но не были помечены compiletime, там им и место, они останутся неинициализированными, программист явно указал экспортируемое состояние, посчитать которое стоило больших, но однократных усилий.
*y может быть посчитан только если есть статические константные N байт памяти программы, на которые он указывает. То есть для компайл-тайм вычисления сначала должны быть определены данные (которые зашьются в тело программы), а только потом вычисляется указатель на них. Поэтому
constexpr struct { int data[3]; } getData() { return {{1,2,3}};}
возможно, а через указатели - нет.
Я же говорю, что
1. malloc может быть пропатчен.
2. важны данные, а не их положение, получение и т.д.
Понятно, сложно или даже невозможно восстановить всё состояние программы. Но ведь тут надо работать как инженер, а не как математик. Возможно с таким приближением - делаем с приближением.
(Кстати, на этапе исполнения абсолютно не важно, что вернёт malloc. Зачем копировать указатели, если они не несут смысла?)
Вы же можете написать вот такую программу:
Что Вы делаете?
1. Вычисляете число Пи
2. Записываете знаки в блокнот
3. Пишете программу
Пусть кто-то вычислял Пи на этапе компиляции.
Известны знаки числа Пи после компиляции? Можно их сохранить? Да и да.
А значит компилятор может создать программу, которая вызывает malloc и заполняет массив.
Или сериализация/десериализация в принципе не возможны, их вообще в мире не существует?
Сериализацию/десериализацию пакетов фиксированной структуры лично я обычно так и делаю.
Вариант первый (выше я его упоминал)
1. Для каждого типа, который участвует в экспортируемых в рантайм выражениях (тип экспротируемой переменной, типы её полей, типы полей их полей и т.д.), генерируется дополнительный конструктор инициализации; для malloc генерируется конструктор массива.
2. Во время компиляции за каждой создаваемой переменной следят, чтобы определить способ её построения. Т.е., какие конструкторы надо вызвать, чтобы получить такую переменную. Но с ограничениями: не помнить иерархию изменений, не следить за кастами указателей в инты и т.п.
Например, был указатель и блок памяти длиной 8 байт, сделали placement new и сконструировали объект типа A размером 8 байт, затем сделали placement new и сконструировали объект B размером 4 байта и экспортировали указатель. Во время исполнения под указатель выделится 8 байт, первые 4 заполнятся объектом B, остальные не будут определены. Если в экспортируемом объекте был указатель на объект, который сейчас в памяти, о котором есть метаданные (кто-то вызвал malloc или конструктор), то записывается сожержимое, иначе - error/warning для компиляции или же нулевой указатель.
3. Во время исполнения вызываются специальные конструкторы и пропатченный malloc, заполняющие экспортированные объекты вычисленными на этапе компиляции значениями. Объекты становятся такими же, как будто бы программист вручную написал код как в предыдущем моём комментарии. Т.е. их можно изменять, удалять и т.д.
1. Определяем правила для compiletime-классов: есть конструктор, инициирующий все поля; все поля - compiletime-типы.
2. Просим пользователя на этапе компиляции засунуть результат в compiletime-типы. Иначе - ошибка. Т.е. на этапе компиляции программа творит любые непотребства, но экспортирует их в строгие compiletime-типы.
3. На этапе компиляции следим только за созданием compiletime-типов.
4. На этапе исполнения восстанавливаем экспортированные объекты как в варианте 1.
Возможно, потребуется создать шаблонный псевдокласс std::compiletime<T>, который будет автоматически преобразовывать T в compiletime-тип. На этапе исполнения std::compiletime<T> будет иметь дополнительный конструктор, но более никак не будет отличаться от T.
Там очень няшный компайлтайм, не то что крестоблядское уёбище по имени constexpr. Даже файлы читать можно. Файлы в компайлтайме, Карл!
Насчёт практичности всего этого - протобуф без внешних генераторов, просто либой. Регулярки с компайлтайм парсингом и статической проверкой. Сериализация без бойлерплейта и генераторов. Разве всё это нинужно?
И printf, который не требует особой компиляторной магии для проверки, при ошибке переходишь в код валидации в стандартной либе.
Я развлекался с D (в основном, правда, решая олимпиадные задачки), прочитал книжку Александреску. В целом весьма приятный язык, рекомендую.
http://dlang.org/template-comparison.html
Вот этот пример, однако, позабавил:
http://media.giphy.com/media/3o85xoH0tmyTKstS9y/giphy.gif
статика в тьюринг-полных языках по-хорошему всегда должна и будет иметь другую семантику, нежели рантайм, поскольку мы хотим, чтобы компиляция завершалась
(не берём в расчёт кресты -- там своя атмосфера)
type-foo в haskell тоже пишется отдельно, и это правильно
Вот занятный пример: человек запилил проверку SQL-запросов в compile-time.
https://github.com/darioteixeira/pgocaml
Правда, компилятору коннект к базе нужен, лол :)
Для произвольной программы определить, закончится ли её компиляция
она и рантайме-то не всегда желательна
Или хочешь сказать, что она вообще никогда не нужна? Если да, с этим утверждением я готов поспорить
рантайм в тьюринг-полных языках по-хорошему всегда должен и будет иметь другую семантику, нежели рантайм, поскольку мы хотим, чтобы исполнение программы завершалось
Но почему для Вас так важно знание о завершении компиляции, что из-за этого даже можно сломать язык потерять универсальность языка?
У нас есть резервный компилятор %windir%\Microsoft.NET\Framework\v4.0.30 319\jsc.exe
P.S. А зомби зачем останавливать? От него и так одна шкурка осталась.
REISUB.
не пытайтесь спорить с Тьюрингом
>вдруг любым первым ходом они ставят себя в невыгодное положение?
А для этого есть возможность скипнуть ход (конём туда-обратно или пешкой не через два поля, а по одному). И тогда чёрные становятся белыми.
> в шахматах
О_о
Кажется, wvxvw нанял вместо себя тролля-теоретика.
они стрёмные
> кстати, факторизация - decidable?
да
>когда можно подождать разумное время и убить
разумное время подождать и убить, смышлёное пространство убить сразу, а истеричную энергию избить в переулке
> тролля-теоретика
wow rude
Это какой-то уход в мир грёз и поиск виновных ради раскрываемости... Я не дождусь, пока компьютер посчитает от 1 до N >> 1 с вероятностью не менее 1 - 1/N, а фанаты Тьюринга что-то про вычислимость говорят. А в то же время где-то крутится сервер с while(1) { processRequest(); } и всем дарит счастье.
> а фанаты Тьюринга что-то про вычислимость говорят
Ээээ.
А подскажите пожалуйста, а для каких чисел N зависнет цикл дописывающий сзади 1 к бинарному представлению N после чего добавляющий к результату исходное N, в случае если N - нечётное,
и убирающий из конца бинарного представления все 0, если N - чётное.
Думаю, даже для UInt64 выдержит, вычисление упрётся в длинную арифметику.
В среднем наверно хватит на 1К десятичных знаков, но где-то там может встретиться роковое число, из-за которого зависнет.
Поздравляю, вы решили одну из нерешённых проблем математики! Не забудте получить свой приз ТУТ
Если без чего-то можно обойтись, это не значит что это не нужно
простите, но мы программиста ищем, а не метапрограммиста
P.S. Кстати, в этом треде собрались удивительно нелогичные люди, которые, с одной стороны, погрязли в формализме, математике и логике с ног до головы и отрицают полезные нововведения, а с другой - пользуются существующими хаками и нелогичностями. То есть, если бы я говорил, что число Пи можно записать и использовать, они бы сказали "да как же, нет, нельзя, теория, формализм", а как только какой-нибудь авторитет показал бы им Пи в double и плавающего питуха, повсеместно используемого, так сразу можно.
Иными словами, некоторые пользователи ГК верят в логику ровно до тех пор, пока какой-нибудь авторитет вроде Страуструпа не покажет им авторитетный нелогичный метод решения их проблем вроде kill и double.
Не знаю. Всегда думал что для любого по-настоящему ленивого чело программиста dry и code reuse не пустые звуки.
К тому же джве разных версии кода имеют свойства разъезжаться при долгом маинтенсе.
>хотят использовать один код и на сервере и на клиенте...
На мой взгляд это единственное что сколь-нибудь оправдывает серверный js. Хотя тут конечно поджидает неприятный нюанс в виде невозможности использования новых фич (надо чтоб в старых браузерах).
А вот arrow functions у меня в node не работают. Хотя я, кажется, обновлял недавно.
Хотя, есть же трансляторы. Особо умные уже пишут на ES7.
Итого: пишем на ES6 или ES7, код автоматически приводим к ранней версии JS (делая его пригодным как минимум для серверной стороны) и переиспользуем.
Нет, уже работают. Таки давно обновлялся.
Это на далёкой машине с линуксом недавно обновлялся, только там в репозитории была версия времён Ленина.
Bytecode Targets produce executable byte code (Neko, SWF, SWF8), that can be executed directly by the runtime (Neko VM, Adobe Flash Player, Adobe AIR). Haxe API and platform-specific API is available.
Language Targets produce source code (AS3, C++, C#, Java). Most source code must be compiled by a third-party compiler to produce an executable file (Flex SDK, GCC, Microsoft Visual C++, Microsoft .NET, Java compiler). JavaScript and PHP code can be run directly, since the runtime uses just-in-time compilation. Inline code written in the target language can be inserted at any point in the application, thereby supporting the entire platform API; even features missing from the Haxe wrapper API.
Т.е. существует .NET, который "что угодно в одно" и Haxe, который "одно во что угодно".
Кстати, штуку "что угодно в что угодно" уже создали?
Нет вроде бы. Зато можно компилить haxe во что угодно и запускать всё это на .net.
Не слышал о таком. Но наверяка это возможно. Только вот если захочется x86 ассемблер откомпилировать в java например, это будет ооооочень медленно
https://ru.wikipedia.org/wiki/Vala
пости С# компилится в сишечку.
http://eu.battle.net/heroes/ru/heroes/valla/
Наконец-то хоть современные технологии и языки, а то всё напитон да напитон.
http://catb.org/jargon/html/p-convention.html
Англоязычные лисполюбы добавляли суффикс “-p” к словам для придания вопросительной интонации:
— Haxe-p?
— T!
The -P Convention
Turning a word into a question by appending the syllable ‘P’; from the LISP convention of appending the letter ‘P’ to denote a predicate (a boolean-valued function). The question should expect a yes/no answer, though it needn't. (See T and NIL.)
[Once, when we were at a Chinese restaurant, Bill Gosper wanted to know whether someone would like to share with him a two-person-sized bowl of soup. His inquiry was: “Split-p soup?” — GLS]
Сейчас же почти что угодно компиляется в JS. Поэтому вполне можно писать и клиент, и сервер, на каком-нибудь Haskell / Clojure, и генерировать клиентскую часть соответствующим компилятором хоть в asm.js. По сути ведь в GWT эту задумку и реализовали, причём уже довольно давно.
Конечно, на клиенский код будут ограничения, но и ведь не любой нодовый JS можно на клиенте использовать.
А уж компилять новый диалект JS в старый при сборке вообще (в теории) не проблема.
JavaScript is new ISA:) (instruction set architecture), лол
Ну и как, окупило себя хождение напитон в клиенте?
Но оно было ОЧЕНЬ простое. Полезность питона в огромной стандартной библиотеке, и я не думаю что вот прямо вся она отлично работает в браузере.
Профессионалы доверяют стандартной библиотеке. Стандартная библиотека — всё проверено до нас.
Логика уже была написана на питоне.
Но я не считаю это серьезным решением: как минимум они не умеют тройку.
А вот GWT я видел в продакшене еще в 2009-м году. Это было single page application которое сосало данные через COMET (вебсокетов тогда еще не умели), и дело было не в переюзании логики, а в нежелании писать на javascript)
во всяком случае на той версии, куда не завезли ключевое слово class
там в визуальщине и метапитушне (где какой инпут зависит от другого, чтобы каскадно их апдейтить, с шашечками как в экселе) больше работы, чем в непосредственно проверке собранной модели на валидность
Писать ДВА раза бизнес-логику это вообще самый ужасный ужас, который может случиться.
Другой вопрос что можно было описать ее языконезависимо и генерить(или программировать) по ней клиент и сервер. Жаль что нет каких-то стандартных языков для этого (ну или мне они неизвестны)
Дак в том и дело, что бизнес-логика на клиенте и на сервере всё равно различна. Один клиент, другой - сервер. Клиент вообще может что угодно заслать - апи то открытое, всё видно в F12, исходники (даже обфусцированные, но исходники) клиента у злоумышленника в наличии.
Пусть даже у них модель будет одинакова, включая связи между сущностями (и это чистая правда, и даже мы предпринимали потуги по автогенереции .ts моделей из .java, в итоге фронтовики сказали - лан, это всё заебись, но руками мы более качественный кот напишем, это 10 минут работы) - сама логика (сервисы) будут иметь различную реализацию - потому что ты в одном месте (фронт) контролируешь пользовательский ввод на уровне связи инпутов с моделью и взаимозависимостей вьюх (так, ага, тыкнули сюда, показываем вот это), а в другом (бек) тупо проверяешь уже пачку этих объектов, собранных воедино в объект AllEnteredUserStuffToProcessFoo - беку насрать на атомарные действия юзера, он контролирует шаги более крупно (в пределе - в один пост сразу весь конечный самодостаточный итог, который проверяет бек и ТОЖЕ может отказать фронту, но уже по причине того, что весь кумулятивный объект ему не понравился)
Ты же не будешь на фронте считать конечную стоимость КАСКО, и потом уже захуяривать на бек запрос "выстави этому придурку счет на 100500 рублей, вот конечное число, я тут на фронте пощитал", как и не будешь на бек слать "так, он тут фамилию свою ввёл, и перешёл на другой инпут, че делать"
В любом случае, я не настаиваю, хозяин барин. Прост хотелось узнать как так вышло. Ответ устроил.
Мы, например, кое-где в жабьем беке сами движок v8 заембеддили, у нас тоже причины были на это (не код реюз).
* валидация полей (регулярки, граничные значения для числовых полей)
* доступность полей в зависимости от других: если в поле A я ввел foo, а в поле B ввел bar, то в поле C можно выбирать только 1 или 2, а иначе там будет еще 3.
* если заполнены поля A и B, то так же нужно заполнить поле C.
Разумеется, сервер не доверяет клиенту и заново все это валидирует. Просто пользователю приятнее когда ГУИ ему помогает, а не сообщает в конце что он не заполнил нужное поле.
И конечно сервер может валидировать более глобальные вещи чем один объект, представляющий форму. Ну это гую никак не мешает.
Есть разные попытки решить это генерацией HTML. Скажем, в джанге можно указать max_length поля и некоторые формочки отрендерят ее с HTML5 input type=number, но это не везде работает, и не всё можно этим покрыть.
Ты говоришь вполне разумные доводы, которые посещали каждого, кто подступался к таким задачам, но в реальной жизни выходит все не так сферично.
Порассуждаю вслух.
Каждый инпут должен быть связан с моделью, поменяли инпут - изменился объект, изменился объект - изменился инпут. Модель в т.ч. подразумевает, что ты должен насосать кучу справочников, в т.ч. иногда подсосать по мере ввода. Что изменяя инпут А и Б, у тебя подмножество допустимых значений инпута Ц должно пройти фильтрацию (влияя ли на UI, сокращая количество опций в дропдауне, или просто на результат проверки инпута Ц - дело второе). При этом фронту еще огого сколько делать кроме общения непосредственно с модулем валидации.
Т.к. на фронте и так сосать все эти справочники, в варианте с подключением питона надо учесть момент, что в режиме работы на фронте эти справочники ему скормит жс, а на сервере он те же репозитории найдет с более другой имплементацией. Требуется 1:1 мапинг питоновских объектов на жсные, чтобы питоновская модель соответствовала модели жса (чтобы питон мог в своих объектах сохранить атрибуты isValid, isEnabled, userNoticeText и т.д., на которые соответствующе отреагирует фронт). Ну т.е. взлетит, правда накладных расходов все больше на эту конструкцию.
Чтобы окупилось, требуется чтобы на беке реально был напитон, и чтобы таких форм реально было много и все нетривиальные. Я даже предполагаю в каких отраслях народного хозяйства нужен такой беспредел.
> Жаль что нет каких-то стандартных языков для этого
Для агностик решения потребуется описывать метапитушню на чем-то декларативном, и учить и фронт, и бек эту метапитушню переваривать одинаково (ну или хотя бы генерить из бека метапитушню, разбираемую фронтом), что выйдет ещё дороже, чем когда фронт и бек уже сразу на "питоне" (ну или на реакте+ноде, как советовали выше).
Я тоже не знаю таких библиотек, которые бы что-то автоматизировали (т.к. у нас нет портянок по 50 инпутов, с зависимостями от фаз луны).
Самое позорное случится тогда, когда библиотека перестанет удовлетворять 1% потребностей, и для поиска обходных путей придется вложить столько костов и граблей, что разделение между клиентом и сервером логики валидации с дублированием покажется не такой и плохой темой в реализации и сопровождении.
--------
<a href=https://bezopasnik24.ru>техническое обслуживание пожарной сигнализации</a> | https://bezopasnik24.ru
Пурпурный чай - это мощнейший жиросжигатель, который к тому же препятствует возникновению новых отложений, превращая жир в энергию.
Официальный сайт: http://pur.bxox.info
<a href=http://bit.ly/2oQUzUu>легкий заработок онлайн</a>
<a href=http://bit.ly/2oQUzUu>источники пассивного дохода</a>
<a href=http://bit.ly/2oQUzUu>быстрый заработок</a>
<a href=http://bit.ly/2oQUzUu>стратегии заработка</a>
<a href=http://mikrosaym.blogspot.ru>Онлайн займы</a>
hhhh=
Доставка по России. Анонимно.
[email protected]