По сути получается, что в шарпе с помощью библиотеки, реализующий основные пролог функции, программа, написанная на прологе, использующая основные функции, выглядит так же, как и в прологе? Ну допустим, но что из этого следует? На шарпе можно добиться того же результата? Да, конечно, это же тьюринг-полный язык, а как мы помним тезис тьюринга-черча, это значит что на нем мы можем посчитать что душе угодно. С тем же успехом можно взять ассемблер и брейнфак, можно даже с помощью макросов получить что-то похожее. Значит ли это, что этот язык подходит для реализации задачи? Не думаю.
Шарп замечательный язык, но тогда уж предоставляйте честное решение с имплементацией всех методов, без сторонних библиотек. Потому что если мы у языков заберем стандартные библиотеки, то останется только синтаксис, который в данном примере тоже проигрывает прологовскому, а по числу скобочек приближается к лиспу.
Но в любом случае, спасибо за статью. Я не согласен лишь в выводом, что если примотать кирпич к отвертке — то получится сносный молоток. Каждой задаче — свой инструмент. There is no silver bullet, Neo.
И, да, инструкция callvirt не проверяет на “правильность” объекта.
А можно поподробнее? Насколько я знаю, как раз-таки проверяет, и как раз-таки поэтому её используют для вызова методов, даже если они не являются виртуальными. Извиняюсь за многабукв, но для полноты информации процитирую всё:
We can use a similar dispatch sequence to call non-virtual methods as well. However, for non-virtual methods,
there is no need to use the method table for method dispatch: the code address of the invoked method (or at least
its pre-JIT stub) is known when the JIT compiles the method dispatch. For example, if the stack location EBP-64
contains the address of an Employeeobject, as before, then the following instruction sequence will call the
TakeVacationmethod with the parameter 5:
mov edx, 5 ;parameter passing through register – custom calling convention
mov ecx, dword ptr [ebp-64] ;still required because ECX contains ‘this’ by convention
call dword ptr [0x004a1260]
It is still required to load the object’s address into the ECXregister – all instance methods expect to receive
in ECXthe implicit thisparameter. However, there’s no longer any need to dereference the method table pointer
and obtain the address from the method table. The JIT compiler still needs to be able to update the call site after
performing the call; this is obtained by performing an indirect call through a memory location (0x004a1260in
this example) that initially points to the pre-JIT stub and is updated by the JIT compiler as soon as the method is
compiled.
Unfortunately, the method dispatch sequence above suffers from a significant problem. It allows method
calls on null object references to be dispatched successfully and possibly remain undetected until the instance
method attempts to access an instance field or a virtual method, which would cause an access violation. In fact,
this is the behavior for C++ instance method calls – the following code would execute unharmed in most C++
environments, but would certainly make C# developers shift uneasily in their chairs:
class Employee {
public: void Work() { } //empty non-virtual method
};
Employee* pEmployee = NULL;
pEmployee->Work(); //runs to completion
If you inspect the actual sequence used by the JIT compiler to invoke non-virtual instance methods, it would
contain an additional instruction:
Recall that the CMPinstruction subtracts its second operand from the first and sets CPU flags according to the
result of the operation. The code above does not use the comparison result stored in the CPU flags, so how would
the CMPinstruction help prevent calling a method using a null object reference? Well, the CMPinstruction attempts
to access the memory address in the ECXregister, which contains the object reference. If the object reference is
null, this memory access would fail with an access violation, because accessing the address 0 is always illegal in
Windows processes. This access violation is converted by the CLR to a NullReferenceExceptionwhich is thrown
at the invocation point; a much better choice than emitting a null check inside the method after it has already
been called. Furthermore, the CMPinstruction occupies only two bytes in memory, and has the advantage of
being able to check for invalid addresses other than null.
На самом деле направление реально может иметь место, потому что в цепи может быть внутри усилитель, и он роляет. Правда, обычно их ставят в кабели типа hdmi, где несравним битрейт и частоты… Так что, хотя в данном случае вы совершенно правы, в целом у кабеля может быть направление.
Если вы этого не осознаёте — так это вам же во благо — иначе ваш маленький мозг (по сравнению с мозгом слона, к примеру) из сотояния покоя (задействованы 2-6% неронов) превратился бы в кипящий ад (задействованы 60-80% нейронов), правда, ненадолго — минут на 5-7 — и просто вы бы умерли или впали в состояние комы.
Насколько я знаю, все эти байки про 3% использования мозга — всего лишь байки, не имеющие научного обоснования, которые используются во всяких Люси.
По форумам претензий нет. Вопрос, что физически происходит? Если 2 космическая у ЧД будет 1.1c, то мы же не сможем увидеть фотон, который затягивается в ЧД на скорости 0.1с, ведь в любой СО фотон будете лететь со скоростью света в направлении движения. Тогда как это будет выглядеть «изнутри»?
Никак не могу примирить у себя в голове скорость света в таких вот задачах и в ОТО. Согласно ОТО в любой системе отсчета фотон движется со скоростью света. С другой стороны, ЧД называются ЧД, потому что гравитационное поле не дает фотонам вылететь за её пределы. Но как ЧД может не давать фотонам вылететь, если нельзя замедлить фотон, который всегда движется со скоростью с? Если гравитационную линзу еще можно понять, мы меняем направление световой волны, но не влияем на скорость, то вот такие вот вопросы остаются для меня без ответа…
а что касается минусов — это же хабрах… то есть гиктаймс. Посмотрите на мою репу — та же история. Удачный коммент — +10 репы к комменту, неудачный — минус 20 в репу, работает это только так и никак иначе, к сожалению. Причем это общеизвестный факт, подробно он обсуждается в недавней новости о сбросе отрицательной кармы на хабре.
Шарп замечательный язык, но тогда уж предоставляйте честное решение с имплементацией всех методов, без сторонних библиотек. Потому что если мы у языков заберем стандартные библиотеки, то останется только синтаксис, который в данном примере тоже проигрывает прологовскому, а по числу скобочек приближается к лиспу.
Но в любом случае, спасибо за статью. Я не согласен лишь в выводом, что если примотать кирпич к отвертке — то получится сносный молоток. Каждой задаче — свой инструмент. There is no silver bullet, Neo.
А можно поподробнее? Насколько я знаю, как раз-таки проверяет, и как раз-таки поэтому её используют для вызова методов, даже если они не являются виртуальными. Извиняюсь за многабукв, но для полноты информации процитирую всё:
Насколько я знаю, все эти байки про 3% использования мозга — всего лишь байки, не имеющие научного обоснования, которые используются во всяких Люси.
lenta.ru/news/2015/01/21/keycbr/
habrahabr.ru/post/236637/#comment_7961043
а что касается минусов — это же хабрах… то есть гиктаймс. Посмотрите на мою репу — та же история. Удачный коммент — +10 репы к комменту, неудачный — минус 20 в репу, работает это только так и никак иначе, к сожалению. Причем это общеизвестный факт, подробно он обсуждается в недавней новости о сбросе отрицательной кармы на хабре.
она не работает, т.к. GetSemanticModel является нестатическим методом, с конструктор типа Compilation — internal