Ычан: [d | b / bro / hr / l / m / mi / mu / o / ph / r / s / sci / tran / tu / tv / vg / x | au / tr | a / aa / c / fi / jp / rm / tan / to / vn / vo]
[Назад] [Вся нить] [Первые 100 сообщений] [Последние 50 сообщений]
Ответ в нить [Последние 50 сообщений]
Имя
Animapcha image [@] [?]
Тема   ( ответ в 21353)
Сообщение flower
Файл 
Пароль  (для удаления файлов и сообщений)
Параметры   
  • Прежде чем постить, ознакомьтесь с правилами.
  • Поддерживаются файлы типов 7Z, BZ, BZ2, GIF, GZ, JPG, MO, MP3, MP4, OGG, OGV, PDF, PNG, PSD, RAR, SVG, SWF, TXT, WEBM, WEBP, XCF, ZIP размером до 5000 кБ.
  • Ныне 3709 unique user posts. Посмотреть каталог
  • Максимальное количество бампов нити: 500
civilized_argument_popukko.jpg - (63.68KB, 720×720)
21353
No. 21353    
Попробуем создать нить, в которой уважаемые разработчики могут поспорить на любые темы:

— Какая IDE удобнее?
— Какой язык лучше?
— Какой фреймворк православнее?
— Agile или не Agile?
— ООП нужно, или не нужно?
— Настоящий разработчик вы, или нет?

Здесь разработчики смогут невозбранно обсудить эти, и другие животрепещущие а иногда и извечные темы.
65 сообщений пропущено. Показаны 50 последних сообщений Развернуть все изображения
No. 25373    
>>25371
Да, традиционно нулл – часть возможных значений указателей.

> Даже деление на ноль на этапе сборки гарантировать нельзя

Ноль не похож на null.

1. Ноль только деление в арифметике ломает. Обычно в ООП-языках у null нельзя вызвать ни один метод, так что если допустить где-то null, то придётся каждый вызов метода оборачивать в проверку вызываемых объектов на null. Если писать чисто в функциональной парадигме, возможно это не такая большая проблема.
2. Null нельзя получить в результате какой-то базовой операции языка, если его явно не сделать, разве что язык поддерживает арифметику указателей. Исключение: чтение структур данных, подразумевающих значение null (например, JSON). Но тут очевидно, что если в языке так контролируется null, то либо такая десериализация создаст nullable-тип, либо null в этой структуре будет выражаться не нуллом языка, а каким-то другим значением. Null в языке похож на значение енума. Если он где-то есть, значит кто-то явно его создал или язык позволил не проинициализировать переменную, и значение дальше куда-то пробросилось без каких-либо модификаций, ведь...
3. операции никакие, кроме проверки на наличие, над нуллами всё равно невозможны.

> Исключением является, наверное, только язык SPARK, в котором каждой функции надо писать математическое доказательство.

Если мы следуем котлиновским правилам, компилятору никакие теоремы доказывать не нужно. Он просто расценивает как ошибку, что nullable-тип передаётся в не-nullable переменную или в не-nullable переменную прямо в коде явно кладётся null. Таким образом, если такие правила действуют во всём проекте, ни в какую не-nullable переменную никогда не сохранится null. Это затем и придумано, чтобы всё сделать простым.

>>25372
Разрешение/запрещение null в языке может вообще не влиять на использование памяти, если это механизм времени компиляции: тогда empty может компилироваться в null, это не важно после проверки.
No. 25374    
>>25373
>механизм времени компиляции
Каким это образом на этапе компиляции ты можешь узнать, где у тебя в рантайме будут нулы?
No. 25375    
>empty может компилироваться в null
И вообще нул - это не тип, а значение типа
No. 25377    
>>25374

> Каким это образом на этапе компиляции ты можешь узнать, где у тебя в рантайме будут нулы?
> И вообще нул - это не тип, а значение типа.

Да все нуллы явно в коде прописаны, что тут непонятного? Если язык позволяет неинициализировать переменные/поля, то компилятор видит все неинициализированные переменные/поля на этапе сборки. Даже компиляторы C++ часто имеют возможность подсвечивать это как ворнинги. В джаве оставлять неинициализированными локальные переменные вообще запрещено, а поля класса по-умолчанию считаются проинициализированными как null.

Дальше, если мы идём по пути джавы, то след нуллов теряется, т.к. система типов не обозначает, где нулл разрешен, а где нет. Ну, т.е. считается, что он разрешен везде. Т.е. потенциально он есть везде.

Если мы идём по пути котлина, то компилятор видит, когда мы передаём что-то из переменной в переменную. Джава и кресты уже контролируют, что мы не можем передать объект типа A в переменную типа B, который не расширяет тип A.

  • Компиляторы многих языков очевидно видят все объявления нуллов и неинициализированные переменные и поля. Если последние возможны в языке, то у них очевидно нуллабл-тип.
  • Компилятор котлина запрещает складывать нулл-литералы в не-нуллабл места.
  • Дальше компилятор котлина запрещает брать любое значение (не только null) из нуллабл мест и без проверки на нулл, складывать их не-нуллабл места.
Это гарантирует, что все не-нуллабл места никогда не содержат нулл, за исключением какого-то прямого вмешательство в память процесса извне или редактирование бинарника после сборки.
No. 25378    
>>25377
>мы не можем передать объект типа A в переменную типа B, который не расширяет тип A.

Вернее, B должен быть более общим типом.

Либо A и есть B, либо A расширяет/реализует B.
No. 25379    
>>25377
В этом твоем котлине та же проверка на нулл, только в профиль, я так понял. Работая с поинтерами это и так обычно делается.

>Да все нуллы явно в коде прописаны, что тут непонятного? Если язык позволяет неинициализировать переменные/поля, то компилятор видит все неинициализированные переменные/поля на этапе сборки.
Твои проги уже на этапе сборки всю работу делают, что их даже запускать потом на надо?
No. 25380    
>>25379
Ты меня троллишь, по-моему.
Объясню по аналогии.
Вот у тебя есть
enum Foobar { FOO, BAR }
и ты нигде в проекте не используешь
Foobar.BAR
, и, допустим, язык не допускает конвертацию между енумами и целыми числами, например. Нужно ли запускать программу, чтобы понять, что в ходе работы программы никак не может появиться
Foobar.BAR
ни в одной переменной?
No. 25381    
Вопрос видимо был про то, как котлин распознаёт проверки на нулл. Думаю, он синтаксически их парсит, и внутри такого ифа, переменная меняет тип с нуллабл на не-нуллабл.
No. 25382    
>>25380
Где тут поинтеры, где тут нул?
No. 25383    
>>25382
Foobar - это поинтер, неподдерживающий арифметику указателей.
Foobar.BAR - это null.
Если ты его не используешь, он не может появиться в ходе работы программы.

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

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

Затем в коде кто-нибудь пишет, "кладём зелёную фишку в коробку". Компилятор говорит: "ты нормальный вообще?".
No. 25384    
>>25383
Я по-прежнему с трудом понимаю твою философию. Если нулл - это тип (или его характеристика), то на уровне компиляции типы можно проверить без проблем. Это собственно почти везде и делается.

Я пытаюсь сказать про нулл как значение, которое может появится в ходе выполнения. Например ты объявляешь поинтер на тип. А дальше по коду ты аллоцируешь структуру данных этого типа по этому поинтеру. Но сама аллокация условна, могут случится ошибки i/o например и поинтер останется указывающим в никуда. Далее по коду может быть обращение по нему, и разумеется где-то перед этим разумно сделать проверку на нул. Проверять такое наверное все же не работа компилятора, потому что это условно, это рантайм. Возможно это работа линтера. Но границы функционала могут сливаться.

Я пишу это, держа в уме гошечку.
No. 25385    
>>25384

>ты объявляешь поинтер на тип. А дальше по коду ты аллоцируешь структуру данных этого

В моём понимании это эквивалентно такому коду.

Something p = null;

p = new Something();


Т.е. нулл появился не сам. Переменная уже была создана как содержащая нулл. И как следствие, её тип должен был иметь возможность содержать null.

>сама аллокация условна, могут случится ошибки i/o например и поинтер останется указывающим в никуда.

>Я пишу это, держа в уме гошечку.

Я, кстати, не уверен, как это в Go сделано.
Там ведь вроде нет исключений.

Если мы пишем что-то вроде

Something p = new Something();


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

Если же нам явно нужно создать что-то потенциально nullable, а затем превратить в не-nullable, то в котлине есть правила, как эти проверки на null должны в коде выглядеть. Вот документация:

https://kotlinlang.org/docs/null-safety.html#checking-for-null-in-conditions

Там оказывается это должна быть еще и константа (val), иначе компилятор не может гарантировать, что внутри ифа переменной не будет присвоен null.

С переменными там можно через Elvis-оператор. Например:

var a: Something? = null


// попытка аллоцировать, завёрнутая в try-catch

val b: Something = a ?: объектЗаглушка

No. 25386    
>>25385
>Там ведь вроде нет исключений
Там есть паники, вызывающие стектрейс. И их можно ловить и рековериться. Но обрабатывать ошибки паниками - это антипаттерн в го, в пакетах их по каким-то там правилам вообще делать нельзя.

Для ошибок там есть интерфейс(тип) error, и обычным делом для функции иметь в добавок к обычному возвращаемому значению так же и ошибку, которая в свою очередь будет nil, если все ок.

Возвращаясь к исходному вбросу, нуллы не так страшны, если проверяются везде, где они могут возникнуть. Другое дело, что это может вылиться в множество проверок и код будет выглядеть не оч, но это уже проблема языка и/или личных вкусов программера. В питоне например есть писать обрабатывая абсолютно все исключения, то код при этом теряет всю фирменную "лаконичность".
No. 25387    
Первым делом, как автор вброса, хочу извиниться за своё неучастие. Как-то интерес пропал, тем более, что в Аде всё это было уже в 2005-м году, так что ваши новости мне — бородатые старости.

Вторым делом, напомню одну вещь из Жабы: GC грохает лишь те объекты, на которые не указывает ни одна ссылка. Если ссылка с “not null”, то как отправить объект в мусорку? Или коллекции у вас без этого ограничения и возвращают null?
No. 25388    
>>25387
Ну это общее правило для сферического gc в вакууме. Поинтер может никуда не ссылаться, но на него ссылаться могут, и тогда в gc он не попадет.
No. 25390    
>>25388
Я спрашиваю, как отцепить объект от сети ссылок в языках, в которых есть GC и нет прямого доступа к памяти, если ссылка на него объявлена как “not null”. Обычно единственная оставшаяся ссылка на объект зануляется, и... всё, «мы его потеряли». Аллоцировать в статике константой объект-затычку NotAnObject, который будет имитировать null? Ну и в чём тогда смысл, что проверять на null, что проверять на затычку. Этот подход используется в Аде с 1995-го года в ситуациях, когда отсутствует необходимость вводить ссылочные типы для объектов, но здесь он хотя бы оправдан.

Ну и вам к сведению: поинтер — это адрес в памяти, отображается обычно натуральным числом, и с ним можно делать арифметику; ссылка — это объект внутри языка, обычно содержит адрес и флаги. Не путайте. Поинтер на может быть “constant” или “not null”, в нём просто негде эту информацию размещать.
No. 25391    
>>25390
>объект-затычку NotAnObject
В случае с Жабой посмотрите ради интереса, как сделан Collections.emptyList () — ради одной этой затычки создан дополнительный класс.
No. 25392    
>>25387
>Если ссылка с “not null”, то как отправить объект в мусорку?
Программа вместе со всеми своими даже синглтонами — не более, чем функция main. И другие потоки — это тоже функции с вложенными блоками кода.
Блоки кода рано или поздно заканчиваются, делая недействительными локальные переменные, которые, если являются объектами со своими полями, утягивают в бездну и их.
No. 25394    
b9ytw7dsdzx31.jpg - (69.40KB, 1078×1440)
25394
>>25390
>Я спрашиваю, как отцепить объект от сети ссылок в языках, в которых есть GC и нет прямого доступа к памяти, если ссылка на него объявлена как “not null”. Обычно единственная оставшаяся ссылка на объект зануляется, и... всё, «мы его потеряли». Аллоцировать в статике константой объект-затычку NotAnObject, который будет имитировать null?
Можно наверное и так, но этим никто не занимается, раз есть GC. Зачем в этом случае программисту думать, что и когда ему обнулить (очистить)? Если алгоритм не допускает утечек, то рано или поздно объекты выйдут за пределы стека выполнения и будут удалены, так и ссылки на другие объекты по мере этого удаления будут постепенно исчезать и они тоже попадут в sweep.
No. 25396    
>>25392
>>25394
Так, подождите-ка... То есть, вы делаете микросервисы просто потому, что в вашей парадигме нельзя освободить неиспользуемую память и в итоге при длительной работе она на сервере тупо заканчивается? О, храбрый новый мир!
No. 25398    
>>25396
Не понимаю, как ты сделал такой вывод. Я не освобождаю память потому что это делает за меня рантайм языка.
No. 25399    
>>25398
>Не понимаю, как ты сделал такой вывод.
Функция main заканчивается вместе с программой, память программы в данном случае освобождается операционной системой, лол. Это подход CGI-bin, там управление памятью не нужно ни в каком виде. Отсюда и вывод.

>Я не освобождаю память потому что это делает за меня рантайм языка.
Веруйте, кто ж вам запретит-то.
No. 25400    
>>25399
GC к функциям не привязывается. У меня такое ощущение, что все в этом треде друг друга не понимают.
>Веруйте, кто ж вам запретит-то.
Хотя зачем понимать, когда можно просто покидаться чванливством.
No. 25402    
raccoon-4004766_1920.jpg - (601.06KB, 1920×1276)
25402
>>25399
Есть стек вызовов функций или блоков кода, не суть (зависит от языка). Локальные переменные и константы, в том числе not-null, прекращают существовать, когда блоки кода (или функции, зависит от языка), в которых они объявлены, доходят до конца, т.е. когда исчезает этот scope.

Это ответ на вопрос, как GC может подобрать объект, который находится в not-null-переменной. После того, как она исчезнет.

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

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

А вообще, да, GC что-то там мутит с графом взаимосвязей объектов, наверно. В Википедии можно почитать в статье Сборка мусора, как достижимость работает в mark-and-sweep (я не специалист).

Если какие-то объекты были достижимы только как поля объекта, ссылка на который была только в локальной переменной, которая больше не существует, то можно по идее собрать все эти объекты.
No. 25404    
>>25402
>GC что-то там мутит с графом взаимосвязей объектов, наверно.
Ты прав. Используются алгоритмы, похожие на Dijkstra's on-the-fly algorithm
https://lamport.azurewebsites.net/pubs/garbage.pdf
No. 25405    
>>25402
Если доступ к объекту осуществляется по ссылке, то единственный способ убить объект в языках без прямого доступа к памяти — это присвоить ссылке другое значение. Это вроде бы элементарно. Для этого обычно используется null. Но вы null запретили. Единственный выход у вас — это создать в статике объект-константу специально скостыленного подкласса, который будет заменой null. Но теперь вам надо проверять, не является ли какой-либо объект этой заменой. От чего бежали, к тому и пришли.

У взрослых, т.е. в Аде и Яве not null (@NotNull) — это по сути хинт для компилятора, заставляющий его пихать в нужные места код проверки на null и выбрасывания исключения. Область же применения ограниченных ссылочных типов, вроде
type ObjectAccess is not null access all Object'Class;

крайне ограничена.

Также хочу заметить, что ни один проект не делается с нуля, т.е. в любом проекте достаточно кода, который вы не контролируете. Отсюда любой объект, передаваемый по ссылке, который создан не вами, надо проверять на null.

Лол. Как с вами сложно.
No. 25406    
>>25394
> Зачем в этом случае программисту думать, что и когда ему обнулить (очистить)?
Так вот отчего некоторые категории современного софта сжирают столько памяти даже на самый элементарный функционал? Ясно. Понятно. Действительно, зачем думать.
No. 25407    
>>25406
А в чем проблема, чванливая няша? Ты пишешь, держа в уме gc, а не беспокоишься в каком месте поставить free. Прогресс не стоит на месте и на дворе не 2005. А память утекает не по этой причине, ты это прекрасно понимаешь, я надеюсь
No. 25408    
raccoon-anger.jpg - (91.24KB, 492×482)
25408
>>25405
>единственный способ убить объект в языках без прямого доступа к памяти — это присвоить ссылке другое значение

Да не единственный этот способ.

Допустим, есть методы
void doSomething() {

    A a = new A();
    // Что-то делаем.
}

void doSomethingElse(B b) {
    // Что-то делаем c b.
}


Есть некий другой метод. Неважно, в том же классе или нет.
void sdf() {

    doSomething();  // создалась ссылка "a"
    // Ссылка "a" больше не существует.
    // Мы ей не присваивали null, но это и не важно,
    // ведь её больше нет.

    // Ссылка zxc копируется в ссылку "b".
    doSomethingElse(this.zxc);
    // Ссылка "b" исчезла.
}

No. 25409    
>>25407
> чванливая няша
Зато не вруша, смешивающая взаимоисключающие параграфы.
No. 25410    
>>25409
Ну, во-первых, "зато" вряд ли уместно. Во-вторых, никакого смешивания не подразумевалось.
No. 25413    
>>25406
CGI-bin-щикам проще микросервис перезапустить, чем разбираться с памятью. Это у них уже проф.деформация. Ну привык человек всю жизнь гвозди камнем забивать.

>>25407
Я пишу, держа в уме механизмы работы с памятью конкретного языка. GC, malloc, счетчик ссылок. Все эти механизмы имеют четко определённые алгоритмы работы. Ни один из этих механизмов не является аналогом pizdato_lib, т.е. не умеет додумывать за программиста, что делать.

>>25408
В вашем мире проектов уровня laba1 не используются коллекции, многопоточность, сторонние библиотеки; там не надо хранить объекты между запросами, потоками, сессиями; там не порождаются объекты на каждый чих, даже коллекции копий самих себя не создают? Какой чудесный и простой мир!

З.Ы.: Я понимаю, о чём вы говорите, но к реальным проектам это не имеет никакого отношения, увы , если только вы не пишете системы управления для аэро-космической отрасли в стандарте Ravenscar, где ссылки и динамические объекты в бане — тогда делаю реверанс: написать на SPARK-е программу, которая компилируется — это само по себе достижение, можно лечь в гроб и спокойно умереть.
No. 25414    
>>25413
Забудь про cgi, это говно мамонта, к микросервисам не относится.

Я полностью согласен про четкий алгоритм работы и что gc не делает pizdato. Gc делает gc, и если не вставлять ему палки в колеса, он прекрасно будет делать свое дело.
No. 25415    
dog-days-026.jpg - (334.51KB, 1280×720)
25415
>>25414
GC подбирает лишь те объекты, которые он не видит со стэка. Он не может угадать, что вам этот объект больше не нужен. Время жизни объектов, если выйти за рамки студенческих лабораторок и CGI-Bin, может исчисляться годами. Даже на поганом ведрофоне приложения расчитаны на длительную работу в фоне.
No. 25416    
>>25415
Тебе выше отвечали, что ничего угадывать не нужно.

И опять cgibin? Тебя он в детстве покусал?
No. 25418    
>>25416
У вас аргументация человека, который никогда не задумывался, как сохранить или передать данные между запросами или потоками; у которого любая программа всегда имеет чёткий вход и четкий выход; и который всегда точно знает, что и где он создал. Это программы вида «посчитать и вывести результат», т.е. утилиты командной строки, лабораторки или скрипты CGI-Bin, вроде вакабы и кусабы.
No. 25420    
>>25418
У тебя аргументации совсем нет. Да и мимо по всем пунктам
No. 25424    
>>25413
> В вашем мире не используются коллекции,

А что с ними не так? Чем коллекция принципиально отличается от любого другого объекта, во-первых? Это обычный объект, который хранит ссылки на другие объекты, иногда в массивах.

> даже коллекции копий самих себя не создают?

В джаве вроде нет такого. Кто-то снаружи коллекции всегда создаёт её копию.

> многопоточность,

У каждого потока свой стек вызовов. В чем проблема?

> сторонние библиотеки;

Библиотека библиотеке рознь. В них тоже работает тот же самый GC.

> там не надо хранить объекты между запросами, потоками, сессиями

Я выше вроде писал static-переменные, например. Хотя, конечно, в CRUDах чаще скидывают данные в БД между запросами. Конечно, могут кэшироваться некоторые вещи фреймворком еще. Как это устроено, хороший вопрос, конечно.

Проблема спринга и хибернейта в том, что они аккумулировали в себя уже критическое количество магии™. Сейчас вот открыл один проект на Spring Boot, и пытаюсь разобраться.

С точки зрения меня, основная точка общения с БД - это интерфейсы, расширяющие JpaRepository. Спринг их находит на этапе запуска и создаёт для них скорее всего SimpleJpaRepository, который использует EntityManager, который берётся из entityManagerFactory. И результирующий JpaRepository, и entityManagerFactory - это синглтоны, которые лежат в ApplicationContext, который берёт бины из поля beanFactory типа DefaultListableBeanFactory, который расширяет DefaultSingletonBeanRegistry, который там внутренне хранит сингтоны в ConcurrentHashMap. И всё это без static-полей.

Сам ApplicationContext создаётся как локальная переменная в главном методе фреймворка (см. приложенную картинку). В общем, судя по коду, он никогда не уничтожается. Даже когда метод run завершится, контекст вернётся как возвращаемое значение. Быстрее программа завершится, чем GC подберёт ApplicationContext, и неважно, куда он там дальше пробрасывается.

Дальше, как устроен кэш. В JPA есть два уровня кэша.

Кэш первого уровня - это такая штука, которая в рамках текущей транзакции позволяет, еще не сохраняя состояние объектов в базу, получая изменённый в этой сессии объект через другой запрос, получить не состояние из базы, а состояние, которое предстоит в базу сохранить. https://stackoverflow.com/a/22732345/1240328

Там черт ногу сломит, как это реализовано в хибернейте. Похоже, что entityManager - это потенциально долгоживущая/вечная штука (их может быть много в проекте). В хибернейте ее реализация - это SessionImpl, которая хранит потенциально вечный StatefulPersistenceContext, который по каким-то сложным правилам хранит в коллекциях (там их много) закэшированные сущности, чистит их по завершению транзакций и т.п. Причем никакой синхронизации потоков я там не нашел... Значит ли это, что сессия гарантировано привязана к потоку. Честно говоря, слегка подзавис на этом вопросе.

Что касается кэша второго уровня, то это кэш, отделённый от сессии. Т.е. он хранит detached-сущности, причем, в зависимости от реализации, он может хранить их даже за пределами java-кучи, т.е. где нет GC, а по запросу создавать объекты в куче, получая данные из этого некоего места. В джаве есть встроенные механизмы выделения оперативной памяти за пределами кучи: https://blogs.oracle.com/javamagazine/creating-a-java-off-heap-in-memory-database
No. 25425    
Есть попытки переписать Spring заново, уменьшить количество внутренней магии, сделать compile-time DI.
Модные-молодёжные Java-фреймворки:
Я сам пока не пробовал, не разбирался.
No. 25427    
Да, кстати, вот это вот off-heap хранение сделано по очевидной причине. GC, так скажем, не очень быстро работает, когда куча разрастается до двузначных гигабайтов.
No. 25428    
shocked-anime-face.jpg - (55.23KB, 1280×720)
25428
А о чем спор? Нужен ли нулл? Нужен ли сборщик мусора? Чем была хороша Ада? Почему настоящие программисты не используют Котлин?
No. 25429    
>>25428
> не используют
Используют!
No. 25430    
2011-05-27-407284.jpg - (152.09KB, 700×1000)
25430
>>25424
Вас куда-то не в ту степь понесло... Мой пойнт заключается в том, что за пределами пары Ada/SPARK и аэрокосмической отрасли весь этот аутизм с ограниченными ссылочными типами тупо не работает, поскольку на одну строку вашего кода приходится сотня строк чужого, который вы не контролируете. Коллекции — самый простой пример такого кода, ни один проект без них не обходится.

Ну и если говорить про Аду, фишки из которой традиционно тырили себе Плюсы и Ява, то в ней типы порождаются где угодно в коде, так что там не является проблемой создать новый тип, локальный для одной из ветвей условия в обработчике исключения локального блока в методе doSomething, и повертеть на причинном месте ограничения при помощи Unchecked_Conversion. Если вы этот аутизм с ограниченными типами хотите внедрить в свой ЯП, то вы должны внедрить также и всё остальное, включая встроенный в скоупы try-catch. Ну или вы отказываетесь от аутизма и делаете not null просто хинтом для компилятора, заменяемом на if (o == null) throw new NullPointerException ();

>В джаве вроде нет такого
ЕМНИП, какой-то из reverse-ов возвращает копию списка; какой-то из итераторов для деревьев создаёт список и перемещается по нему. Не говоря о том, что коллекции могут хранить и возвращать null.
>У каждого потока свой стек вызовов. В чем проблема?
Объекты общие, т.к. потоки банально должны обмениваться информацией. К тому же поток может работать в бесконечном цикле, обрабатывая запросы. Хуже того, он может порождать другие потоки.
>Библиотека библиотеке рознь.
Как правило, у вас есть одна библиотека, которая возвращает null. Этот кактус вам грызть весь проект.

PersistenceContext-ов существует три вида: управляемый контейнером транзакционный (для SlSB), управляемый контейнером транзакционный расширенный (для SfSB), управляемый приложением (для JavaSE окружения и рукоблудия). EntityManager не является thread-safe. EntityManager ассоциируется или с уже существующим PersistenceContext-ом, или с вновь созданным. EntityManager использует одно соединение с базой, потому не может быть @ApplicationScoped. Отвечая на ваш вопрос
>Значит ли это, что сессия гарантировано привязана к потоку.
В случае управляемого приложением это зависит от самого программиста. В случае управляемого контейнером привязка идёт ко времени жизни EJB (транзакция здесь всегда коммитится). Время жизни SfSB ограничено лишь временем жизни самого приложения: если он не убивается по @Remove, он живёт пока на него есть хоть одна ссылка; ассоциированный с ним PersistenceContext живёт столько же, кроме того, может наследоваться другими SfSB.

>>25428
Честно? Не знаю. Я говорю про ограниченные типы в ЯП, мне говорят про JPA и Spring.
No. 25432    
Wanted_Raccoon.jpg - (165.38KB, 1117×954)
25432
>>25430
>Как правило, у вас есть одна библиотека, которая возвращает null. Этот кактус вам грызть весь проект.

Ну так я не предлагаю объять необъятное. Есть наш какой-то модуль. Мы знаем, что для него получить null на вход - бессмыслица. Почему бы не гарантировать во время компиляции (может хинтами, хотя на мой взгляд лучше самим ЯП), что мы не сможем ему передать null на вход, и чтобы внутри модуля была такая типа чистая комната от отсутствующих значений.

Жаль что так же нельзя сделать, ограничивая в компайл-тайме диапазоны целых чисел, например. Тогда бы действительно какой-нибудь квантовый компилятор был бы нужен, чтобы всё все возможные выполнения просчитать. Сейчас прибегут хаскелисты и скажут, что у них это уже реализовано.
No. 25433    
>>25432
Вы действительно считаете, что это — весело? Попробуйте Аду тогда, и её подмножество SPARK с нескучными фичами.
No. 25434    
>>25433
На что тут ещё обратить внимание?

Типы Length и Coord производные от типа Count и наследуют его методы, однако промеж них нельзя делать арифметику напрямую, поскольку по умолчанию не определены арифметические операторы для аргументов разных типов — грубо говоря, надо ещё пару десятков функций прописать вида function "+" (Left: Coord; Right: Length) return Coord. Зато их можно конвертировать друг в друга т.к. они одного диапазона значений. К сожалению типы не всегда возможно безопасно сконвертировать друг в друга, так что приходится по ходу пьесы инстанциировать дженерик-функцию Unchecked_Conversion. Это первое.

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

Третье, арифметику никто не отменял, так что умножение Length на Length может выдать вместо Length исключение Constraint_Error. Эта проблема при строгой типизации практически нерешаема, но для серии арифметических операций добрый адский компилятор сначала сконвертит все типы в какой-нибудь Long_Integer, посчитает и уже потом решит, кидать ли исключение. Однако, эта магия не работает при переопределении операторов.
No. 25435    
>>25434
Не, ну с исключениями, это не серьёзно.
No. 25436    
>>25435
Тогда у вас любая функция вида function "*" (Left, Right: T) return T при любом ограниченном типе T нелегитимна. Максимум, что вы можете сделать для того, чтобы реабилитировать её, — это написать ей контракт посредством расширений SPARK-а. Можете подумать, кстати, на досуге, какими будут условия контракта, чтобы функция стала легитимной.
No. 25437    
>>25436
Ну я и говорю, что с числами это не сработает. Но если просто как бы включить нуллабельность в T, то никаких проблем нет.
Удалить сообщение []
Пароль  
[Mod]