LINUX.ORG.RU

Прототипы.

 , ,


1

1

Недавно наткнлуся на любопытную статейку в которой чувачок поругивает js и всячески расхваливает схему, за ее якобы, простоту и выразительность.

Из следующей цитаты, можно понять пафос его «выступления».

Подход создателей Scheme все-таки предпочтительней. Если бы интерпретатор Scheme находился в каждом браузере, можно было бы писать приложения быстрее и проще, чем на JS. Это печальная, но сермяжная правда. Не надо запиливать фичу за фичей, как это сделано в ПХП, Пыхон, Перл, Цпп, и прочих. Ясно же, как божий день. :)

Он приводит там следующую реализацию ООП на схеме:

(define (make-vec2 x y)
    (lambda (message)
       (cond ((eq? message 'x) x)
             ((eq? message 'y) y))))
(define v (make-vec2 1 5))
(v 'x)
1
(v 'y)
5

(define (make-vec2 x y)
    (lambda (message)
       (cond ((eq? message 'x) x)
             ((eq? message 'y) y))))
> (define v (make-vec2 1 5))
> (v 'x)
1
> (v 'y)
5


Далее в комментариях, можно встретить поросячий восторг:

Нда, ситуация «Нихерасе бахнуло...»

видать для кого-то это явилось шокирующим откровением, не иначе.

Не буду спорить о корректности и соответствии его кода концепции, хочу сказать о другом. Почему-то (как я понял из контекста его статьи) профессиональному разработчику на JS, не пришло в голову реализовать то же самое на самом JS?

Я сделал это за него, и получилось то же самое, тока чуть компактней и лаконичней.


mk_vec2=function(x, y){return function(msg){return eval(msg)}}
v=mk_vec2(1, 5)

v("x")// 1
v("y")// 5


mk_proto=function(field, prototype){
	return function(msg){
		try{return eval(msg)}catch(e){return prototype(msg)}
	}
}
f=mk_proto("foobar", v)

f("field")// foobar
f("x")// 1

C-на вопрос, это че тренд такой - обсирать JS и превозносить Лисп?

это че тренд такой - обсирать JS и превозносить Лисп?

Да. Не стоит забывать, что JS - это такой лисп без скобочек, который выстрелил, который в каждом браузере, на каждой, мать её, страничке, у каждого юзера перед носом исполняется. JS всюду.

А вот лисп - вперде.

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

это такой лисп без скобочек

Ну да, но он еще и self, при этом, что существенней, ИМХО:)

anonimous ()

(define (make-vec2 x y)
(lambda (message)
(cond ((eq? message 'x) x)

Что это за нечитаемая параша?

ritsufag ★★★★★ ()

че тренд такой - обсирать JS и превозносить Лисп?

Не прошло и шестидесяти лет, как появилась замена лиспу. Ты это имел в виду? Такие вещи надо доказывать. И не десятком строк.

ziemin ★★ ()

Потому что JS убогое говно, а лисп божественнен. Но автор вброса тоже дурак, ООП вредно и не нужно.

PolarFox ★★★★★ ()
Ответ на: комментарий от ziemin

Не прошло и шестидесяти лет, как появилась замена лиспу. Ты это имел в виду?

Если честно, я имел ввиду другое, схема, по большому счету сливает JS'у в мощи и выразительности, не столько в этом примере, хотя и в нем тоже, сколько вообще. JS - это лисп, родом из 60-х...

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

лисп божественнен
ООП вредно и не нужно

Лисп, во всяком случае распространенные его диалекты, содержит в себе, неявно класс-ооп. Это замыкания.

anonimous ()
f("field")// foobar
f("x")// 1

И тут мне вспомнился супер-петух-киллер. Да епт, уже придумали прототипы и объекты, сколько можно вот так «самовыражаться»? Профита же 0.

KennyMinigun ★★★★★ ()
Ответ на: комментарий от anonimous

Лисп, во всяком случае распространенные его диалекты, содержит в себе, неявно класс-ооп. Это замыкания.

Да ладно. Замыкания — это проявления функциональщины.

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

Замыкания — это проявления функциональщины.

Это обитатели матрицы так думают, хаскель-фанбои. Вот почему полезно иногда

вот так «самовыражаться»

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

Замыкания - это первый шаг к состоянию!

Имхо, это и есть состояние, точнее объекты с состоянием, иногда иммутабельным, да.

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

Это замыкания.

Замыкания с мутабельными переменными, если быть точнее. Сами по себе замыкания к ООП не приводят.

PolarFox ★★★★★ ()
Последнее исправление: PolarFox (всего исправлений: 1)
Ответ на: комментарий от yoghurt

ооп полезно и нужно, дискач!

ООП поощряет усложнение программы путём введения чёрных ящиков (инкапсуляция), которые могут находиться в невалидном состоянии (полиморфизм), у которых неочевидная семантика копирования (полиморфизм), которые очень плохо параллелизуются, усложняют доступ к данным (инкапсуляция), изменение кода в одном месте может ломать код совершенно в другом (наследование).

PolarFox ★★★★★ ()
Ответ на: комментарий от yoghurt

Замыкания - это первый шаг к состоянию!

Хм, точно. Значит императивщина. Но всё равно не ООП.

KennyMinigun ★★★★★ ()
Ответ на: комментарий от PolarFox

А если рассмаиривать замыкания как классы, которые плодят свои экземпляры-объекты, в виде внутренних функций, замкнутых на свой иммутабельный контекст? Это разве не есть элемент ООП?

PS С классовым ООП я на практике не знаком, поэтому могу путатся как в терминологии так и в концепции, прошу меня извинить.

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

ООП поощряет усложнение программы путём введения чёрных ящиков (инкапсуляция)

Неужели мне тебе придется объяснять, что это есть необходимая сложность для дальнейшей гибкости и обеспечения слабой связанности?

в невалидном состоянии (полиморфизм)

wut

у которых неочевидная семантика копирования (полиморфизм)

wut

которые очень плохо параллелизуются

Ну это смотря как писать

усложняют доступ к данным (инкапсуляция)

Разделяют полномочия, прошу не путать.

изменение кода в одном месте может ломать код совершенно в другом (наследование).

Это если LSP нарушать. Сдуру можно и болт сломать, как известно.

А без этого всего неподдерживаемый, нерасширяемый макаронный монстр породится ещё раньше.

Напрашивается соответствующий вывод о том, что все «беды» ООП лишь от неправильного его применения (и неполного понимания, пожалуй).

yoghurt ★★★★★ ()
Ответ на: комментарий от anonimous

Это разве не есть элемент ООП?

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

PolarFox ★★★★★ ()
Ответ на: комментарий от yoghurt

> у которых неочевидная семантика копирования (полиморфизм)

wut

Почему такая сущность как «конструктор копирования» существует в С++? Почему в жабе у немаленькой части классов навелосипежен метод с названием типа copy() или set()?

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

Почему такая сущность как «конструктор копирования» существует в С++?

Ну а как ещё-то?

В плюсах это объясняется нулевой стоимостью плюшек, объект, вернее, программист, его кодящий, должен сам знать, как его копировать. Если сгенерированный компилятором не подходит по ряду причин - только в путь!

Как ты сюда полиморфизм привязал? Пример хотя бы приведи, где бы оно в ногу выстреливало.

За джяву не скажу, не джявист, но в этом моём смолтоке #copy, а так же #deepCopy и #shallowCopy являются базовыми для всех и по-умолчанию реализованы в корне иерархии. Представляют три разных политики копирования. Да, котёнок жив

yoghurt ★★★★★ ()
Последнее исправление: yoghurt (всего исправлений: 1)
Ответ на: комментарий от yoghurt

Представляют три разных политики копирования

В то время как у простой структуры данных вроде

{
    "id" : 8629360,
    "author" : {
      "nick" : "Jaga",
      "stars" : [ true, true ]
    },
    "processedMessage" : "<p>Скрин в студию.</p>",
    "deletable" : false,
    "editable" : false,
    "deleted" : false,
    "postdate" : "2012-12-24T11:44:22.543+0000"
  }

Политика копирования может быть только одна. Данные круче объектов.

(И нет, постинг нового сообщения не есть копирование данных, это постинг нового сообщения).

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

Данные круче объектов.

Объекты — не значения.

У одного бита вообще два состояния, он же не круче всего на свете.

ilammy ★★★ ()

Я так понимаю, вам моска для схемы не хватило.

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

Хуйню какую-то пишете

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

Чё тут дискутировать, конечно нужно

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

Объекты — не значения.

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

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

Что-то тебя не в ту степь совсем понесло. Ясень пень плэйн-данные можно просто копировать, тут и в плюсах все будет ок.

Политика копирования может быть только одна.

Опять же нет, можно скопировать структуру с ссылками на те же данные (shallow), а можно и все целиком (deep). В зависимости от того, что тебе нужно. Shallow copy, кстати, я даже в Си реализую порой для некоторых своих структур данных.

А если объект умнее, например в нем есть ресурсы вроде мьютексов, просто так его уже не скопировать (если вообще допустимо).

Проблематика семантики копирования с участием полиморфизма - вообще в другом. Она возникает, например, в плохо спроектированных иерархиях (или сценариях), когда к нам в КК прилетает скастованная вниз ссылка на объект некоторого супер класса, например. Вот тогда могут начаться казусы.

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

Во первых, это примитивная модель, во вторых - не класс-ооп, а прототипная, в третьих, инкапсуляция и наследование там есть, просто х-во смотрите.

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

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

ilammy ★★★ ()
Ответ на: комментарий от yoghurt

Те проблемы (и соответствующие им решения), которые ты описал, не возникнут, если отказаться от ООП и использовать ссылочные типы данных лишь в специально отведённых для этого местах.

А то получается что всё сложно не потому что проблема сложная, а потому что мы всё сложно решаем.

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

А в четвертых, кстати, это паста, с моими поправочками, не моя модель, внимательно надо читать, прежде чем коментировать.

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

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

наследование там есть

Это где же?

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

Те проблемы (и соответствующие им решения), которые ты описал,

Да я вроде не описывал еще никаких проблем (разве что кроме последнего абзаца), и уж тем более решений

не возникнут, если отказаться от ООП и использовать ссылочные типы данных лишь в специально отведённых для этого местах.

С высоты своего полета не вижу абсолютно никакой связи. Видимо, высоко лечу!

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

любитель замыканий вы наш

Я их не люблю f наследует от v его с-во x.

anonimous ()

реализацию ООП

И тут же FAIL. Лисапедистов нам и с JS хватало. Ещё этих не хватало.

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

Это где же?

Это типа когда я вот так делаю трёхмерный вектор!

(define (make-vec2 x y)
  (lambda (message)
    (case message
      ((x) x)
      ((y) y) ) ) )

(define (make-vec3 x y z)
  (let ((super (make-vec2 x y))
    (lambda (message)
      (case message
        ((z) z)
        (else (super message)) ) ) ) )

А вот так уже и CLOS можно заткнуть за пояс! Мы тоже можем объявлять методы вне класса!

(define (make-vec2 x y)
  (lambda (extern-func)
    (extern-func x y) ) )

(define (vec2-x vec)
  (vec (lambda (x y) x)) )

(define (vec2-y vec)
  (vec (lambda (x y) y)) )

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

Объект нельзя просто так взять и скопировать

Однако в JS практически так оно и делается.

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

Это типа когда я вот так делаю трёхмерный вектор!

Что за говно? В кложуре трёхмерный вектор делается так:

[x y z]
PolarFox ★★★★★ ()
Ответ на: комментарий от PolarFox

Это ООП, чувак.

Если без него, то я тоже могу написать

#(x y z)

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

Да, я там неправильно скопипастил в примере с лиспом, 2 выхлоп, а править уже поздно, см либо пример на js, либо оригинал статьи.

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

Объект нельзя просто так взять и скопировать

Однако в JS практически так оно и делается.

В js вообще нету нормального средства для копирования объектов, сплошные костыли. Так же как еще куча простых задач которые под js решаются костылями. За это js и не любят.

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

Вот так следует читать первую портянку. Как попросить модераторов чтоб подправили? Это можно?

(define (make-vec2 x y)
    (lambda (message)
       (cond ((eq? message 'x) x)
             ((eq? message 'y) y))))
(define v (make-vec2 1 5))
(v 'x)
1
(v 'y)
5


(define (make-proto field prototype)
    (lambda (message)
        (cond ((eq? message 'field) field)
              (else (prototype message)))))
(define f (make-proto "foobar" v))
(f 'field)
"foobar"
(f 'x)
1

anonimous ()

Пишите на всех языках и не ругайтесь :-)

vertexua ★★★★☆ ()
Ответ на: комментарий от TDrive

Да, малясь ошибся, хотел было написать вот так:

ob={one: 1}
ob2=Object.create(ob)
ob2==ob// false
ob2===ob//false
Но там получается вот такая фигня:

ob={one: 1}
ob2=Object.create(ob)
ob2.one // 1
ob2// {}
Это, по ходу не копирование, а наследование. А где это может иметь значение?

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

Object.create создает объект и указывает переданный в параметрах объект в качестве прототипа.

А где это может иметь значение?

Что именно? Прототипы или копирование объектов?

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

Второе. Какой нибудь пример, где нужен именно объект «как есть».

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

Не «как есть», а копия. Если тебе нужно произвести какие то изменения объекта при этом сохранив оригинал.

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

Я, кстати, догадываюсь, смутно, почему такая фигня. Это наверное связано с тем, что в js, только замыкания могут хранить состояния.


mkOb=function(){return {one: 1}}
ob1=mkOb()
ob2=mkOb()

ob1==ob2// false
ob2// { one: 1 }
ob2// { one: 1 }

Т.е. только из замыкания может быть возврат самостоятельного состояния. Или прямой декларацией. Иначе, наверное неаозможно, язык не позволит. Так, я хз, просто предположение.

anonimous ()

автор кода на лиспе, лисп, JS - отстои. Я признаю только ms silverlight скрипты на Pure C

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