Как я могу делать такие вещи, как Clojure при использовании неизменяемых коллекций в Objective-C?

Я стал несколько пристраститься к использованию неизменяемых коллекций (главным образом в Clojure, который называет их "стойкими структурами данных" ) и хотел бы иметь возможность программировать этот путь в некоторых контекстах в iOS и OS X.

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

Да, вы можете сделать это сейчас, используя неизменяемые экземпляры NSArray и NSDictionary, но становится все более неэффективным, чтобы копировать их, чтобы сделать "измененные" версии, поскольку у вас есть большие и большие коллекции и/или часто вносить изменения: небольшое изменение в большой структуре данных приводит к непропорциональному объему работы.

Я ищу способ включить непреложное программирование данных в Objective-C. Чтобы прояснить, как это может выглядеть, и для некоторых других преимуществ, которые предлагает он, исследования Фила Багвелла, упомянутые в этом вопросе SO, имеют большое значение.

Ответ 1

Я не думаю, что здесь есть ярлык.

Точно так же, как вы подразумеваете, Clojure стойкие структуры данных - это совсем другое дело из классов неизменяемых коллекций, которые предоставляет Cocoa.

Если вы хотите использовать Clojure постоянные структуры данных из Obj-C, единственный способ сделать это - повторно реализовать их в Objective-C. Я понимаю, что многие из них описаны в книге Окасаки, чисто функциональные структуры данных, а в документы Фила Багвелла.

В этом другом ответе есть несколько ссылок: Какова структура данных для наборов Clojure?.

Ответ 2

Пожалуйста, посмотрите эту статью на Riciculous Fish (написано, я считаю, Кори Дорас, инженер команды AppKit, а также создатель оболочки Fish):

Массив: наши массивы не. http://ridiculousfish.com/blog/posts/array.html

Вы уже ответили на свой вопрос:

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

Красота рамки Cocoa - это ее простота, особенно в отношении структур данных. Идея заключается в том, что закулисный код должен определять, как реализовать структуру, а не вы. На практике вам понадобятся только два "типа" структур данных: массивы и словари (или Карты, если вы пришли с других языков). Конечно, вам нужно много "типов" реализаций, но вам действительно нужны только два способа доступа к вашим данным; если вам нужно больше способов, а затем, когда вступают в игру пользовательские классы и композиции.

Что касается вашей заботы об эффективности: не беспокойтесь об этом. В статье Кори (Riciculous Fish) показано, что под капотом Apple уже выполнила ваши условия для эффективности. В конце концов, это всего лишь указатели, как указал Ян Мюррей в комментариях: все подсчитывается и копируется только при необходимости. Наиболее вероятно, что когда вы "копируете" или "mutableCopy" NSArray или NSDictionary, базовые данные на самом деле не копируются. Чтобы увидеть, как это можно реализовать, см. Статью Роб Пайка на языке Go здесь: http://blog.golang.org/slices. Я почти уверен, что Cocoa следует аналогичной схеме, возможно, даже в большей степени.

Кроме того, с появлением блоков Objective-C "теперь все более и более возможно программировать в вариантах функционального стиля à la LISP (например, Clojure). На самом деле, я очень рекомендую это и призываю вас продолжить этот путь. Это может привести к значительно более стабильному, более чистому коду, если это будет сделано правильно.