LINUX.ORG.RU

Чисто-функциональный иммутабельный словарь на js

 , ,


1

1

Коллега сказал, что это не возможно сделать, но:

let assoc = (dict, key, value) => {
  return (getKey) => {
    if (getKey == key)
      return value;
    else if (dict === null)
      return undefined;
    else
      return dict(getKey);
  };
};

let d1 = assoc(null, "a", 1);
let d2 = assoc(d1, "b", 2);

console.log(d2("b"), d2("a"), d1("a"), d1("b"));
// 2, 1, 1, undefined


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

Погодите, вирус анонимуса начал перекидываться на других ЛОРовцев или я упустил какой-то из его смурфов?

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

так шестая версия жеж, сэр!

Ну хорошо, вы с Kilte меня убедили. Я прочитал про arrow functions. Но тем не менее, я правильно понимаю, что ТС попотчевал нас обыкновенным замыканием, которое возвращает объекты из привязанного к нему словаря, только припудренным синтаксическим сахаром? В чём тут заключается достижение?

proud_anon ★★★★★
()

Где у тебя там иммутабельность? Че ты гонишь? Ты можешь напрямую изменить любой словарь, у тебя просто обертка.

Вот пацановская версия

Dictionary = Object.create(Object.prototype)
Dictionary.create=function(dict){
 var o = Object.create(this)
 o.get=function(name){return dict[name]}
 return o
}

dict1 = Dictionary.create({foo: "bar", bar: 1})
dict2 = Dictionary.create({foo: "baz", bar: 2})

console.log(
 dict1.get("foo"), dict1.get("bar"), dict2.get("foo"), dict2.get("bar")
)

//bar 1 baz 2

ЗЫ Думаешь, обмазался говном стрелками, и язык понял? Это тебе не фапе, это Real язык, тут мозг надо включать.

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

Это че, типо, достижение какое-то? Дрочат на какую-то юхету, как дети малые. Кстати, стрелка не является полноценной заменой function

anonymous
()

И ты теги anonimous и наркомания убери, не позорься, то что ты тут накалякал, это банальнейшая фигня. Тебе и до одного и до другого как до китая раком.

anonymous
()

Замыкания являются частным случаем объектов. Это, де-факто, подковерный объект+метод. Забавно наблюдать, как с помощью эамыканий все время пытаются накостылить объекты. Это, видимо, комплекс неполноценности.

anonymous
()

Если ты не патчишь Object и prototype, то какая ж это наркомания? Вон, в комментах анонимус правильную наркоманию развел.

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

У анонимуса Object.prototype не пропатчен, от него просто наследуется. Так все и должно быть. Нет там никакой наркомании, это обычный код.

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

Этот код можно вот так переписать

Dictionary ={
  create: function(dict){
  var o = Object.create(this)
  o.get=function(name){return dict[name]}
  return o 
 }
}

dict1 = Dictionary.create({foo: "bar", bar: 1})
dict2 = Dictionary.create({foo: "baz", bar: 2})

console.log(  dict1.get("foo"), dict1.get("bar"), dict2.get("foo"), dict2.get("bar") )  //bar 1 baz 2
Это одно и то же, это че то меня слегка переклинило спросонья:)

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

Но тем не менее, я правильно понимаю, что ТС попотчевал нас обыкновенным замыканием, которое возвращает объекты из привязанного к нему словаря, только припудренным синтаксическим сахаром?

Нет, тут js словарь/объект не используется, только замыкания.

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

Для ининимов, не смогших в arrow-functions, эквивалент кода на старом js:

var assoc = function(dict, key, value) {
  return function(getKey) {
    if (getKey == key)
      return value;
    else if (dict === null)
      return null;
    else
      return dict(getKey);
  };
};

var d1 = assoc(null, "a", 1);
var d2 = assoc(d1, "b", 2);

console.log(d2("b"), d2("a"), d1("a"), d1("b"));

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

Да, я слегка ошибся, по поводу иммутабельности, не глянул внимательно, но код твой все равно говно, усложнение на пустом месте.

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

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

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

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

А если нужно создать новый словарь, со значениями из старого и с одним новым? Без этого иммутабельный словарь беполезен.

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

Сложна не реализация, она как раз проста как три копейки, ничего сложней ты не осилишь, естественно, а сложна (и неюзабельна) абстракция, которую ты построил. Там постоянно надо голову забивать, что на что замкнуто, это только для даунов годиться.

anonymous
()
Ответ на: комментарий от holuiitipun
Dictionary ={
  create: function(dict){
  var o = Object.create(this)
  o.get=function(name){return dict[name]}
  o.copyWithExtend=function(src){
   var o = {}
   for(var i in dict) {
     if(!dict.hasOwnProperty(i)) break
     o[i] = dict[i]
   }
   for(var j in src){
     if(!src.hasOwnProperty(j)) break
     o[j] = src[j]
   }
   return o
  }
  return o 
 }
}

dict1 = Dictionary.create({foo: "bar", bar: 1})
dict2 = Dictionary.create(dict1.copyWithExtend({baz: 100}))

console.log( 
 dict1.get("foo"), dict1.get("bar"), dict1.get("baz"), dict2.get("foo"), dict2.get("bar"), dict2.get("baz") //bar 1 undefined bar 1 100
)
javaQest
()
Ответ на: комментарий от holuiitipun

Тебе еще раз говорят, простота не в реализации, а в употреблении. Ты один раз написал, а потом просто пользуешься

dict1=Dictionary.create({a: 1})
dict2=Dictionary.create(dict1.copyWithExtend({b: 2}))
Что ты сложного тут нашел? почти естественный язык. По русски, небось, тоже для тебя трудновато лапотать?

В твоем случае, имеет место обратное, реализовать легко, использовать неудобно.

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

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

Да, это бессмысленно, но красиво.

Какую ты там красоту увидел, хз

javaQest
()

А вообще, иммутабельность — это зло. Особенно для таких языков как JS. Это противоречит идеологии Ъ-ООП, которое по определению экстремально динамично и муттабельно. Иммутбаельность сильно ограничивает выразительность языка.

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

Что ты сложного тут нашел? почти естественный язык. По русски, небось, тоже для тебя трудновато лапотать?

Зачем после `copyWithExtend` нужен `Dictionary.create`, у тебя `dict1` и так должен знать, что он `Dictionary`.

И у тебя `copyWithExtend` копирует, а у меня копирования нет. Ну и у тебя там не иммутабельный словарь, а просто обёртка. С таким же успехом можно было бы просто использовать `Object.freeze`.

В твоем случае, имеет место обратное, реализовать легко, использовать неудобно.

Тебе сахарка не хватает?

holuiitipun
() автор топика
Ответ на: комментарий от javaQest

которое по определению экстремально динамично и муттабельно

Вот сами это «экстремально динамично и муттабельно» разрабатывайте (в молодой развивающейся компании с динамичным коллективом, ага), мне такие проблемы не нужны.

Иммутбаельность сильно ограничивает выразительность языка.

Как-то в clojure не страдают.

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

а у меня копирования нет

Каждое вновь созднное замыкание — это то же копирование, вид сбоку.

Остальное я вообще не понял, если хочешь объяснений, изъясняйся внятно.

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

Зачем после `copyWithExtend` нужен `Dictionary.create`, у тебя `dict1` и так должен знать, что он `Dictionary`.

Твое непонимание, видать, идет от ФП головного мозга

Смотри на код с позиций передачи сообщений, и все встанет на свои места

dict2=Dictionary.create(dict1.copyWithExtend({b: 2}))
объясняю пошагово. посылаем dict1 сообщение copyWithExtend({b: 2}), на которое он шлет назад свой экземпляр, расширенный источником. Далее, посылается сообщение create(...) объекту Dictionary, который возвращает экземпляр себя в соответствии с параметром. Далее шлется сообщение объекту global, который создает слот с именем dict2 и связывает его с полученным ответом.

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

Как-то в clojure не страдают.

страдают, только они об этом не знают. Парадокс блоба на лицо. И с каких это пор у нас калоша стала ООП-языком?

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

на которое он шлет назад свой экземпляр, расширенный источником

Точней не свой, а Object.prototype, расшитенный внутренним объектом и источником

//fixed

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

И с каких это пор у нас калоша стала ООП-языком?

С самого начала?

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

И у тебя `copyWithExtend` копирует

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

Dictionary ={
  create: function(dict){
  var o = Object.create(this)
  o.get=function(name){return dict[name]}
  o.selfWith=function(src){
    src.__proto__=dict
    return src
  } 
  return o 
 }
}

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

Можно вызывать Dictionary.create и внутри copyWithExtend.

можно, просто в данном случае не нужно, так как Dictionary.create принимает в качестве параметра обычный объект

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

Это не копирование, конечно, в прямом смысле, но это такое-же разбрасывание памятью, так например, в твоем случае, каждый вызов assoc создает новое окружение вместе с возвращаемой ф-цией. Это в общем случае еще хуже, чем копирование. Кроме всего прочего, ты и ф-цию каждый раз создаешь заново, тогда как в JS часть поведения мы могли бы делегировать(правда не в этом случае). Злоупотребления замыканиями — признак быдляцкого стиля, во всех отношениях. По возможности, надо их избегать.

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

Но тем не менее, я правильно понимаю, что ТС попотчевал нас обыкновенным замыканием, которое возвращает объекты из привязанного к нему словаря, только припудренным синтаксическим сахаром?

да вроде бы.

В чём тут заключается достижение?

ну, человеку понравилось, он поделился, ЖЖ, сэр.

UPD. не, мне нравится. ТС забавно придумал. правда я не уверен что это не велосипед, совсем не занимаюсь яваскриптом, только быдлокодю на ангуляр. вообще яваскрипт не люблю.. но некоторую внутреннюю красоту решения не могу не отметить, дейсвтительно иммутабельный словарь. вроде бы оно самоочевидно, но лично я не пользуюсь таким. а может быть было бы полезно.

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 2)

Кстати, а как насчет наследования? Если ты утверждаешь, что твой быдлофункциональный стиль ничем не уступает ООП, тогда покажи, вот, у тебя есть твой ассок, который, по сути, фабрика, можно считать его классом. Как ты запилишь, допустим, субкласс. Запили субкласс, который будет наследовать поведение твоего assoc, но будет специализирован по чему-нибудь, или, расширен по функционалу.

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

Кстати, а как насчет наследования?

Зачем? Есть же композиция.

Запили субкласс, который будет наследовать поведение твоего assoc, но будет специализирован по чему-нибудь, или, расширен по функционалу.

Сойдёт?

let assocInt = (dict, key, val) => assoc(dict, key, parseInt(val, 10))
holuiitipun
() автор топика
Ответ на: комментарий от holuiitipun

Есть же композиция.

Не думаю, что это замена

Сойдёт?

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

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

Ты не специализировал существующий класс, ты запилил новый класс, то есть, переписал все заново.

Я ничего не переписывал, а только сделал маленькую функцию, использующую оригинальный assoc.

Читать уже научись.

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

Читать уже научись.

Придерживайся стандартного синтаксиса, и люди тебя будут понимать.

а только сделал маленькую функцию, использующую оригинальный assoc.

А с каких это пор у нас процедурщина стала ООП? Это можно конечно назвать субклассом, с натяжечкой, но скорей выглядит как yet_another_function

В моем случае, логично было бы запилить это как просто дополнительный метод


Dictionary ={
 
  create: function(dict){
  var o = Object.create(this)
  o.get=function(name){return dict[name]}
  return o 
 },

 createToInt: function(dict){
  for(var i in dict){
   if(!dict.hasOwnProperty(i)) return this.create(dict)
   dict[i]=parseInt(dict[i], 10)
  }
 return dict
 }

}

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

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

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

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

Придерживайся стандартного синтаксиса, и люди тебя будут понимать.

Это стандартный синтаксис - http://www.ecma-international.org/ecma-262/6.0/

А с каких это пор у нас процедурщина стала ООП? Это можно конечно назвать субклассом, с натяжечкой, но скорей выглядит как yet_another_function

Это просто функция, что тебе тут даст ооп?

В моем случае, логично было бы запилить это как просто дополнительный метод

И таким образом переусложнить интерфейс Dictionary.

К примеру, ты не можешь в твоем случае, создать за раз словарь с 10 полями.

Можно создать функцию, которая сможет это делать, зачем это в assoc?

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