Что тут надо исправить чтобы изменить исходную последовательность? почему так не меняется?
begin
var s := Seq(1, 2, 3); s.Println;
s.ForEach(x -> begin if x = 2 then x := 5; Print(x) end);
Println;
s.Println;//1,2,3
end.
Что тут надо исправить чтобы изменить исходную последовательность? почему так не меняется?
begin
var s := Seq(1, 2, 3); s.Println;
s.ForEach(x -> begin if x = 2 then x := 5; Print(x) end);
Println;
s.Println;//1,2,3
end.
begin
var s := Seq(1, 2, 3); s.Println;
s := s.Select(x -> x = 2 ? 5 : x); s.Println;
end.
А не меняется “так” потому, что у Вас нет операции присваивания для s.
.ForEach
передаёт в вашу лямбду только копию x
, потому что integer
это value
-тип. @RAlex правильно написал, можно через Select
. А ещё будет работать если элементы последовательности будут иметь ссылочный тип:
type
c1=class
b:byte;
constructor(b:byte) :=
self.b := b;
end;
r1=record
b:byte;
constructor(b:byte) :=
self.b := b;
end;
begin
var sc := Seq(new c1(2));
var sr := Seq(new r1(2));
sc.ForEach(procedure(o)->o.b := 3); //Сработает, потому что c1, как любой класс - ссылочный тип
sc.ForEach(procedure(o)->o := new c1(4)); //Не сработает потому что тут мы заменяем ссылку, а не меняем то что находится по этой ссылке
sr.ForEach(procedure(o)->o.b := 3); //Не сработает, потому что r1, как любая запись - value тип
sc.Select(o->o.b).Println;
sr.Select(o->o.b).Println;
end.
Что делает ключевое слово match
?
Это оператор сопоставления:
begin
var o: object := 5;
match o with
real(var r): writeln($'real({r})');
integer(var i): writeln($'integer({i})');
object(var o2): writeln($'object({o2})');
end;
end.
по селекту это понятно, что можно, я то думал что ForEach это же процедура, а последовательность это ссылочный тип, значит должно сработать, а оно видимо еще и в лямбды нужно по ссылке передавать
Ну так в лямбде действие выполняется не над всей последовательностью, а над элементом. Поэтому и зависит от того - по ссылке ли передан элемент.
А как насчет этого?
begin
var s := Seq(1, 2, 3);
var (sum, sum2) := (0, 0);
var p: integer->() := x -> begin x := x*x; sum += x; Print(x) end;
foreach var x in s do
begin
p(x);
sum2 += x
end;
Println; s.Println; //1,2,3
Print(sum, sum2)//14 6
end.
Здесь внешняя переменная sum изменяется лямбдой. Т.е. лямбда захватывает sum по ссылке. Но при этом элементы последовательности внутри ForEach не меняются, изменяются только в лямбде. Т.е. может быть это не столько в лямбде дело, сколько в foreach? В справке написано “Изменение переменной цикла (foreach) внутри тела цикла не меняет элементы контейнера”.
Цикл foreach
это другое:
var s:sequence of byte;
foreach var b in s do
Но экстеншн метод foreach
работает примерно так же. Что касается захвата внешней переменной - это не так работает. Тут sum
объявляет как глобальную, и когда лямбда разворачивается в обычную процедуру - она может без проблем захватить sum
. Никаких ссылок для этого не создаётся.
Ещё одна странность, но на этот раз с указателями. На Паскале в режиме Debug работа с массивом по указателям быстрее, чем по стандартному индексатору, а в Release - наоборот. На C# этот же код работает правильно(в Release и со включённой оптимизацией). Как это вообще понять?
Наверное потому, что вы производите дополнительные преобразования к integer и назад, чтоб работать с указателями. А в Debug вообще всё работает как хочет, по скорости. Просто больше дебага сделали для for чем для работы с указателями))
Тогда предложение к разработчикам. @Admin , @ibond , почему бы не оптимизировать указатели? Сейчас для изменения адреса приходится преобразовывать указатель к int32, затем прибавлять или вычитать требуемое значение, а затем сначала в Pointer и уж только потом в типизированный указатель. Можно ли сделать работу более эффективной? Представлять их как число int32?
Так уже писали про указатели, что это не основная тема, которой стоит заниматься, может, когда руки дойдут и нечем больше будет заняться. В целом правильно, ведь работают они? Да, работают.
Приходит сын к папе, программисту:
- Папа, почему Солнце всходит на востоке, а заходит на Западе?
Папа - ноль эмоций...
- Папа, ну почему Солнце каждый день всходит на востоке, а заходит на Западе?
Папа - опять ноль эмоций...
Сын, нетерпеливо дергая папу за рукав - Папа, папа, ну почему Солнце
каждый день всходит на востоке, а заходит на Западе?
- Солнце ?
- Да
- Всходит на востоке ?
- Да
- Заходит на западе ?
- Да, папа
- Каждый день?
- Да...
- И давно так?
- Ну, я не знаю... Всегда...
- Знаешь что, сынок? Работает - не трогай!!!
Это не наша основная цель. Указатели работают для совместимости. Мы развиваем .NET-составляющую языка, и там много идей и еще больше проблем.
Если бы разработчиков было ну хотя бы 10 человек - ну тогда можно было бы.
Согласен, но разве нет интереса к оптимизации? 2.5 РАЗА, КАРЛ! Тем более, не думаю, что исправление указателей такая уж сложная задача. Есть проблемы и сложнее, корень которых не известен(почему программа на Паскале работает в 2 раза медленнее, чем на C#?). Я конечно извиняюсь, но какой смысл в синтаксическом сахаре, который постоянно вводится в язык, если это всё работает долго? Приведу в пример Питон, на который очень часто ссылаются в новых фичах. В Питоне нереально много специфических фичей, но тем не менее его используют только как обёртку для кода на C++, причём используют его возможности при этом крайне редко. Почему? Да потому что весь сахар(и не только он) работает чрезвычайно долго. Тут даже не вижу смысла докапываться до причин, важен результат. А почему все выбирают C(даже не C++) для реализации объёмных по вычислениям программ, несмотря на его громоздкость? Только лишь потому, что его код получается крайне эффективным. Почему сейчас поливают грязью FreePascal и Lazarus, хотя они гораздо моложе того же C++, но более красивы? А потому что программы получаются неэффективными. Будет обидно, если PascalABC.NET постигнет та же участь что и TurboPascal. Разумеется, всё сказанное выше - ИМХО. Если кого обидел - прошу прощения.
Потому, что они с Фортраном не умеют работать. Либо, просто снобы от программирования, когда шашечки важнее того, чтобы ехать. Для объемных вычислений - только Фортран. “С” там и рядом не стоял по оптимизации и результирующей производительности. Весь ученый и инженерный мир серьезные расчеты делает в Фортране, не доверяя никаким С. И не надо, если что, общеизвестную эту истину пытаться опровергнуть. Конечно, право на собственное мнение Вы имеете. Но и только.
Какой весь? Там скорее только в физике, математике и химии. Там принято использовать этот язык. Если посмотреть, например, на что-то более земное, то вот Вам, например, драйвера устройств и всевозможные низкоуровневые части ОС. Там требуется максимальная производительность. Даже сейчас некоторые части пишутся на Ассемблере. Фортран - устаревший язык, пора бы это признать, несмотря на все его заслуги. Если бы он был перспективным, то его явно развивали бы, а там…
Вы себе же противоречите. Какое отношение перечисленное Вами имеет к “объемным по вычислениям расчетам” ? Не нужно скакать с темы на тему, желая что-то свое доказать - я уже писал об этом Вам.
Драйвера и иные компоненты писали на С - он для этого и создавался - пишут сейчас и будут писать еще достаточно долго. Поскольку С - почти полноценная замена Ассемблеру. И что дальше?
Дело не в объёмах вычислений, а в их эффективности. Для объёмных задач эффективность крайне важна, как и для драйверов.