DG>>зы DG>>напомню, что ООП не требует, чтобы все сообщения обязаны доходить до адресата без потерь. S>Я напомню свой вопрос про машину Тьюринга, оборудованную ненулевым количеством ошибок. Подумайте на досуге, зачем вам нужно такое ООП, в котором сообщения не обязаны доходить до адресата, и будет ли в нём хоть что-то, что не моделируется "обычным" ООП.
потому что ни любая реальная программа на длительном периоде (или распределенная программа даже на коротких периодах), ни реальная жизнь — этой идеальной машине тьюринга с бесконечной лентой и с бесконечным временем с идеальной устойчивости к ошибкам не соответствует.
на практике: время конечно, память конечна, есть потери внутри программы, есть потери в реальности, есть потери на стыке между программой и реальностью.
и если использовать идеальную модель в которой ничего этого нет, то не получится ни описывать, ни решать проблемы и задачи, которые в действительности происходят в программах и в реальной жизни.
а цель модели именно в этом, а не в чем-то другом.
S>и будет ли в нём хоть что-то, что не моделируется "обычным" ООП.
будет. как минимум, появляется знание — какие алгоритмы можно использовать, а какие нельзя.
например, с точки зрения модели с потерями — нельзя использовать алгоритмы с итерационными сообщениями без синхронизации состояния между объектами (прибавь единицу, вычти пять; поверни налево, пройди два метра, поверни направо).
а как раз такими алгоритмами злоупотребляет большинство программистов, которые почему-то считают, что они находятся в идеальном мире в идеальной модели в которой ничего не теряется.
S>Прикольный поток сознания. S>1. Вообще, время у нас появляется сразу же, как только появляются понятия "раньше" и "позже".
позже/раньше -это всего лишь еще одна координата, и при этом ничего дополнительного кроме еще одной координаты не вводится.
раньше значение от 0 до 255 могло находиться в ячейке с координатами от 0 до 1петабайта,
а после введения позже/раньше — значение от 0 до 255 может находится в двухмерной сетке: по одной координате — от 0 до 1петабайта, а по другой — от 0 до 1 петатакта)
S>2. Вы по-прежнему путаете отношение идентичности с отношением эквивалентности.
я их не путаю. а знаю, что любое отношение идентичности является таковым только в небольшой локальной модельке, как только модель берется чуть шире оно сразу из отношения идентичности переходит в отношение эквивалентности.
S>3. Время совершенно не обязано быть глобальным. "Синхронизация" времени в ООП-модели выполняется только в момент обмена сообщениями. Если два объекта получают сообщения независимо друг от друга, то нельзя определить, кто из них получает что раньше. У каждого из них своё локальное время.
согласен. ну хоть какая-то неопределенность и неоднородность допускается в модели — уже хорошо.
но вот такой, например, не однозначный вопрос: допустим локальное время с точки зрения каждого объекта непрерывное.
но при этом является ли оно таковым же с точки зрения стороннего наблюдателя: как внутри системы? так и снаружи?
и что про это говорит твой канонический вариант ООП?
зы
в реальности так себя ведет sleep (или гибернейт): программа внутри слипа считает, что у нее время непрерывное, у программы снаружи слипа тоже непрерывное, но при этом с точки зрения второй программы время первой программы разрывное.
S>4. Понятие однородности времени и пространства в ООП не имеют никакого смысла, как бы красиво ни звучали эти слова. Особенно однородность относительно друг друга.
мне непонятно это утверждение.
у меня один критерий — можно ли это применить к реальности или нет.
вот твой вариант может описать ситуацию с гибернейтом, в чем там проблема? и как ее решать? или не может? если не может — значит в топку.
и нужен другой вариант ООП, для которого такие вещи имеют смысл.
DG>>вы рассматриваете ООП лишь для случая: строго однородное строго атомарное строго непрерывное пространство, S>Где вы это увидели? Никакого условия непрерывности пространства в ООП нету, как бы ни вводилось понятие пространства.
есть же, конечно. как только ты начинаешь утверждать, что сообщения гарантированно доходят — это вводит требование, что пространство непрерывно.
что опять же не умеет описывать поведение такой реальной штуки, как работу тонкого клиента в браузере в мобильнике.
вот для него пространство разрывное, при чем в строго определенные промежутки времени.
S>Понятие однородности я уже прокомментировал выше. DG>>условное время (в виде лишь условной последовательности сообщений), есть строго полное знание ("мир" знает всё про всех), все состояния строго однозначные (нет неопределенных состояний) S>Как раз такое время, как я описал — это самое минималистичное определение времени, при котором ООП ещё работает.
что значит еще работает? если этого нет, то какая модель это описывает? вот, например, в аналогом компьютере — нет никакой последовательности сообщений. при этом его работу какая модель описывает? и в чем ее отличие от Канонической Модели ООП с большой буквы?
S> Поверх него можно вводить более сильные модели времени — например, с глобальным временем или понятием "длительности". S>Никакого требования "мира" знать всё про всех нету — это вы придумываете что-то своё.
как только ты ввел требование, что есть единая функция идентичности в любой момент времени, ты потребовал — что мы все объекты мира можем перечислить в любой момент времени, что и означает, что "мир" знает про все объекты.
DG>>и соответственно, всех этих ограничений нет в самой модели ООП, а вы их накладываете сами. S>Вы не понимаете, что такое "ограничение", и что такое "накладывать". Вся математика строится на том, что изучает минимальные модели.
так минимальная модель как раз и вводит ограничения — что, если не сказано обратное, то всё независимо, всё атомарно, всё однородно, непрерывно и т.д.
например, когда арифметика говорит, что 1 + 1 = 2, она накладывает ограничение, что эти единицы есть независимы друг от друга, являются однородными объектами и т.д. если же мы хотим в реальности сложить 1 программиста с 1 автобусом будут требоваться более сложные модели(теории), чем арифметика. например, теория множеств и категорий
S> Вот мы вам пытаемся рассказать, что такое минимальное ООП. А вы пытаетесь то выкинуть из него неотъемлемые свойства (думая, что что-то добавляете), то засовываете в него то, без чего ООП работает.
ООП есть универсальный базис для программирования, так же как теория множеств в математике. в конечном итоге, всё сводится к этому базису: есть что-то (то, что в ООП определяется как объект), это как-то можно пощупать(то, что в ООП называется состоянием), оно как-то взаимодействуют (то, что в ООП называется сообщениями).
а дальше на этом базисе рассматриваются более слабые или более сильные модели. с введением тех или иных наборов ограничений, и получений следствий.
при чем вики говорит про тоже самое: там нет, например, никакого требования идентичности.
Object-oriented analysis and design (OOAD) is a software engineering approach that models a system as a group of interacting objects. Each object represents some entity of interest in the system being modeled, and is characterised by its class, its state (data elements), and its behavior.
The object-oriented paradigm assists the programmer to address the complexity of a problem domain by considering the problem not as a set of functions that can be performed but primarily as a set of related, interacting Objects.
Object-oriented programming (OOP) is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs.
DG>>в данном коде, с точки зрения клиента ответ приходит раньше, чем сообщение отправлено. S>С чего это вы взяли? Ничего подобного. Вы слишком вольно общаетесь с терминологией. Pong() здесь — никакой не ответ. Если хотите, я вам этот пример разберу поподробнее.
давай разбирать. в итоге, конечно, всё сведется к тому, что на данном примере накручено две ООП-модели. для той, которая считает, что Ping — это полноценное сообщение, Pong не будет ответом, а для той — которая считает, что Ping это есть половинка запроса Ping/Pong — будет ответом.
но разобраться пожалуйста — это всегда интересно.
DG>>это я к тому, что даже все ООП-языки, которые существуют, работают в рамках намного более полной ООП-модели, чем та, на которую вы ссылаетесь. S>Конечно. Реальные языки работают со значительно более сложными моделями. Но они получаются из базовой модели ООП. S>Для того, чтобы разобрать кашу в голове, нужно разделить всё, что можно разделить. Например, изучить в совершенстве базовую модель. Потом из этих мелких запчастей можно начинать строить более полезные модели.
другими словами полная цепочка получается следующей: сложная модель (например, та, которая описывает поведение хренек для которых нет полной идентичности) получена из базовой модели (в данном случае, ООП), но при этом сложная модель базовой моделью не является? (это следует из того, что ранее утверждалось, что модель в которой нет идентичности, не является ООП)
если являться не подходит, то какое здесь отношение тогда есть — между полной моделью и базовой? содержит? использует?
и чем является тогда полная модель? если она не является ООП?
DG>>в данном коде, чтобы понять в чем проблема — требуется уже вводит такое понятие как неатомарность операции отправки сообщения. S>Вы хотели сказать "неатомарность операции получения ответа на сообщение". Если что, в вашем примере есть минимум четыре момента времени (это если никаких сообщений более не происходит).
это с точки зрения модели, когда каждое вызов функции есть отдельное сообщение.
так же, как я же уже выше говорил, здесь есть и вторая модель, когда только вместе ping/pong образуют одну пару запрос/ответ.
и вторая модель более лаконично описывает поведение данного кода, но требует более сложных понятий — в данном случае, требуется понятие не атомарности запроса (уже в процессе выполнения запроса мы можем получить ответ)
Здравствуйте, Sinclair, Вы писали:
V>>Обращение по токену относитльно экземпляра. Большая разница? что должен озанчать токен, чтобы всё это работало правильно У ЛЮБОГО экземпляра этого типа? И чем тебе токен не адрес, в случае даже ассоциативной адресации, как в объектах языка JS, например? S>Разница — принципиальна. Понятие адрес в программировании подразумевает определённую арифметику.
Даже в случае ассоциативной адресации? Заметь, числовой арифметики над адресами нет, а относительная ассоциативная адресация еще как есть. Просто другая арифметика. И как-то ты странной иноходью передвигаешься... Когда я говорил о конкретике, ты перешел к абстракциям. Я тебе показываю, что и в абстракциях ничего не меняется, ты пытаешься их ограничивать св-вами некоей конкретики. Давай определяться. Адрес, это в общем случае ключ, служащий для доступа к значению. В упорядоченном множестве адресом может быть номер элемента. В неупорядоченном — некий уникальный токен. Отсюда и есть вид ассоциативной адресации. Прием относительной адресации применим и к ассоциативной, коль правила формирования токена это позволяют, тебе домены интернета в пример. Если адрес — число, то и арифметика числовая, а если символ, то арифметика символьная. Так вот, ввиду того, реализации дотнета известны пока на архитектурах с числовой адресацией, ассоциативные адреса MSIL (namaspace1::namespace2::type::member) переводятся однозначно рантаймом в адреса целевой платформы. А раз соответствие однозначное, то мы можем безопасно рассуждать на любом уровне, как на уровне MSIL, так и на уровне числовых адресов низлежащей системы, рассуждения будут оставаться верными.
S>В частности, возможность оперировать смещениями, что вы и пытаетесь делаеть, когда выдаёте за ликбез свои заблуждения.
Оперирование смещениями это самая естественная операция в любом адресе: USA-Indiana-Sevastopol, Ukraina-Sevastopol. Просто Sevastopol недостаточно.
S>Вы всё же почитайте это описание. Те стеки, которые фигурируют в описании семантики дотнетной байт-машины, это совсем не тот стек, которым вы управляете на ассемблере. А то, как вам преподавали понятие "локальных переменных", пусть остаётся на совести вашего преподавателя.
Читал неоднократно, "совсем не тот стек" — это не определение. Совесть преподавателя чиста, спасибо ему за отсылку к Форту с двумя стеками.
S>Поэтому семантика, которой мы оперируем, не имеет права опираться на потенциально устраняемые вещи типа "смещение относительно фрейма стека".
Имеет. Для исполнения на целевой платформе, повторюсь, должно быть взаимно-однозначное соответствие адреса ячейки в стеке в терминах MSIL (индекс), и адреса реальной воплощенной переменной. Учитывая, что на текущих платформах, для которых существует сегодня дотнет, тоже есть стек, который даже используется весьма похоже, и в плане фреймов высокоуровневых языков тоже, я вообще проблемы не вижу в понимании этого соответствия. Это надо совсем уж что-то себе отвлеченное надумать.... но тогда предлагаю опять же целиком оперировать терминологией и признанными абстракциями, чтобы окончательно не запутаться.
Здравствуйте, DarkGray, Вы писали: DG>и если использовать идеальную модель в которой ничего этого нет, то не получится ни описывать, ни решать проблемы и задачи, которые в действительности происходят в программах и в реальной жизни.
Чушь. Почитайте же хоть что-нибудь из букварей. Никакая, подчёркиваю, никакая реальная машина не является более мощной, чем машина Тьюринга.
DG>позже/раньше -это всего лишь еще одна координата, и при этом ничего дополнительного кроме еще одной координаты не вводится.
Это не координата. Это то единственное понятие времени, которое минимально необходимо в ООП.
DG>раньше значение от 0 до 255 могло находиться в ячейке с координатами от 0 до 1петабайта, DG>а после введения позже/раньше — значение от 0 до 255 может находится в двухмерной сетке: по одной координате — от 0 до 1петабайта, а по другой — от 0 до 1 петатакта)
Такты, как таковые, вводят несколько другое понятие времени, чем необходимое в ООП.
DG>я их не путаю. а знаю, что любое отношение идентичности является таковым только в небольшой локальной модельке, как только модель берется чуть шире оно сразу из отношения идентичности переходит в отношение эквивалентности.
И тем не менее вы пишете бред типа "сравнение состояния объектов вводит ещё одно отношение идентичности".
DG>но вот такой, например, не однозначный вопрос: допустим локальное время с точки зрения каждого объекта непрерывное. DG>но при этом является ли оно таковым же с точки зрения стороннего наблюдателя: как внутри системы? так и снаружи?
Понятие непрерывности ко времени в дискретной системе неприменимо. Разве это не очевидно?
Если нет — погуглите определение термина "непрерывность времени".
DG>в реальности так себя ведет sleep (или гибернейт): программа внутри слипа считает, что у нее время непрерывное, у программы снаружи слипа тоже непрерывное, но при этом с точки зрения второй программы время первой программы разрывное.
В реальности слип себя так не ведёт. Кроме того, мы говорим не про реализацию конкретного слипа, а про математическую модель ООП.
DG>мне непонятно это утверждение. DG>у меня один критерий — можно ли это применить к реальности или нет.
Всё можно применить к реальности. Но если хочется лезть в область теории программирования (а это совершенно необязательно), то нужно привыкнуть к тому, что в модели главное — непротиворечивость. А похожесть терминов на бытовые слова играет второстепенную роль.
Вот, к примеру, не-физики очень обижаются, когда физики говорят им, что переноска тяжестей по горизонтальной поверхности работы не совершает.
DG>вот твой вариант может описать ситуацию с гибернейтом, в чем там проблема? и как ее решать? или не может? если не может — значит в топку.
Конечно же может. А в чём там проблема?
DG>есть же, конечно. как только ты начинаешь утверждать, что сообщения гарантированно доходят — это вводит требование, что пространство непрерывно.
Опять каша в голове. Пространство — это категория взаиморасположенности и протяжённости.
Ни о чём подобном модель ООП не берётся рассуждать.
Гарантия доставки не имеет никакого отношения к пространству. DG>что опять же не умеет описывать поведение такой реальной штуки, как работу тонкого клиента в браузере в мобильнике.
Очередной бред. Оставим гон про разрывность пространства, сосредоточимся на осмысленном разговоре о негарантии доставки.
Очевидно, что модель с гарантией доставки легко может эмулировать модель без гарантии — достаточно ввести посредника, который будет либо доставлять сообщения, либо дропать/отказывать, в зависимости от своего состояния.
Обратное смоделировать в общем случае невозможно.
DG>что значит еще работает?
Значит, что если убрать понятия "раньше" и "позже", то ООП перестанет работать.
DG>если этого нет, то какая модель это описывает? вот, например, в аналогом компьютере — нет никакой последовательности сообщений. при этом его работу какая модель описывает? и в чем ее отличие от Канонической Модели ООП с большой буквы?
Его работу описывает какая-то вычислительная математика. ООП будет из рук вон плохо моделировать аналоговый компьютер. А вы этого не знали?
DG>как только ты ввел требование, что есть единая функция идентичности в любой момент времени, ты потребовал — что мы все объекты мира можем перечислить в любой момент времени, что и означает, что "мир" знает про все объекты.
Нет. Мне достаточно знать, что для любого конечного подможества множества всех объектов функция идентичности ведёт себя нужным мне образом. Я же говорю — тренируйте формальную логику.
DG>например, когда арифметика говорит, что 1 + 1 = 2, она накладывает ограничение, что эти единицы есть независимы друг от друга, являются однородными объектами и т.д. если же мы хотим в реальности сложить 1 программиста с 1 автобусом будут требоваться более сложные модели(теории), чем арифметика. например, теория множеств и категорий
Почитайте же букварь!
Арифметика строится на теории множеств, а не наоборот! Арифметика сложнее теории множеств!
DG>ООП есть универсальный базис для программирования, так же как теория множеств в математике.
Нет. Никто этого не обещал. Универсальным базисом для программирования являются функции Чёрча или Машина Тьюринга.
А ООП — это всего лишь модель, удобная для описания каких-то специфических программ.
DG>в конечном итоге, всё сводится к этому базису: есть что-то (то, что в ООП определяется как объект), это как-то можно пощупать(то, что в ООП называется состоянием), оно как-то взаимодействуют (то, что в ООП называется сообщениями).
DG>а дальше на этом базисе рассматриваются более слабые или более сильные модели. с введением тех или иных наборов ограничений, и получений следствий.
DG>при чем вики говорит про тоже самое: там нет, например, никакого требования идентичности.
Просто вики, на которую вы ссылаетесь, не является формальной моделью ООП. Там написан текст для среднестатистического читателя.
DG>давай разбирать. в итоге, конечно, всё сведется к тому, что на данном примере накручено две ООП-модели. для той, которая считает, что Ping — это полноценное сообщение, Pong не будет ответом, а для той — которая считает, что Ping это есть половинка запроса Ping/Pong — будет ответом. DG>но разобраться пожалуйста — это всегда интересно.
Синхронная посылка сообщения в ООП — это два события: "отправить сообщение" и "получить ответ". Эти события не обязаны идти "подряд", т.е. между ними могут происходить и другие события.
В примере есть две посылки сообщения. Последовательность событий такова:
1. отправить Пинг
2. отправить Понг
3. получить ответ на Понг
4. получить ответ на Пинг
В нашем случае ответы имеют тип void, тем не менее, это ответы (мы дожидаемся их прихода)
Если хочется выбрать асинхронную модель, то набор событий станет несколько другим:
1. отправить Пинг
2. получить Пинг
3. отправить Понг
4. получить Понг
Из-за асинхронности наша модель времени стала несколько слабее. Тем не менее, 4е событие не может произойти раньше первого.
Какую бы модель мы ни выбрали, ответ не может прийти раньше запроса — это бы нарушило принцип причинности.
DG>другими словами полная цепочка получается следующей: сложная модель (например, та, которая описывает поведение хренек для которых нет полной идентичности) получена из базовой модели (в данном случае, ООП)
DG>это с точки зрения модели, когда каждое вызов функции есть отдельное сообщение. DG>так же, как я же уже выше говорил, здесь есть и вторая модель, когда только вместе ping/pong образуют одну пару запрос/ответ.
Я же говорю: в модели главное — непротиворечивость. Если в вашей модели ответ приходит раньше запроса, то вы где-то ошиблись. DG>и вторая модель более лаконично описывает поведение данного кода, но требует более сложных понятий — в данном случае, требуется понятие не атомарности запроса (уже в процессе выполнения запроса мы можем получить ответ)
Вторая модель плоха ещё и тем, что она непригодна для описания примеров, хоть чуть-чуть отличающихся от приведённого:
class Server
{
public int Ping(Action<int> pong)
{
return pong();
}
}
class Client
{
static public int Pong()
{
return 42;
}
static void Main()
{
var server = new Server();
var r = server.Ping(Pong);
}
}
Кто здесь запрос, а кто ответ?
class Server
{
public Server(Action<int> pong)
{
_pong = pong;
}
public int Ping()
{
return pong();
}
}
class Client
{
static public int Pong()
{
return 42;
}
static void Main()
{
var server = new Server(Pong);
var r = server.Ping();
}
}
А здесь?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vdimas, Вы писали: V>Даже в случае ассоциативной адресации? Заметь, числовой арифметики над адресами нет, а относительная ассоциативная адресация еще как есть.
Конечно. По традиции, то, что поддерживает только операцию dereference, называется ссылкой.
Просто другая арифметика. И как-то ты странной иноходью передвигаешься... Когда я говорил о конкретике, ты перешел к абстракциям. Я тебе показываю, что и в абстракциях ничего не меняется, ты пытаешься их ограничивать св-вами некоей конкретики. Давай определяться. Адрес, это в общем случае ключ, служащий для доступа к значению. В упорядоченном множестве адресом может быть номер элемента. В неупорядоченном — некий уникальный токен. Отсюда и есть вид ассоциативной адресации. Прием относительной адресации применим и к ассоциативной, коль правила формирования токена это позволяют, тебе домены интернета в пример. Если адрес — число, то и арифметика числовая, а если символ, то арифметика символьная. Так вот, ввиду того, реализации дотнета известны пока на архитектурах с числовой адресацией, ассоциативные адреса MSIL (namaspace1::namespace2::type::member) переводятся однозначно рантаймом в адреса целевой платформы. А раз соответствие однозначное, то мы можем безопасно рассуждать на любом уровне, как на уровне MSIL, так и на уровне числовых адресов низлежащей системы, рассуждения будут оставаться верными.
Нет. Вы делаете логический "перепрыг". Из однозначности соответствия никак не следует то, что арифметика тоже обладает однозначным соответствием.
Поясню на пальцах: пусть у вас будет два исходных "адреса", A1 и A2. Они отображаются в целевые адреса, A1' и A2', функцией M: A1' = F(A1).
Теперь вы почему-то предполагаете, что если у нас есть операция, определённая над одним пространством адресов, то будет и соответствующая ей операция в другом пространстве.
Проверим:
Offset' = A2' — A1'.
Из этого должно следовать, что
1. есть операция "-", определённая на адресах A2 и A1:
A2 — A1 = Offset.
2. Offset' = M(Offset)
А теперь попробуйте найти мне спецификацию этой "операции", которая применима к Metadata Token, в ECMA.
V>Оперирование смещениями это самая естественная операция в любом адресе: USA-Indiana-Sevastopol, Ukraina-Sevastopol. Просто Sevastopol недостаточно.
Только в том, который поддерживает арифметику. Учите букварь.
V>Имеет. Для исполнения на целевой платформе, повторюсь, должно быть взаимно-однозначное соответствие адреса ячейки в стеке в терминах MSIL (индекс), и адреса реальной воплощенной переменной.
Нет. Это вы придумываете. Исполнять дотнет можно и на платформе, где адреса не подразумевают понятия смещения. Просто потому, что "смещения", которые вам так нравятся, нигде в спецификации не используются.
V>Учитывая, что на текущих платформах, для которых существует сегодня дотнет, тоже есть стек, который даже используется весьма похоже, и в плане фреймов высокоуровневых языков тоже, я вообще проблемы не вижу в понимании этого соответствия. Это надо совсем уж что-то себе отвлеченное надумать.... но тогда предлагаю опять же целиком оперировать терминологией и признанными абстракциями, чтобы окончательно не запутаться.
Согласен. Если хочется поговорить о переменных в дотнете, будьте любезны оперировать терминологией ECMA-335. А рассуждения про адреса и фреймы стеков оставьте для тех платформ, где они являются терминологией и признанными абстракциями (например, для x86-ассемблера)
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S>Поясню на пальцах: пусть у вас будет два исходных "адреса", A1 и A2. Они отображаются в целевые адреса, A1' и A2', функцией M: A1' = F(A1). S>Теперь вы почему-то предполагаете, что если у нас есть операция, определённая над одним пространством адресов, то будет и соответствующая ей операция в другом пространстве. S>Проверим: S>Offset' = A2' — A1'. S>Из этого должно следовать, что S>1. есть операция "-", определённая на адресах A2 и A1: S>A2 — A1 = Offset. S>2. Offset' = M(Offset) S>А теперь попробуйте найти мне спецификацию этой "операции", которая применима к Metadata Token, в ECMA.
Ну дык проще простого. Если ты имел ввиду индексы переменных, то напиши код получения адресов стековых переменных в терминах MSIL и возьми разницу. Посмотри на полученный код. Вот тебе способ описать в одних терминах другие.
V>>Оперирование смещениями это самая естественная операция в любом адресе: USA-Indiana-Sevastopol, Ukraina-Sevastopol. Просто Sevastopol недостаточно. S>Только в том, который поддерживает арифметику. Учите букварь.
Ох уж эти мне "учителЯ" доморощенные, путающиеся в трех соснах.
V>>Имеет. Для исполнения на целевой платформе, повторюсь, должно быть взаимно-однозначное соответствие адреса ячейки в стеке в терминах MSIL (индекс), и адреса реальной воплощенной переменной. S>Нет. Это вы придумываете. Исполнять дотнет можно и на платформе, где адреса не подразумевают понятия смещения.
Нельзя, и если попробуешь хотя бы на пальцах нарисовать, оч быстро поймешь, почему. Даже если у нас ассоциативная иерархическая память (для поддержки ООП), тебе для доступа к мемберу объекта нужен будет сам объект, т.е. база, в терминологии адресации.
S>Просто потому, что "смещения", которые вам так нравятся, нигде в спецификации не используются.
Используется индекс элемента, какая фиг разница. Фрейм локальных переменных дотнета — это множество объектов, доступ к которым мы ведем по индексу. Имея только индекс элемента, но не имея базы — самого текущего фрейма, ты не сможешь получить переменную. В общем, ф-ия доступа к переменной — она от двух аргументов, фрейма и индекса:
el = F(frame, index);
А теперь можно смело goto букварь... а домашнее задание будет: что это за вид адресации?
Здравствуйте, samius, Вы писали:
V>>Я тебе уже показывал, что ссылка занимает вполне конкретную память, могу опять: S>А я могу показать что память, которую занимает ссылка, не размещает в себе значение, на которое она ссылается.
А указатель размещает?
V>>Но это ссылочный тип, поэтому в сравнении с обычной переменной мы имеем лишние уровни косвенности (тут +1), т.е. сначала идет обращение к переменной-ссылке, извлечение адреса целевого объекта из нее, а затем обращение к целевому объекту по этому адресу. S>Ну так лишний уровень косвенности и отличает ссылку от переменной, а не сближает их.
Правильно, прямо как указатель! Не забыл еще исходное утверждение?
V>>Аналогично использованию переменной ссылочного типа в дотнете. S>ссылочный тип в дотнете семантически ближе к указателю C++, чем к ссылке.
Смотря какой ссылочный. Если тот, который ref в аргументах, то это точная аналогия ссылки С++. В любом случае, для ссылочного типа главное, что он хранит не значение, а его адрес. Даже если это адрес времени компиляции, т.е. константа.
Здравствуйте, DarkGray, Вы писали:
DG>следующий вопрос задаю чисто с точки зрения разбора каких-то вырожденных ситуаций.
V>>Без сущности "переменная" ООП даже не взлетит. DG>что есть в данном случае "переменная"? это синоним одного из терминов "память", "внутреннее состояние" или "ссылка"? или что-то еще?
Это синоним слота памяти. По-определению переменная — это именованный адрес, т.е. известный во время компиляции, и доступный в виде некоего удобного программисту символа.
Не против, если я так же отвечу остальным высказываниям вокруг этого вопроса, чтобы не размазывать по ветке? Спасибо.
Я, конечно, догадываюсь, откуда ноги растут у утверждения, типа в "настоящем" ООП в переменной (т.е. по известному адресу времени компиляции) может храниться только ссылка на объект, но не боже упаси сам объект, а это, якобы, будет уже не объект, а некое "значение". Спасибо Java и дотнету, прям низкий поклон... Не согласен. Мы имеем полное право размещать объекты по известным адресам времени компиляции, так же как и по неизвестным, т.е. выделяя память для них динамически. Почему объект вдруг должен перестать быть объектом только из-за факта, что мы знаем его фактический адрес на момент компиляции — самостоятельно понять не могу, а вразумительного объяснения столь загадочной точки зрения пока не увидел.
Так же, как упоминал про способы адресации. Способ адресации — это просто способ "добраться" до цели, и этих способов может быть несколько. То, что целью является объект, не влияет каким-то загадочным способом на разновидности адресации, бо самим этим способам характеристика цели до фени: объект там, или просто набор байт...
Ну и вопросы, типа не путаю ли я тем самым (т.е. оперируя способами адресации) ООП и "просто" ЯП вводят меня, признаюсь, в глубокий ступор...
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Sinclair, Вы писали:
S>>Поясню на пальцах: пусть у вас будет два исходных "адреса", A1 и A2. Они отображаются в целевые адреса, A1' и A2', функцией M: A1' = F(A1). S>>Теперь вы почему-то предполагаете, что если у нас есть операция, определённая над одним пространством адресов, то будет и соответствующая ей операция в другом пространстве. S>>Проверим: S>>Offset' = A2' — A1'. S>>Из этого должно следовать, что S>>1. есть операция "-", определённая на адресах A2 и A1: S>>A2 — A1 = Offset. S>>2. Offset' = M(Offset) S>>А теперь попробуйте найти мне спецификацию этой "операции", которая применима к Metadata Token, в ECMA.
V>Ну дык проще простого. Если ты имел ввиду индексы переменных, то напиши код получения адресов стековых переменных в терминах MSIL и возьми разницу. Посмотри на полученный код. Вот тебе способ описать в одних терминах другие.
Нет в IL способов определить "адрес стековых переменных". Переменные в стеке il могут оказать вовсе не в стеке в сгенерированном коде.
S>>Просто потому, что "смещения", которые вам так нравятся, нигде в спецификации не используются.
V>Используется индекс элемента, какая фиг разница. Фрейм локальных переменных дотнета — это множество объектов, доступ к которым мы ведем по индексу. Имея только индекс элемента, но не имея базы — самого текущего фрейма, ты не сможешь получить переменную. В общем, ф-ия доступа к переменной — она от двух аргументов, фрейма и индекса: V>el = F(frame, index);
Хрень ты написал. Переменная в стеке в IL может превратиться в обращение к регистру процессора. Именно поэтому IL не оперирует понятием адреса, чтобы был больший простор для генерируемого кода. Введение адресов и смещений в язык напрочь убивает возможные оптимизации и типобезопасность.
Ты это еще не осознал? Выгоднее иметь язык, который не оперирует адресами.
V>>Ну дык проще простого. Если ты имел ввиду индексы переменных, то напиши код получения адресов стековых переменных в терминах MSIL и возьми разницу. Посмотри на полученный код. Вот тебе способ описать в одних терминах другие. G>Нет в IL способов определить "адрес стековых переменных". Переменные в стеке il могут оказать вовсе не в стеке в сгенерированном коде.
Вы тут сговорились, что ле?
using System;
namespace ConsoleApplication2 {
struct Probe { public int i; }
class Program {
unsafe static void Main(string[] args) {
var safeVar = new Probe();
Console.WriteLine(safeVar.i);
Probe* unsafeVar = &safeVar;
Console.WriteLine(unsafeVar->i);
}
}
}
Для обоих случаев используются одни и те же опкоды (я уже упоминал этот ключевой момент сообщением выше):
Понятие safe/unsafe работает ВНЕ байт-машины, а именно: обслуживается верификатором. И нужно исключительно для типобезопасности в угоду программиста и для корректной работы GC. О наличии GC, заметь, байт-машина даже не подозревает, это внешний, по отношению к ней, механизм.
ldloca.s index
Загружает в стек вычислений адрес локальной переменной с индексом index (короткая форма).
Определение семантики этой операции байт машины оперирует понятием "локальная переменная", считая его известным читателю, и оперирует термином "адрес", так же считая сей термин общеизвестным. А вы мне оба пытаетесь внушить, что нет ни локального фрейма памяти, ни адреса внутри фрейма. Смешно. Кстати, почему эти фреймы памяти образуют именно структуру "стек" во время работы программы, т.е. сущность с дисциплиной LIFO, но никак иначе — оставлю для самостоятельной медитации, это не сложно.
Ну и то, что адрес МОЖЕТ располагаться не на стеке — подобные половые трудности предлагаю держать при себе, они не интересуют программиста. Я писал долго для микроконтроллеров, где стек сильно ограничен, и там компилятор тоже использовал области глобальной памяти для размещения локальных переменных, т.е. эмулировал еще один стек, а именно стек данных, ввиду недостаточной глубины имеющегося, используемого только под стек возвратов. Но эти моменты программисту должны быть абсолютно до фени. Кстати, программист в любом случае должен считать, что стек возвратов и стек данных — это разные стеки, по крайней мере все компиляторы высокоуровневых ЯП обеспечивают такую семантику, даже если у целевого процессора всего один стек. Это прозрачно для программиста.
V>>Используется индекс элемента, какая фиг разница. Фрейм локальных переменных дотнета — это множество объектов, доступ к которым мы ведем по индексу. Имея только индекс элемента, но не имея базы — самого текущего фрейма, ты не сможешь получить переменную. В общем, ф-ия доступа к переменной — она от двух аргументов, фрейма и индекса: V>>el = F(frame, index);
G>Хрень ты написал. Переменная в стеке в IL может превратиться в обращение к регистру процессора. Именно поэтому IL не оперирует понятием адреса, чтобы был больший простор для генерируемого кода.
Ты бы что ле освежил свои познания IL, а то действительно хрень выходит. Можешь начать с приведенной ссылки, там слева все остальные опкоды. Мало-ли во что JIT превратит твою программу? С чего ты взял, что обязательно в регистр процессора? А если он вообще спекулятивно произведет расчеты и вернет сразу результат-константу в результате инлайнинга и распространения констант после этого инлайнинга? Занимаешься гаданиями, короче, не существенными для дела.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Ну дык проще простого. Если ты имел ввиду индексы переменных, то напиши код получения адресов стековых переменных в терминах MSIL и возьми разницу. Посмотри на полученный код. Вот тебе способ описать в одних терминах другие. G>>Нет в IL способов определить "адрес стековых переменных". Переменные в стеке il могут оказать вовсе не в стеке в сгенерированном коде.
V>Вы тут сговорились, что ле? V>
V>using System;
V>namespace ConsoleApplication2 {
V> struct Probe { public int i; }
V> class Program {
V> unsafe static void Main(string[] args) {
V> var safeVar = new Probe();
V> Console.WriteLine(safeVar.i);
V> Probe* unsafeVar = &safeVar;
V> Console.WriteLine(unsafeVar->i);
V> }
V> }
V>}
V>
V>Для обоих случаев используются одни и те же опкоды (я уже упоминал этот ключевой момент сообщением выше): V>
Так это не не адрес переменной, который фрейм+смещение, а адрес некоторого объекта, который очевидно есть, так как объект размещен в памяти. При этом ссылка != указатель.
V>Понятие safe/unsafe работает ВНЕ байт-машины, а именно: обслуживается верификатором. И нужно исключительно для типобезопасности в угоду программиста и для корректной работы GC. О наличии GC, заметь, байт-машина даже не подозревает, это внешний, по отношению к ней, механизм.
Не понял фразы. Байт-машины нету вообще, есть абстракция, эта абстракция описывается ecma-335, в нем есть GC и верификация. Для указателей есть определенные правила, позволяющие им работать к таком окружении коректно.
И вообще, указатель это адрес, но нельзя взять любой адрес и превратить его в указатель. Поэтому и адресной арифметики как таковой нету.
V>ldloca.s index
V>Загружает в стек вычислений адрес локальной переменной с индексом index (короткая форма).
V>Определение семантики этой операции байт машины оперирует понятием "локальная переменная", считая его известным читателю, и оперирует термином "адрес", так же считая сей термин общеизвестным.
Последнее неверно, оно просто не соотвествует тому что в Ecma написано.
V>А вы мне оба пытаетесь внушить, что нет ни локального фрейма памяти, ни адреса внутри фрейма. Смешно. Кстати, почему эти фреймы памяти образуют именно структуру "стек" во время работы программы, т.е. сущность с дисциплиной LIFO, но никак иначе — оставлю для самостоятельной медитации, это не сложно.
Во время работы программы все это есть, но этим не надо и вообще говоря нельзя оперировать в терминах .NET. Ты не можешь получить фрейм стека и вычислить адрес переменной. Стековые переменные "адресуются" по индексу и все.
V>Ну и то, что адрес МОЖЕТ располагаться не на стеке — подобные половые трудности предлагаю держать при себе, они не интересуют программиста. Я писал долго для микроконтроллеров, где стек сильно ограничен, и там компилятор тоже использовал области глобальной памяти для размещения локальных переменных, т.е. эмулировал еще один стек, а именно стек данных, ввиду недостаточной глубины имеющегося, используемого только под стек возвратов. Но эти моменты программисту должны быть абсолютно до фени. Кстати, программист в любом случае должен считать, что стек возвратов и стек данных — это разные стеки, по крайней мере все компиляторы высокоуровневых ЯП обеспечивают такую семантику, даже если у целевого процессора всего один стек. Это прозрачно для программиста.
V>>>Используется индекс элемента, какая фиг разница. Фрейм локальных переменных дотнета — это множество объектов, доступ к которым мы ведем по индексу. Имея только индекс элемента, но не имея базы — самого текущего фрейма, ты не сможешь получить переменную. В общем, ф-ия доступа к переменной — она от двух аргументов, фрейма и индекса: V>>>el = F(frame, index);
G>>Хрень ты написал. Переменная в стеке в IL может превратиться в обращение к регистру процессора. Именно поэтому IL не оперирует понятием адреса, чтобы был больший простор для генерируемого кода.
V>Ты бы что ле освежил свои познания IL, а то действительно хрень выходит. Можешь начать с приведенной ссылки, там слева все остальные опкоды. Мало-ли во что JIT превратит твою программу? С чего ты взял, что обязательно в регистр процессора? А если он вообще спекулятивно произведет расчеты и вернет сразу результат-константу в результате инлайнинга и распространения констант после этого инлайнинга? Занимаешься гаданиями, короче, не существенными для дела.
Из-за флеймов на форуме я перечитываю excma-334 и 335 не реже раза в месяц, и тебе советую.
Как переменная стека определяется в ассемблерном коде: чаще всего фрейм стека хранится в регистре ebp и переменные в стеке являются смещениями, вроде ebp+4. Чтобы взять адрес объект в куче надо выполнить mov eax,[ebp+4], а чтобы обратиться к самому объекту надо еще раз обратиться по адресу, полученному в eax.
В терминах il операция вроде mov eax,[ebp+4] записывается как ldloc, причем JIT может решить что нет смысла выполнять много раз такую операция и положить локальную переменную в регистр.
То что ты написал уже выполняется после вычисления адреса переменной, и для получения адреса по ссылке не нужен фрейм стека.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>Я тебе уже показывал, что ссылка занимает вполне конкретную память, могу опять: S>>А я могу показать что память, которую занимает ссылка, не размещает в себе значение, на которое она ссылается.
V>А указатель размещает?
Указатель размещает значение, т.к. значением указателя является не то значение, на которое он ссылается, а именно адрес того значения.
V>>>Но это ссылочный тип, поэтому в сравнении с обычной переменной мы имеем лишние уровни косвенности (тут +1), т.е. сначала идет обращение к переменной-ссылке, извлечение адреса целевого объекта из нее, а затем обращение к целевому объекту по этому адресу. S>>Ну так лишний уровень косвенности и отличает ссылку от переменной, а не сближает их.
V>Правильно, прямо как указатель! Не забыл еще исходное утверждение?
Прямо как указатель, но это не приближает ссылку к переменной-указателю.
S>>ссылочный тип в дотнете семантически ближе к указателю C++, чем к ссылке.
V>Смотря какой ссылочный. Если тот, который ref в аргументах, то это точная аналогия ссылки С++.
Ссылочный тип в дотнете ровно один — тот, чьи экземпляры размещаются в управляемой куче. ref-же является чисто модификатором способа передачи аргумента и не образует нового типа в терминах системы типов дотнета.
V>В любом случае, для ссылочного типа главное, что он хранит не значение, а его адрес. Даже если это адрес времени компиляции, т.е. константа.
В общем, ссылочный тип в C++ был бы тождественнен ref-параметрам дотнета, если бы ECMA не позволяла использовать copy-in/copy-out механизм для ref/out параметров
Здравствуйте, gandjustas, Вы писали:
G>Так это не не адрес переменной, который фрейм+смещение, а адрес некоторого объекта, который очевидно есть, так как объект размещен в памяти. При этом ссылка != указатель.
Во-первых, посмотри внимательно код. Речь шла об адресах переменных на стеке, поэтому код показывает взятие адреса именно стековой переменной. В этом случае адрес не может "просто быть", если сделать указанную ф-ию рекурсивной и каждый раз брать адрес локальной переменной, разве будет этот адрес одним и тем же? Или таки разным в каждом фрейме? Чувствуешь подвох, не? Код один и тот же, но для каждого фрейма будет свой адрес экземпляра одной и той же переменной. Я товарищу Sinclair предлагал чуть порассуждать, чтобы организовать работу такой машины без стека, или без явной его эмуляции (если в железке стека нет). Не выйдет.
G>Не понял фразы. Байт-машины нету вообще, есть абстракция, эта абстракция описывается ecma-335, в нем есть GC и верификация. Для указателей есть определенные правила, позволяющие им работать к таком окружении коректно.
Пока что мы работаем с двумя наличествующими в природе независимыми реализациями, где "абстракция" описывает как раз конкретную байт-машину, с точностью до расположения бит в инструкциях.
G>И вообще, указатель это адрес, но нельзя взять любой адрес и превратить его в указатель. Поэтому и адресной арифметики как таковой нету.
Во-первых можно взять любой адрес и превратить его таки в указатель.
Во-вторых, ты случайно не забыл еще, что есть адресная арифметика? Нельзя сравнивать или вычитать адреса из разных областей и разных типов. Например, если у нас есть некий массив элементов по значению, то адреса его элементов сравнивать и вычитать можно, т.к. эти адреса принадлежат одной области памяти и одному типу. Но, обрати внимание, разница указателей — это не кол-во байт м/у этими элементами, а кол-во элементов м/у указываемыми адресами на эти элементы. Вспомнил? Аналогично этому моменту я не понимаю, какие проблемы преобразования индекса в конкретный адрес, если есть информация о типах?
V>>ldloca.s index
V>>Загружает в стек вычислений адрес локальной переменной с индексом index (короткая форма).
V>>Определение семантики этой операции байт машины оперирует понятием "локальная переменная", считая его известным читателю, и оперирует термином "адрес", так же считая сей термин общеизвестным. G>Последнее неверно, оно просто не соотвествует тому что в Ecma написано.
Т.е. документация MSDN неверна?
G>Во время работы программы все это есть, но этим не надо и вообще говоря нельзя оперировать в терминах .NET. Ты не можешь получить фрейм стека и вычислить адрес переменной. Стековые переменные "адресуются" по индексу и все.
Ошибаешься. Я тебе пример привел, в чем проблема? Или сложности с прочтением?
V>>Ты бы что ле освежил свои познания IL, а то действительно хрень выходит. Можешь начать с приведенной ссылки, там слева все остальные опкоды. Мало-ли во что JIT превратит твою программу? С чего ты взял, что обязательно в регистр процессора? А если он вообще спекулятивно произведет расчеты и вернет сразу результат-константу в результате инлайнинга и распространения констант после этого инлайнинга? Занимаешься гаданиями, короче, не существенными для дела. G>Из-за флеймов на форуме я перечитываю excma-334 и 335 не реже раза в месяц, и тебе советую.
Читай себе. Но здесь пиши конкретно по делу.
G>Как переменная стека определяется в ассемблерном коде:
не важно
G>чаще всего фрейм стека хранится в регистре ebp и переменные в стеке являются смещениями, вроде ebp+4. Чтобы взять адрес объект в куче надо выполнить mov eax,[ebp+4], а чтобы обратиться к самому объекту надо еще раз обратиться по адресу, полученному в eax.
опять не важно
G>В терминах il операция вроде mov eax,[ebp+4] записывается как ldloc, причем JIT может решить что нет смысла выполнять много раз такую операция и положить локальную переменную в регистр.
Не важно с т.з. стандарта, важно другое, что ldloc означает загрузку локальной переменной, причем, эта операция должна работать непротиворечиво при произвольных вызовах метода, даже рекурсивных. А это не будет работать без формулы:
el = F(frame, index)
которая есть суть относительной адресации (или базовой)
G>То что ты написал уже выполняется после вычисления адреса переменной, и для получения адреса по ссылке не нужен фрейм стека.
Таки сложности с прочтением примера... так и думал.
DG>>и если использовать идеальную модель в которой ничего этого нет, то не получится ни описывать, ни решать проблемы и задачи, которые в действительности происходят в программах и в реальной жизни. S>Чушь. Почитайте же хоть что-нибудь из букварей. Никакая, подчёркиваю, никакая реальная машина не является более мощной, чем машина Тьюринга.
лучше ты прочитай что-нибудь еще кроме букварей. скоро уж внукам необходимо будет читать буквари, а ты всё о них талдычишь.
ты сейчас используешь лишь один показатель — алгоритмическая эквивалетность(мощность).
кроме него еще есть, например, вычислительная сложность(кол-во тактов необходимое для выполнения), информационная сложность (кол-во бит необходимое для описания программы), выразительная мощность и т.д.
алгоритмическая эквивалентность не обещает, что перевод программы при сохранении вычислительной сложности программы из одного тьюринг полного языка в другой тьюринг полный язык является не NP-полной задачей (а значит практически выполнимой).
соответственно, какая разница что они в теории эквиваленты, если на практике этим вспользоваться нельзя.
при этом, например, перевод из C++ в asm с сохранением вычислительной мощности — является P-задачей, а из asm в C++ — уже NP-задачей. соответственно, C++ получается мощнее чем asm с точки зрения выразительности.
тоже самое и с другими задачами: проверка корректности, слиянии двух алгоритмов и т.д.
в разных моделях эти задачи будут решаться с разной вычислительной сложностью.
например, проверка корректности работы с памятью для C#-а является чуть ли не линейной задачей, а проверка C++-программы будет экспонециальной от размера программы (а значит опять же практически не разрешимой).
тоже самое и с разными моделями ООП: алгоритмически они эквиваленты, но обладают разной выразительной мощностью
DG>>я их не путаю. а знаю, что любое отношение идентичности является таковым только в небольшой локальной модельке, как только модель берется чуть шире оно сразу из отношения идентичности переходит в отношение эквивалентности. S>И тем не менее вы пишете бред типа "сравнение состояния объектов вводит ещё одно отношение идентичности".
если что-то непонятно, то лучше спроси. это все-таки формум, а не диссертация по математике, и тут общаются на ЕЯ со всеми его плюсами и недостатками, а не на математической нотации которую ты больше любишь.
DG>>но вот такой, например, не однозначный вопрос: допустим локальное время с точки зрения каждого объекта непрерывное. DG>>но при этом является ли оно таковым же с точки зрения стороннего наблюдателя: как внутри системы? так и снаружи? S>Понятие непрерывности ко времени в дискретной системе неприменимо. Разве это не очевидно? S>Если нет — погуглите определение термина "непрерывность времени".
ты хороший образец оппонента, который руководствует логикой: если не получается ничего сказать по существу — придеритель к выбранным терминам, если не получилось придраться к терминам придеритель к грамотности.
DG>>у меня один критерий — можно ли это применить к реальности или нет. S>Всё можно применить к реальности. Но если хочется лезть в область теории программирования (а это совершенно необязательно), то нужно привыкнуть к тому, что в модели главное — непротиворечивость. А похожесть терминов на бытовые слова играет второстепенную роль.
любое утверждение необходимо обосновывать, а не просто ссылаться на авторитеты. если человек часто выдает какие-то утверждения без обоснований — это показывает, что он не понимает то, о чем он говорит.
> то нужно привыкнуть к тому, что в модели главное — непротиворечивость.
а обосновать это можешь? как ты любишь — формально в математической нотации?
опять же главное для чего? кроме обоснования как я уже несколько раз говорил в треде — очень важно понимать границы применимости какдого утверждения.
зы
вон диалектика, вообще, утверждает — что нет противоречий -> нет движения(развития), а значит нет и жизни.
а ты предлагаешь при моделирование отсутствие противоречий объявить самым главным критерием.
S>Вот, к примеру, не-физики очень обижаются, когда физики говорят им, что переноска тяжестей по горизонтальной поверхности работы не совершает.
и как всегда обе стороны правы. и противоречие наносное из-за использования разных моделей.
при этом переноска человеком тяжести в горизонтальном плоскости с точки зрения одной модели(бытовой) — не является переном тяжести в горизонтальной плоскости в другой модели(физической).
DG>>вот твой вариант может описать ситуацию с гибернейтом, в чем там проблема? и как ее решать? или не может? если не может — значит в топку. S>Конечно же может. А в чём там проблема?
и как задается функция идентичности с точки зрения распределенной системы для объектов которые сейчас спят?
DG>>есть же, конечно. как только ты начинаешь утверждать, что сообщения гарантированно доходят — это вводит требование, что пространство непрерывно. S>Опять каша в голове. Пространство — это категория взаиморасположенности и протяжённости.
если лента тьюринга не пространство (как и любая память в других машинах), то что это?
S>Ни о чём подобном модель ООП не берётся рассуждать. S>Гарантия доставки не имеет никакого отношения к пространству.
неправда. для гарантированности доставки (тем более за разумное время) пространство должно обладать определенными свойствами.
это как-то слабо похоже на "не имеет никакого отношения".
DG>>что опять же не умеет описывать поведение такой реальной штуки, как работу тонкого клиента в браузере в мобильнике. S>Очередной бред. Оставим гон про разрывность пространства, сосредоточимся на осмысленном разговоре о негарантии доставки. S>Очевидно, что модель с гарантией доставки легко может эмулировать модель без гарантии — достаточно ввести посредника, который будет либо доставлять сообщения, либо дропать/отказывать, в зависимости от своего состояния. S>Обратное смоделировать в общем случае невозможно.
передергиваешь, либо не понимаешь.
есть две модели — в одной все сообщения гарантированно доставляются, в другой — есть несколько различных классов доставки: гарантированная, негарантированная и т.д.
первая модель является частью второй, а значит всё смоделированное в первой модели в 1-1 переносится во вторую модель.
а обратное как раз неверно. для корректного же описания алгоритма описанного в терминах второй модели при описании в первой модели может уже потребоваться экспонециальный рост сложности (что на практике непременимо).
DG>>если этого нет, то какая модель это описывает? вот, например, в аналогом компьютере — нет никакой последовательности сообщений. при этом его работу какая модель описывает? и в чем ее отличие от Канонической Модели ООП с большой буквы? S>Его работу описывает какая-то вычислительная математика. ООП будет из рук вон плохо моделировать аналоговый компьютер. А вы этого не знали?
где обоснование?
DG>>например, когда арифметика говорит, что 1 + 1 = 2, она накладывает ограничение, что эти единицы есть независимы друг от друга, являются однородными объектами и т.д. если же мы хотим в реальности сложить 1 программиста с 1 автобусом будут требоваться более сложные модели(теории), чем арифметика. например, теория множеств и категорий S> Почитайте же букварь! S>Арифметика строится на теории множеств, а не наоборот! Арифметика сложнее теории множеств!
что значит сложнее? формализуй.
ты постоянно требуешь что тебе всё разжевали и формализовали, при этом ни одно свое нетривиальное утверждение ты формализовать не можешь... по крайней мере еще ни разу не сделал
DG>>при чем вики говорит про тоже самое: там нет, например, никакого требования идентичности. S>Просто вики, на которую вы ссылаетесь, не является формальной моделью ООП. Там написан текст для среднестатистического читателя.
давай ссылку на формальное определение. или может оно вообще существует только в твоей голове?
DG>>давай разбирать. в итоге, конечно, всё сведется к тому, что на данном примере накручено две ООП-модели. для той, которая считает, что Ping — это полноценное сообщение, Pong не будет ответом, а для той — которая считает, что Ping это есть половинка запроса Ping/Pong — будет ответом. DG>>но разобраться пожалуйста — это всегда интересно. S>Если хочется выбрать асинхронную модель, то набор событий станет несколько другим: S>1. отправить Пинг S>2. получить Пинг S>3. отправить Понг S>4. получить Понг S>Из-за асинхронности наша модель времени стала несколько слабее. Тем не менее, 4е событие не может произойти раньше первого.
ок.
возьмем "отправить Пинг" и исходную программу.
в какой точке программы Client может считать, что "отправить Пинг" с точки зрения гарантированности доставки выполнено?
DG>>это с точки зрения модели, когда каждое вызов функции есть отдельное сообщение. DG>>так же, как я же уже выше говорил, здесь есть и вторая модель, когда только вместе ping/pong образуют одну пару запрос/ответ. S>Я же говорю: в модели главное — непротиворечивость. Если в вашей модели ответ приходит раньше запроса, то вы где-то ошиблись. DG>>и вторая модель более лаконично описывает поведение данного кода, но требует более сложных понятий — в данном случае, требуется понятие не атомарности запроса (уже в процессе выполнения запроса мы можем получить ответ) S>Вторая модель плоха ещё и тем, что она непригодна для описания примеров, хоть чуть-чуть отличающихся от приведённого: S>
S>class Server
S>{
S> public int Ping(Action<int> pong)
S> {
S> return pong();
S> }
S>}
S>class Client
S>{
S> static public int Pong()
S> {
S> return 42;
S> }
S> static void Main()
S> {
S> var server = new Server();
S> var r = server.Ping(Pong);
S> }
S>}
S>
S>Кто здесь запрос, а кто ответ?
асинхронная пара Ping/Pong с последующей синхронной парой Pong/Pong.return
S>
S>class Server
S>{
S> public Server(Action<int> pong)
S> {
S> _pong = pong;
S> }
S> public int Ping()
S> {
S> return pong();
S> }
S>}
S>class Client
S>{
S> static public int Pong()
S> {
S> return 42;
S> }
S> static void Main()
S> {
S> var server = new Server(Pong);
S> var r = server.Ping();
S> }
S>}
S>
S>А здесь?
тоже самое: асинхронная пара Ping/Pong и синхронная пара Pong/Pong.return
изменилась лишь структура связей (в первом случае, сервер был независим от client-а, сейчас он стал зависимым.
S>А рассуждения про адреса и фреймы стеков оставьте для тех платформ, где они являются терминологией и признанными абстракциями (например, для x86-ассемблера)
ты постоянно делаешь одну и тужу ошибку — ты постоянно забываешь, что ты общаешься на ЕЯ.
а ЕЯ сам по себе очень противоречив ради повышения эффективности общения, это в частности проявляется, что одни и те же слова используются для обозначения совершенно разных вещей.
когда vdimas говорит про stack — он имеет ввиду, что при описании семантики локальных переменных (в том числе, когда есть рекурсия) необходимо в любом случае вводить структуру данных LIFO (которая и есть stack-структура данных).
ты же отвечаешь про stack, как про конкретную штуку из реализации конкретных ЯП, которые в данном случае вообще никакого отношения к дискуссии не имеют.
зы
перед каждым ответом советую сначала определиться, какие слова каким терминам соответствуют, и только отвечать; а не брать первое подходящий термин и отвечать именно на него.
Здравствуйте, DarkGray, Вы писали:
DG>ты же отвечаешь про stack, как про конкретную штуку из реализации конкретных ЯП, которые в данном случае вообще никакого отношения к дискуссии не имеют.
Сказать честно, я и тут не вижу разницы. Особенно потому что юзал одни и те же ЯП на процах которые имеют стек и на тех, которые не имеют, т.е. комплятор эмулирует стек. "Конкретная штука" любого высокоуровневого ЯП так же оперирует лишь абстракцией, не давая прямого доступа к подробностям фреймов стека. И правильно, процессор все-равно, даже если имеет специальный индексный/базовый регистр для нужд стека, предоставляет максимум нетипизированные области байт, как и в других своих возможностях, т.е. только язык+компилятор дают нам работать с типизированными переменными в локальных областях, на себя тонкости реализации своих абстракций. Чем локальные переменные дотнета "абстрактнее" локальных переменных Паскаля, наприме, в упор не понимаю. В Паскале даже чуть покруче из-за фичи объединения фреймов.
Ну и создание фреймов стека исторически было на совести компиляторов, это была сугубо прикладная штуковина, выполняемая низкоуровневыми инструкциями. Например, после устаканивания правил для выскокоуровневых языков для x86-й платформы, потом дополнили ее инструкцией enter. Могли бы и не дополнять, просто 4 байта кода теперь экономят на каждой высокоуровневой процедуре/ф-ии.
Здравствуйте, samius, Вы писали:
V>>Не продлевает ни разу, ссылки на временный объект нельзя хранить. S>объявление ссылки на временный объект продлевает жизнь временного объекта до выхода из скопа, в котором определена ссылка. Это не я придумал. Если какой-то компилятор это не выполняет, моя хата с краю.
Есть разные виды временных объектов. Если речь про r-value, то на него нельзя получить обычную ссылку, только константную, и я об этом уже говорил. Если же мы получаем ссылку на l-value, то мы заведомо имеем дело не со значением, а со ссылкой, поэтому ничего не продлеваем, а просто запоминаем/делаем копию ссылки.
S>Я о временных объектах, которые создает компилятор на стеке при вычислении выражений, включая приведения типов, вызов функций и т.п. При отсутствии ссылки на такой объект, компилятор волен удалить его сразу после того, как тот перестал быть нужен. А ссылка продляет время жизни такого объекта до выхода из скопа.
Опять же, речь о константной ссылке, и она должна быть стековой переменной. Т.е. это не работает, если мы инициализируем ссылкой некий мембер-ссылку.
V>>Если адрес взять нельзя, то стадию разыменования адреса мы пропускаем в любом случае. Иначе просто ничего не сойдется. S>А мы ее итак пропускаем, ведь ссылка — псевдоним объекта, а не указателя на него.
Это всего-лишь означает, что этот адрес компилятор разыменовывает за тебя.
V>>Гы: V>>
V>>int * pi = NULL;
V>>int & ri = *pi;
V>>
V>>Дарю! S>Да не стоит оно того. Здесь ссылка, кстати, проинициализирована не NULL-ом, а тем int-ом, который получается при разыменовании NULL-а.
Нет, именно NULL-ом. *pi не создает копии значения, а приводим напрямую к ссылочному типу. Кстати, этот момент когда-то напрягал в С, бо семантика ссылок в таких точно местах в С используется, а самих ссылок в языке нет. Обрати внимание, выражению *p ты можешь присвоить значение (если в "p" валидный адрес), т.е. тип этого выражения фактически int&, оно же l-value. То, что этот адрес невалидный в этом снипетте никак не влияет на типы.
V>>В общем, в сухом остатке имеем отсутствие operator-> и невозможность взять адрес для обеспечения этого. S>Ну и область памяти, которая не имеет отношение к значению, если вообще существует.
Дык, точно так же как и в случае любых других констант: не факт что занимает память когда в статике или локально, но обязательно занимает, когда является экземплярным мембером. Такие вот в С++ константы.
V>>>>Так же как могу привести пример, где ссылка на нестатические члены никогда не будет занимать лишней памяти: V>>>>ref_i будет вычислена в compile-time, как и любое вычислимое в compile-time выражение, напр:
V>>Упс, хотел написать int & ref_i = i; S>Занимает или не занимает память ссылка — неважно. Важно то, что значение лежит не в той памяти, которую занимает или не занимает ссылка. Значение лежит в памяти переменной (если у той она есть).
Значение может и на куче лежать, какие проблемы? Только это уже будет не константа времени компиляции, а константа времени выполнения. В любом случае, то, что ты написал, верно и для констант-указателей.
S>>>Усмотрение компилятора в отношении ООП меня совершенно не волнуют. Я вообще могу (теоретически) допустить, что компилятор может произвести graph rewriting с редукцией и не оставить ничего, что бы напоминало об исходном коде. Ни узнаваемых структур данных, ни переменных... Это не заставит меня считать что в исходном коде на C++ не стало структур данных и переменных.
V>>Я конкретно про гарантированные compile-time вычисления говорил, не уводи в сторону. Фишка в том, что гарантрованные compile-time вычисления происходят даже в отсутствии оптимизаций. И вычисление констант из той же области видимости — аналогично. Поэтому и привел пример с ref_i (с опиской), что там константа вычислима в compile-time. S>А я говорил о том что результат компиляции может быть несопоставим с терминами языка, потому решать, что есть переменная (в языке) а что нет, на основании бинарного кода не годится.
Для С/С++ это слишком вольное допущение. Он получил популярность именно из-за возможности обеспечить фактически побитовую детерминированность результата. Т.е. абсолютно любой комплятор С++ имеет и специфицированное ABI, и возможность управлять кодогенерацией. А абстрактный стандарт описывает самые общие вещи, независимые от платформ. На этом уровне можно обсуждать что угодно, вплоть до компиляции С++ программы в программу на Лиспе... А что, запросто.
S>Ссылка на переменную оозначает ссылку на значение, хранящееся в переменной.
Ну а ссылка на выражение что означает? А если результат выражения не временный, а вполне постоянный?
V>>Ну? Точно так же как объявление T * const ptr прямо по стандарту не обязательно приводит к выделению памяти под переменную, если выражение вычислимо в compile-time. Потому что константа. А если не вычислимо в рантайм, то в обоих случаях память под переменную еще как выделяется. Потому что переменная константного типа. Это такой хитрый ньюанс С++, который следовало бы иметь ввиду, из-за которого оч разное поведение у статических констант и экземплярных, например. Я именно это тебе и толкую, что для аналогичных случаев оба варианта ведут себя полностью аналогично. S>А я толкую что мы не определяем будет ли то что написано в исходниках функцией по тому заинлайнит компилятор тело или нет. Так же мы не будем определять что является переменной по результату компиляции.
Не, ты не понял. Разное поведение у статический и экземплярных констант потому, что в первом случае под них выделение памяти на усмотрение компилятора (и здесь применимо всё то, что ты сказал), а во втором случае под константу обязательно выделяется память в теле типа-владельца. Ссылки не исключение. Но это очень узко и ничего не объясняет, на самом деле достаточно отличать compile-time константу и runtime константу, тогда твои предположения сойдутся с реальным положением дел. И не только в плане ссылок, а в плане любых констант.
Здравствуйте, samius, Вы писали:
V>>А указатель размещает? S>Указатель размещает значение, т.к. значением указателя является не то значение, на которое он ссылается, а именно адрес того значения.
И как мне получить этот адрес в дотнете из ссылочной переменной? (ты же предположил, что они к указателям ближе)
S>>>ссылочный тип в дотнете семантически ближе к указателю C++, чем к ссылке.
V>>Смотря какой ссылочный. Если тот, который ref в аргументах, то это точная аналогия ссылки С++. S>Ссылочный тип в дотнете ровно один — тот, чьи экземпляры размещаются в управляемой куче. ref-же является чисто модификатором способа передачи аргумента и не образует нового типа в терминах системы типов дотнета.
Гхы.........
class Program {
public void Test(ref int arg) {}
static void Main(string[] args) {
Console.WriteLine(typeof(Program).GetMethod("Test").GetParameters()[0].ParameterType.Name);
}
}
Что выведет?
И кстати, уже можно создавать переменные этого типа в 4-м дотнете, хоть в шарпе пока не поддержали.
V>>В любом случае, для ссылочного типа главное, что он хранит не значение, а его адрес. Даже если это адрес времени компиляции, т.е. константа. S>В общем, ссылочный тип в C++ был бы тождественнен ref-параметрам дотнета, если бы ECMA не позволяла использовать copy-in/copy-out механизм для ref/out параметров
Ну, для случая out-параметров по другому и никак, я же говорил про ref. Допускаю что такое легко обеспечить, коль в дотнете отсутствуют кастомные конструкторы копирования для типов которые могут идти как ref/out, поэтому любая копия гарантированно идентична побитово оригиналу.
S>В этом контексте Вась (immutable) как минимум двое. Один — значение 123, второй — переменная.
123-это литерал, а какое он примет значение, зависит от инициализируемого литералом типа. Не представляю, как литерал может быть не-immutable, в исходниках разве что... ведь он живет только в момент компиляции.
DG>>ты же отвечаешь про stack, как про конкретную штуку из реализации конкретных ЯП, которые в данном случае вообще никакого отношения к дискуссии не имеют.
V>Сказать честно, я и тут не вижу разницы.
я о том, что структура данных stack не обязана один в один реализовываться в виде массива растущего с одной стороны (как это реализовано во многих языках), возможны и другие реализации.
например, stack можно реализовать поверх ассоциативной памяти(ассоциативного массива) — при этом туда-сюда будет меняться имя текущей записи.
при этом это все равно будет stack, как структура данных, но это уже не будет тем самым stack-ом, которые используется в яп.
Здравствуйте, Lloyd, Вы писали:
V>>Если бы способы адресации были не важны, их бы не проходили на первых курсах профильной специальности. Надо понимать что и как работает, чтобы адекватно использовать любую технологию, не делая заведомо неверных допущений (суть проявляя безалаберность и безответственность). Таки запас по эффективности и ресурсам пока еще не тысячекратный, чтобы позволить себе это.
L>Это-то тут причем?
Дык, не представляя способа адресации в каждом конкретном случае трудно получить представление об эффективности в этом месте. Да, обсуждаемые здесь языки таки поддерживают всевозможные способы адресации.