Функциональное программирование: неизменность и т.д.

Я думаю, что вы можете использовать что-то вроде

public static async void ReadAllBytes(string filePath, Action successCallback)
{
    byte[] result;
    using (FileStream stream = File.Open(filePath, FileMode.Open))
    {
        result = new byte[stream.Length];
        await stream.ReadAsync(result, 0, (int)stream.Length);
    }

    // Now pass the byte[] to the callback
    successCallback.Invoke();
}

( Источник )

Чем, я думаю, вы можете использовать его как

TheClass.ReadAllBytes(
    "a/file/path/",

    // What shall be done as soon as you have the byte[]
    (bytes) =>
    {
        // What you want to use the bytes for
    }
);

[1111 ] Я не эксперт по многопоточности, но здесь , а также здесь вы можете найти больше примеров и инструкций для async - await с Unity3d.


В качестве альтернативы вам может быть также интересна новая Unity Jobsystem .

12
задан Community 23 May 2017 в 12:15
поделиться

6 ответов

Ответ на часть 1: Неизменные объекты не делают собой, поддерживают что-либо как "слияние", чтобы позволить результатам обновлений двух потоков быть объединенными. Существует две главных стратегии этого: пессимистическое и оптимистическое. Если Вы пессимистичны, Вы предполагаете, что довольно вероятно, что два потока захотят обновить ту же часть данных одновременно. Таким образом, Вы используете блокировку, такую, что второй поток заморозится вплоть до первого потока, говорит, что это закончилось. Если Вы оптимистичны, что это будет происходить только редко, Вы позволяете обоим потокам работать над своей собственной логической копией данных. Тот, который заканчивает первые предоставления новая версия и другой, должен запуститься снова с начала - только теперь это начинает с результатов изменений первого потока. Этот дорогой перезапуск только иногда происходит, хотя, таким образом, по всему он работает лучше из-за отсутствия блокировки (хотя это только верно, если Ваш оптимизм был хорошо помещен о том, как редко столкновение происходит).

Часть 2: Чистые функциональные языки не сохраняющие состояние действительно не устраняют ту проблему. Даже чистая программа Haskell может иметь состояние, связанное с ним. Различие - то, что код с сохранением информации имеет другой тип возврата. Функция, которая управляет состоянием, выражается как последовательность операций, которые воздействуют на объект, представляющий то состояние. В абсурдном примере рассмотрите файловую систему компьютера. Каждый раз программа изменяет содержание файла (даже единственным байтом), она создала новую "версию" целой файловой системы. И следовательно, новая версия всей вселенной. Но давайте сфокусируемся на файловой системе на данный момент. Любая другая часть программы, которая исследует файловую систему, может теперь быть затронута тем измененным байтом. Таким образом, Haskell говорит, что функции, воздействующие на файловую систему, должны эффективно раздать объект, представляющий версию файловой системы. Затем, потому что это было бы утомительно для ручного контакта с, это выворачивает требование наизнанку и говорит, что, если функция хочет смочь сделать IO, она должна возвратить своего рода контейнерный объект. В контейнере значение, которое функция хочет возвратить. Но контейнер служит доказательством, что функция также или имеет побочные эффекты, или видьте побочные эффекты. Это означает, что система типов Haskell может различать functions-with-side-effects и "чистые" функции. Таким образом, это помогает содержать и управлять с сохранением информации из кода, действительно не устраняя его.

6
ответ дан 2 December 2019 в 06:27
поделиться

"Неизменный" означает точно что: это не изменяется.

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

1
ответ дан 2 December 2019 в 06:27
поделиться
  1. Неизменные структуры данных не похожи на VCS. Думайте о Неизменной структуре данных как о файле только для чтения. Если ее только для чтения, не имеет значения, кто читает, какая часть файла в любой момент времени, все считают корректную информацию.

  2. Тот ответ говорит о http://en.wikipedia.org/wiki/Monad_ (functional_programming)

3
ответ дан 2 December 2019 в 06:27
поделиться

Думайте о Строковом классе в .NET (который является неизменным объектом). При вызове метода на строке Вы получаете новую копию:

String s1 = "there";
String s2 = s1.Insert(0, "hello ");

Console.Writeline("string 1: " + s1);
Console.Writeline("string 2: " + s2);

Это произведет:

строка 1: там

строка 2: привет там

Сравните это поведение с StringBuilder, который имеет в основном ту же сигнатуру метода:

StringBuilder sb  = new StringBuilder("there");
StringBuilder sb2 = sb.Insert(0, "hi ");

Console.WriteLine("sb 1: " + sb.ToString());
Console.WriteLine("sb 2: " + sb2.ToString());

Поскольку StringBuilder изменяем, обе переменные указывают на тот же объект. Вывод будет:

сурьма 1: привет там

сурьма 2: привет там

Так, Вы абсолютно не можете поменять струну, после того как Вы создали ее. s1 всегда будет "там" до конца времени (или до его собравшего "мусор"). Это важно в поточной обработке, потому что можно всегда ступать через каждый символ и печатать его значение, зная, что это будет всегда печатать 'там'. Если бы Вы начали печатать StringBuilder после того, как он был создан, Вы могли бы распечатать первые два символа там и get'th'. Теперь, предположите, что другой поток приходит, реклама вставляет 'привет'. Значение теперь отличается! При печати третьего символа это - пространство от 'привет'. Таким образом, Вы печатаете: 'th там'.

7
ответ дан 2 December 2019 в 06:27
поделиться

Относительно № 2...

Несколько других вещей могут зависеть от новые данные.

Это - то, что пуристы называют "эффектом". Понятие нескольких ссылок на объект на тот же изменяемый объект является сущностью изменяемого состояния и затруднением проблемы. В ООП у Вас может быть объект "a" типа BankAccount, и если Вы читаете a. Баланс или этажерка в разное время можно видеть различные значения. Напротив, в чистом FP, если "a" имеет, вводят BankAccount, то это неизменно и имеет то же значение независимо от времени.

Так как однако BankAccount является, по-видимому, объектом, который мы хотим смоделировать, чье состояние действительно меняется в зависимости от времени, мы были бы в FP кодировать ту информацию в типе. Таким образом, "a" мог бы иметь тип "IO BankAccount" или некоторый другой одноместный тип, который по существу сводится к созданию "a" на самом деле быть функцией, которая берет в качестве входа "предыдущее состояние мира" (или предыдущее состояние банковских процентных ставок, или безотносительно), и возвращает новое состояние мира. Обновление процентной ставки было бы другой операцией с типом, который представляет эффект (например, другая операция IO) и таким образом возвратил бы новый 'мир', и всем, что может зависеть от процентной ставки (мировое состояние) были бы данные с типом, который знает, что это должно взять тот мир в качестве входа.

В результате единственный возможный способ звонить "a. Баланс" или этажерка состоят в том, чтобы использовать код, который, благодаря статическим типам, осуществляет ту некоторую 'всемирную историю, которая получила нас вплоть до сих пор', был правильно установлен вертикально на грани вызова, и независимо от того, что всемирная история является входным влиянием, что заканчивается, мы доберемся от a. Баланс.

Чтение на Монаде состояния может быть полезным для получения смысла того, как Вы моделируете 'совместно использованное изменяемое состояние' просто.

4
ответ дан 2 December 2019 в 06:27
поделиться

В эти дни я думаю, что самый простой способ узнать, как настроить пружинное приложение, это попробовать Spring Roo . Возможно, это не то, что вы в конечном итоге используете при кодировании проекта, но это показывает, как именно настроить веб-приложение Spring MVC.

-121--1845127-

Я был на 1-й презентации Гурона в S 'vale и должен был быть техником Скандинавии, пока другие скандинавские ребята не подошли к скорости. Замечательное время, были проекты в Копенгагене, Стокгольме, Сиднее и различных местах в Европе. Ты знал, что оригинальным изобретателем Гурона был датчанин? Я, очевидно, указываю на это, потому что я сам датчанин и лично знал этого парня.

Это было чудесное время, и я очень скучаю по нему. Как кто-то сказал: Когда вы знаете O * нет другого языка программирования - кроме Assembler, конечно. Сейчас я на пенсии, но очень скучаю по «старым добрым дням!»

-121--3580177-

MVCC ( MultiVersion Concurrency Control )

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

Вкратце : вместо передачи данных по ссылке непосредственно клиентам необходимо добавить еще один уровень по косвенности и передать ссылку по ссылке на данные. ( Ну, на самом деле вы хотели бы иметь по крайней мере еще один уровень косвенности. Но предположим, что структура данных очень проста, как и «массив». )
Поскольку данные являются неизменяемыми, при каждом изменении данных создается копия измененной части ( в случае массива необходимо создать другой массив! ), а также создать другую ссылку на все «измененные» данные.
Таким образом, для всех клиентов, которые использовали первую версию массива, они используют ссылку на первую версию. Каждый клиент, пытающийся получить доступ ко второй версии, использует вторую ссылку.
Структура данных «массива» не очень интересна для этого метода, потому что нельзя разделить данные и вы вынуждены все копировать. Но для более сложных структур данных, таких как деревья, некоторые части структуры данных могут быть «общими», поэтому вы не вынуждены копировать все каждый раз.

Для получения подробной информации, пожалуйста, посмотрите на этот документ: «Структуры чисто функциональных данных» Криса Окасаки.

3
ответ дан 2 December 2019 в 06:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: