Страницы

Поиск по вопросам

пятница, 5 октября 2018 г.

Программирование загрузочного сектора C

Разбираюсь с программированием загрузочного сектора. Делаю согласно этой статье. Всё получалось до момента программирования вывода "Hello, World!" на языке C. Вот код, который приводится в статье (собственно, я его просто копирую):
__asm__(".code16
"); __asm__("jmpl $0x0000, $main
");
void printString(const char* pStr) { while(*pStr) { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0e00 | *pStr), "b"(0x0007) ); ++pStr; } }
void main() { printString("Hello, World"); }
Компилирую, линкую и тд опять же согласно той статье:
gcc -c -g -Os -m32 -ffreestanding -Wall -Werror test.c -o test.o ld -melf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o objcopy -O binary test.elf test.bin dd if=/dev/zero of=floppy.img bs=512 count=2880 dd if=test.bin of=floppy.img
На всякий случай приведу содержимое test.ld:
ENTRY(main); SECTIONS { . = 0x7C00; .text : AT(0x7C00) { *(.text); } .sig : AT(0x7DFE) { SHORT(0xaa55); } }
Запускаю bochs, но вместо того, чтобы напечатать "Hello, World", у меня выводится только один символ "S".
Перенёс функцию в main:
__asm__(".code16
"); __asm__("jmpl $0x0000, $main
"); void main() { char s[] = "Hello, World"; char *str = s; while (*str) { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0e00 | *str), "b"(0x0007) ); ++str; } }
После этого он перестал выводить что-либо в принципе. Помогло исключение флага оптимизации -Os. Вывод стал верным. Немного поэкспериментировав, я понял, что эта оптимизация "убивает" цикл.
Однако, тот же самый код, но перенесённый в функцию, всё так же выводит символ "S".
Прошу помощи в решении этой проблемы. А так же, если возможно, разъяснения, почему флаг оптимизации "убивает" цикл. Спасибо!
UPD.
Hex от test.bin:
66 EA 3A 7C 00 00 00 00 66 55 66 89 E5 EB 19 67 66 8B 45 08 67 66 0F B6 00 66 0F BE C0 80 CC 0E CD 10 67 66 83 45 08 01 67 66 8B 45 08 67 66 0F B6 00 84 C0 75 D9 90 66 5D C3 66 55 66 89 E5 66 68 4F 7C 00 00 E8 C0 FF 66 83 C4 04 90 C9 C3 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 00 14 00 00 00 00 00 00 00 01 7A 52 00 01 7C 08 01 1B 0C 04 04 88 01 00 00 1C 00 00 00 1C 00 00 00 8C FF FF FF 32 00 00 00 00 42 0E 08 85 02 43 0D 05 6C C5 0C 04 04 00 00 1C 00 00 00 3C 00 00 00 9E FF FF FF 15 00 00 00 00 42 0E 08 85 02 43 0D 05 4F C5 0C 04 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
Файл был получен из следующего исходника:
__asm__(".code16
"); __asm__("jmpl $0x0000, $main
");
void printString(const char* str) { while (*str) { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0e00 | *str)); ++str; } }
void main() { printString("Hello, World"); }
UPD.
Результат дизассемблирования файла test.elf:
% objdump -d test.elf
test.elf: file format elf32-i386
Disassembly of section .text:
00007c00 : 7c00: 66 ea 3a 7c 00 00 ljmpw $0x0,$0x7c3a ...
00007c08 : 7c08: 66 55 push %bp 7c0a: 66 89 e5 mov %sp,%bp 7c0d: eb 19 jmp 7c28 7c0f: 67 66 8b 45 08 mov 0x8(%di),%ax 7c14: 67 66 0f b6 00 movzbw (%bx,%si),%ax 7c19: 66 0f be c0 movsbw %al,%ax 7c1d: 80 cc 0e or $0xe,%ah 7c20: cd 10 int $0x10 7c22: 67 66 83 45 08 01 addw $0x1,0x8(%di) 7c28: 67 66 8b 45 08 mov 0x8(%di),%ax 7c2d: 67 66 0f b6 00 movzbw (%bx,%si),%ax 7c32: 84 c0 test %al,%al 7c34: 75 d9 jne 7c0f 7c36: 90 nop 7c37: 66 5d pop %bp 7c39: c3 ret
00007c3a

: 7c3a: 66 55 push %bp 7c3c: 66 89 e5 mov %sp,%bp 7c3f: 66 68 4f 7c pushw $0x7c4f 7c43: 00 00 add %al,(%eax) 7c45: e8 c0 ff 66 83 call 83677c0a 7c4a: c4 04 90 les (%eax,%edx,4),%eax 7c4d: c9 leave 7c4e: c3 ret
UPD.
Вот дизассемблирование hiew как просессор видит программу:
7c00: 66EA3A7C00000000 jmpf 00000:07C3A 7c08: 6655 3push ebp 7c0A: 6689E5 mov ebp,esp 7c0D: EB19 jmps 000000028 --↓1 7c0F: 67668B4508 2mov eax,[ebp][8] 7c14: 67660FB600 movzx eax,b,[eax] 7c19: 660FBEC0 movsx eax,al 7c1D: 80CC0E or ah,00E 7c20: CD10 int 010 7c22: 676683450801 add d,[ebp][8],1 7c28: 67668B4508 1mov eax,[ebp][8] 7c2D: 67660FB600 movzx eax,b,[eax] 7c32: 84C0 test al,al 7c34: 75D9 jnz 00000000F --↑2 7c36: 90 nop 7c37: 665D pop ebp 7c39: C3 retn ; 7c3A: 6655 push ebp 7c3C: 6689E5 mov ebp,esp 7c3F: 66684F7C0000 push 000007C4F ;' |O' 7c45: E8C0FF call 000000008 --↑3 7c48: 6683C404 add esp,4 7c4C: 90 nop 7c4C: 90 nop 7c4D: C9 leave 7c4E: C3 retn ; 7c4F: 48 65 6C 6C 6F-2C 20 57 6F-72 6C 64 Hellow, World
Методом тыка, заметил, что действительно указатель необходимо смещать. Для загрузочной области необходимо поместить код в первый сектор диска со смещением в 0x7C00 байт. Это я указываю в файле test.ld. Я попробовал вывести всё, что у меня идёт после. И в куче разнообразных символов затаился желаемый "Hello, World". При этом изменение кода влечёт изменение в смещении, но я почти уверен, что оно будет всегда больше 0x7C00. Осталось понять, как правильно отслеживать это смещение...


Ответ

В случае написание загрузочного сектора - проверяйте дизассемблером что у вас вышло. Для линукса незнаю как, для винды hiew.exe - хороший дизассемблер. Не забывайте что на старте - процессор находится в 16-битном режиме команд и в 16-битном режиме адресации - это важно 1) при сборке бинарника 2) для понимания что происходит 3)при дизассемблировании.
Анализ даного случая показал, что код "неправильно" собран то ли компилятором то ли линкером. Коды 66 - переход в режим 32-битной команды, и 67 - переход в 32-битную адресацию
7c22: 676683450801 add d,[ebp][8],1 7c28: 67668B4508 1mov eax,[ebp][8] 7c2D: 67660FB600 movzx eax,b,[eax]
эти переходы должны напрягать. Их использовать можно (66), но с умом. 32-битную адресацию (67) лучше избегать вообще, вплоть до переключения в защищенный режим, но первичный загрузчик этого не делает. Как вывод - Если код не работает, хотя он проверен, а картинка не складывается - то проблема с опциями сборки.
Конкретно в даном случае помогло поменять директиву code16 (она в новой версии gcc исчезла) на code16gcc. Указывать code16 или code16gcc зависит от версии GCC.

Адаптивная таблица

Задача - немного упростить процесс работы с таблицами на мобильных устройствах. Простым превращением таблицы в блок не обойтись, так как при наличии нескольких колонок будет невозможным разобрать где какие значения отображаются.
Пример таблицы:
$('button').click(function() { $('.two-col-table td').css("display", 'block'); }); .two-col-table { width: 100%; margin: 30px 0; background: #fefefe; border-radius: 4px; border-collapse: collapse; font-size: .9em; } .two-col-table td { border: 1px solid #ccc; padding: 10px 12px; } .two-col-table td p { margin: 0; }

Условия эксплуатации покрытия Огнезащита Антисептик
Наружные поверхности, не подверженные вымыванию, при переменной влажности и температуре под воздействием солнечного излучения и ветра 5 лет 10 лет
Внутри неотапливаемых жилых и нежилых помещений 16 лет 25 лет
Наружные поверхности помещений, находящихся в условиях Крайнего Севера 3 лет 5 лет
Внутренние поверхности закрытых неотапливаемых помещений, находящихся в условиях Крайнего Севера 5 лет 8 лет

Как можно заменить из примера, если задать .two-col-table td {display:block} все ячейки перекинутся на новую строку и будет непонятно, какие данные видит пользователь, так как заголовка вверху таблицы не будет.
Вопрос следующий, как можно раскидать заголовок по строкам таблицы? Чтоб по итогу получить вот такой вид:
$('button').click(function() { $('.two-col-table td').css("display", 'block'); }); .two-col-table { width: 100%; margin: 30px 0; background: #fefefe; border-radius: 4px; border-collapse: collapse; font-size: .9em; } .two-col-table td { border: 1px solid #ccc; padding: 10px 12px; } .two-col-table td p { margin: 0; } .two-col-table span { display: block; color: grey } .two-col-table tr:first-child { display: none; }
Условия эксплуатации покрытия Огнезащита Антисептик
Условия эксплуатации покрытия Наружные поверхности, не подверженные вымыванию, при переменной влажности и температуре под воздействием солнечного излучения и ветра Огнезащита 5 лет Антисептик 10 лет
Условия эксплуатации покрытия Внутри неотапливаемых жилых и нежилых помещений Огнезащита 16 лет Антисептик 25 лет
Условия эксплуатации покрытия Наружные поверхности помещений, находящихся в условиях Крайнего Севера Огнезащита 3 лет Антисептик 5 лет
Условия эксплуатации покрытия Внутренние поверхности закрытых неотапливаемых помещений, находящихся в условиях Крайнего Севера Огнезащита 5 лет Антисептик 8 лет

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


Ответ

$(document).on('click', function() { $('tr:not(.first-tr)').each(function() { $(this).find('td').each(function() { $(this).prepend('' + $('tr.first-tr td').eq($(this).index()).text() + '') }); }); }); $('button').click(function() { $('.two-col-table td').css("display", 'block'); }); .two-col-table { width: 100%; margin: 30px 0; background: #fefefe; border-radius: 4px; border-collapse: collapse; font-size: .9em; } .two-col-table td { border: 1px solid #ccc; padding: 10px 12px; } .two-col-table td p { margin: 0; } .grey-span { display: block; color: grey; }

Условия эксплуатации покрытия Огнезащита Антисептик
Наружные поверхности, не подверженные вымыванию, при переменной влажности и температуре под воздействием солнечного излучения и ветра 5 лет 10 лет
Внутри неотапливаемых жилых и нежилых помещений 16 лет 25 лет
Наружные поверхности помещений, находящихся в условиях Крайнего Севера 3 лет 5 лет
Внутренние поверхности закрытых неотапливаемых помещений, находящихся в условиях Крайнего Севера 5 лет 8 лет

Не знаю, как подключить здесь jQuery. Добавил класс .first-tr (но лучше используйте thead и tbody), и добавил класс .grey-span (не отрывайте руки :) ).
Click для примера - здесь любое событие.
$('tr.first-tr td').eq($(this).index()).text() - берем текст с первой tr, которая по индексу такая же, как текущая.
На коленке и по-быстрому, надеюсь, смысл ясен :)

Как эффективней писать ПО

Пишу средний проект на java. Сроки довольно сжатые. Как лучше распределить свое время: 1.Писать код по намеченной логике, и уже в конце начать его тестировать. 2.Или разбить логику на под задачи и писать/тестировать по кусочкам.
Второй способ кажется логичней, но допустим написав 1-5 пункты своей задачи и протестировав я пойму что 8 и 9 пункты вынуждают меня 1-5 пункты переписать. Так собственно и произошло, поэтому я этот вопрос и задаю. В итоге время на тесты было потрачено впустую.
И если есть хорошие статьи на эту тему буду благодарен.


Ответ

Agile (итеративное) управление проектом удлиняет сроки разработки (во втором варианте вы по сути описываете именно agile технологию), но минимизирует риски не неверного проектирования.
К сожалению в 90% проектов при написании ТЗ (или планировании проекта) невозможно на 100% сразу определить все возможные проблемы. Как правильно отметили вы же сами ответили, проект после какой-то стадии начинает жить своей собственной жизнью, а именно:
1-5 пункты своей задачи и протестировав я пойму что 8 и 9 пункты вынуждают меня 1-5 пункты переписать.
Если проект небольшой или вы уверены в том, что риски неверного проектирования минимальны, то можно сразу писать и тестировать в конце.
Можно выбрать другой способ разбить задачу не на 8-9 пунктов, а только на 2-3 пункта ибо чем больше пунктом/итераций, тем более вы даете свободу нелинейности проектирования, зато чем меньше пунктов, тем больше рисков неверного проектирования.
Соответственно, вам нужно определить этапы/итерации проекта не исходя из внутренней логики проекта, а исходя из рисков неверного проектирования, то есть если вы видите в проекте, скажем 10 логических этапов, из которых 5 вам хорошо понятны, а еще 5 "темный лес", то имеет смысл проект разделить на 6 этапов: на 1 этап в котором собрать 5 понятных вам пунктов, а 5 непонятных так и оставить как 5 этапов. Понятно, что такое не всегда возможно, но тем не менее - как общая идея.

Размытый фон под блоком

Подскажите пожалуйста, с помощью чего можно реализовать эффект размытия. Необходимо реализовать так, чтобы под блоком с меню контент размывался. У меню допустим свой фон background: rgba(32, 32, 32, 0.6), а все что под блоком это контент страницы. И нужно, чтобы контент под блоком меню размывался в неподвижном состоянии и при прокрутке страницы. Меню должно быть зафиксировано в верху страницы.
Нужно примерно такого вида:


Ответ

Недавно увидел вопрос Qwertiy, который мне очень понравился. И даже сразу мысленно нашел ему применение... Но на практике ни где не использовал. А когда прочитал окончательный вариант данного вопроса, первая мысль которая пришла, это ответ Sasha Omelchenko на вопрос Qwertiy. Ну сложив всю эту информацию, решил, что это лучший вариант решения для данного вопроса.
P.S. Для лучшего эффекта разверните на весь экран...
document.querySelector('main').addEventListener('scroll', function(e) { var dy = this.scrollTop; document.querySelector('#text').style.transform = "translateY(" + -dy + "px)"; }); document.querySelector('#text').addEventListener('wheel', function(e) { document.querySelector('main').scrollTop -= e.wheelDeltaY; e.preventDefault(); }); * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; background: #272727; color: white; background: url(https://wallbox.ru/wallpapers/main/201447/89de87d17b78c12.jpg); background-attachment: fixed; } #wrapper { overflow-x: hidden; position: relative; width: 100%; height: 100%; } header { overflow: hidden; width: 100%; height: 220px; position: sticky; top: 0; background: transparent; top: 0; } #layerBlurwhite { overflow: hidden; width: 100%; height: 100%; position: sticky; top: 0; background: rgba(255, 255, 255, .5); filter: blur(3px); } #layerBlurBg { overflow: hidden; width: 100%; height: 100%; position: sticky; top: 0; background-image: url(https://wallbox.ru/wallpapers/main/201447/89de87d17b78c12.jpg); background-position: 0 0; filter: blur(10px); } #layerText { z-index: 155; width: 100%; height: 220px; position: fixed; top: 0; background: transparent; color:white; text-align: center; line-height: 2; font-size: 50px; } main { position: relative; overflow-y: scroll; overflow-x: hidden; width: calc(100% + 20px); height: calc(100% - 220px); background: transparent; } main p { margin-top: 150px; } header p { position: relative; top: -220px; margin-top: 150px; color: white; filter: blur(10px); }

MENU BAR

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo veniam cumque earum sit aspernatur voluptas magni, neque repellendus obcaecati, cupiditate quae facilis necessitatibus praesentium officiis et rem minus, atque, voluptatem totam voluptate nobis quibusdam asperiores! Ipsa, cupiditate maxime velit rem nulla vel optio, consequuntur enim eos neque doloribus. Doloribus vel odio et adipisci placeat ut, quia temporibus, sit laudantium ipsam consectetur quas culpa sequi libero commodi non, veniam. Maiores fugiat, amet! Sequi optio dolor cupiditate animi, earum necessitatibus quae vel nisi doloremque eos eligendi sunt ipsa, ex atque dolorum sint nulla voluptatibus libero et similique consequatur dolorem iste, distinctio labore!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam mollitia laborum placeat, saepe, voluptates exercitationem consequuntur ea reiciendis esse voluptate sit illo tempore nobis, doloribus sunt nesciunt ipsa fugit. Minus earum, amet fuga exercitationem dolore nobis, possimus adipisci accusantium odit libero facere cumque nostrum dolorum nemo veritatis modi vel pariatur fugiat. Sapiente quos qui reiciendis saepe adipisci sint placeat accusantium. Saepe ipsam aut nostrum, ratione, fugit, culpa iusto, illum atque dicta delectus error explicabo ex? Dolorem saepe veritatis ea delectus quaerat fugit architecto quis error hic vero, laboriosam enim, exercitationem. Obcaecati, illum? Sed minus, deleniti fuga labore, odit totam et.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore tempora libero temporibus impedit veniam. Necessitatibus totam iusto, ducimus voluptas voluptate sed doloribus consequatur quidem nisi veniam tempore aliquid ratione, provident adipisci nobis animi placeat quisquam recusandae. Eaque nihil modi officiis accusamus, repellat libero, expedita adipisci explicabo voluptatum minima, quibusdam quo sequi. Aliquid nobis, eos voluptate repudiandae eius provident officiis enim ad nemo quod beatae ex expedita distinctio quia at, voluptatum iste cum? Sint possimus quam saepe iure perspiciatis consectetur accusantium excepturi asperiores animi, cumque dolores itaque accusamus! Cum quia iste aperiam, minima quas quam ipsam adipisci at sunt rem porro.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab excepturi quis dolores odit mollitia sint perferendis voluptas delectus eaque quas dolorum nesciunt iure repellat cum architecto, in maiores! Consectetur ratione iste nemo eos doloribus soluta ut quas accusantium rerum labore beatae omnis tempora neque, laboriosam ducimus non, itaque expedita eaque quidem. Veniam nemo eligendi, voluptatem quidem accusantium, doloribus sed, explicabo, ex fugiat vel ab exercitationem molestias error repudiandae sunt tempora maiores. Repellendus aut, id corporis nobis rerum eum debitis quod porro reprehenderit illo nulla, in iure. Eius, quidem! Cumque earum ipsam vel sapiente soluta, iste animi, illo aliquam aspernatur est.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio voluptas molestias perspiciatis ex quidem ullam facere esse ab qui voluptatem alias eligendi praesentium, unde, dolores, enim aperiam quam in, eum deleniti vel! Accusamus dolorum, dolore ut sequi sunt quidem earum, quis recusandae sint esse consectetur veritatis distinctio explicabo nemo dignissimos sed? Ut quibusdam sequi, est laudantium inventore, minus facilis sed dignissimos id, eum dolore. Unde voluptas veritatis suscipit quia ab mollitia magni hic nisi vero odio harum quos, molestiae ullam autem rerum earum explicabo temporibus minus quasi numquam dolores provident quibusdam adipisci! Ea quasi doloribus reiciendis ducimus cupiditate alias recusandae.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fuga iste voluptates culpa, est velit perspiciatis natus eaque quod quibusdam omnis et impedit voluptatem recusandae officia assumenda, atque quasi fugiat praesentium beatae tempora dolorem, earum nulla dolor. Esse eveniet error aut repudiandae quaerat quis provident inventore aliquam minima harum magni sapiente cum quisquam omnis, quidem molestias possimus dolores numquam tempore officia sed modi. Aliquid quisquam sint aliquam ratione, officiis quibusdam! Esse amet consectetur dolorem, dolor velit alias facere vero eaque non tempora minus illo maxime quis recusandae debitis eos pariatur, voluptas quasi autem ex! Harum architecto repellat dolore libero placeat natus.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis quibusdam alias, tempora nam enim, explicabo non molestiae, earum magni rem consectetur totam tenetur ratione necessitatibus iure vitae. Nam tenetur quo sunt voluptates deleniti, et iure quod architecto aspernatur eaque nesciunt at modi ex nostrum possimus impedit maiores quae optio quas dignissimos similique incidunt aliquid eum facere commodi. Officiis perspiciatis aperiam alias numquam voluptatum, vitae aut accusamus ratione, expedita quibusdam odit, ipsa? Eum rerum quasi nobis, recusandae voluptatum accusamus alias, labore non odio quaerat fugiat, fuga nam fugit maxime sed eveniet! Est aliquid, iure tempora repellendus provident autem obcaecati voluptas dolorem!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis eos commodi molestias, sed labore impedit quo. Dolorem assumenda dolore, facere, at temporibus eos facilis dolorum quas doloribus nesciunt sequi ut voluptas dolores est. Dolore aliquid quasi inventore quam dolorum maiores, id placeat dolores autem numquam, beatae? Consectetur aspernatur sequi deleniti unde labore iusto earum fuga eius est distinctio tempore cum, quo non veniam, adipisci animi corporis voluptatibus iure delectus velit numquam ea enim repellat debitis. Maiores quas quibusdam id provident a magnam molestias tempore dolores nemo vero in laboriosam assumenda accusantium, quaerat, deserunt ratione numquam molestiae. Sint, placeat consequuntur dolores.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quo repudiandae doloribus accusamus accusantium, odit mollitia expedita omnis recusandae dolorem quos quidem consequatur, ab iste fugit, eum veritatis ex eaque culpa quis praesentium. Voluptas perferendis cumque, magni at error enim pariatur fuga, reprehenderit quidem odio ex non omnis dolorem ab vero asperiores molestiae ipsum praesentium aliquam. Accusantium ipsam aut autem voluptatum non nostrum tempore illum atque ducimus. Quis sit omnis ea, odio quae eum nostrum fugit dignissimos autem, veniam dicta sed quia minima debitis magnam harum inventore nobis architecto nihil. Recusandae aspernatur unde repudiandae, excepturi laborum, commodi dolorum suscipit tempora. Laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maxime explicabo magni delectus repudiandae, esse mollitia ullam pariatur, ad quaerat atque asperiores consequatur quos iure facilis sit placeat neque incidunt, ipsam nesciunt voluptas modi debitis! Consequuntur, suscipit libero quisquam illum rem reprehenderit, nisi tenetur. Vero rem sed neque quia soluta, sapiente reprehenderit aspernatur quaerat unde suscipit, cum error voluptatibus laudantium quos hic, modi voluptates praesentium eum repellat impedit recusandae quam alias voluptatum fuga. Ex nisi tempora corrupti, amet ea iusto vero, repellat quidem autem, pariatur similique. Aperiam officia consequatur explicabo illo cupiditate, iusto, voluptates sed dolorum dolorem qui corporis nam eligendi!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo veniam cumque earum sit aspernatur voluptas magni, neque repellendus obcaecati, cupiditate quae facilis necessitatibus praesentium officiis et rem minus, atque, voluptatem totam voluptate nobis quibusdam asperiores! Ipsa, cupiditate maxime velit rem nulla vel optio, consequuntur enim eos neque doloribus. Doloribus vel odio et adipisci placeat ut, quia temporibus, sit laudantium ipsam consectetur quas culpa sequi libero commodi non, veniam. Maiores fugiat, amet! Sequi optio dolor cupiditate animi, earum necessitatibus quae vel nisi doloremque eos eligendi sunt ipsa, ex atque dolorum sint nulla voluptatibus libero et similique consequatur dolorem iste, distinctio labore!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam mollitia laborum placeat, saepe, voluptates exercitationem consequuntur ea reiciendis esse voluptate sit illo tempore nobis, doloribus sunt nesciunt ipsa fugit. Minus earum, amet fuga exercitationem dolore nobis, possimus adipisci accusantium odit libero facere cumque nostrum dolorum nemo veritatis modi vel pariatur fugiat. Sapiente quos qui reiciendis saepe adipisci sint placeat accusantium. Saepe ipsam aut nostrum, ratione, fugit, culpa iusto, illum atque dicta delectus error explicabo ex? Dolorem saepe veritatis ea delectus quaerat fugit architecto quis error hic vero, laboriosam enim, exercitationem. Obcaecati, illum? Sed minus, deleniti fuga labore, odit totam et.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore tempora libero temporibus impedit veniam. Necessitatibus totam iusto, ducimus voluptas voluptate sed doloribus consequatur quidem nisi veniam tempore aliquid ratione, provident adipisci nobis animi placeat quisquam recusandae. Eaque nihil modi officiis accusamus, repellat libero, expedita adipisci explicabo voluptatum minima, quibusdam quo sequi. Aliquid nobis, eos voluptate repudiandae eius provident officiis enim ad nemo quod beatae ex expedita distinctio quia at, voluptatum iste cum? Sint possimus quam saepe iure perspiciatis consectetur accusantium excepturi asperiores animi, cumque dolores itaque accusamus! Cum quia iste aperiam, minima quas quam ipsam adipisci at sunt rem porro.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab excepturi quis dolores odit mollitia sint perferendis voluptas delectus eaque quas dolorum nesciunt iure repellat cum architecto, in maiores! Consectetur ratione iste nemo eos doloribus soluta ut quas accusantium rerum labore beatae omnis tempora neque, laboriosam ducimus non, itaque expedita eaque quidem. Veniam nemo eligendi, voluptatem quidem accusantium, doloribus sed, explicabo, ex fugiat vel ab exercitationem molestias error repudiandae sunt tempora maiores. Repellendus aut, id corporis nobis rerum eum debitis quod porro reprehenderit illo nulla, in iure. Eius, quidem! Cumque earum ipsam vel sapiente soluta, iste animi, illo aliquam aspernatur est.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio voluptas molestias perspiciatis ex quidem ullam facere esse ab qui voluptatem alias eligendi praesentium, unde, dolores, enim aperiam quam in, eum deleniti vel! Accusamus dolorum, dolore ut sequi sunt quidem earum, quis recusandae sint esse consectetur veritatis distinctio explicabo nemo dignissimos sed? Ut quibusdam sequi, est laudantium inventore, minus facilis sed dignissimos id, eum dolore. Unde voluptas veritatis suscipit quia ab mollitia magni hic nisi vero odio harum quos, molestiae ullam autem rerum earum explicabo temporibus minus quasi numquam dolores provident quibusdam adipisci! Ea quasi doloribus reiciendis ducimus cupiditate alias recusandae.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fuga iste voluptates culpa, est velit perspiciatis natus eaque quod quibusdam omnis et impedit voluptatem recusandae officia assumenda, atque quasi fugiat praesentium beatae tempora dolorem, earum nulla dolor. Esse eveniet error aut repudiandae quaerat quis provident inventore aliquam minima harum magni sapiente cum quisquam omnis, quidem molestias possimus dolores numquam tempore officia sed modi. Aliquid quisquam sint aliquam ratione, officiis quibusdam! Esse amet consectetur dolorem, dolor velit alias facere vero eaque non tempora minus illo maxime quis recusandae debitis eos pariatur, voluptas quasi autem ex! Harum architecto repellat dolore libero placeat natus.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis quibusdam alias, tempora nam enim, explicabo non molestiae, earum magni rem consectetur totam tenetur ratione necessitatibus iure vitae. Nam tenetur quo sunt voluptates deleniti, et iure quod architecto aspernatur eaque nesciunt at modi ex nostrum possimus impedit maiores quae optio quas dignissimos similique incidunt aliquid eum facere commodi. Officiis perspiciatis aperiam alias numquam voluptatum, vitae aut accusamus ratione, expedita quibusdam odit, ipsa? Eum rerum quasi nobis, recusandae voluptatum accusamus alias, labore non odio quaerat fugiat, fuga nam fugit maxime sed eveniet! Est aliquid, iure tempora repellendus provident autem obcaecati voluptas dolorem!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis eos commodi molestias, sed labore impedit quo. Dolorem assumenda dolore, facere, at temporibus eos facilis dolorum quas doloribus nesciunt sequi ut voluptas dolores est. Dolore aliquid quasi inventore quam dolorum maiores, id placeat dolores autem numquam, beatae? Consectetur aspernatur sequi deleniti unde labore iusto earum fuga eius est distinctio tempore cum, quo non veniam, adipisci animi corporis voluptatibus iure delectus velit numquam ea enim repellat debitis. Maiores quas quibusdam id provident a magnam molestias tempore dolores nemo vero in laboriosam assumenda accusantium, quaerat, deserunt ratione numquam molestiae. Sint, placeat consequuntur dolores.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quo repudiandae doloribus accusamus accusantium, odit mollitia expedita omnis recusandae dolorem quos quidem consequatur, ab iste fugit, eum veritatis ex eaque culpa quis praesentium. Voluptas perferendis cumque, magni at error enim pariatur fuga, reprehenderit quidem odio ex non omnis dolorem ab vero asperiores molestiae ipsum praesentium aliquam. Accusantium ipsam aut autem voluptatum non nostrum tempore illum atque ducimus. Quis sit omnis ea, odio quae eum nostrum fugit dignissimos autem, veniam dicta sed quia minima debitis magnam harum inventore nobis architecto nihil. Recusandae aspernatur unde repudiandae, excepturi laborum, commodi dolorum suscipit tempora. Laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maxime explicabo magni delectus repudiandae, esse mollitia ullam pariatur, ad quaerat atque asperiores consequatur quos iure facilis sit placeat neque incidunt, ipsam nesciunt voluptas modi debitis! Consequuntur, suscipit libero quisquam illum rem reprehenderit, nisi tenetur. Vero rem sed neque quia soluta, sapiente reprehenderit aspernatur quaerat unde suscipit, cum error voluptatibus laudantium quos hic, modi voluptates praesentium eum repellat impedit recusandae quam alias voluptatum fuga. Ex nisi tempora corrupti, amet ea iusto vero, repellat quidem autem, pariatur similique. Aperiam officia consequatur explicabo illo cupiditate, iusto, voluptates sed dolorum dolorem qui corporis nam eligendi!


Откуда берется интернет?

Понимаю, что вопрос тупой, но все же, он меня мучает.Что такое интернет я понимаю. Мне непонятен один ньюанс лишь:Есть провайдеры, которые продают трафик, откуда они его берут?Я знаю одного провайдера (мой знакомый), он берет и покупает "оптом" трафик у другого провайдера, бьет на более мелкую ширину канала и продает сам, как провайдер.Ок, допустим, подавляющее большинство провайдеров (наверное) берут также трафик у кого-то другого, а откуда берет трафик этот "кто-то другой" ?Возможно, вопрос мой совсем идиотский, скажите хоть что гуглить.Спасибо.


Ответ

Из точек обмена трафиком А также почитайте про пиринг

Долгое установление соединения с Mysql

Есть три машины находящиеся в одной сети. На одной крутится Mysql, две другие выступают в роли клиента. При этом на одной клиентской машине соединение устанавливается в доли секунды, на второй то долго соединяется то быстро. Проверял командой: telnet database.server 3306
Отличия двух клиентских машин заключаются в том что на одной стоит Ubuntu 14.04 на другой Ubuntu 16.04
Вопрос, куда копать?


Ответ

Скорее всего проблема в том, что для каждого клиента MySQL делает DNS lookup, добавьте в конфигурацию (my.cnf) следующую строку (skip-name-resolve) в раздел mysqld и перезапустите сервер
[mysqld] skip-name-resolve
Для установления причин подобных проблем изучите и пользуйтесь командой tcpdump, она Вам скажет на каком этапе случилась проблема соединения.

Как создавать контрастные по отношению друг к другу цвета?

В моем проекте есть возможность рисовать график по некоторым наборам данных. Их количество варьируется от 1 до... до тех пор, пока пользователю не надоест добавлять новые наборы данных.
Необходимо, чтобы на графике были хорошо различимы ВСЕ линии. Для этого, нужно чтобы все линии были более-менее контрастны по отношению к друг-другу, на сколько я понимаю.
Вопрос - как создавать эти контрастные цвета?


Ответ

По совету @Kromster'a воспользовался вот этим скриптом
for (int i = 0; i < 10; i++) colors[i] = HSV(0.1 * i, 0.5, 1.0);

Голосовое заполнение формы

Подскажите кто какие библиотеки знает для голосового заполнения HTML форм или у кого какие идеи и мысли есть насчет этого. Слышал что x-webkit-speech уже не работает ни в одном браузере. Интересуют оффлайн решения


Ответ

А вот если у Яндекса использовать SpeechKit? https://tech.yandex.ru/speechkit/jsapi/
Сразу дополню, вот такая реализация от самого Яндекса: https://tech.yandex.ru/speechkit/jsapi/doc/dg/concepts/speechRecognition-docpage/#textline

Непонятные символы при открытии файла с PHP-кодом

Что это такое, и как править этот код?
Это индексный файл index.php. Таким вот образом отображаются остальные файлы сайта.


Ответ

файл зашифрован zend'овский шифровщиком. Просто так править не получиться. Ищите оригинальные сорцы. Но поговаривают, что можно найти декомпилятор этого дела. Но я этим не увлекался.

Какой id вернёт lastInsertId() из PDO?

Использую PHP и MySQL. Насколько я понял, lastInsertId() возвращает id последнего добавленного элемента.
Но я не понимаю, это будет id последнего, добавленного мною элемента, или это id вообще последнего добавленного элемента (возможно другим пользователем)? И как указать этому методу нужную таблицу.
То есть, если я сделаю INSERT в таблицу, а потом вызову lastInsertId(), то гарантируется, что получу id именно этого INSERT? Или если другой пользователь успеет сделать свой INSERT в промежутке, то я могу получить его id вместо своего?


Ответ

Вернуть id последнего добавленного тобою элемента - единственное предназначение этой функции. Если бы она этого не делала, то попросту не имела бы смысла.
Для mysql эта функция возвращает результат функции LAST_INSERT_ID(), про которую сказано, что значение возвращается для текущего соединения. Поэтому бояться этой функции не надо.
Никакую "таблицу" при работе с mysql указывать не надо.

Пользовательская структура как точка входа в программу

Может ли быть пользовательская структура быть точкой входа (main entry) в программе?
Вопрос риторический, ибо насколько мне показывает IDE, такое возможно(т.е. достаточно создать Main метод,и все пройдет на ура).
Но отсюда вытекает иной вопрос - а чем это чревато и считается ли это дурным тонном!?


Ответ

точкой входа в программу в языке C# является метод Main. Этот метод обязан быть статическим. Статические элементы класса или структуры, являются самостоятельными программными единицами, не требуют наличия экземпляра для вызова и, фактически, используют имя класса или структуры в которой объявлены только для расширения собственного имени и обеспечения его уникальности. Статические члены не наследуются, не могут быть абстрактными или виртуальными, вы можете даже писать полностью в процедурном стиле, используя только статические классы и их элементы.
Структура - это по сути класс, но с ограниченными возможностями, в котором на уровне языка запрещено использовать некоторые принципы ООП (запрещено наследование от других классов или структур, но реализация интерфейсов разрешена, остальное - следствия). Ну и да, структуры относятся к ValueType, что накладывает еще некоторые ограничения, но, в то же время, дает возможности недоступные классам. Однако по части статических элементов - структуры ни чем от классов не отличаются, разве что сама структура не может быть статической.
Поэтому, с точки зрения CLR, нет никакой разницы, к чему будет привязан метод Main, и никаких последствий от такой замены не будет. Другой вопрос. как вы будете использовать этот класс или структуру в дальнейшем, но это уже действительно другой вопрос.

Десериализация поврежденных данных json.net

Использую библиотеку newtonsoft json.net. В файле у меня хранится коллекция json объектов. Допустим у нас есть поврежденная json строка в одном из объектов, например:
{ "PublicationDate": "1999-04-14T00:00:00", !error!, "Authors": ["Vasya","Dima"], "Location": "Moscow" }
Могу ли я как-нибудь пропустить данный объект и перейти к парсингу следующего?


Ответ

Данные в некорректном формате не должны обрабатываться. Данные в некорректном формате JSON — это данные не в формате JSON
Правильный способ
Почините то, что выдаёт вам некорректные данные.
Костыльный способ
Если вы не можете починить источник, то конвертируйте данные в корректный формат.
Если ошибка очень простая, например, некоторые элементы принимают вид !error!, как в вашем примере, то можно натравить на исходную строку регулярное выражение. Если ошибка сложная, то и решение сложное. Возьмите класс, разбирающий лексемы JSON из JSON.NET (JsonTextReader), модифицируйте под ожидаемую грамматику. Унаследоваться не получится, потому что весь важный код приватен. Придётся копипастить.
@VladD и другие пытаются найти обходные пути для "игнорирования" ошибки, но этот путь тупиковый, потому что для лексера нет выхода из состояния "ошибка". В этом состоянии он не знает, где он находится, и что следует дальше.

Движение объекта по svg path при скролле

Есть такой код:
$(window).on('load resize', function() { initContainer(); }); $(window).scroll(function(){ setMotionPath(); }); function initContainer() { var element = $('.svg'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way").reverse(); TweenLite.set("#circle", { transformOrigin: "50% 50%" }); setMotionPath(); }; function setMotionPath() { var element = $('.svg'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way").reverse(); TweenLite.to("#circle", 0, { x: motionPath["x"], y: motionPath["y"] }); }; #circle { transform-origin: 0px 0px 0px; } html, body { height: 200%; width: 100%; margin: 0; padding: 0; } svg { width: 100%; }
CodePen
Вопрос: Как можно застваить круг двигаться по пути path плавно при скролле (желательно с использованием TweenMax)?
P.S: Путь path может быть какой угодно, прямая выбрана для примера, а так он может быть и такой:


Ответ

Вот обновленный вариант ответа. Это именно то что вы хотели.
Попытаюсь примерно объяснить что и как работает.
motionPath - это массив в котором содержится координаты линии, но в нем не по пиксельно есть все координаты. А линия разделяется на куски, и по каждому куску выбирается координат(центр). Когда вы методом TweenLite.to задаете одну пару координат то анимация доходит до него и останавливается. Но если попытаться так при скролле каждый раз дать новые координаты то анимация не будет плавной потому что при скролле не закончив первую часть пути круг уже получает новые координаты и идет по ним (выходя из линии).
Есть второй вариант. Даем сразу массив координат в метод TweenLite.to и в переменной сохраним идентификатор анимации tween = TweenLite.to......... После этого мы уже можем манипулировать с анимацией (к примеру сделать паузу). И еще один важным момент, tween уже имеет метод progress(), и его значение может быть от 0 до единицы. И если мы зададим промежуточный прогресс, то анимация возвратиться к нему.
Вот так и делаем, задаем прогресс при каждом скролле, и с разу же делаем паузу анимации.
Вот и наш ожидаемый результат.
$(window).on('load resize', function() { initContainer(); }); $(window).scroll(function(){ setMotionPath(); }); function initContainer() { var element = $('.svg'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way",{align:"#circle"}).reverse(); TweenLite.set("#circle", {xPercent:-50, yPercent:-50}); setMotionPath(); }; function setMotionPath() { var element = $('.svg'); var way = $('#way'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way",{align:"#circle"}).reverse(); var progress_val = $(window).scrollTop()/5000; tween = TweenLite.to("#circle", 3, {bezier:{values:motionPath, type:"cubic"}}); tween.progress( progress_val ).pause(); }; #circle { transform-origin: 0px 0px 0px; } html, body { height: 400%; width: 100%; margin: 0; padding: 0; } svg { position: fixed; width: 100%; }
Для прямой линии.
Здесь не нужен reverse получаемых координат. Этот плагин имеет большое количество опций. Все это уже можете посмотреть сами.
$(window).on('load resize', function() { initContainer(); }); $(window).scroll(function(){ setMotionPath(); }); function initContainer() { var element = $('.svg'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way",{align:"#circle"}).reverse(); TweenLite.set("#circle", {xPercent:-50, yPercent:-50}); setMotionPath(); }; function setMotionPath() { var element = $('.svg'); var way = $('#way'); var motionPath = MorphSVGPlugin.pathDataToBezier("#way",{align:"#circle"}); var progress_val = $(window).scrollTop()/1000; tween = TweenLite.to("#circle", 3, {bezier:{values:motionPath, type:"cubic"}}); tween.progress( progress_val ).pause(); }; #circle { transform-origin: 0px 0px 0px; } html, body { height: 400%; width: 100%; margin: 0; padding: 0; } svg { position: fixed; width: 100%; }

Откуда берётся лишняя цифра?

Следующий код в VS2015 выводит x, но в ideone результат почему-то x1. Почему??
http://ideone.com/K5ZKxR
#include #include #include
using namespace std;
int main() { string s = "x";
s = regex_replace(s + "0123456789", regex("(\\b(?=9.*(1))|0(?=.*(1))|1(?=.*(2))|2(?=.*(3))|3(?=.*(4))|4(?=.*(5))|5(?=.*(6))|6(?=.*(7))|7(?=.*(8))|8(?=.*(9))|9(?=.*(0)))(?=9*-)|\\d{10}$"), "$2$3$4$5$6$7$8$9$10$11$12"); cout << s << '
';
return 0; }
В приведённом примере совпадение должно идти только по последней ветви |\\d{10}$, т. е. все группы должны быть пустыми. Т. о. должен удалиться добавленный хвост из 10 цифр. Но откуда-то берётся цифра 1. Из-за чего так происходит? И как исправить?

Уменьшил пример http://ideone.com/THHiay
#include #include #include
using namespace std;
int main() { string s = "x";
s = regex_replace(s + "0123456789", regex("0(?=.*(1))(?=9*-)|\\d{10}$"), "<$1>"); cout << s << '
';
return 0; }

x<1>
При этом другие нули в строке не портятся (меняются только перед девятками и дефисом) http://ideone.com/XcFF6M
#include #include #include
using namespace std;
int main() { string s = "100#100-100,101#101-101,109#109-109";
s = regex_replace(s + "0123456789", regex("0(?=.*(1))(?=9*-)|\\d{10}$"), "<$1>"); cout << s << '
';
return 0; }
100#10<1>-100,101#101-101,109#1<1>9-109<1>
Тем временем, VS на последний пример выдаёт
100#10<1>-100,101#101-101,109#1<1>9-109<>
Что логично - группы нет, но замена со стиранием хвоста есть.


Ответ

Судя по всему это не баг ideone, а баг gcc, появившийся где-то в районе версии 5.
4.9.3 дает:
x<>
5.1.0 дает:
x<1>

Методы с одинаковыми сигнатурами в C#

Предположим, есть такой класс.
public class SomeClass { public void DoSomething(int x) { Console.WriteLine("DoSomething(int x) called"); }
public void DoSomething(T x) { Console.WriteLine("DoSomething(T x) called"); } }
А также вот такой фрагмент кода
var someObj = new SomeClass();
У меня два вопроса.
1) У закрытого типа SomeClass получаются два метода с одинаковой сигнатурой. Тогда почему компилятор же не ругается на них?
2) Скажем, если вызвать
someObj.DoSomething(0);
Данный фрагмент кода пишет "DoSomething(int x) called". Почему был вызван именно вариант с целочисленным параметром, а не с обобщённым параметром?


Ответ

Выдержка из спецификации (пункт 7.5.3.2):
... In case the parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are equivalent (i.e. each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member. • If MP is a non-generic method and MQ is a generic method, then MP is better than MQ. ...
по русски это звучит примерно так:
Если последовательности параметров эквивалентны, применяются следующие правила выбора лучшего метода: Если метод Mp не обобщенный и метод Mq обобщенный, то Mp лучше чем Mq
Там еще много правил отсева, но для этого случая остальные правила несущественны.
Ок, откуда ноги растут выяснили, данное поведение прописано в спецификации. Как это выглядит в реализации? Давайте заглянем в скомпилированный код и сравним обобщенный и не обобщенный методы. Я использую ILSpy, но можно воспользоваться любым знакомым инструментом, например ILDasm.
// Methods .method public hidebysig instance void DoSomething ( int32 x ) cil managed { // Method begins at RVA 0x205a // Code size 11 (0xb) .maxstack 8
IL_0000: ldstr "DoSomething(int x) called" IL_0005: call void [mscorlib]System.Console::WriteLine(string) IL_000a: ret } // end of method SomeClass`1::DoSomething
.method public hidebysig instance void DoSomething ( !T x ) cil managed { // Method begins at RVA 0x2066 // Code size 11 (0xb) .maxstack 8
IL_0000: ldstr "DoSomething(T x) called" IL_0005: call void [mscorlib]System.Console::WriteLine(string) IL_000a: ret } // end of method SomeClass`1::DoSomething
как видите, код обобщенного метода класса остался обобщенным после компиляции (обратите внимание на ! перед именем типа во втором методе).
На вопрос почему выбор происходит так, а не наоборот ответили. Теперь немного о возможных причинах такой реализации и правил выбора. Возможных, потому что я не являюсь разработчиком данной спецификации, но из общей логики некоторые выводы сделать можно.
В обобщенных методах вы ограничены в применении языковых средств к переменным обобщенного типа. Например нельзя применять операторы сравнения, кроме проверок на равенство и не равенство, т.к. мы не можем гарантировать что они реализованы в типе, для которого будет вызван обобщенный метод. Соответственно при наличии подходящего не обобщенного метода, с большой вероятностью он может быть реализован более эффективно за счет использования специализированных средств конкретного типа. Перед вызовом обобщенного метода, компилятор должен заменить обобщенные типы на реальные. Эти действия не требуются при использовании не обобщенных методов, а значит даже в тривиальных случаях, когда эффективность методов одинакова, стоимость вызова обобщенного метода незначительно, но выше.
Получается что обобщенные методы немного теряют производительность, а что в замен? Ведь у нас есть общий корень - тип object, к которому также можно привести любой другой тип. Я вижу это так:
При использовании обобщенных методов не используется приведение типов как в случае использование object, а это выигрыш в скорости, особенно для ValueType типов, т.к. отсутствует боксинг. При использовании обобщенных типов можно быть уверенным, что если у двух переменных указан один и тот же обобщенный тип. то при выполнении их типы также будут одинаковы, в отличие от переменных типа object, внутри которых может лежать что угодно, и требуются дополнительные проверки для исключения ошибок во время выполнения. При использовании обобщенных типов, мы можем использовать уточнения или ограничения, кому как нравится, и явно указать: класс это или структура, наличие конструктора (пока только конструктор по умолчанию), базовый тип, а также список интерфейсов, которые должны быть реализованы в типах, которые разрешено использовать в конкретном обобщенном методе или классе. Этот вариант, как и предыдущий, для типа object можно реализовать только путем дополнительных проверок и увеличения объема необходимого кода.
Естественно я могу ошибаться насчет истинных причин конкретно такой реализации. Естественно списки преимуществ и недостатков далеко не полные. Но я считаю что этого достаточно для общего понимания почему обобщенные типы и все с ними связанное такие, какие есть и применения их по назначению и с пользой для дела.

PS: Все, кроме цитаты из спецификации и IL-кода, является моим личным мнением, если вы с ним не согласны, то мы можем обсудить это в чате или вы можете написать собственный ответ на данный вопрос и изложить свою точку зрения.
Отдельное спасибо @Vadim Ovchinnikov за критику предыдущего варианта.

Уровень изоляции транзакций и Hibernate

Первый вопрос. Какая связь существует между уровнем изоляции транзакций, параметрами JPA Lock.READ / Lock.WRITE и версиями @Version (Оптимистическая блокировка)? Я более менее понял по отдельности каждую из этих 3 разделов, но не понимаю, как они связаны между собой. Выбранный уровень изоляции транзакций дает некие «гарантии» при проведении операций с таблицами. Параметры Lock.READ/Lock.WRITE позволяют добиться блокировки полей таблицы при проведении операций. Если я правильно понял, для этого как раз и используются поле @Version. Но все таки не до конца улавливаю связь между эти тремя понятиями. Или они дополняют друг друга, или это разные способы решения одних и тех же проблем. В общем, буду очень благодарен за ответ или же ссылку, где можно прочесть информацию именно по вопросы связи между этими понятиями и их совместном использовании. Второй вопрос. Каким способом в Hibernate можно указать требуемый уровень изоляции транзакции для конкретной транзакции? И принято ли так делать? Спасибо.


Ответ

Попробую ответить по порядку:
Как соотносятся Lock и уровни изоляции
Уровень изоляции транзакций (transaction isolation level) - относится к чтению данных, но не к записи данных; Lock относится к доступу к данным (то есть затрагивает и чтение и запись и модификацию); Можно сказать так, что механизм Lock обеспечивает работоспособность различных уровней изоляции данных, в самом тупом примере: если у вас стоит уровень изоляции READ_COMMITTED, то вставка произведенная параллельной сессией будет локирована на запись пока сессия не выдаст commit(), но лок на чтение будет открыт сразу при запросе вашего select, а при REPEATABLE_READ оба лока (на чтение и запись) будут стоять до commit() - соответственно ваш select увидит результаты модификации только после коммита.
Каким способом в Hibernate можно указать требуемый уровень изоляции транзакции для конкретной транзакции?
Вообще это не сильно здорово. Уровень изоляции транзакций это принадлежность коннекта к БД, соответственно фактически изменение уровня изоляции равносильно переконнекту к БД, а насколько это дорогая операция вы сами можете оценить исходя из имеющейся у вас ситуации.
Тем не менее, если вы таки решили менять перед каждой транзакцией уровень изоляции транзакций, то самый простой способ это отправить в СУБД raw SQL query (любой ORM это поддерживает), типа:
ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE

Почему в JS 1.65 - 1 = 0.6499999999999999 [дубликат]

На данный вопрос уже ответили: Вычисления на числах с плавающей точкой не работают 2 ответа или 1.85 - 1 = 0.8500000000000001 А числа больше двух уже имеют только два знака после запятой 2.65 - 1 = 1,65 2.85 - 1 = 1,85


Ответ

Basic Answers Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004? Why do computers use such a stupid system? What can I do to avoid this problem? Why do other calculations like 0.1 + 0.4 work correctly?

Правило контравариантности в Scala

Скомпилируется ли следующий код?
class GenericCellMut[-T](var x:T)
Если да, то почему? Если нет, то почему, и как сделать так, чтобы скомпилировался?
Он, естествено, не компилируется. Остается два вопроса - почему и что изменить, чтобы скомпилировался.
Пробовал читать статьи про ко/контравариантности, но так для себя ничего и не вынес.


Ответ

Насколько мне известно, Scala проверяет, что все контравариантные типы встречаются только на позициях аргументов, а все ковариантные типы -- на позициях возвращаемых значений.
Ваше выражение не проходит проверку из-за того, что наличие поля x подразумевает то, что его можно получить из этого класса, т.е. использовать в ковариантной позиции. Из-за этого не поможет и сделать поле x константным.

Насколько я понимаю, вы хотите сделать изменяемую ячейку.
Мне не очень понятно, для чего может потребоваться изменяемая ячейка со свойством контравариантности. Единственное, что я могу предложить для того, чтобы этот пример компилировался -- это написать следующий код:
class GenericCellMut[+T](val x:T)
Это будет неизменяемая ячейка со свойством ковариантности (замечу, что у неё теперь не очень подходящее название). Сделать поле изменяемым нельзя, так как это будет требовать наличия метода установки значения x, что, в свою очередь, требует поставить тип T в контравариантную позицию.
Если вы хотите иметь изменяемую ячейку, то придётся сделать её инвариантной:
class GenericCellMut[T](val x:T)

Возможность коммита с заранее обнуленными (пустыми) переменными

Имеется проект с исходниками (на python), которые я регулярно выкладываю на Github. В нём присутствуют переменные (пока что одна, является токеном: TOKEN="..."), которые я не хочу выкладывать для всеобщего доступа. Однако у себя в процессе отладки и проверки эти переменные заполняю соответствующими значениями.
До этого я просто вручную перед коммитом удалял значение, потом, в процессе запуска и прочего, вставлял значение снова. Но теперь меня интересует, есть ли в Git возможность обнулять определенную переменную перед коммитом и пушем?
Пока что я вижу 2 выхода без использования возможностей Git:
либо иметь экспортируемый конфигурационный файл, который можно не использовать в общем репозитории; но пока что ради 1 переменной я считаю это избыточным решением; либо просто написать однострочник с sed`ом, что не так интересно, в отличие от познавания возможностей Git. Да и костыльно это, по-моему.


Ответ

В папке проекта создайте подпапку для скрытых конфигов. Добавьте её в .gitignore. Если приложению не требуется читать её от другого пользователя, ограничьте права.
mkdir .hidden chmod 0600 .hidden echo '.hidden' >> .gitignore
Почему папку, а не просто файл: потому что однажды вы можете его случайно переименовать, закоммитить и запушить. И ваш токен будет навсегда потерян, потому что гитхаб зеркалируется в реальном времени. Вариант с хуком я считаю опасным по той же причине — вы можете переименовать переменную в конфиге или как-то изменить формат, после чего хук тихо и молча не сработает.
В этой папке и храните конфиги с токенами в любом удобном вам формате. Конфиг даже для одной переменной — это нормально. Ваш ssh-ключ это, грубо говоря, тоже одна большая строка в файле.

Haskell аппликативный или нормальный?

Я изучаю язык Haskell и параллельно читаю SICP. В SICP нашёл следующее. Бен Битобор (согласно книге SICP) придумал тест для проверки интерпретатора на то, с каким порядком вычислений он работает, аппликативным или нормальным. Бен определяет такие две процедуры:
(define (p) (p)) (define (test x y) (if (= x 0) 0 y))
Затем он вычисляет выражение:
(test 0 (p))
Если результатом является 0, то интерпретатор - нормальный, если впадает в вычисление "p" - аппликативный. Согласно теста язык Scheme является аппликативным. Я переписал проверку под Haskell для интерпретатора GHCi:
let p = p let test x y = if (x == 0) then 0 else y test 0 p
Результатом получил 0. Правильно ли я применил тест Битобора, результатом которого является факт, что Haskell (GHCi) является нормальным языком программирования? Равносильно ли это понятию "ленивые вычисления"?


Ответ

Всё правильно
Да, Haskell в терминах этой книги нормальный
...и речь действительно идёт о ленивых вычислениях, а именно ленивом вычислении аргументов функции при её вызове. Термина нормальный стоит в этом контексте избегать ввиду его излишней общности и распространённости в самых разных областях, термин ленивый куда осмысленнее.
Первая процедура — очевидная "рекурсивная бомба", которая вешает выполнение программы при попытке вызова (если нет оптимизации хвостовой рекурсии, то ещё и уронит программу). Поэтому весь тест упирается в то, будет ли вычислен второй аргумент независимо от того, потребует ли его значения функция в процессе выполнения.
Внимание стоит обратить лишь на ту деталь, что нельзя просто так выкинуть вторую процедуру и заинлайнить её вызов в её реализации как-то так:
(if (= 0 0) 0 (p))
...потому что if в лиспах обычно является особой формой (special form), а не функцией, а потому имеет другой порядок вычислений, чем для вызовов функций.

Как работает self в Ruby?

Как работает self? Понял что метод self передает ссылку на сам себя, а вот в каких случаях использовать self а в каких нет я не понял...


Ответ

Ruby - полностью объектно-ориентированный язык. В любой момент времени вы действуете в рамках какого-то объекта, даже если все выглядит так, что вы работаете вне объекта. В языке нет функций и процедур в привычном понимании, только методы, причем метод не может вызываться без получателя, т.е. объекта.
self - это ссылка на текущий объект. Для обращений к элементам интанс-объекта не обязательно указывать self, так как он подразумевается по умолчанию, но иногда он нужен. Например, при создании методов класса
class MyClass def hello p 'hello' end end
o = MyClass.new o.hello # MyClass.hello - ошибка
Однако
class MyClass def self.hello p 'hello' end end
MyClass.hello o = MyClass.new # o.hello - ошибка
Это не единственный случай, когда вы не сможете обойтись без self, однако чтобы всех их осветить потребуется небольшая книга. При работе с self главное помнить, что это ссылка на текущий объект и что такой объект всегда существует, даже когда вы работаете в корневой области видимости
self => main

Как дефрагментировать даты в базе данных?

Здравствуйте. Имеется вот такая база данных: http://sqlfiddle.com/#!9/9554b . Первая таблица отвечает за отображение номеров в гостинице, которые существуют, вторая - за существующие брони в гостинице. Я попытался её визуализировать: За такой порядок расстановки/распределения номеров отвечает sql код. Он берёт новые даты заезда и выезда, сравнивает их с таблицей main и проверяет свободный номер на эти даты. Первый попавшийся свободный номер он присвоит новой броне. Всё логично. От сюда и следует такой "хаотичное" распределение номеров. Вот, собственно, сам select запрос на выдачу номера.
SET @start = '2016-12-12'; -- Новая дата заезда SET @end = '2016-12-20'; -- Новая дата выезда SELECT a.nomer FROM allnomer a LEFT JOIN main m ON a.nomer = m.numbernomer AND DATEDIFF(m.datestart, @end) * DATEDIFF(m.dateend, @start) <= 0 WHERE a.type = 'lux' AND m.numbernomer IS NULL LIMIT 1
Но есть у меня одна проблема. По сути, 12, 13, 14... 20 числа в гостинице жить никто не будет. Это свободные дни. Они образовались из-за распределения дат моим скриптом. Но если 11 числа придёт бронь на даты с 12 по 20, то скрипт её отвергнет (вернёт null), ибо даты заезда/выезда пересекаются. И это вполне ожидаемо, но хотелось бы решить эту проблему. Если перераспределить брони, то всё встанет на свои места, и номер с 12 по 20 число откроется. Я не трогал еще действующие брони, я перемещал только будущие. Хотелось бы узнать, на сколько реальна эта затея с перераспределением/дефрагментацией, и как её воплотить в жизнь (может быть уже было что-то подобное, либо есть такой sql запрос для моего случая) ?


Ответ

Спасибо за интересный вопрос.
Я попробовал реализовать алгоритм на MS SQL, и проигнорировал в большинстве мест фильтрацию по типу номера, надеюсь, у вас получится транслировать его в код для MySQL и добавить где надо условия на тип - должно быть несложно.
Основной смысл алгоритма - сбрасываем номера у всех броней, чье начало больше текущей даты, после чего заново присваиваем им номера по одному, распределяя их как можно плотнее к уже занятым датам.
declare @start date = '2016-12-12'; -- Новая дата заезда declare @end date = '2016-12-20'; -- Новая дата выезда declare @today date = '2016-12-11';
update main set numbernomer = null where datestart > @today;
declare @mainnumber int;
while exists (select * from main where numbernomer is null) begin
select top(1) @mainnumber = id from main where numbernomer is null order by datestart asc, datediff(day, datestart, dateend) desc;
update m0 set numbernomer = m1.nomer from main m0 cross apply (SELECT top 1 a.nomer FROM allnomer a LEFT JOIN main m ON a.nomer = m.numbernomer AND DATEDIFF(day, m.datestart, m0.dateend) * DATEDIFF(day, m.dateend, m0.datestart) <= 0 left join (select m2.numbernomer, max(m2.dateend) as dateend from main m2 group by m2.numbernomer) as m2 on a.nomer = m2.numbernomer WHERE a.type = 'lux' AND m.numbernomer IS NULL order by datediff(day, m2.dateend, m0.datestart), a.nomer ) as m1 where m0.id = @mainnumber;
end;
SELECT a.nomer FROM allnomer a LEFT JOIN main m ON a.nomer = m.numbernomer AND DATEDIFF(day, m.datestart, @end) * DATEDIFF(day, m.dateend, @start) <= 0 WHERE a.type = 'lux' AND m.numbernomer IS NULL;

Смысловая нагрузка значения “минус NaN”

В другом вопросе обнаружилось, что деление нуля на переменную, содержащую вещественный ноль, в результате даёт значение -nan
#include
int main() { double zero = 0; std::cout << 0/zero << "
"; }
Результат получается одинаковым для основных наиболее популярных компиляторов:
Clang GCC MSVC
Есть ли какой-то практический смысл в этом минусе, почему не просто nan?


Ответ

Получается это из-за того, что все вышеозначенные примеры были запущены на x86 архитектуре, а для FPU оной есть такое правило:
When neither of the source operands is a NaN, but the operation generates a floating-point invalid-operation exception (see Tables 8-10 and 11-1), the result is commonly a QNaN FP Indefinite (Section 4.8.3.7).
Взятое из Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture параграфа 4.8.3.5.
Заглянув в таблицу, указанную в цитате выше, мы обнаружим там следующую операцию, которая даёт на выходе QNaN:
Division: ∞ by ∞ ; 0 by 0.
Т.е. как раз то, что у нас и есть в вопросе (там есть и другие операции). А если мы посмотрим на таблицу 4-3, из секции 4.2.2, то увидим, что у QNaN знаковый бит выставлен в 1, что объясняет появление отрицательного NaN в выводе.

А если посмотреть на это всё с точки зрения языка, то получается неопределённое поведение, поэтому видеть мы можем всё, что угодно.
C++14, [expr]p4:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

Ответ навеян замечательный постом от Реймонда Чена.

C#, Как скопировать поля объекта в другой объект, создав для этого expression

Хочу написать функцию, которая будет копировать одинаковые свойства из одного объекта в другой, но при этом чтобы она работала быстро. Вот что есть:
static class Copy { private static readonly ConcurrentDictionary> PropertiesDictionaries = new ConcurrentDictionary>();
public static void Сopyfields(object source, object target) { var sourceType = source.GetType(); var targetType = target.GetType(); var sourceProperties = GetProperties(sourceType); var targetPropertyes = GetProperties(targetType);
foreach (var targetProperty in targetPropertyes) { if (sourceProperties.TryGetValue(targetProperty.Key, out var sourceProperty)) { targetProperty.Value.SetValue(target, sourceProperty.GetValue(source)); } } }
private static ConcurrentDictionary GetProperties(Type objType) { if (!PropertiesDictionaries.TryGetValue(objType, out var propertiesInfoDictionary)) { var infos = objType.GetProperties(); propertiesInfoDictionary = new ConcurrentDictionary(); foreach (var propertyInfo in infos) { propertiesInfoDictionary.GetOrAdd(propertyInfo.Name, propertyInfo); } PropertiesDictionaries.GetOrAdd(objType, propertiesInfoDictionary); } return propertiesInfoDictionary; } }
Как мне переписать эту функцию, чтобы создавать expression и использовать рефлексию только 1 раз для каждой комбинации типов?


Ответ

Вот вам простейший вариант:
class MapperFactory { public static Action CreateMapper() { var sourceType = typeof(P); var targetType = typeof(Q);
var sourceProperties = GetVisibleProperties(sourceType); var targetProperties = GetVisibleProperties(targetType);
var fromVar = Expression.Variable(sourceType, "from"); var toVar = Expression.Variable(targetType, "to");
Expression CreateCopyProperty(string name) { try { return Expression.Assign( Expression.Property(toVar, targetProperties[name]), Expression.Property(fromVar, sourceProperties[name])); } catch (Exception ex) { throw new ArgumentException($"Невозможно скопировать свойство {name}", ex); } }
var commonProperties = sourceProperties.Keys.Intersect(targetProperties.Keys) .OrderBy(n => n); var assignExpressions = commonProperties.Select(CreateCopyProperty); var assignment = Expression.Block(assignExpressions); var lambda = Expression.Lambda>(assignment, fromVar, toVar); return lambda.Compile(); }
static Dictionary GetVisibleProperties(Type type) { IEnumerable GetTypeChain(Type t) => t == null ? Enumerable.Empty() : GetTypeChain(t.BaseType).Prepend(t);
Dictionary result = new Dictionary(); foreach (var t in GetTypeChain(type)) { var properties = t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (var prop in properties) { if (!result.ContainsKey(prop.Name)) result.Add(prop.Name, prop); } } return result; } }
Он не проверяет доступность, не заглядывает в private/protected, не проверяет совместимость типов. Если свойства с одинаковыми именами не могут быть скопированы, произойдёт исключение при создании маппера. Если целевое свойство недоступно для записи, произойдёт исключение при создании маппера. Не имеющие пары свойства молча игнорируются. Если свойство базового класса перекрыто по имени свойством производного класса, базовое свойство игнорируется (а что ещё можно делать?). Статические свойства игнорируются (это кажется правильным). Свойства, являющиеся явными реализациями интерфейса, игнорируются (потому что я не придумал, что можно с ними делать).
Пользоваться так:
class From { public int A { get; set; } public string B { get; set; } }
class To { public int A { get; set; } public string C { get; set; } }
class Program { static void Main(string[] args) { Action map = MapperFactory.CreateMapper(); var from = new From() { A = 15, B = "hello world" }; var to = new To(); map(from, to); Console.WriteLine(to.A); // 15 } }

Варианты, которые правильно работают и не падают:
interface I { int X { get; set; } }
class FromBase { public string A { get; set; } public int B { get; set; } }
class From : FromBase, I { public new int A { get; set; } static public string C { get; set; } int I.X { get; set; } }
class To { public int A { get; set; } public string C { get; set; } }

Объяснение.
Давайте для начала разберём функцию GetVisibleProperties. Нам нужно получить список всех свойств. Обычно это делается при помощи простого type.GetProperties(), но что делать в случае, когда у нас есть несколько свойств с одним именем? Такое может быть, если свойство из базового класса перекрыть при помощи new, как в последнем примере. Как получить только самое последнее свойство?
Для этого давайте сделаем такой трюк: пройдём по цепочке базовых типов от нашего типа до object, и будет добавлять на каждом шаге только свойства, которые определяются в этом типе, и только те, имя которых ещё не встречалось у нас. Для этого нам нужно получить цепочку базовых типов. Это проще всего сделать рекурсивно: к цепочке для базового класса добавить в начало наш собственный тип. Получается просто:
IEnumerable GetTypeChain(Type t) => t == null ? Enumerable.Empty() : GetTypeChain(t.BaseType).Prepend(t);
Окей, дальше мы походим по этой цепочке, и для каждого типа получаем только открытые свойства (BindingFlags.Public), только нестатические (BindingFlags.Instance), и только определённые прямо в этом типе, а не унаследованные (BindingFlags.DeclaredOnly). Для каждого из них мы проверяем, есть ли уже свойство с таким именем, и добавляем новое свойство в результат только если свойства с таким же именем ещё не было.
С GetVisibleProperties всё. Теперь, главная функция: CreateMapper
Мы передаём типы как обобщённые параметры, чтобы можно было возвращать типизированный делегат Action. Для начала, мы получаем свойства с помощью уже разобранной функции GetVisibleProperties. Далее, мы берём пересечение множества имён: это те имена свойств, которые есть обоих типах (commonProperties). Я ещё сортирую их по алфивиту, чтобы порядок был одинаковым.
Мы идём через System.Linq.Expressions, которые позволяют конструировать выражения (типа Expression) в коде. Это стандартный приём для подобной кодогенерации, у нас много ответов на сайте, использующих эту технику.
Итак, вспомогательная функция CreateCopyProperty. Она создаёт аналог выражения to.Prop1 = from.Prop1;. Мы предварительно определяем Expression-переменные fromVar и toVar, соответствующие «реальным» переменным типов P и Q с именами from и to. Expression.Property(toVar, targetProperties[name]) — это полный аналог to.Prop1, где свойство Prop1 определено через PropertyInfo (это необходимо для случая, когда у нас могут быть перекрытые имена). Expression.Assign создаёт, понятно, код для присвоения. Создание выражения может бросить исключение если, например, свойства несовместимых типов, или у целевого свойства нету сеттера. Можно было бы и не ловить это исключение, но тогда непонятно было бы, какое именно свойство «виновато», поэтому я добавил блок try/catch, и в тексте нового исключения упоминаю имя проблемного свойства.
Окей, дальше. У нас есть набор имён свойств (commonProperties), при помощи Select из него создаётся набор Expression'ов. Этот набор нужно упаковать в одно при помощи Expression.Block, который создаёт аналог блока из фигурных скобок:
{ to.Prop1 = from.Prop1; to.Prop2 = from.Prop2; ... }
Теперь из этого блока делаем лямбду:
(from, to) => { to.Prop1 = from.Prop1; to.Prop2 = from.Prop2; ... }
при помощи Expression.Lambda
Финальный трюк состоит в вызове Compile, который Expression компилирует в реальную функцию, которую мы и возвращаем пользователю.

Как именовать методы/функции?

using DAO.Operations; namespace BBL.Operations {
public class OperationService { public Operation Get(int id) {} public IEnumerable GetAll() {} public void Add(Operation operation) {}
//или
public Operation GetOperation(int id) {} public IEnumerable GetOperations() {} public void AddOperation(Operation operation) {} } }
Как принято называть методы/функции? Какие рекомендации существуют на сей счет?
UPD: В приведенном мной примере я указал противоречивые конструкции: короткая форма Get() против более полной GetOperations() мне хочется понять в каких случаях правильней использовать тот или иной способ, какие плюсы/минусы меня могут возникнуть позднее.


Ответ

Я бы выбрал первый вариант. Потому что второй вариант предполагает некоторое дублирование и лишнюю писанину:
var operationService = new OperationService(); var all = operationService.GetOperations();
в сравнении с
var operationService = new OperationService(); var all = operationService.GetAll();
Если вы правильно называете переменные, то кратких вариантов достаточно.

В чем отличие @yield от @show?

В чем отличие @yield от @show разве они не выполняют одно и то же действие?


Ответ

Нет. У этих директив разное назначение.
@show, как и @endsection, используется для обозначения конца секции.
@show выводит содержимое секции на экран, сразу после объявления секции. @endsection не делает ничего, кроме обозначения конца объявления секции. @show и @endsection не могут существовать без предшествующей директивы @section.
@yield используется для вывода содержимого секции с определенным именем. Эта директива вполне может существовать без предшествующей директивы @section, если та, например, была объявлена в одном из дочерних шаблонов. Возможен вариант использования @yield, когда секция с указанным именем вообще не была объявлена, тогда надо передать в нее второй параметр, который будет служить значением по умолчанию.

Пример шаблона:
Мое приложение @yield('non-existent-section', 'работает') @section('displayed-content') Это содержимое секции, которое будет сразу выведено на экран. @show
@section('declared-content') Это содержимое секции, для вывода которого надо использовать @yield @endsection

@yield('declared-content')

Пример итогового файла:
Мое приложение работает Это содержимое секции, которое будет сразу выведено на экран.
Это содержимое секции, для вывода которого надо использовать @yield


Подробнее в документации

В чем отличие @endsection от @stop
Как говорится в этом сообщении на SO:
Существует авторитетный ответ от Taylor Otwell
Директива @endsection стала @stop в L4, а @yieldSection стала @show
Оригинальная цитата Taylor Otwell на github
В Laravel 5 можно использовать любой из вариантов: @endsection или @stop Отличий в функционале нет, это одно и то же.

Безопасность статического сайта

Имеется статический сайт на GitHub Pages, где допустимо хранить только html, css и javascript . Читал, что статические сайты менее уязвимы к взлому, но не на 100%.
Пароли хранятся в надёжном месте, браузер портативный.
Каким образом могут осуществляться хакерские атаки на статический сайт, и как от них защититься?


Ответ

Прежде чем говорить о возможности взлома, надо оценить возможный профит от этого:
Получение контроля над чужими вычислительными мощностями: малореально, Github защищается даже от вас в этом отношении: он не позволяет использовать пользовательские плагины для Jekyll (единственного поддерживаемого движка), которые могут содержать произвольный код на Ruby.
Держитесь крепче за свой GitHub-аккаунт:
Включите двухфакторную аутентификацию. Для аутентификации через Git используйте SSH-ключи, и назначайте им такие имена, чтобы можно было узнать, какому ключу при случае закрывать доступ. Получение конфиденциальных данных пользователей: а вы их собираете? Храните? Github Pages не даёт никаких возможностей по хранению на стороне сервера. Остаётся вариант хранения данных на клиенте (там чего только нет нынче: WebSQL, IndexedDB, LocalStorage) или перехват прямо при вводе.
При отсутствии доступа к клиенту хотя бы на уровне браузера (если у пользователя вредоносные расширения в браузере или дыры/лазейки в ОС, вы вряд ли что-то сделаете) остаётся только обманом заставить пользователя выполнить JS-код злоумышленника: это XSS
Самый банальный случай — вывод фрагмента URL без экранирования: если там "случайно" (по присланной кем-то ссылке) окажется