LINUX.ORG.RU

баг или фича

 , джон маккарти


1

1

Почитываю на досуге книжку «Интерпретация лиспа и scheme», Кристиана Кеннека, и обнаружил любопытную фразу:

Под влиянием лямбда-исчисления, в честь которого названа специальная форма lambda, LISP-1.0 был сделан динамическим, но вскоре Джон Маккарти осознал,что он ожидал получить от следующего выражения (2 3), а не (1 3):

(let((a 1))
((let((a 2))(lambda(b)(list a b)))
3))
Эта аномалия (неосмелюсь назвать её ошибкой)была исправлена введением новой cпециальной формы function. Она принимала lambda-форму и создавала замыкание...

В связи с этим сразу 2 вопроса:

1) Почему лямбда исчисление здесь ассоциируется с динамическим связыванием, а не лексическим, как сейчас принято считать в мейнстриме?
2) Почему автор считает это аномалией (и это мнение я вижу вообще часто в различных источниках), когда это совершенно нормальное поведение для динамического связывания. What a fucking «аномалия», это что как если бы НЛО прилетело? Неужели Маккарти был настолько туп, что это казалось ему «аномалией»?



Последнее исправление: cetjs2 (всего исправлений: 3)

Ответ на: комментарий от anonymous

Я же сказал - 1в1. Ничего переводить не надо.

Ты не говори. Ты код покажи.

forCe
()
Ответ на: комментарий от anonymous

Ты еще не доказал что это не одно и то же.

А я и не должен. У них разные названия и разные способы применения. Поскольку именно ты утверждаешь, что эти две концепции являются одной, то и бремя доказательства лежит на тебе. Я легко соглашусь с тобой, если ты аргументируешь свою позицию.

forCe
()
Ответ на: комментарий от forCe

Пока ты не докажешь тождественность тайпклассов и интерфейсов, остальное обсуждение будет бессмысленным.

Доказать тождественность каких-либо явлений невозможно, так же как нельзя доказать, что бога нет.

anonymous
()
Ответ на: комментарий от forCe

А я и не должен. У них разные названия и разные способы применения.

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

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

Интерфейс относится к объекту скорее, а вот тайпклассы именно что с типами работают.

К чему относится - это несущественно. Да, есть объектные системы в которых тайпклассы относится к объекту (прототипное ООП), но такие системы редки, обычно же тайпклассы относятся именно к типу (плюсы, жаба, шарп, етц.)

anonymous
()
Ответ на: комментарий от anonymous

У вас за что не возьмись - все несущественно. Совершенно разные механизмы, со своими преимуществами и недостатками. Нет никакого смысла все мешать в одну кучу. И про объекты это не только прототипного ООП касалось. В ООП информация о типе и интерфейсах привязана к объекту. Тайпклассы же не делают ничего подобного, отсюда стирание типа, которое было продемонстрировано выше. Объект же в ООП не забудет, что для него есть лучшая специализация. И если уж ты упомянул кресты, то в них есть и ООП механизмы и шаблоны с концертами, которые ближе тайпклассам

anonymous
()
Ответ на: комментарий от anonymous

Гребанная умная клавиатура. Концептами, конечно, а не концертами

anonymous
()
Ответ на: комментарий от anonymous

Совершенно разные механизмы

Что в них разного кроме названия ты так и не ответил.

И про объекты это не только прототипного ООП касалось. В ООП информация о типе и интерфейсах привязана к объекту.

Нет. Так только в прототипном ООП. В «классическом» ООП она привязана к классу (то есть к типу).

Тайпклассы же не делают ничего подобного, отсюда стирание типа, которое было продемонстрировано выше.

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

И если уж ты упомянул кресты, то в них есть и ООП механизмы и шаблоны с концертами, которые ближе тайпклассам

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

anonymous
()
Ответ на: комментарий от anonymous

Ещё раз, объект типа Int «забыл», что его тип имеет специализацию и была выбрана реализация для Num. В случае интерфейсов этого бы не произошло. Это ещё один пример отличий в семантике. В общем переводи приведенный в теме код... А то не серьёзно.

anonymous
()
Ответ на: комментарий от anonymous

Ещё раз, объект типа Int «забыл», что его тип имеет специализацию и была выбрана реализация для Num.

Нигде он ничего не забыл. Из двух инстансов согласно правилам был выбрана одна конкретная специализация. Именно так и ведут себя интерфейсы.

В случае интерфейсов этого бы не произошло.

Где не произошло? Во всех известных мне ЯП именно так и происходит - согласно правилам выбирается конкретная специализация из набора.

Это ещё один пример отличий в семантике.

Как пример того, что семантика совпадает может быть примером отличий?

anonymous
()
Ответ на: комментарий от anonymous

В общем переводи приведенный в теме код...

Ну ладно:

data Yoba = SharedPtrA | SharedPtrB | SharedPtrIA
make "aaa" = SharedPtrA
make "bbb" = SharedPtrB
make x = SharedPtrIA
только совершенно непонятно при чем тут тайпклассы и ооп. как видно, ни того ни другого этот пример не требует.

anonymous
()
Ответ на: комментарий от anonymous

И это один в один? В ОО-варианте был интерфейс и его реализации. У тебя тут просто один тип. Т.е. ты и тут не смог показать тождественность тайпклассов и интерфейсов.

anonymous
()
Ответ на: комментарий от anonymous

лол. Ты столько времени рожал код, а родил что-то никак не относящееся к теме. В исходном примере IA - интерфейс, а A и B разные типы, реализующие этот интерфейс. Ты пытался сказать, что тайпклассы - это интерфейсы, но не смог переписать этот простой пример использования интерфейсов...

anonymous
()
Ответ на: комментарий от anonymous

И это один в один? В ОО-варианте был интерфейс и его реализации.

В ОО варианте была одна функция. И тут одна функция. Один в один.

Т.е. ты и тут не смог показать тождественность тайпклассов и интерфейсов.

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

То, что это не имеет отношения ни к тайпклассам ни к интерфейсам - уже твои проблемы, не мои. Это же ты пример придумал.

anonymous
()
Ответ на: комментарий от anonymous

лол. Ты столько времени рожал код, а родил что-то никак не относящееся к теме.

К теме не относится _исходный код_. И этО, как я уже выше сказал - не моя проблема, дай пример, который к теме относится будет.

В исходном примере IA - интерфейс, а A и B разные типы, реализующие этот интерфейс.

То говно, что ты написал, в общем случае не будет работать _ни в каком_ статическом ЯП с полноценным полиморфизмом, не важно какое там будет ООП. В плюсах оно работает только из-за того, что шаблоны - это макроподстановка, а не полиморфизм. При чем тут тайпклассы? Если мы сравниваем тайпклассы с интерфейсами - то изволь приводить в пример интерфейсы, а не шаблоны. То, что шаблоны и тайпклассы вещи разные - это и так всем ясно, речь не о шаблонах.

anonymous
()
Ответ на: комментарий от anonymous

Шаблоны там ни при чем вообще. Ты даже код не понял. Вместо shared_ptr подставь A*, B*, IA* соответственно. И не будет никаких шаблонов. Можешь на яву переписать, один в один будет. И код не мой.

anonymous
()
Ответ на: комментарий от anonymous

Какие шаблоны?

IA *make(const string &name)
{
     if (name == "aaa") {
          return new A;
     }
     else (name == "bbb") {
          return new B;
     }
     return NULL;
}
Или на яве:
public class MyFactory {
    public static IA make(String name) {
        if (name == "aaa") {
            return new A();
        }
        else if (name == "bbb") {
            return new B();
        }
        return null;
   }
}

IA - интерфейс, A и B - классы, его реализующие.

anonymous
()
Ответ на: комментарий от anonymous

Шаблоны тут ни при делах. Ты не можешь написать аналог на хаскеле потому, что тайпклассы там работают с типами, а не с объектами.

anonymous
()
Ответ на: комментарий от anonymous

Какие шаблоны?

Теперь нету шаблонов. Но это уже совершенно другой код и теперь он совершенно ничем не отличается от того, что привел я на хаскеле - функция принимает строку и возвращает тот или иной подтип в зависимости от значения аргумента.

IA - интерфейс

Ок, надо немного исправить:

data Yoba = SharedPtrA | SharedPtrB | SharedPtrIA derived (Show)
make "aaa" = SharedPtrA
make "bbb" = SharedPtrB
make :: (Show a) => String -> a
make x = SharedPtrIA
все, код в точности совпадает с оригинальным.

anonymous
()
Ответ на: комментарий от anonymous

Шаблоны тут ни при делах.

В первом примере кода - конечно же при делах.

Ты не можешь написать аналог на хаскеле потому, что тайпклассы там работают с типами, а не с объектами.

Я написал. Никаких проблем не испытал при этом.

anonymous
()
Ответ на: комментарий от anonymous

Что? Это совершенно другой код. IA у тебя по прежнему не интерфейс/тайпкласс.

anonymous
()
Ответ на: комментарий от anonymous

В первом примере кода - конечно же при делах.

Нет.

Я написал.

Нет, ты не написал. В примере один интерфейс(IA) и несколько типов(A и B), реализующих этот интерфейс. В твоем коде просто один тип(алгебраический т.д.), реализующий Show.

anonymous
()
Ответ на: комментарий от anonymous

Нет.

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

В примере один интерфейс(IA) и несколько типов(A и B), реализующих этот интерфейс.

Точно так же в моем примере - один интерфейс (Show) и несколько типов, реализующих этот интерфейс.

anonymous
()
Ответ на: комментарий от anonymous

В твоем коде просто один тип(алгебраический т.д.), реализующий Show.

Все компоненты алгебраического типа, вообще-то, сами являются типами. Там 4 типа в примере - супертип и три подтипа.

anonymous
()
Ответ на: комментарий от anonymous

Все компоненты алгебраического типа, вообще-то, сами являются типами. Там 4 типа в примере - супертип и три подтипа.
data Yoba = SharedPtrA | SharedPtrB | SharedPtrIA derived (Show)

Что-то ты фигню сказал. SharedPtrA, SharedPtrB, и т.д. справа - это не типы, а конструкторы данных. Yoba - конструктор типа, т.е. тип тут один - Yoba. Учи матчасть.

anonymous
()
Ответ на: комментарий от anonymous

Не только Haskell, но и просто абстрактные типы данных. Может это scala мозг съела - там case-классы отдельные типы.

anonymous
()
Ответ на: комментарий от anonymous

а как ты предлагаешь с помощью интерфейсов писать такую штуку в java?

foo :: (Show a, Ord a) => a -> a -> String
foo a b|a < b = show a
       |otherwise = show b

Если в java делать интерфейс, который наследует Show и Ord (что уже дополнительная писанина и неудобство), то такое решение будет работать лишь для новых классов. А как же быть со старыми в этом случае?

anonymous
()
Ответ на: комментарий от anonymous

Что-то ты фигню сказал. SharedPtrA, SharedPtrB, и т.д. справа - это не типы, а конструкторы данных.

Это типы. Учи матчасть.

anonymous
()
Ответ на: комментарий от anonymous

Я-то знаю. При чем тут сказал? Там по-другому все.

anonymous
()
Ответ на: комментарий от anonymous

а как ты предлагаешь с помощью интерфейсов писать такую штуку в java?

А в джаве нельзя потребовать от параметра генерика реализации двух интерфейсов?

anonymous
()
Ответ на: комментарий от anonymous

Нет, это конструкторы алгебраического типа данных. Ты, кстати, можешь проверить свои предположения о типе в интерпретаторе haskell.

anonymous
()
Ответ на: комментарий от anonymous

Даже если принять твою точку зрения, твой пример не соответствует ОО-примеру. Т.к. возвращаешь ты объект конкретного типа, а не интерфейса.

anonymous
()
Ответ на: комментарий от anonymous

В ОО-примере тоже возвращается объект конкретного типа. Объект интерфейса вообще нельзя вернуть - ну банально потому что его нельзя создать.

anonymous
()
Ответ на: комментарий от yyk

Это будет требование третьего интерфейса, не то.

anonymous
()
Ответ на: комментарий от anonymous

Я о типе метода/функции. В ОО-примере функция возвращает объект, реализующий интерфейс. У тебя же жёстко задан тип.

anonymous
()
Ответ на: комментарий от anonymous

Почитай документацию, попробуй в ghci и убедись, что ты не знаешь хаскеля.

anonymous
()
Ответ на: комментарий от anonymous
Prelude> :{
Prelude| data Yoba = SharedPtrA | SharedPtrB | SharedPtrIA
Prelude|             deriving Show
Prelude| :}
Prelude> :{
Prelude| let foo :: Yoba
Prelude|     foo = SharedPtrA
Prelude| :}
Prelude> :t foo
foo :: Yoba
Prelude> :{
Prelude| let foo1 :: SharedPtrA
Prelude|     foo1 = SharedPtrA
Prelude| :}

<interactive>:18:13:
    Not in scope: type constructor or class `SharedPtrA'
    A data constructor of that name is in scope; did you mean -XDataKinds?
Prelude> :t SharedPtrA
SharedPtrA :: Yoba
Prelude> :t Yoba

<interactive>:1:1: Not in scope: data constructor `Yoba'
Prelude>

И чего же оно ругается там, где оно не нужно и наоборот, если по твоему SharedPtrA - тип?

anonymous
()
Ответ на: комментарий от anonymous

Кстати, не derived, а deriving. Ну и и в довесок [url = http://book.realworldhaskell.org/read/defining-types-streamlining-functions.h...

Algebraic data types

The familiar Bool is the simplest common example of a category of type called an algebraic data type. An algebraic data type can have more than one value constructor. 9 comments

-- file: ch03/Bool.hs data Bool = False | True

The Bool type has two value constructors, True and False. Each value constructor is separated in the definition by a | character, which we can read as “or”: we can construct a Bool that has the value True, or the value False. When a type has more than one value constructor, they are usually referred to as alternatives or cases. We can use any one of the alternatives to create a value of that type.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

И чего же оно ругается там, где оно не нужно и наоборот, если по твоему SharedPtrA - тип?

Потому что его нельзя использовать.

anonymous
()
Ответ на: комментарий от anonymous

А, ну пусть будет make :: String -> (exists a. (Show a) => a)

anonymous
()
Ответ на: комментарий от anonymous

Ты читать сообщения не умеешь что ли? это для кого сообщение

A data constructor of that name is in scope;

Ты также еще и английский не знаешь? Я для кого отрывок из известной книги привел?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.