Это короче, но более скомкано. Можно и в 1 строчку, но сейчас то важно чтоб суть была понятна…
Не понял, что именно “скомкано”? Тип s1 пусть объявляют любители С-образных языков, а тут автовывода вполне достаточно. Ясно, что этот тип - последовательность, поскольку указано Seq. И совершенно ясно, что последовательность кортежей, что видно из записи инициализации. Касательно s2 - я лишь убрал Вашу функцию, потому что она дублирует все ту же Seq, использованную выше.
Если бы… Из за #492 анализатор кода, без явного объявления типа, путает всё:
A объявление типа и кортежи на 1 строчке не работают, поэтому на разные вынес.
Моя более “чистая” . Ну хотя да, в ней сильно то смысла нет.
Программа работает? Работает! Так работает, как задумано? Так!. Ну и чего страдать о каких-то там “анализаторах”? Если не будет что-то работать, тогда и описывать типы явно. Я не понимаю Вашу позицию. Можно работать, на чем есть, а можно ничего не делать и страдать о том, что весь мир - один большой склеп. У Вас попеременно то одна позиция, то другая, смотря кому и по какому поводу пишете . Так и хочется сказать, как тому еврею в бане: “Вы или крестик снимите, или трусы наденьте”.
Может, это имелось в виду:
var s := Seq((1,2),(3,4),(5,6));
var (a,b) := s.UnZipTuple;
Print(a+b);
Наверху правильно поняли. Последовательно элементы кортежей один за другим в новую последовательность. Теперь я пытаюсь переварить то что вверху выложили - обобщенный extensionmethod по точке. В пятой лекции переподготовки вы показываете внешние Where и Select. А то же самое в extensionmethod у вас есть где-нибудь? Если я правильно понимаю, то это уже в объектах? Строго не судите, я только начинаю в этом всем разбираться, приходится некоторую информацию упорядочивать.
Да, тут не все понятно. Понятно что это обобщенный метод (или метод обобщенног типа, не знаю как правильно), но непонятно как такие методы самому писать. Там переменная self это что за такая переменная. И еще, могли бы вы написать то же самое только для внешней функции, т.е. var s2 := s1.SelectMany(t->ToSeq(t)). И еще вопрос, как тут вставлять код?
Код окаймляется строками, содержащими три обратных апострофа подряд (это клавиша под Esc с символами Ё и ~
Self используется в расширениях, подменяя собой первый параметр - тот самый объект, который мы “расширяем”. Это делается для того, чтобы при вызове функции в виде расширения получить доступ к объекту, не указывая его в списке параметров.
// PascalABC.NET 3.3.5, сборка 1662 от 29.04.2018
function Prod(a:array of integer):int64;
begin
Result:=1;
foreach var k in a do Result*=k
end;
function Prod(Self:array of integer):int64; extensionmethod;
begin
Result:=1;
foreach var k in Self do Result*=k
end;
begin
var a:=ArrRandom; a.Println;
Writeln('П1=',Prod(a));
Writeln('П2=',a.Prod)
end.
Большую часть выше написали, но обощение типа это другое. Это описание типа или подпрограммы, работающей с любыми. К примеру:
function f1<T>(a:T):T := a;//функция, возвращающая элемент, который ей дали
//работающая с элементом любого типа
begin
writeln(f1(0));//тут работает с integer
writeln(f1('текст'));//тут работает со string
end.
При описании обобщённой, в данном случае, функции надо поставить в угловых скобочках произвольные названия типов (обычно T
при одном типе и T1,T2,T3,...
при нескольких), которые заменит тем типом, с которым её использовали (тут integer
и string
). Ещё можно ограничивать, какими типами может становится T
, почитайте в справке про where
. А когда вам нужно явно указать с какими типами вы пытаетесь вызвать подпрограмму - надо поставить знак &
(иначе угловые скобочки будет воспринимать как знаки сравнения) и в угловых скобочках указать типы, к примеру:
function f1<T>(a:T):T := a;
begin
writeln(
f1&<word>(0)//тут работает с word, неявно преобразовывая 0 из integer в word
);
end.
Так же можно делать обобщённые типы:
type
t1<T>=class
o: T;
constructor(o: T) :=
self.o := o;
end;
begin
var a := new t1<word>(0);//тут работает с word
var b := new t1<string>('тест');//тут работает со string
end.
А то что вы спрашивали называется extensionmethod
.
Что касается extensionmethod
-ов, у них не редкая практика - использование обобщённого типа когда работаешь с массивом или последовательностью, чтоб эта подпрограмма работала для массива/последовательности с любым типом элементов. К примеру:
procedure p1<T>(self:array of T); extensionmethod := exit;//пустая процедура
begin
var a:array of byte := new byte[10];
a.p1;//тут как self принимает array of byte, заменяя T на byte
var b:array of string := new string[10];
a.p1&<string>;//так же можно явно указывать каким типом заменяется T
end.
Говоря про обобщенные подпрограммы, я бы отметил, что они имеют не такое уж широкое применение. Их удел - разного рода перестановки элементов, их вывод и с определенным шаманством - сравнение значений. Любая арифметика с обобщенными параметрами фактически запрещена, т.е. тривиальную сумму двух параметров обобщенного типа не написать. Паскаль при вызове обобщенной подпрограммы не умеет автоматически приводить даже совместимые типы данных друг к другу (например, integer к int64), поэтому программист обязан заблаговременно озаботиться всеми необходимыми явными приведениями типа. А вот как это сделать с обобщенным параметром - загадка…
Я бы такой “анализатор” кода просто бы отключил - не сильно то он и полезен, по крайней мере на данной стадии развития.
Я понимаю и Вашу позицию, но и @Sun_Serega, всем хочется чтобы анализаторы были адекватными. И помогали вместо того чтобы путать программиста. Он прав в том, что анализатор кода еще сыроват, скажем так. Вы - в том что надо пользоваться тем что есть. Однако, как говорится, если нужен более адекватный компилятор с хорошим анализатором - добро пожаловать в VS. И в C#.
Сродни ситуации, когда человек рассказывает, что у автомобиля “ВАЗ” есть такие-то проблемы, а ему говорят “А если она не так ездит - добро пожаловать в баварский автопром, купите BMW мюнхенской сборки”
А кто сказал что мне не нравится паскаль? Он на много лучше простотой написания кода. А глючные компилятор и анализатор кода - это повод помогать их исправлять (как умеешь, если умеешь. Если нет - стоит научиться, скил не бесполезный), а не сбегать. Кстати на форуме уже когда было сказано, добиться чтоб баг репорт C# услышали разработчики на много сложнее чем у паскаля, поэтому минимум багов ниже. И не говорите что в масштабных проектах багов нет, я вон уже несколько багов студии нашёл.
Какие например?
Ну, к примеру, у меня, в С++, несколько раз было так, что когда я нажимал создать реализацию у для метода класса - реализации приписывало inline
, хотя в описании его нет. А это не давало проекту откомпилироваться. Но это явно не вся ошибка, потому что только это отдельно не воспроизводится. Было ещё парочка ошибок, но я их уже вряд ли вспомню…
Например, 100% CPU при отладке PascalABC.NET. А раньше было хорошо. Где-то после 2012-й все похерили. Жаль, SharpDevelop загнулся и там нельзя отлаживать 64-битные сборки.
анализатор справляется с большинством задач. а все эти обобщенные хренотени имеют для меня лично приоритет ниже плинтуса.