Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
for I := 0 to Pred(Length(Self)) dofor I := Length(Self) - 2 downto 0 doFrac(X) = 0Сравнивать double через равенство — это нормально?
for i := 1 to N или for i := N downto 1. В сях естественная индексация с нуля, а циклу for вообще пофиг на индексы: хоть for (i = 0; i < N; i++), хоть for (i = 1; i <= N; i++). Когда же в дельфи индексация с нуля, получается глупость: язык не приспособлен для этого, и появляются странные и неестественные вычитания единиц.Позвольте, но это в паскале или в бейсике, а в Delphi для массивов индексация идет с нуля.А вы какие массивы имеете в виду — статические или динамические? Статические индексируются как пользователь задаст. Динамические да, с нуля.
Когда же в дельфи индексация с нуля, получается глупость: язык не приспособлен для этого, и появляются странные и неестественные вычитания единиц.
Ну и таки в цикле for на уровне машинного кода обычно никаких «ArrayPointer + Index * ElementSize» нет, потому что это тормозное выражение ни для компилятора, ни для машинного кода естественным не является.Мы сейчас про индексацию? Или конкретно вот этот цикл? Вы утверждаете, что индексация массива с нуля — архитектурный недостаток? То есть проблема не в том, что for использует только <= для сравнения, а именно в индексации, да?
Далеко не все преобразования возможно провести во время компиляции.
Вы утверждаете, что индексация массива с нуля — архитектурный недостаток?
Так и так накладные расходы, и чтобы минимизировать накладные расходы и быть ближе к железу — индексация с нуля.На современных процессорах под современные ОС это экономия на спичках. А если учесть, что поправку достаточно вычислить единожды при входе в цикл — так и вовсе.
var
I: Integer;
Buff: array [0..5] of Byte;
begin
for I := 0 to 5 do
Buff[I] := I;
Unit1.pas.43: for I := 0 to 5 do
005DAA67 33D2 xor edx,edx
005DAA69 8BC4 mov eax,esp
Unit1.pas.44: Buff[I] := I;
005DAA6B 8810 mov [eax],dl
005DAA6D 42 inc edx
005DAA6E 40 inc eax
Unit1.pas.43: for I := 0 to 5 do
005DAA6F 83FA06 cmp edx,$06
005DAA72 75F7 jnz $005daa6b
var
I: Integer;
Buff: array [10..15] of Byte;
begin
for I := 10 to 15 do
Buff[I] := I;
Unit1.pas.34: for I := 10 to 15 do
005DAA4F BA0A000000 mov edx,$0000000a
005DAA54 8BC4 mov eax,esp
Unit1.pas.35: Buff[I] := I;
005DAA56 8810 mov [eax],dl
005DAA58 42 inc edx
005DAA59 40 inc eax
Unit1.pas.34: for I := 10 to 15 do
005DAA5A 83FA10 cmp edx,$10
005DAA5D 75F7 jnz $005daa56
for i := Low(X) to High(X)
for i := High(X) downto Low(X)
function ConvertBadChars(const aStr: String): String;
var
i: Integer;
begin
Result := aStr;
for i := 1 to Length(Result) do
case Result[i] of
'«', '»': Result[i] := '"';
'„', '“', '”': Result[i] := '"';
'–', '—': Result[i] := '-'; // тире на знак "минус"
'‹': Result[i] := '<';
'›': Result[i] := '>';
'`', '‘', '’': Result[i] := ''''; // Апострофы разного вида
end;
end;
а вот делать конечного пользователя бетатестером
программа не должна ни при каких обстоятельствах допускать выход за границы диапазона
программы МОГУТ быть написаны без багов только это долго и нудно, а люди ленивые — поэтому имеем что имеем
в хелпе к делфи черным по белому написано что конструкция S[i] небезопасна и оставлена только для обратной совместимостиНе могли бы вы привести цитату про небезопасность и обратную совместимость?
Если потребуется прервать итерации раньше, внутри функции можно возбуждать исключение, а вызов ForEach помещать в блок try.
гораздо проще
т.е. функция вернет случайное «нечто». Я хотел избежать только этого (т.е. чисто архитектурно-проектное соображение при проектировании того класса, т.к. так меньше способов накосячить, забыв присвоить результат).Так а сейчас вам что мешает избежать этого?
dcc32 -W^NO_RETVAL и шанса на ошибку не останется.директивой можно обернуть импорт этих модулей
надо избавляться от этих модулей, разработчики которых не устраняют все предупреждения
-W^NO_RETVAL предупреждение «Return value of function '%s' might be undefined» будет приводить к ошибке компиляции. Того же можно достичь через настройки проекта.-W^^NO_RETVAL т.к. "^" в командной строке трактуется как escape-символ.Все переменные, на которые есть ссылки из анонимного метода, будут «захвачены» компилятором и размещены не на стеке, а в куче
будут «захвачены» компилятором и размещены не на стеке, а в куче, за счет чего обратиться к их значениям из другого потокаА это безопасно?
var a: Integer;
begin
DoSome();
a := 2;
DoSomeWithCallBack( function : Integer;
begin
Result := a;
WriteLn(a);
end;
);
end;IRefToProc = interface
function Execute: Integer;
end;
TNewObject = class(TInterfacedObject, IRefToProc)
a : Integer;
FStaticProcPointer: Pointer;
function Execute: Integer;
end;
у которого есть заполненное поле a = 2У них, кстати, есть крайне бюджетная starter. Не бесплатно, согласен, но и не 1000$ уж никак.
Просто захватывается self
type
TSimple = procedure of Object;
TAnonymous = reference to procedure;
type
TMyObj = class
public
procedure Simple;
end;
function CallMeSimple(const aCallback: TSimple): Integer;
var
i: Integer;
t: Cardinal;
begin
t := GetTickCount;
Result := 1;
while GetTickCount-t < 1000 do
begin
aCallback;
inc(Result);
end;
end;
function CallMeAnonymous(const aCallback: TAnonymous): Integer;
var
i: Integer;
t: Cardinal;
begin
t := GetTickCount;
Result := 1;
while GetTickCount-t < 1000 do
begin
aCallback;
inc(Result);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
vObj: TMyObj;
begin
vObj := TMyObj.Create;
ShowMessage(IntToStr(CallMeSimple(vObj.Simple)));
ShowMessage(IntToStr(CallMeAnonymous(procedure
var
x: Integer;
begin
x := Random(1000);
x := x + 1;
end)));
end;
{ TMyObj }
procedure TMyObj.Simple;
var
x: Integer;
begin
x := Random(1000);
x := x + 1;
end;
procedure MeanAndStdDev;
var
Data: TArray<Double>;
V, Sum, Mean, StdDev: Double;
begin
Data := [1, 1, 3, 5, 5];
Sum := 0;
for V in Data do Sum := Sum + V;
Mean := Sum / Length(Data);
Sum := 0;
for V in Data do Sum := Sqr(V - Mean);
StdDev := Sqrt(Sum / Pred(Length(Data)));
WriteLn('Mean: ', Mean, ' StdDev: ', StdDev); // => Mean: 3.0 StdDev: 2.0
end;
Mean = Data.Reduce((a, b) => a + b); // даже не нужно описывать функцию Sum
StdDev = Sqrt(Data.Map(v => Sqrt(v - Mean)) / Pred(Length(Data)));
Использование анонимных методов в Delphi