есть два утверждения — свойства всегда существуют в независимости от нашего знания, свойства не всегда существуют в независимости от нашего знания.
ты постулируешь первое из этих утверждений.
и я тебя спрашиваю: что тебя убедит, что первое утверждение не всегда верно? (это и есть возможность фальсификации)
DG>>не научное (не конструктивное) определение — потому что нечего фальсифицировать S>Хм. Мне лично вот кажется, что свойство воды занимать весь предоставленный ей объём можно легко фальсифицировать, опровергнув, таким образом, предположение о возможности классифицировать её как газ.
это ты о конкретном свойстве, а я тебя спрашиваю про возможность фальсификации общей формулировки "свойства существуют в независимости от нашего знания о них".
для появление фальсифицируемости — "существование свойства" вводят:
или через изменение поведения объекта: свойство X существует — если поведение объектов со свойством X отличается от поведения объектов без свойства X
или через изменение поведения окружения объекта: свойство X существует — если поведение окружения для объектов со свойством X отличается от поведения для объектов без свойства X
если под "существование свойства" понимается одна из таких формулировок, тогда уже можно говорит о возможности фальсификации утверждения "свойства всегда существуют в независимости от нашего знания".
пример попробую привести еще раз:
есть свойство S: последовательность упорядочена по возрастанию
есть другие свойства (которые базируются на свойстве S):
1. IEnumerable-последовательность про которую известно, что в ней все элементы отсортированы по возрастанию можно преобразовать за O(1) в IOrderedEnumerable
2. минимальный элемент для упорядоченной последовательности по возрастанию ищется за O(1)
и т.д.
при этом если код не знает, что последовательность обладает свойством упорядоченности по возрастанию, то код не может обеспечить время выполнения за O(1), и упорядоченные последовательности будут обрабатываться за время O(n) и больше (сравнимое с обработкой неупорядоченных последовательностей).
или другими словами: код ведет себя так, как будто свойства "упорядоченность по возрастанию" у последовательности не существует.
DG>>ты говоришь, что конструкция foreach(x in items) в ФЯ есть функция, потому что кто-то такой ярлык наклеил S>Я такое не говорил. Я говорю что в хаскеле нет конструкции foreach. Какой ярлык — это я без понятия. К чему клеить-то, если такой конструкции в языке нет?
DG>>, а такая же конструкция в C++ (for (var it = s.begin(); it != s.end(); ++it) — не есть функция, потому что в книжке про это не написано. S>В книжке написано что это statement. Если разуешь глаза, то увидишь что он никак не обладает признаками функции.
чтобы это увидеть необходимо эти признаки выписать.
как только ты их выпишешь, то даже самостоятельно увидишь, что для современных языков C#, Java, C++ — statement по этим признакам не отличается от функции (и уж тем более от монадной функции).
S>Ты знаешь что такое монада? Почитай определение на досуге. А потом подумай, как монада может обеспечить продолжение с произвольного места. Так вот, goto там это функция, которая берет монадное вычисление и возвращает монадное значение (со слов автора). DG>>goto делает тоже самое S>Тебя смутил ярлык "goto". Делает goto из C совершенно другое.
по какому признаку goto в C делает другое?
DG>>тоже самое можно принять и для C++, и для C#, что это просто такой хитрый результат вызова функции S>С исключением можно работать, можно строить на нем логику, как и на результате. halt/exit таким свойством не обладает, значит не может быть ни рассмотрен, ни смоделирован в качестве результата функции.
вот здесь ты конструктивен (в отличии от ситуаций выше), здесь ты уже приводишь реальный признак на основе которого отличаешь halt/exit от исключений.
и на это есть конструктивный ответ:
halt/exit является результатом функции, когда в качестве функции берется вся программа.
и логику можно построить и на halt/exit, но в качестве функций придется уже брать целые программы, что и делается, например, в unix way.
DG>>если не требуется сохранить время выполнения, то означает. S>Покажи мне автоматический перевод sql (без процедур) в регулярные выражения
дай реализацию машины тьюринга поверх регулярных выражений (раз ты утверждаешь, что регулярные выражения тьюринг-полные), а я тебе в ответ дам: транслятор sql в стековую машину, и транслятор стековой машины в машину тьюринга.
DG>>для перевода языка L1 в язык L2 без сохранения времени выполнения программы достаточно: DG>>1. на языке L2 иметь компилируемый эмулятор языка L3 стековой машины (или, например, эмулятор asm x86), S>А ты его автоматически получил?
конечно.
раз утверждается, что haskell тьюринг полный, то это означает, что для хаскеля есть транслятор, который умеет переводить машину тьюринга в хаскель.
а дальше берется готовый транслятор стековой машины для МТ: и в результате применения одного транслятора к результату другого транслятора — получаем, что поверх haskell-я выполняется стековая машина.
все это есть. но на практике это никому не надо, потому что оверхеды получаются дикие, и время выполнения растет лавинообразно после каждого преобразования.
соответственно, для практической применимости эквивалентности по тьюрингу мало. Для практической применимости добавляется требование "возможность преобразования с сохранением времени выполнения".
а обрабатывают данные потоково, в качестве этапа конвейера — никакая монада IO не нужна: K>
K>main = interact $ чистая_функция
K>
в данном случае программа — это "interact $ чистая функция", и эта конструкция использует монаду IO (а значит монада IO нужна) — как минимум, interact имеет тип: (String -> String) -> IO ()
если слова "использовать" и "нужна" заменить на слова "использовать в явном виде" и "учитывать особенности", то я согласен с исходным утверждением.
программа main = putStr "Hellow" тоже использует монаду IO, но не явно.
это доказывается тем, что если бы putStr "Hello" не использовал бы IO, то эту строку можно было бы вынести в функцию не имеющую "пометку" IO, а так сделать нельзя.
DG>>>ты говоришь, что конструкция foreach(x in items) в ФЯ есть функция, потому что кто-то такой ярлык наклеил S>>Я такое не говорил. Я говорю что в хаскеле нет конструкции foreach. Какой ярлык — это я без понятия. К чему клеить-то, если такой конструкции в языке нет?
DG>что значит нет? когда по ссылке она первой указана DG>>>>>http://www.xoltar.org/old_site/2003//sep/09/haskellLoops.html
Где ты там видишь конструкцию? Это функция чистой воды.
DG>>>, а такая же конструкция в C++ (for (var it = s.begin(); it != s.end(); ++it) — не есть функция, потому что в книжке про это не написано. S>>В книжке написано что это statement. Если разуешь глаза, то увидишь что он никак не обладает признаками функции.
DG>чтобы это увидеть необходимо эти признаки выписать. DG>как только ты их выпишешь, то даже самостоятельно увидишь, что для современных языков C#, Java, C++ — statement по этим признакам не отличается от функции (и уж тем более от монадной функции).
Вот тебе первый признак. Функция возвращает результат. Ни foreach, ни for этим признаком не обладают.
S>>Ты знаешь что такое монада? Почитай определение на досуге. А потом подумай, как монада может обеспечить продолжение с произвольного места. Так вот, goto там это функция, которая берет монадное вычисление и возвращает монадное значение (со слов автора). DG>>>goto делает тоже самое S>>Тебя смутил ярлык "goto". Делает goto из C совершенно другое.
DG>по какому признаку goto в C делает другое?
Он не возвращает результат. Это действительно тупой переход.
DG>>>тоже самое можно принять и для C++, и для C#, что это просто такой хитрый результат вызова функции S>>С исключением можно работать, можно строить на нем логику, как и на результате. halt/exit таким свойством не обладает, значит не может быть ни рассмотрен, ни смоделирован в качестве результата функции.
DG>вот здесь ты конструктивен (в отличии от ситуаций выше), здесь ты уже приводишь реальный признак на основе которого отличаешь halt/exit от исключений. DG>и на это есть конструктивный ответ: DG>halt/exit является результатом функции, когда в качестве функции берется вся программа.
Если тебе нужен в результате программы int — зачем тебе вся остальная программа? Сделай
int main { return 4; }
DG>и логику можно построить и на halt/exit, но в качестве функций придется уже брать целые программы, что и делается, например, в unix way.
А почему в unix way не заменяют программы на результат, не задумывался об этом?
Здравствуйте, DarkGray, Вы писали:
DG>в данном случае программа — это "interact $ чистая функция", и эта конструкция использует монаду IO (а значит монада IO нужна) — как минимум, interact имеет тип: (String -> String) -> IO ()
Вот именно. Как видите, никакой монады тут нет.
DG>если слова "использовать" и "нужна" заменить на слова "использовать в явном виде" и "учитывать особенности", то я согласен с исходным утверждением. DG>программа main = putStr "Hellow" тоже использует монаду IO, но не явно. DG>это доказывается тем, что если бы putStr "Hello" не использовал бы IO, то эту строку можно было бы вынести в функцию не имеющую "пометку" IO, а так сделать нельзя.
IO a и монада IO — разные вещи. IO a — тип для "действия". Монада — набор функций, которые позволяют комбинировать действия безопасным способом (с соблюдением порядка). В случае хаскеля, монада IO — это инстанс класса Monad. Комбинировать действия можно и другими инструментами. С помощью аппликативного функтора IO, стрелок и т.д.
В некоторый случаях, когда действие одно — можно вообще не комбинировать. Такие примеры приведены.
Если монады для комбинации действий не используются — значит не используются, а не "неявно используются". Неявно они используются, например, в случае синтаксического сахара вроде do-нотации, которая рассахаривается в комбинаторы класса Monad.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, DarkGray, Вы писали:
DG>>>если не требуется сохранить время выполнения, то означает. S>>Покажи мне автоматический перевод sql (без процедур) в регулярные выражения
DG>дай реализацию машины тьюринга поверх регулярных выражений (раз ты утверждаешь, что регулярные выражения тьюринг-полные), а я тебе в ответ дам: транслятор sql в стековую машину, и транслятор стековой машины в машину тьюринга.
А я такого не утверждал, перечитай на что отвечаешь.
DG>>>для перевода языка L1 в язык L2 без сохранения времени выполнения программы достаточно: DG>>>1. на языке L2 иметь компилируемый эмулятор языка L3 стековой машины (или, например, эмулятор asm x86), S>>А ты его автоматически получил?
DG>конечно. DG>раз утверждается, что haskell тьюринг полный, то это означает, что для хаскеля есть транслятор, который умеет переводить машину тьюринга в хаскель.
1. Вот ты его автоматически получил?
2. Ты обобщил в предыдущих ответах утверждение до вообще эквивалентных по тьюрингу, а не только для полных. Расхлебывай. DG>а дальше берется готовый транслятор стековой машины для МТ: и в результате применения одного транслятора к результату другого транслятора — получаем, что поверх haskell-я выполняется стековая машина.
DG>все это есть. но на практике это никому не надо, потому что оверхеды получаются дикие, и время выполнения растет лавинообразно после каждого преобразования.
DG>соответственно, для практической применимости эквивалентности по тьюрингу мало. Для практической применимости добавляется требование "возможность преобразования с сохранением времени выполнения".
К полноте по Тьюрингу это уже не имеет никакого отношения.
DG>>чтобы это увидеть необходимо эти признаки выписать. DG>>как только ты их выпишешь, то даже самостоятельно увидишь, что для современных языков C#, Java, C++ — statement по этим признакам не отличается от функции (и уж тем более от монадной функции). S>Вот тебе первый признак. Функция возвращает результат. Ни foreach, ни for этим признаком не обладают.
функция может вернуть пустой результат. монадическая функция может вернуть пустой результат + монаду
foreach и for в зависимости от условий может рассматриваться или как первый вариант, или как второй.
S>>>Ты знаешь что такое монада? Почитай определение на досуге. А потом подумай, как монада может обеспечить продолжение с произвольного места. Так вот, goto там это функция, которая берет монадное вычисление и возвращает монадное значение (со слов автора). DG>>>>goto делает тоже самое S>>>Тебя смутил ярлык "goto". Делает goto из C совершенно другое.
DG>>по какому признаку goto в C делает другое? S>Он не возвращает результат. Это действительно тупой переход.
можно считать, что goto возвращает результат блока на который произошел переход, и будет тоже самое, что делает goto в haskell.
или другими словами, код с goto можно автоматически нарезать на куски от метки до метки, и каждой такой кусок оформить как отдельную функцию (при этом локальные переменные исходного кода перейдут во входные/выходные параметры этих кусков), а дальше каждый goto заменить на вызов соответствующей функции.
и можно строго доказать, что код после такого преобразования будет эквивалентен исходному.
DG>>halt/exit является результатом функции, когда в качестве функции берется вся программа. S>Если тебе нужен в результате программы int — зачем тебе вся остальная программа? Сделай S>int main { return 4; }
halt/exit используются в основном для возврата результата для вырожденных данных (например, не соответствующих контракту).
полный тип спецификации batch-программы как функции: (string-cin, string) -> (int-result-code, string-cout, error-string-cerr) или (sequence-cin, string) -> (int-result-code, sequence-cout, error-sequence-cerr). возможны и более сложные варианты.
DG>>и логику можно построить и на halt/exit, но в качестве функций придется уже брать целые программы, что и делается, например, в unix way. S>А почему в unix way не заменяют программы на результат, не задумывался об этом?
как минимум, потому что такая замена имеет смысл при компиляции (и делать ее может лишь компилятор), а в unix way для связывания программ обычно используются скриптовые языки.
Здравствуйте, DarkGray, Вы писали:
S>>Вот тебе первый признак. Функция возвращает результат. Ни foreach, ни for этим признаком не обладают.
DG>функция может вернуть пустой результат. DG>монадическая функция может вернуть пустой результат + монаду
Что-что? Монаду? DG>foreach и for в зависимости от условий может рассматриваться или как первый вариант, или как второй.
Как первый не может, т.к. кроме возврата пустого результата для чего-то эти конструкции нужны. Второй — даже не понимаю, о чем речь. Загляни в определение монады.
DG>>>по какому признаку goto в C делает другое? S>>Он не возвращает результат. Это действительно тупой переход.
DG>можно считать, что goto возвращает результат блока на который произошел переход, и будет тоже самое, что делает goto в haskell.
Блок, на который произошел переход ничего возвращать не собирается. Это блок, а не выражение. DG>или другими словами, код с goto можно автоматически нарезать на куски от метки до метки, и каждой такой кусок оформить как отдельную функцию (при этом локальные переменные исходного кода перейдут во входные/выходные параметры этих кусков), а дальше каждый goto заменить на вызов соответствующей функции. DG>и можно строго доказать, что код после такого преобразования будет эквивалентен исходному.
Ты хочешь доказать, что код с goto можно преобразовать в функциональный? Пожалуйста. Но это будет уже другой код, а не тот, свойства которого ты пытаешься рассмотреть.
DG>>>halt/exit является результатом функции, когда в качестве функции берется вся программа. S>>Если тебе нужен в результате программы int — зачем тебе вся остальная программа? Сделай S>>int main { return 4; }
DG>halt/exit используются в основном для возврата результата для вырожденных данных (например, не соответствующих контракту). DG>полный тип спецификации batch-программы как функции: (string-cin, string) -> (int-result-code, string-cout, error-string-cerr) или (sequence-cin, string) -> (int-result-code, sequence-cout, error-sequence-cerr). возможны и более сложные варианты.
DG>>>и логику можно построить и на halt/exit, но в качестве функций придется уже брать целые программы, что и делается, например, в unix way. S>>А почему в unix way не заменяют программы на результат, не задумывался об этом?
DG>как минимум, потому что такая замена имеет смысл при компиляции (и делать ее может лишь компилятор), а в unix way для связывания программ обычно используются скриптовые языки.
Я толсто намекаю на то, что если бы от программы нужны были лишь ее коды, то не нужна бы была сама программа.
K>>IO a и монада IO — разные вещи.
DG>сами по себе IO, MayBe и т.д. как принято называть? монадический тип?
Это просто типы. Добавь к ним список хаскеля [] или IEnumerable из дотнета, есть куча других примеров. Nullable<T>, Lazy<T> и т.п.
Сами по себе они ничем не лучше и не хуже других. Но если рассмотреть их в совокупности с некоторыми функциями, то окажется что эти типы вместе с этими функциями обладают замечательными свойствами, позволяющие применять к ним некоторый прием.
Однако в Хаскеле, монада является еще и абстракцией, т.е. эти типы могут быть объявлены (а могут и нет) инстансом спецкласса. Само по себе к монаде это отношения имеет не больше, чем задание совместимых для Query Expressions методов в C#. Конечно, абстракция в Хаскеле позволяет делать с монадами более высокоуровневые вещи, чем можно себе позволить дотнет.
Здравствуйте, DarkGray, Вы писали:
S>>2. Ты обобщил в предыдущих ответах утверждение до вообще эквивалентных по тьюрингу, а не только для полных. Расхлебывай.
DG>утверждения "ЯП эквивалентен МТ" и "ЯП полный по тьюрингу" — это синонимы. из первое следует второе, а из второго первое.
DG>
если не брать время, то из эквивалентности языка C и языка haskell следует, что программу на языке C можно автоматически перевести на язык haskell, и соответственно любую императивную программу на языке C можно автоматически представить в декларативном виде.
Ты написал что автоматический перевод следует из эквивалентности. А я написал что не следует.
Здравствуйте, DarkGray, Вы писали:
DG>сами по себе IO, MayBe и т.д. как принято называть? монадический тип?
IO a и Maybe a — типы. IO и Maybe — конструкторы типов. Выражение "монадический тип" вообще довольно бессмысленно. Потому, что в типах не бывает ничего "монадического". Декларация типа никак его с монадами не связывает. А вот декларация инстанса класса Monad с типом связана. Поэтому логичнее говорить "монада Maybe", имея в виду набор операций определенных для типа Maybe, а не "монадический тип Maybe". Натуральные числа — это не сложение, и не "слагательные числа". Это множество, на котором определена операция "сложение натуральных чисел".
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
K> Выражение "монадический тип" вообще довольно бессмысленно. Потому, что в типах не бывает ничего "монадического".
т.е. на вики написано не правильно, и необходимо использовать какой-то другой источник для понимания монад. какой?
Definition
A monad is a construction that, given an underlying type system, embeds a corresponding type system (called the monadic type system) into it (that is, each monadic type acts as the underlying type). This monadic type system preserves all significant aspects of the underlying type system, while adding features particular to the monad.
The usual formulation of a monad for programming is known as a Kleisli triple, and has the following components:
1.A type construction that defines, for every underlying type, how to obtain a corresponding monadic type. In Haskell's notation, the name of the monad represents the type constructor. If M is the name of the monad and t is a data type, then "M t" is the corresponding type in the monad.
2.A unit function that maps a value in an underlying type to a value in the corresponding monadic type. The result is the "simplest" value in the corresponding type that completely preserves the original value (simplicity being understood appropriately to the monad). In Haskell, this function is called return due to the way it is used in the do-notation described later. The unit function has the polymorphic type t→M t.
3.A binding operation of polymorphic type (M t)→(t→M u)→(M u), which Haskell represents by the infix operator >>=. Its first argument is a value in a monadic type, its second argument is a function that maps from the underlying type of the first argument to another monadic type, and its result is in that other monadic type. The binding operation can be understood as having four stages: 1.The monad-related structure on the first argument is "pierced" to expose any number of values in the underlying type t.
2.The given function is applied to all of those values to obtain values of type (M u).
3.The monad-related structure on those values is also pierced, exposing values of type u.
4.Finally, the monad-related structure is reassembled over all of the results, giving a single value of type (M u).
In object-oriented programming terms, the type construction would correspond to the declaration of the monadic type, the unit function takes the role of a constructor method, and the binding operation contains the logic necessary to execute its registered callbacks (the monadic functions).
S>>>2. Ты обобщил в предыдущих ответах утверждение до вообще эквивалентных по тьюрингу, а не только для полных. Расхлебывай.
DG>>утверждения "ЯП эквивалентен МТ" и "ЯП полный по тьюрингу" — это синонимы. из первое следует второе, а из второго первое.
DG>> S>
S>если не брать время, то из эквивалентности языка C и языка haskell следует, что программу на языке C можно автоматически перевести на язык haskell, и соответственно любую императивную программу на языке C можно автоматически представить в декларативном виде.
S>Ты написал что автоматический перевод следует из эквивалентности. А я написал что не следует.
ты выдернул цитату из контекста.
полный контекст:
G>>Мощность языков программирования по тьюрингу одинакова и они все выполняются на x86 процессорах. Так что фраза твоя ни о чем.
DG>эта эквивалентность не обещает, что алгоритм после преобразования останется вычислимым за заданное время.
G> А причем тут время? Мы про время еще ничего не говорили. Не надо лишние, для понимания сути, вещи включать.
DG> если не брать время, то из эквивалентности языка C и языка haskell следует, что программу на языке C можно автоматически перевести на язык haskell, и соответственно любую императивную программу на языке C можно автоматически представить в декларативном виде.
тут четко прослеживается, что под эквивалентностью языков понимается полнота по тьюрингу.
а из полноты по тьюрингу двух языков программирования L1 и L2 следует, что можно автоматически программу на языке L1 преобразовать в программу на языке L2 с помощью цепочки преобразований: L1 -> стековая машина -> МТ -> L2
это особенные типы для которых действует особые правила.
в частности, для монадического типа утверждается, что нельзя задать функцию вида monadic type -> type
можно лишь задавать функции вида:
m a -> m b
a -> m b
где m — монадический тип; a и b — обычный тип
S>>>Вот тебе первый признак. Функция возвращает результат. Ни foreach, ни for этим признаком не обладают.
DG>>функция может вернуть пустой результат. DG>>монадическая функция может вернуть пустой результат + монаду S>Что-что? Монаду?
пустой результат + монадический тип
DG>>foreach и for в зависимости от условий может рассматриваться или как первый вариант, или как второй. S>Как первый не может, т.к. кроме возврата пустого результата для чего-то эти конструкции нужны. Второй — даже не понимаю, о чем речь. Загляни в определение монады.
по первому согласен. с точки зрения haskell-я так не пройдет.
значит тогда второй вариант, for/foreach есть функция которая возвращает, например, монадический тип State (http://en.wikipedia.org/wiki/Monad_(functional_programming)#State_monads)
DG>>>>по какому признаку goto в C делает другое? S>>>Он не возвращает результат. Это действительно тупой переход.
DG>>можно считать, что goto возвращает результат блока на который произошел переход, и будет тоже самое, что делает goto в haskell. S>Блок, на который произошел переход ничего возвращать не собирается. Это блок, а не выражение.
каждый statement(если не брать пока ввод/вывод) императивной программы может рассматриваться как функция (vars) => (vars)
слева исходный statement, справа соответствующая функция на псевдокоде
var x = expr(); // vars => vars.concat((x, expr(vars)));
y = expr(); //vars => vars.where(pair => pair.var != y).concat((y, expr(vars)))if(expr())statement1 else statement2; // vars => expr(vars) ? statement1(vars) : statement2(vars)
;// vars => vars
{statement1; statement2; .. statementn;} // vars => statementn(..(statement2(statement1(vars))))while(expr) statement; // while(vars) => expr(vars) ? while(statement(vars)) : vars
для удобства vars можно завернуть в монаду state
DG>>или другими словами, код с goto можно автоматически нарезать на куски от метки до метки, и каждой такой кусок оформить как отдельную функцию (при этом локальные переменные исходного кода перейдут во входные/выходные параметры этих кусков), а дальше каждый goto заменить на вызов соответствующей функции. DG>>и можно строго доказать, что код после такого преобразования будет эквивалентен исходному. S>Ты хочешь доказать, что код с goto можно преобразовать в функциональный? Пожалуйста. Но это будет уже другой код, а не тот, свойства которого ты пытаешься рассмотреть.
это будет код, который делает то же самое, что и исходный. а значит это тот же самый код.
DG>>>>halt/exit является результатом функции, когда в качестве функции берется вся программа. S>>>Если тебе нужен в результате программы int — зачем тебе вся остальная программа? Сделай S>>>int main { return 4; }
DG>>halt/exit используются в основном для возврата результата для вырожденных данных (например, не соответствующих контракту). DG>>полный тип спецификации batch-программы как функции: (string-cin, string) -> (int-result-code, string-cout, error-string-cerr) или (sequence-cin, string) -> (int-result-code, sequence-cout, error-sequence-cerr). возможны и более сложные варианты.
DG>>>>и логику можно построить и на halt/exit, но в качестве функций придется уже брать целые программы, что и делается, например, в unix way. S>>>А почему в unix way не заменяют программы на результат, не задумывался об этом?
DG>>как минимум, потому что такая замена имеет смысл при компиляции (и делать ее может лишь компилятор), а в unix way для связывания программ обычно используются скриптовые языки. S>Я толсто намекаю на то, что если бы от программы нужны были лишь ее коды, то не нужна бы была сама программа.
то, что ты считаешь, что программы возвращают только код результата — это твое частное мнение, какое оно отношение имеет к реальному миру?
Здравствуйте, DarkGray, Вы писали: DG>и я тебя спрашиваю: что тебя убедит, что первое утверждение не всегда верно? (это и есть возможность фальсификации)
Независимая проверка. Берём двух "проверяющих", один проверяет наличие свойства и пишет на бумажке.
Второй пока ничего об этом свойстве не знает, и не знает, выполнялась ли вообще проверка первым.
Теперь он проверяет наличие свойства и обращается к первому — тот показывает бумажку.
Если во всех таких экспериментах результаты проверки первым и вторым совпадают — значит, свойства существуют независимо. Если не совпадают — значит это не свойства в нашем определении.
DG>для появление фальсифицируемости — "существование свойства" вводят: DG> или через изменение поведения объекта: свойство X существует — если поведение объектов со свойством X отличается от поведения объектов без свойства X DG> или через изменение поведения окружения объекта: свойство X существует — если поведение окружения для объектов со свойством X отличается от поведения для объектов без свойства X
Вам придётся сильно потрудиться в поисках объектов, поведение которых зависит от нашего знания о них.
DG>при этом если код не знает, что последовательность обладает свойством упорядоченности по возрастанию, то код не может обеспечить время выполнения за O(1), и упорядоченные последовательности будут обрабатываться за время O(n) и больше (сравнимое с обработкой неупорядоченных последовательностей). DG>или другими словами: код ведет себя так, как будто свойства "упорядоченность по возрастанию" у последовательности не существует.
Ваша ошибка в том, что вы путаете свойства последовательности и свойства кода. Последовательность вместе с её свойствами существует совершенно незаависимо от того, есть вообще какой-то код или нет. А вот разный код имеет разные свойства: один код умеет пользоваться априорной информацией о последовательности, другой — не умеет. Эти свойства кода также являются объективными, и существующими независимо от того, знаете вы про них или нет. И поведение кода, конечно же, будет зависеть от этих свойств.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали:
DG>во-вторых: ты в своих рассуждениях из утверждения: программа X — декларативная, делаешь вывод программа Z — не императивная. а такой вывод можно делать только если доказано, что свойства классов декларативная и императивная не пересекаются.
Не обязательно. Мне достаточно ввести определения следующим образом:
1. Императивная программа — это та, которая сформулирована в терминах последовательного преобразования состояния некоторого вычислителя, причём стадий преобразования состояний — не менее чем три.
2. Декларативная программа — это любая программа, не являющаяся императивной.
DG>конструктивно это можно записать так: было проверено, что вода при нормальных условиях (примеси такие-то, температура такая-то, давление такое-то, сила тяжести такая-то, кол-во воды такое-то и т.д.) имеет такие-то и такие-то свойства и поэтому мы ее относим к классу жидкости. из отнесения к классу жидкости следует, что вода обладает при нормальных условиях такими-то, такими-то свойствами.
Я понимаю, чего вы хотите — каких-то нетривиальных выводов, предсказания одних свойств по другим свойствам.
DG>с ЯП все тоже самое: 40 лет назад нормальные условия были другие — свойства декларативного ЯП и императивного ЯП не пересекались. DG>в частности, декларативную программу можно было выполнить множеством способом, а императивную — только одним.
Это вы пытаетесь придумать своё определение декларативности, которое вам кажется более полезным, чем моё. Однако с вашим определением есть проблема — оно не вводит никакой классификации. Потому, что любую программу можно исполнить бесконечным количеством способов (то есть, есть несложный способ сконструировать произвольное количество эквивалентных ей императивных программ).
DG>для императивной программы был известен пошаговый алгоритм выполнения, для декларативной — нет. DG>прошло 40 лет и нормальные условия поменялись: развились алгоритмы, появились оптимизирующие исполнители и т.д.
С точки зрения внутреннего устройства, т.н. "оптимизирующий исполнитель" всегда устроен более-менее одинаковым образом: он сначала преобразует императивную программу (или её часть) в эквивалентную декларативную программу, а потом выбирает для этой декларативной программы некоторую другую императивную программу. Почитайте, к примеру, Аппеля про то, как устроен оптимизирующий компилятор.
Императивную программу "просто так" преобразовывать нельзя — она диктует поведение вычислителя в подробностях, не оставляющих места для манёвра. Вопрос о том, какие из этих подробностей являются существенными, а какие — нет, и решается при преобразовании в декларативную форму.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.