четверг, 19 октября 2017 г.

first:second:tail

first:second:tail

ARRAY VAR A
VAR first
VAR second
VAR tail

A .Split ( first second tail )

first:second:tail

ARRAY VAR A
VAR first
VAR tail

A .Split ( first tail )

first:second:third:tail

ARRAY VAR A
VAR first
VAR second
VAR third
VAR tail

A .Split ( first second third tail )

ToDo. Изменение положения оператора

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

1 2 + =>
1 :`  + 2

Или:

1 2 + =>
1 `  + 2

operator `
 in ValueLeft
 ^ in Lambda
 ^ in ValueRight
 ValueLeft // - значение слева
 ValueRight DO // - разыменовываем значение справа
Lambda DO // - вызываем "лямбду"/"функтор"
;

Реализация sum на Haskell

sum ( [] ) = 0
sum (x:xs) = x + sum (xs)

Concat на Haskell

Как нить так (это сходу и наверняка не совсем верно):
concat' [] = []
concat' ([]:ys) = concat' ys
concat' ((x:xs):ys) = x : concat' (xs:ys)

Ссылка. Чат про Haskell для новичков

https://gitter.im/ruHaskell/novice

среда, 18 октября 2017 г.

Ссылка. Чат про Haskell

https://gitter.im/ruHaskell/forall

Ссылка. О Haskell по-человечески

https://www.ohaskell.guide/init.html

Вопрос

[ [ 1 2 ] [ 3 4 ] ] как на Haskell преобразовать к [ 1 2 3 4 ] ?

Ну или на каком-нибудь другом функциональном языке?

У меня так:

[ [ 1 2 ] [ 3 4 ] ] .Fold

Но у меня же - "на коленке". Хочется понимать как "у людей" устроено.

А [ 1 2 ] .Join [ 3 4 ] как?

А [ 1 2 ] .Map .ToString как?

А [ 1 2 ] .Filter .IsOdd как?

А 0 [ 1 2 ] .For + /*сумма элементов*/ как?

Надеюсь, что смысл примеров понятен. Хотя они конечно "на коленке".

Если они всё же понятны, то может быть кто-то откликнется и расскажет как подобное на настоящих языках можно сделать?

ToDo. Сериализация

Похоже, что элементы опубликованные в скрипты автоматом сериализуются. Типа как в json.

Надо эту тему "покурить".

ToDo

Опубликовать конструкторы от tryFinally и tryExcept.

И ещё ко всем конструкторам сделать "пару" - CreateWithClass/XXXCreateWithClass.

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

Для финальных классов не делать такую пару.

пятница, 13 октября 2017 г.

Массивы

Range: 0 10 // диапазон от 0 до 10
.Filter .IsOdd // отбираем нечётные
.Join ( // объединение
Range: 20 30 // диапазон от 20 до 30
.Filter . IsEven // отбираем чётные
)
.Join // объединение
 [ 31 32 33 ] // массив из элементов 31 32 33
.Join // объединение
ProduceArray: 100 Random // генерируем массив из 100 случайных элементов
.Join // объединение
ProduceArray: 200 ReadIntFromFile: File // читаем 200 элементов из файла
.Join // объединение
[ 100 1024 ] // массив из элементов 100 1024
.Map ( + 1 ) // прибавлям 1
.Map ( * 3 ) // умножаем на 3
.Map .ToString // преобразуем к строке
.Slice 2 // разбиваем массив на пары
.Slice 3 // разбиваем массив на тройки
.Trunc 10 // обрезаем массив до 10 элементов

Array Var A // объявляем переменную типа массив

>>> A // кладём результат вычислений в A

A .Copy // делаем копию массива

>>> A // кладём результат вычислений в A

A .Join A // объединяем A с A

>>> A // кладём результат вычислений в A

A .Fold // преобразуем массив массивов обратно к плоскому списку
.Map .ToInt // преобразуем строки обратно к числам
.RemoveDuplicates // удаляем дубликаты
.Sort // сортируем массив
.Invert // инвертируем массив
.Slice 2 // разбиваем на пары
.Map ( 0 .Swap .For + ) // суммируем пары
.Sort // сортируем
.For // перебираем массив
.Print // печатаем элемент массива

Все вычисления - "ленивые".

Кроме Copy, RemoveDuplicates и Sort.

понедельник, 9 октября 2017 г.

Тут подумалось

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

Можно сравнивать строки, а можно их хеш-функции. Хеш-функции сравнивать проще. Но их сравнение менее "однозначно". Ибо там есть "потеря полноты картины". Но зачастую полнота картины и не нужна. Собственно это тогда и есть аллегория.
"

Рекомендую книгу

https://www.ozon.ru/context/detail/id/35009452/
https://m.livelib.ru/work/1002522273/reviews-abstraktnye-tipy-dannyh-v-yazyke-atpaskal-anatolij-dedkov

четверг, 5 октября 2017 г.

Научился делать "настоящие" immutable объекты

Научился делать "настоящие" immutable объекты.

Через перекрытие NewInstance + VirtualAlloc + VirtualProtect.

Перекрываем NewInstance - там аллоцируем память через VirtualAlloc (там есть тонкости с размером страниц и стратегией выделения памяти).

Потом заполняем поля объекта в конструкторе. И "закрываем" доступ на запись через VirtualProtect + Page_ReadOnly - в AfterCreate.

Потом в FreeInstance (или destroy - тут есть тонкости) опять разрешаем доступ.

Получаем гарантировано неизменяемые объекты.

Например для паттерна flyweight.

Или например для случая:

ConstString = interface
 Function S: PChar;
End;

Ничто не мешает сделать так:

Var Cs: ConstString;

Cs := Factory.GetCs('value');
Cs.S^ := 'xxx';

Т.е "кишки" объекта будут испорчены.

А вот virtualProtect + page_readonly - решают эту проблему.

Просто

Крысу поймал, телевизор "починил". Теперь бы на работе с заковыристой ошибкой разделаться бы.

Компонент разрушается, но из списка компонент родителя - не удаляется.

А под отладчиком - вроде всё хорошо.

Только под Delphi Tokyo. Под Berlin и Delphi 7 - всё хорошо.

Уже разные способы ловли испробовал. Вплоть до VirtualProtect...

Меняю способ распределения памяти под компонент - ошибка уходит.

Не помогает...

Завтра тупо начну логировать убитые компоненты с их адресами и адресами родителей. И trhreadId.

Смущает тот факт, что ошибка под Tokyo есть, а под Berlin - её нет. Обязательно напишу, если чего накопаю. Хотя конечно скорее всего это какая-то наша ошибка.

среда, 4 октября 2017 г.

Иногда случаются проезды по памяти при использовании getMem/freeMem

Иногда случаются проезды по памяти при использовании getMem/freeMem.

Как их искать?

VirtualAlloc/VirtualProtect далеко не всегда помогают. В силу их специфики.

Как быть?

Придумал вот что:

Const
 Filler : array [0..1] of integer = (high(integer), high(integer) -1);

SafeGetMem: Pointer
Var allocated: pointer;
 GetMem(result, SizeOf(pointer) + sizeOf(Filler));
 GetMem(allocated, aSize + SizeOf(pointer));

Move(result^, result^, sizeOf(result));
Move(result + SizeOf(result)^, Filler, SizeOf(filler));

Move(allocated^, result^, SizeOf(result));

Result := allocated + SizeOf(result);

А в safeFreeMem - проверяем все инварианты.

ToDo

Сделать newInstance через getMem + offset + high(pointer).

Возможно так можно будет отследить - кто ездит по памяти.