Re[12]: Интерфейс vs. протокол.
От: WolfHound  
Дата: 15.04.11 19:03
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Но на вопрос "зачем оно надо?" она вряд ли даст ответ. Тут нужен опыт реального применения.

Дает. Я об этом способе применения уникальных типов еще несколько лет назад писал.

VD>Да и на второй вопрос ответ интересен в разрезе немерлового компилятора, а не общей теории.

Я не думаю что в данном контексте между немерлом и скалой есть хоть какаято разница.
А в статье описаны правила проверки типов которые вообще ни к какому языку не привязаны и могут быть навешаны на какой угодно язык.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Интерфейс vs. протокол.
От: WolfHound  
Дата: 15.04.11 19:17
Оценка:
Здравствуйте, adontz, Вы писали:

A>Ты "в уме" создал для НКА соответствующий ДКА, а теперь пытаешься меня убедить что так и было?

Да, так и было.

A>Нет, не выйдет. Давай немножечко усложним задачу. После Open можно вызвать Read или Write, но потом их надо чередовать.

A>Получим НКА
A>CanOpen -{Open}-> CanRead,CanWrite,CanClose
A>CanRead -{Read}-> CanWrite,CanClose
A>CanWrite -{Write}-> CanRead,CanClose
A>CanClose -{Close} -> nil (пустое множество)
ЛОЛ! Рома ты мне не поверишь но это просто альтернативный метод записать ДКА
Вот это "CanRead,CanWrite,CanClose" состояние.
Из него 3 перехода в состояния "CanWrite,CanClose", "CanRead,CanClose" и nil.
Я вот это могу засунуть в систему типов и использовать как есть. Без всяких трансформаций.

A>Посмотрел. Примитивизм, подогнанный под инструмент. Зато я тебе могу дать действительно реальный пример. Реализовываем сетевой протокол (практически любой). Надо прочитать запрос клиента до конца прежде чем ответить. То есть можно ли после очередного Read выполнять Read или Write определяется прочитанными данными. То есть, цитируя себя самого, "переход между состояниями может определяться не только типом сообщения, но и его содержимым". Естественно, описать это на уровне типов не получится.

Рома ты просто фееричен.
На читай:
  Скрытый текст
namespace NetStack.Contracts
{
    public enum TcpError
    {
        Unknown = 1,
        AlreadyConnected,       // this connection is already in use
        Refused,                // the receiving host actively refused the connection
        Reset,                  // the connection was reset
        Timeout,                // no response was received
        ProtocolViolation,      // we received a TCP segment that is not acceptable in the current state
        ResourcesExhausted,     // out of memory, etc.
        Closed,                 // remote peer has closed socket
    }

    public contract TcpConnectionContract
    {
        // Requests
        in message Connect(uint dstIP, ushort dstPort);
        in message BindLocalEndPoint(uint dstIP, ushort dstPort);

        //
        // Initial state; there is a gratuitous Ready message to
        // ensure the Exp side has been connected before it accepts
        // any messages.
        //
        out message Ready();

        state Start : Ready! -> ReadyState;

        state ReadyState : one
        {
            Connect? -> ConnectResult; // Can connect without binding first
            BindLocalEndPoint? -> BindResult; // Can't listen without binding first
            Close? -> Closed;
        }

        //
        // Binding to a local endpoint
        //
        state BindResult : one
        {
            OK! -> Bound;
            InvalidEndPoint! -> ReadyState;
        }

        in message Listen(int backlog);

        state Bound : one
        {
            Listen? -> ListenResult;
            Connect? -> ConnectResult;
            Close? -> Closed;
        }

        //
        // Attempts to connect to a remote host
        //
        out message OK();
        out message CouldNotConnect(TcpError error);

        state ConnectResult : one
        {
            CouldNotConnect! -> ReadyState;
            OK! -> Connected;
        }

        //
        // Attempts to listen for inbound connections
        //
        out message CouldNotListen();

        state ListenResult : one
        {
            CouldNotListen! -> ReadyState;
            OK! -> Listening;
        }

        out message InvalidEndPoint();

        in message GetLocalAddress();
        in message GetLocalPort();
        in message Accept(TcpConnectionContract.Exp:PreConnected! newConnection);
        in message IsSessionAvailable(); // Is there a new session waiting to be serviced?

        out message IPAddress(uint ip);
        out message Port(ushort port);
        out message SessionIsAvailable(bool isAvailable);

        state Listening : one
        {
            GetLocalAddress? -> IPAddress! -> Listening;
            GetLocalPort? -> Port! -> Listening;
            IsSessionAvailable? -> SessionIsAvailable! -> Listening;
            Accept? -> OK! -> Listening; // Blocks until a connection is received

            Close? -> Closed;
        }

        //
        // The pre-connected state exists so we can confirm that the endpoint
        // has been wired to the NetStack before accepting messages on it
        //
        state PreConnected : Ready! -> Connected;

        //
        // Operations on an established connection
        //

        // Requests
        in message Read(); // Read as much data as possible without blocking
        in message PollRead(int timeout); // Wait up to timeout ms for data
        in message IsDataAvailable(); // Is there queued data that can be read immediately?
        in message Write(byte[]! in ExHeap data);
        in message Close(); // Performs a non-blocking but graceful shutdown
        in message Abort(); // Performs an immediate, hard close (unsent data is discarded)
        in message GetRemoteAddress();
        in message GetRemotePort();
        in message DoneSending();
        in message DoneReceiving();

        // Response messages
        out message ConnectionClosed(); // Connection has been shut down
        out message NoData(); // There was nothing to read
        out message NoMoreData(); // Will never be more data
        out message CantSend(); // Remote side refuses more data
        out message Data(byte[]! in ExHeap data);
        out message DataIsAvailable(bool isAvailable);

        state Connected : one
        {
            Read? -> ReadResult;
            PollRead? -> PollReadResult;
            Write? -> WriteResult;

            IsDataAvailable? -> (DataIsAvailable!) -> Connected;
            GetLocalAddress? -> IPAddress! -> Connected;
            GetLocalPort? -> Port! -> Connected;
            GetRemoteAddress? -> IPAddress! -> Connected;
            GetRemotePort? -> Port! -> Connected;

            DoneSending? -> ReceiveOnly;
            DoneReceiving? -> SendOnly;
            Close? -> Closed;
            Abort? -> Closed;
        }

        state ReadResult : one
        {
            Data! -> Connected;
            // This indicates that there will never be any more
            // data, but that sending is still allowed
            NoMoreData! -> SendOnly;
            // This indicates that sending has been closed by the
            // remote side
            ConnectionClosed! -> Zombie;
        }

        state PollReadResult : one
        {
            Data! -> Connected;
            // No data available within the poll window; try again
            NoData! -> Connected;
            NoMoreData! -> SendOnly;
            ConnectionClosed! -> Zombie;
        }

        state WriteResult : one
        {
            OK! -> Connected;
            // This indicates that writing has been closed by the
            // remote side, but reading is still allowed.
            CantSend! -> ReceiveOnly;
        }

        //
        // Operations on a receive-only connection (send side has been closed)
        //
        state ReceiveOnly : one
        {
            Read? -> ROReadResult;
            PollRead? -> ROPollReadResult;

            IsDataAvailable? -> (DataIsAvailable!) -> ReceiveOnly;
            GetLocalAddress? -> IPAddress! -> ReceiveOnly;
            GetLocalPort? -> Port! -> ReceiveOnly;
            GetRemoteAddress? -> IPAddress! -> ReceiveOnly;
            GetRemotePort? -> Port! -> ReceiveOnly;

            DoneReceiving? -> Zombie;
            Close? -> Closed;
            Abort? -> Closed;
        }

        state ROReadResult : one
        {
            Data! -> ReceiveOnly;
            // If there is no more data, there's nothing more to do.
            NoMoreData! -> Zombie;
        }

        state ROPollReadResult : one
        {
            Data! -> ReceiveOnly;
            NoData! -> ReceiveOnly;
            NoMoreData! -> Zombie;
        }

        //
        // Operations on a send-only connection (receive side has been closed)
        //
        state SendOnly : one
        {
            Write? -> SOWriteResult;

            GetLocalAddress? -> IPAddress! -> SendOnly;
            GetLocalPort? -> Port! -> SendOnly;
            GetRemoteAddress? -> IPAddress! -> SendOnly;
            GetRemotePort? -> Port! -> SendOnly;

            DoneSending? -> Zombie;
            Close? -> Closed;
            Abort? -> Closed;
        }

        state SOWriteResult : one
        {
            OK! -> SendOnly;
            // Remote side refuses further data
            CantSend! -> Zombie;
        }

        //
        // Zombied connection (nothing left to do but user hasn't explicitly
        // closed yet)
        //
        state Zombie : one
        {
            Close? -> Closed; // Wrap up gracefully
            Abort? -> Closed; // Drop any unsent data
        }

        state Closed : {} // Nothing is acceptable here
    }
}


A>Совсем даже не так, потому что гвозди всё же весьма распространены, а КА с фиксированным и малым числом возможных переходов — нет.

Скачай уже исходники сингулярити.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Интерфейс vs. протокол.
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.04.11 19:19
Оценка:
Здравствуйте, jazzer, Вы писали:

VD>>То и говорю. Наличие состояния и контроль за ним еще не означает, что это КА.


J>В общем случае — может быть


А наш случай частный?

J> (хотя математически сам компьютер — это КА, и соответственно все, что на нем работает, тоже КА),


Ой как интересно! С удовольствием послушаю о том какое состояние конечное у компьютера.

А машина Тьюринга или лямбда-исчисления Черча — это тоже КА? Тогда можно за одно рассказать и о конечном состоянии машины Тьюринга.

J> но вот в этом конкретном обсуждаемом случае я вижу КА в чистом и незамутненном виде. Объясни, почему то, о чем говорит 0x7be — это не КА.


Да всем. Нет входных данных, например. Да и вообще никаких атрибутов КА. Не, безусловно, многие задачи можно описать в том числе и КА. Но и без них тоже можно. При этом КА описывают не все задачи. Например, бесконечные (рекурсивные) или задачи требующие для работы дополнительной памяти (например, парсинг).

По сему не надо привязывать сюда КА. Они тут не причем. Вот внутри уникального типа может использоваться КА для обработки логики. Но уникаьные типы сами по себе — это всего лишь контроль за тем, чтобы в один момент времени на объект не было более одной ссылки. А логика у него может быть любой сложности, как укладывающейся в КА, так и не укладывающейся.

J>>>Явно описываемые состояния у 0x7be есть — "можно позвать метод1", "нельзя позвать метод2", и т.д. Что ты понимаешь под инкапсуляцией здесь, я тоже не понял.


VD>>КА — это реализация. А оных может быть много. С монадами знаком?


J>Знаком. Чем КА-то не угодил, если он укладывается в требования 0x7be?


Тем что ты их за уши притянул. Я с тем же успехом могу притянуть монады. Они тоже позволяют связать вычисления.

J> И КА — это в первую очередь математическая абстракция


Есть много мат.абстракций. И что? Эта интересна тем, что ты ей уделил больше внимания?

J>объекта с состоянием и графом разрешенных переходов: http://en.wikipedia.org/wiki/Finite-state_machine. Так что это не КА — реализация, а КА допускает много реализаций.


Где ты переходы то усмотрел? У тебя метод может получить ссылку и она может остаться в нем.

J>Да ну? А если файл открыть не удалось, много тебе скажут дескриптор и смещение?


Многое. Хэндл будет некорректным (например, равный нулю).
Меня другое интересно. А что делать, если система типов сложнее чем в случае открытия файлов?

Пойми. Ну, нельзя прописать какую-то сложную логику в типах. Только простой набор связей. Там и вычислений то никаких не будет. Это чистая декларация.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Интерфейс vs. протокол.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 15.04.11 19:35
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

WH>ЛОЛ! Рома ты мне не поверишь но это просто альтернативный метод записать ДКА


Да, он называется НКА.

WH>Вот это "CanRead,CanWrite,CanClose" состояние.


Если НКА преобразовать в ДКА.

WH>Из него 3 перехода в состояния "CanWrite,CanClose", "CanRead,CanClose" и nil.


A>>Посмотрел. Примитивизм, подогнанный под инструмент. Зато я тебе могу дать действительно реальный пример. Реализовываем сетевой протокол (практически любой). Надо прочитать запрос клиента до конца прежде чем ответить. То есть можно ли после очередного Read выполнять Read или Write определяется прочитанными данными. То есть, цитируя себя самого, "переход между состояниями может определяться не только типом сообщения, но и его содержимым". Естественно, описать это на уровне типов не получится.

WH>Рома ты просто фееричен.
WH>На читай:

"NoMoreData! -> SendOnly;" это твои фантазии, а не парсинг запроса. Если клиент приклал больше чем надо (пайплайнинг) или меньше (лаги, фрагментация) и сейчас данных больше нет, то это не значит что запрос прислали.

A>>Совсем даже не так, потому что гвозди всё же весьма распространены, а КА с фиксированным и малым числом возможных переходов — нет.

WH>Скачай уже исходники сингулярити.

Сингуларити... дай вспомнить.... Веб-сервер в 8 раз медленее на там же железе, 50Мб/с — максимальная пропускная способность TCP/IP стека и твои уверения, что безопасность не влияет на скорость. Нет, не интересно.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[18]: Интерфейс vs. протокол.
От: WolfHound  
Дата: 15.04.11 19:45
Оценка:
Здравствуйте, adontz, Вы писали:

A>Да, он называется НКА.

Нет. Тут именно что ДКА записан.

WH>>Вот это "CanRead,CanWrite,CanClose" состояние.

A>Если НКА преобразовать в ДКА.
Я знаю как из НКА делают ДКА. Так вот тут никаких преобразований не недо.
Совсем.
Это можно прямо так в коде использовать.

A>"NoMoreData! -> SendOnly;" это твои фантазии, а не парсинг запроса.

Это протокол работы с TCP/IP из реально работающей системы.

A>Сингуларити... дай вспомнить.... Веб-сервер в 8 раз медленее на там же железе, 50Мб/с — максимальная пропускная способность TCP/IP стека и твои уверения, что безопасность не влияет на скорость. Нет, не интересно.

Рома ты просто фееричен. Сравнивать вылизанную ОС и вылизанный веб сервер с экспериментальной системой...
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: Интерфейс vs. протокол.
От: adontz Грузия http://adontz.wordpress.com/
Дата: 15.04.11 20:27
Оценка:
Здравствуйте, WolfHound, Вы писали:

A>>"NoMoreData! -> SendOnly;" это твои фантазии, а не парсинг запроса.

WH>Это протокол работы с TCP/IP из реально работающей системы.

Значит эта система значительно примитивнее популярных систем.

A>>Сингуларити... дай вспомнить.... Веб-сервер в 8 раз медленее на там же железе, 50Мб/с — максимальная пропускная способность TCP/IP стека и твои уверения, что безопасность не влияет на скорость. Нет, не интересно.

WH>Рома ты просто фееричен. Сравнивать вылизанную ОС и вылизанный веб сервер с экспериментальной системой...

Вот не надо ля-ля. Вылизать можно тормоза в раза в два, а 50Мбит/с, это тормоза в 20 раз и это архитектурные проблемы.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[9]: Интерфейс vs. протокол.
От: Pavel Dvorkin Россия  
Дата: 16.04.11 07:16
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Pavel Dvorkin, Вы писали:


WH>А самое плохое в твоем поведении то что ты уперто утверждаешь что это все не нужно.


Не утверждаю, а сомневаюсь.

WH>Это как "Пастернака не читал но осуждаю"


Это явно не к месту.

WH>Да хоть заусложняйся.


Тогда упростим. Я подобный вопрос уже несколько раз задавал. От своего невежества, конечно. Только почему-то никто на него не ответил. Вот давай ответь.

Итак...

Мне надо вычислить :
При отрицательном f — корень модуля f
При положительном f — минус корень f
При 0, сам понимаешь, все равно.

Пишу вот такой код (к коду не придираться и не объясять, как его можно изменить)


class A{
 public float SqRoot(float f) {return sqrt(f);}
 public float Minus(float f) { return -f;}
 public float Func(float f)
 {
   if(f < 0)
    return Minus(SqRoot(f));
   else
    return SqRoot(Minus(f));
}


Меня сомнение гложет — в правильном порядке я функции вызываю или нет в Func ?. Может, надо было наоборот ? 2 теста в рантайме дадут вполне определенный ответ.

WH>Это из-за твоего невежества.


Ну вот я тебе пример привел выше, с минусом и корнем. Объясни просто и понятно, каким образом, не запуская программы, можно проверить правильность порядка вызова функций. Продемонстрируй свои знания в ответ на мое невежество. Только, пожалуйста, останься в рамках предложенного ТС C#.
With best regards
Pavel Dvorkin
Re[10]: Интерфейс vs. протокол.
От: hardcase Пират http://nemerle.org
Дата: 16.04.11 07:26
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Ну вот я тебе пример привел выше, с минусом и корнем. Объясни просто и понятно, каким образом, не запуская программы, можно проверить правильность порядка вызова функций. Продемонстрируй свои знания в ответ на мое невежество. Только, пожалуйста, останься в рамках предложенного ТС C#.


В C# нет зависимых типов. Так что тут только PEX может найти логические ошибки.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[11]: Интерфейс vs. протокол.
От: Pavel Dvorkin Россия  
Дата: 16.04.11 08:36
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Ну вот я тебе пример привел выше, с минусом и корнем. Объясни просто и понятно, каким образом, не запуская программы, можно проверить правильность порядка вызова функций. Продемонстрируй свои знания в ответ на мое невежество. Только, пожалуйста, останься в рамках предложенного ТС C#.


H>В C# нет зависимых типов. Так что тут только PEX может найти логические ошибки.


Ну ладно, пусть не C#. Объясни просто на пальцах — каким вообще образом, не запуская этот код, можно сказать, в правильном ли порядке я вызвал функции или нет ?
With best regards
Pavel Dvorkin
Re[10]: Интерфейс vs. протокол.
От: Sorc17 Россия  
Дата: 16.04.11 09:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>
PD>class A{
PD> public float SqRoot(float f) {return sqrt(f);}
PD> public float Minus(float f) { return -f;}
PD> public float Func(float f)
PD> {
PD>   if(f < 0)
PD>    return Minus(SqRoot(f));
PD>   else
PD>    return SqRoot(Minus(f));
PD>}

PD>


PD>Ну вот я тебе пример привел выше, с минусом и корнем. Объясни просто и понятно, каким образом, не запуская программы, можно проверить правильность порядка вызова функций. Продемонстрируй свои знания в ответ на мое невежество. Только, пожалуйста, останься в рамках предложенного ТС C#.


Вопрос был не мне Но у меня есть идея как можно это сделать не запуская программы. Если где-то "запомнить", что аргумент sqrt() должен быть больше нуля, то можно для всех вызовов sqrt() проверить, гарантировано ли ему передастся положительное число. Отсюда можем найти сомнительное место в SqRoot(), для него тоже запомним, что ему должен передаваться аргумент больше нуля, чтобы и в sqrt() он пришел положительным. Исследуя вызовы SqRoot() можно обнаружить, что ему передаётся в качестве аргумента результат выполнения Minus() а её возвращаемое значение может быть меньше нуля, значит в строчке

    return SqRoot(Minus(f));

можно смело выдать ворнинг.
Для нас [Thompson, Rob Pike, Robert Griesemer] это было просто исследование. Мы собрались вместе и решили, что ненавидим C++ [смех].
Re[11]: Интерфейс vs. протокол.
От: Pavel Dvorkin Россия  
Дата: 16.04.11 09:28
Оценка:
Здравствуйте, Sorc17, Вы писали:

S>Вопрос был не мне Но у меня есть идея как можно это сделать не запуская программы. Если где-то "запомнить", что аргумент sqrt() должен быть больше нуля, то можно для всех вызовов sqrt() проверить, гарантировано ли ему передастся положительное число.


Чуть подробнее, пожалуйста. Что значит "для всех вызовов" ? В рантайме нельзя, не о нем речь. В компайл-тайме откуда ты знаешь, что ему будет передано ? Да еще гарантированно. Передается ему какое-то f, а чему оно может быть равно — бог знает.

>Отсюда можем найти сомнительное место в SqRoot(), для него тоже запомним, что ему должен передаваться аргумент больше нуля, чтобы и в sqrt() он пришел положительным.


Интересная история. А если в ней перед sqrt выполняется некая обработка этого f, результат которой даже в принципе предвидеть нельзя, если не просчитать ? Например, f — стартовая точка для итерационного решения уравнения, а какой там корень уравнения получится, если с нее стартануть — бог знает (предполагаю, что у уравнения не 1 корень). Не возьмешься же ты ответить на вопрос, будет корень уравнения положительным или отрицательным, если начать итерации с некоторого f.
With best regards
Pavel Dvorkin
Re[10]: Интерфейс vs. протокол.
От: dotneter  
Дата: 16.04.11 09:39
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Что вам мешает сделать как то так?
class A{
 public IPlus SqRoot(IPlus f) {return sqrt(f);}
 public IMinus Minus(IPlus f) { return -f;}
 public IPlus Minus(IMinus f) { return -f;}
 public IPlus Func(IPlus f)
 {
    return Minus(SqRoot(f));
}

public IPlus Func(IMinus f)
 {
    return SqRoot(Minus(f));
}

По сути вы значение f вместе с условием if выносите в тип.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re[11]: Интерфейс vs. протокол.
От: Pavel Dvorkin Россия  
Дата: 16.04.11 09:45
Оценка:
Здравствуйте, dotneter, Вы писали:

D>Здравствуйте, Pavel Dvorkin, Вы писали:


D>Что вам мешает сделать как то так?

D>
D>class A{
D> public IPlus SqRoot(IPlus f) {return sqrt(f);}
D> public IMinus Minus(IPlus f) { return -f;}
D> public IPlus Minus(IMinus f) { return -f;}
D> public IPlus Func(IPlus f)
D> {
D>    return Minus(SqRoot(f));
D>}

D>public IPlus Func(IMinus f)
D> {
D>    return SqRoot(Minus(f));
D>}


D>

D>По сути вы значение f вместе с условием if выносите в тип.

А все же на вход Func должна передаваться переменная типа float. Я не знаю, положительна она или отрицательна, ее с консоли введут. Кроме того, Func должна вернуть IMinus, (при положительном f — минус корень f). Что-то не клеится.
With best regards
Pavel Dvorkin
Re[12]: Интерфейс vs. протокол.
От: dotneter  
Дата: 16.04.11 09:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А все же на вход Func должна передаваться переменная типа float. Я не знаю, положительна она или отрицательна, ее с консоли введут.

Это как чистые функции и IO, что то нужно придумать что бы их подружить, так же и здесь. Есть внешний мир при соедитетие с программой нужно что то сделать что бы данные перевести в типы, можно тот же if, а можно наверное что то еще, суть в том что вне зависимости что там будет происходить у вас есть описание функций решающие вашу проблему и при этом устраняют возможные ошибки которые в них могли бы содержаться.

PD>Кроме того, Func должна вернуть IMinus, (при положительном f — минус корень f). Что-то не клеится.

Да, при этом эту ошибку сможет найти компилятор.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Talk is cheap. Show me the code.
Re[12]: Интерфейс vs. протокол.
От: dotneter  
Дата: 16.04.11 10:03
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Можно рассмотреть пример проще

public void DoSomething(A a){
    if(A == null)
       throw new ArgumentException(a);
}
public void DoSomething(NotNull<A> a){

}



То есть где то эта проверка должна произойти, либо у каждой функции, либо вы можете ее сделать один раз, и тогда у вас по программе будет гулять переменная у которой в типе NotNull<A> уже содержится какая то информация о ее значении;
Talk is cheap. Show me the code.
Re[8]: Интерфейс vs. протокол.
От: 0x7be СССР  
Дата: 16.04.11 10:03
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Все равно идею не понимаю. Перенести в compile-time логику работы программы... Так ведь, если доводить до предела, можно потребовать в compile-time определение правильной последовательности всех действий программы. А это означает, что эта последовательность должна быть жестко фиксированной и не зависеть от данных — от них зависимость в compile-time не проверишь же...


Попробую проиллюстрировать свою идею. Положим, есть у нас сервер, умеющий что-нибудь считать.
Для того, что бы работать с ним надо:
1. Открыть сессию.
2. Загрузить данные.
3. Вызвать функцию вычисления (их может быть много).
4. Если вычисление прошло успешно, то выгрузить данные.
5. Закрыть сессию.

Как бы выглядел "обчный" порошо... интерфейс сервера и сессии:
interface IServer
{
  ISession CreateSession();
}

interface ISession : IDisposable
{
  void UploadData(Data);
  Data DownloadData();

  bool DoFuncA();
  bool DoFuncB();
  bool DoFuncC();
}

Интерфейс сервера меня устраивает, поработаю над интерфейсом сессии.

interface ISessionUploadData : IDisposable
{
  Variant<ISessionDoJob, ISessionUploadData> UploadData(Data);
}

interface ISessionDoJob : IDispoable
{
  Variant<ISessionDownloadData, IDisposable> DoFuncA();
  Variant<ISessionDownloadData, IDisposable> DoFuncB();
  Variant<ISessionDownloadData, IDisposable> DoFuncC();
}

interface ISessionDownloadData : IDisposable
{
  Tuple<Data, IDisposable> DownloadData();
}

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

Обрати внимание на Variant. По сути это должен быть алгебраический тип, в который можно завернуть несколько вариантов возврата, параллельно с нужными кодами возврата (ошибки и т.п.)

В частности, функция UploadData в случае успеха возвращает ISessionDoJob, что бы продолжать работать с данными, либо снова ISessionUploadData, если данные не загрузились.

Функции вычисления возвращают либо ISessionDownloadData, если вычисление прошло, либо IDisposable, если ошибка.

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

Дальше, положим что мы решили поменять протокол. Сказали, что после загрузки но перед обработкой надо вызвать функцию PreparеData, которая как-нибудь данные готовит. Мы меняем интерфейсы, добавляя ISessionPrepareData "между" ISessionUploadData и ISessionDoJob:
interface ISessionUploadData : IDisposable
{
  Variant<ISessionPrepareData, ISessionUploadData> UploadData(Data);
}

interface ISessionPrepareData : IDisposable
{
  ISessionDoJob UploadData(Data);
}

interface ISessionDoJob : IDispoable
{
  Variant<ISessionDownloadData, IDisposable> DoFuncA();
  Variant<ISessionDownloadData, IDisposable> DoFuncB();
  Variant<ISessionDownloadData, IDisposable> DoFuncC();
}

interface ISessionDownloadData : IDisposable
{
  Tuple<Data, IDisposable> DownloadData();
}

Клиентский код, который мы забыли поправить, тут же перестанет собираться, мы получим по рукам во время сборки продукта и сможем подумать, не погорячились ли мы с новым протоколом, или просто поправить клиента. Теперь понятно, как статически описать и проконтролировать альтернативные варианты workflow протокола?
Re[10]: Интерфейс vs. протокол.
От: WolfHound  
Дата: 16.04.11 10:07
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Тогда упростим. Я подобный вопрос уже несколько раз задавал. От своего невежества, конечно. Только почему-то никто на него не ответил. Вот давай ответь.

Я тебя уже не первый год тыкаю носом в эту ссылку.
http://en.wikipedia.org/wiki/Dependent_type

Вот тебе ссылки про адаптацию этой теории для практики.
http://scholar.google.com/scholar?hl=ru&amp;q=type+refinements+programming&amp;btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&amp;as_ylo=&amp;as_vis=0
Только ты же всеравно учиться не будешь.

PD>Ну вот я тебе пример привел выше, с минусом и корнем. Объясни просто и понятно, каким образом, не запуская программы, можно проверить правильность порядка вызова функций. Продемонстрируй свои знания в ответ на мое невежество.

Я тебе уже много всякого разного показывал но ты все проигнорировал.
Заниматься твоим образованием мне лень.
Ссылку я дал.
Читай.
Там более чем достаточно информации чтобы ты сам понял как сделать твой пример.

PD>Только, пожалуйста, останься в рамках предложенного ТС C#.


Я же говорю ты меня совсем не слушаешь.
В рамках C# это не решается. Тут как минимум type refinements нужны, а их в C# нет.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Интерфейс vs. протокол.
От: 0x7be СССР  
Дата: 16.04.11 10:08
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Nemerle тут может помочь только тем, что его код открыт и можно реализовать нужную функциональность в компиляторе. Но синтаксические навороты тут мало что дадут. Эта фича требует вмешательства в типизатор.

Хм. А как тебе следующий подход: метапрограмма, в самом общем виде — это программа которая обрабатывает другие программы. Помимо кодогенерации или трансформации она может заниматься и верификацией. Чисто теоретически легко себе представить макрос, который обходит AST программы, ищет все места использования типа, помеченного нужным атрибутом, и следит за тем, что бы выполнялись ограничения.
Re[20]: Интерфейс vs. протокол.
От: WolfHound  
Дата: 16.04.11 10:11
Оценка:
Здравствуйте, adontz, Вы писали:

A>Значит эта система значительно примитивнее популярных систем.

Все там на месте. Просто ты не понял что это такое.

A>Вот не надо ля-ля. Вылизать можно тормоза в раза в два, а 50Мбит/с, это тормоза в 20 раз и это архитектурные проблемы.

Сам наблюдал ругонь человека который пилил файловую систему для линуха когда после очередного обновления девелоперской версии ядра производительность просела в разы.
Он долго сидел и искал что же там такого сделали что тормоза на ровном месте завелись.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Интерфейс vs. протокол.
От: 0x7be СССР  
Дата: 16.04.11 10:17
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Сколько еще лет тебе показывать эту ссылку?

WH>

WH>In computer science and logic, a dependent type is a type that depends on a value.

WH>http://en.wikipedia.org/wiki/Dependent_type
Справедливости ради надо сказать, что я зависимые типы изначально не думал применять
Мне кажется, что алгебраических типов с паттернматчингом вполне хватит для комфортной работы с такими протоколами.
Впрочем, раз уж зависимые типы упомянули, подумаю над их приложимостью к этой идее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.