Вышла версия 3.8.1. Основное - атрибут [Cache] и модуль PlotWPF. Список изменений - здесь.
{$zerobasedstrings}
это дубль {$string_nullbased+}
? Или последний полностью заменили?
[Cache]
-
Потоко-безопастность. Используйте
System.Collections.Concurrent.ConcurrentDictionary
. -
Сейчас вы по 2 раза ищите ключ, потому что используйте
.TryGetValue
. -
В этой программе кеш не работает:
[Cache] function f1(x: byte): byte; begin Result := x; exit; end;
Потому что
exit
пропускает сохранение результата в кэш.
Из за проблемы с exit
наверное проще и эффективнее будет сгенерировать отдельную программу, а не пытаться лепить костыли. То есть из:
[Cache]
function fib(n: integer): integer :=
if n in 1..2 then 1
else fib(n-1) + fib(n-2);
Лучше генерировать:
function fib(n: integer): integer; forward;
function fib_uncached(n: integer): integer :=
if n in 1..2 then 1
else fib(n-1) + fib(n-2);
var fib_cache := new System.Collections.Concurrent.ConcurrentDictionary<System.Tuple<integer>, integer>;
function fib(n: integer): integer;
begin
var cache_key := Tuple.Create(n);
if fib_cache.TryGetValue(cache_key, Result) then exit;
Result := fib_uncached(n);
fib_cache[cache_key] := Result;
end;
Да и, это падает:
[Cache]
function f1(q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h: byte): byte := 0;
[Cache]
function f2: byte := 0;
Первое потому что Tuple
не может иметь столько аргументов. В идеале вообще бы генерировать свою запись/класс для ключей.
А второе просто запретить бы…
Функции с атрибутом [Cache] должны быть определены глобально
По моему нет смысла запрещать [Cache]
внутри класса/записи.
Возможность стрелять себе в ногу в обоих случаях одинаковая:
var a: byte;
[Cache]
function f1(b: byte): integer := a+b;
begin
a := 2;
f1(1).Println;
a := 3;
f1(1).Println;
end.
type
t1 = class
a: byte;
[Cache]
function f1(b: byte): integer := a+b;
end;
begin
var a := new t1;
a.a := 2;
a.f1(1).Println;
a.a := 3;
a.f1(1).Println;
end.
В то же время внутри классов у меня не редко встречается код вроде:
private static KMP_Cache := new System.Collections.Concurrent.ConcurrentDictionary<string, array of StringIndex>;
public static function KMP_GetHeader(str: string): array of StringIndex;
Где этот атрибут был бы очень кстати.
Лучше сказать - полностью заменили. В Delphi - ровно эта директива компиляции. Старый остался пока, но нигде в документации его нет
Не совсем. Экземплярные методы для того и предназначены чтобы менять данные-члены. Но понимаю, что в некоторых случаях хотелось бы.
Пока так. Потом видимо статически будем искать, нет ли каких замыканий, и если есть, то выводить ошибку. Хотя от функции, возвращающей random, это не спасёт
Да, этот атрибут не потокобезопасный. Надо сказать, что все стеки, очереди и словари не потокобезопасны. Так что не будем делать. Это придётся программировать программисту.
Да, исправили
А как искать единожды?
Да, спасибо - здОрово, это исключение не пришло в голову.
На первых порах можно вообще запретить кешировать с exit
И кстати функции с yield тоже запретить
И помечать атрибутом этим не функции
Я же написал, и в том абзаце, и в примере ниже - используя .TryGetValue
вместо .ContainsKey
.
- Не обязательно, есть ещё случаи с инкапсуляцией вроде:
Searcher = sealed class
private search_target: string;
public constructor(search_target: string) :=
self.search_target := search_target;
public function FindIn(text: string) :=
text.IndexOf(search_target);
end;
- Кроме экземплярных есть ещё статические методы. Им уже точно нечем отличаться от глобальных подпрограмм.
System.Collections.Concurrent.ConcurrentDictionary
потоко-безопасен, чем он не подходит?
А сделать через дополнительную подпрограмму, как я привёл в примере, будет не быстрее, чем бежать всё запрещать?
Из за exit
даже ничего не ломается, только по скорости не идеально эффективно…
Неплохо было бы еще добавить в список изменений по системной библиотеке о поддержке многоязычного вывода в консоль по умолчанию (т.е. про переход на вывод в UTF-8 вместо однобайтовой системной кодировки). Упомянув при этом о необходимости в старых версиях Windows дополнительно настроить консольный шрифт, поддерживающий Юникод (напр., Lucida Console), в настройках cmd.exe
(и для пункта Defaults, и для Properties).
Для некоторых пользователей это может быть полезно.
P.S. Консоль Windows нормально поддерживает только 65K подмножество символов UCS-2/BMP (т.е. до U+FFFF) и простой рендеринг юникод-глифов: корректный вывод составных символов, лигатур и суррогатных пар не гарантируется (особенно до Win10 Creators Update).
Это надо делать и тестировать. А сейчас ошибка. Стандартный ход в таких случаях - делается с ограничениями, а потом ограничения снимаются.
Упомянул - спасибо. Меня честно говоря пугает это. У нас во многих школах еще Windows XP стоит или Windows 7/
Тормознутый потому-что. Лучше пометить поле атрибутом ThreadStatic
Да вроде нормально все у XP c выводом в консоль в этом плане (кроме нюансов, упомянутых выше), сейчас вынужденно сижу на ней. Lucida Console – родной майкрософтовский шрифт, входит в стандартную поставку XP и Win7, на более поздних версиях идет нативный Consolas. При необходимости быстрой перенастройки на многих машинах можно простенький батник написать для замены консольного шрифта у всех профилей.
Я тут другой странный баг сегодня заметил:
- При выводе в UTF-8 во внешнюю консоль все работает нормально (кроме азиатских символов, которых просто нет в стандартном шрифте):
Но при этом в служебном окне вывода внутри IDE у меня в тесте одновременно (!) появилось сразу 3 разных шрифта, два из которых не моноширинные, хотя в настройках редактора у меня дефолтный моноширинный Courier New. Из-за этого выравнивание столбцов теперь иногда не работает и мультиязычный текст выглядит довольно забавно:
Если же выставить в коде принудительно System.Console.OutputEncoding := System.Text.Encoding.GetEncoding(1251)
, то во внешней консоли остаются только русские и простые латинские буквы (как и ожидалось)
а внутри среды шрифт становится правильным (одинаковым и моноширинным), но с самой кодировкой уже возникает какой-то глюк (русские буквы пропадают!). Та же история с любыми другими однобайтовыми кодировками ANSI – остается видна только латиница:
Где-то мешается двойная перекодировка?
Исходник для сравнения отображения шрифтов и кодировок.
unicode test 2.pas (1.2 КБ)
-
Еще было бы неплохо добавить в настройки размера шрифта промежуточные нечетные значения (как минимум 9, 11, 13, 15) – иногда этого очень не хватает для оптимальной настройки редактора при нестандартном dpi, масштабировании или другом шрифте.
-
И чтобы два раза не вставать – желательно отображать в списке только моноширинные шрифты, остальные отфильтровывать (можно по чекбоксу), а то там много лишнего “мусора”.
Про шрифт окна вывода я уже писал, вот ещё 1 пример:
## uses OpenGL;
Mtr2d.Identity.Println;
При чём так нормально:
## uses OpenGL;
''.Println;
Mtr2d.Identity.Println;
Всё же нужно перед каждым exit вставлять пополнение словаря
Сейчас в дистрибутивах используются 2 версии .NET – v4.0 для Windows XP/Vista и v4.7.1 для всего остального под Windows. При этом XP и Vista совместимы с .NET 4.6, а .NET 4.8 поддерживает Win 7 и выше. Есть какие-то объективные причины не включать в дистры более актуальные версии .NET или просто никто не обращал внимание?
Это давняя история. Помнится, XP не поддерживала 4.5 в ранних версиях. 4.5 отличается от 4.0 очень мало.
4.8 тоже мало отличается от 4.7.1. Это можно поменять. Но при замене у массы пользователей могут быть проблемы. Ввиду незначительности этого мы это не делаем.
Следующая остановка - Net Core, но там проблемы с генерацией кода по вине Microsoft.
Исправили - используем .TryGetValue
Решили проблему с exit, оттестировали - проверяйте