В C# нельзя писать функцию в функции, вас это не напрягает?

6yrop

Сабж. В Java кажеться тоже.....

abrek

меня не напрягает

Papazyan

Когда я хочу написать функцию в функции, я беру OCAML, отрываюсь, так сказать, на все 100.

markmsk

А разве где-н можно?

0000

А нафик это надо?

sergei1969

pascal

Chupa

в C

xz_post

В новой спецификации по С# есть что-то подобное
ps. На С/C++ не писал

otvertka07

это плохой стиль, так делать не нужно

abrek

а смысл, без lexical scoping?

Chupa

> без lexical scoping?
как это без?


int c{int d {}; d;}
int e{d;}




0000000b T c
U d
00000000 t d.0
0000001a T e




00000000 <d.0>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 04 sub $0x4,%esp
6: 89 4d fc mov %ecx,0xfffffffc(%ebp)
9: c9 leave
a: c3 ret
0000000b <c>:
b: 55 push %ebp
c: 89 e5 mov %esp,%ebp
e: 83 ec 08 sub $0x8,%esp
11: 89 e9 mov %ebp,%ecx
13: e8 e8 ff ff ff call 0 <d.0>
18: c9 leave
19: c3 ret
0000001a <e>:
1a: 55 push %ebp
1b: 89 e5 mov %esp,%ebp
1d: 83 ec 08 sub $0x8,%esp
20: e8 fc ff ff ff call 21 <e+0x7>
25: c9 leave
26: c3 ret

abrek

не понял
можно продемонстрировать эффект?

Chupa

как продемонстрировать?
main написать и printf'ы расставить?

xz_post

Вот пример на C# - с делегатами, но эффект такой же.
delegate void Inner;
...
Inner i = delegate{
Console.WriteLine("8237489721489");
Console.ReadLine;
};
i; // вызов

abrek

ну хотя бы
я нифига не понял:


typedef int (*Fvoid);
F a (int x)
{
int y = x+1;
int g(void) {
return y;
}
return &g;
}
int b(void)
{
F a1 = a(1);
F a2 = a(2);
return (*a1 + (*a2;
}




.file "t1.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.type g.3,@function
g.3:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
movl %ecx,-4(%ebp)
movl -4(%ebp%eax
addl $-4,%eax
movl (%eax%edx
movl %edx,%eax
jmp .L3
.p2align 47
.L3:
leave
ret
.Lfe1:
.size g.3,.Lfe1-g.3
.align 4
.globl a
.type a,@function
a:
pushl %ebp
movl %esp,%ebp
subl $40,%esp
leal -20(%ebp%edx
leal 3(%edx%eax
andb $252,%al
movl $g.3,%edx
leal 10(%eax%ecx
subl %ecx,%edx
movb $185%eax)
movl %ebp,1(%eax)
movb $233,5(%eax)
movl %edx,6(%eax)
movl 8(%ebp%eax
incl %eax
movl %eax,-4(%ebp)
leal -20(%ebp%eax
leal 3(%eax%edx
andl $-4,%edx
movl %edx,%eax
jmp .L2
.p2align 47
.L2:
leave
ret
.Lfe2:
.size a,.Lfe2-a
.align 4
.globl b
.type b,@function
b:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %esi
pushl %ebx
addl $-12,%esp
pushl $1
call a
addl $16,%esp
movl %eax,%eax
movl %eax,-4(%ebp)
addl $-12,%esp
pushl $2
call a
addl $16,%esp
movl %eax,%eax
movl %eax,-8(%ebp)
movl -4(%ebp%ebx
call *%ebx
movl %eax,%ebx
movl -8(%ebp%esi
call *%esi
movl %eax,%eax
leal (%eax,%ebx%edx
movl %edx,%eax
jmp .L4
.p2align 47
.L4:
leal -24(%ebp%esp
popl %ebx
popl %esi
leave
ret
.Lfe3:
.size b,.Lfe3-b
.ident "GCC: (GNU) 2.95.4 20011002 (Debian prerelease)"

Dasar

Ты уверен, что стандарт C позволяет определять локальные функции?
АФАИК, можно делать только локальные декларации функций.
вот так можно:


bool a
{
bool b;
return b;
}
bool b {return true;}


а вот так уже нельзя:


bool a
{
bool b {return true;}
return b;
}

Elina74

Может я ничего не понимаю, но плиз,
приведите пример, когда это нужно - функция в функции...

Dasar

> приведите пример, когда это нужно - функция в функции...
Примерно для таких случаев.


void Func
{
double goodValue = GetGoodValue;
bool IsGood(Item item)
{
return item.Value > goodValue;
}
Items items = Filter (&IsGood);
}


Т.е. когда у нас есть некий алгоритм, который в качестве настройки хочет функцию.

6yrop

если я правильно понял, твой пример на C# делается через делегаты, они для этого и придуманы (хотя краткости там не будет )

Dasar

> хотя краткости там не будет
А разве не для улучшения этой характеристики изобретаются все новые языки?

6yrop

зато нет указателей

peter1dav

Что то все равно не въехал нафига так?
Что мешает вложенную функцию описать снаружи?

Dasar

> Что мешает вложенную функцию описать снаружи?
Потому что не получается.
Вот попробуй сам это сделать для следующего примера:


void Func(ICriterion criterion)
{
double goodValue = criterion.GetGoodValue;
bool IsGood(Item item)
{
return item.Value > goodValue;
}
Items items = Filter (&IsGood);
Output(items);
}

6yrop

Моя задача разбивается на три процедурки


void f1
{
void f2
{
f3;
}
void f3
{
с1=a*2;
}
double a=3;
f2;
}


переменная a локальная, больше нигде она не нужна. Что новый класс заводить: новое имя, открывать закрывать скобочки -- некрасиво. И функции f2 b f3 больше нигде не нужны.

Dasar

Причем тут указатели?

peter1dav

При желании

return item.Value > goodValue;


Можно и обойти... например передать еще один параметр.. или завернуть все это в класс...
Ведь не всегда следует до такой степени извращаться?

6yrop

у тебя там передается указатель на функцию

abrek

Скорее всего, это гнутые расширения.
Кто-нибудь может разобраться, что происходит в моём примере?

peter1dav

Да нет... завести новый класс пожалуй красивее, чем описывать дикое количество функций внутри...
По большому счету получается ведь тоже самое, только написаное через попу..
В таком коде потом разбираться сложнее, в классе все будет более наглядно.

Dasar

Могу так записать, без указателей, от этого что-то изменилось?


void Func(ICriterion criterion)
{
double goodValue = criterion.GetGoodVallue;
Items items = Filter (delegate bool(Item item){return item.Value > goodValue;});
Output(items);
}

Dasar

> Можно и обойти... например передать еще один параметр.. или завернуть все это в класс...
И чем это поможет?
Filter-то берет только функцию, и ни о каких твоих дополнительных параметрах, и классах ничего не знает.

6yrop

это почему через попу?
а вот какое жопное имя этому классу придумывать? и где его описывать?
эти функции испльзуются толко здесь, тут им и место. Зачем загромождать и так не маленький список классов?

Dasar

> Ведь не всегда следует до такой степени извращаться?
Да, согласен. Вот именно, что не хочется извращаться, и придумывать что-то страшное для решения простенькой задачки.
Хочется иметь простое стандартное решение для стандартных задач

Dasar

> а вот какое жопное имя этому классу придумывать?
f1 + что-нибудь типа utils, hlp и т.д.
> и где его описывать?
рядом с функцией.


private class f1_utils
{
double a;
void f2;
void f3;
void f1;
}
void f1
{
new f1_utils.f1;
}

6yrop

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

6yrop

да и вопрос про быстродействие, каждый раз в куче выделяется память, а это не быстро. К меня эта функция стоит в цикле 1 000 000 итераций.

xz_post

А чем Вам аналогичный код на C# не нравится.

d = (D)delegate{
Console.WriteLine("Second variant");

Inn e = delegate {
Console.WriteLine("345435234");
return 2;
};
e(23); //вызов e
};
d(4); // вызов d

6yrop

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

читать вот такие _utils имена напрягает. Что за фигня имя функции диктуется ограничениями языка.

Dasar

В целом, я с тобой согласен, что фича удобная.
Но в C/C++ есть объективные проблемы с реализацией таких вещей, есть проблемы со стековыми переменными.
Java - как язык, консервативна, и почти не меняется
C# - пока молод, чтобы говорить о том, что будет в нем, а что не будет.
ps
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.

Dasar

> А чем Вам аналогичный код на C# не нравится.
Всем устраивает.
Только такой код можно будет писать не раньше лета.

xz_post

Так ставь сейчас .net framework 1.2 - там вроде бы все уже работает...

Dasar

Сам Framework сейчас alpha, beta или FinalRelease?

Papazyan


Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.

Такие языки есть - Lisp. Что-то не заметно, чтобы он широко распространился среди программистов. Зато С++, где синтаксические конструкции самые ужасающие и труднопонимаемые, распространился дай боже.

Dasar

Могу тебя обрадовать.
Самое большое число программистов - это VB-ешники.
Потом скорее всего идут Java-программисты
И только потом C++.

xz_post

Сам framework непонятно в каком состоянии. К лету обещали бету; финальный релиз возможно будет только в составе Whidbey. Сейчас у меня стоит 1.2 версия от Yukon'a,- все новые фичи C# уже реально работают - сам проверял.

xz_post

Кстати уже есть приличная документация + 2 книжки от Addison Wesley с обзором возможностей ASP.NET 2.0 & ADO.NET

abrek

> Самое большое число программистов - это VB-ешники.
> Потом скорее всего идут Java-программисты
> И только потом C++.
Это не программисты.
Программисты Лисп знают, естественно. И используют, когда нужно.

Dasar

alpha-у использовать для серьезных проектов страшно, потому что в release-е может очень многое поменяться. Тем более, что сейчас вводятся довольно серьезные расширения.
с beta-ми обычно уже получше, но риск все равно остается.

Chupa

> Кто-нибудь может разобраться, что происходит в моём примере?
Псевдокод, думаю, будет понятен, квадратные скобки - обращение по адресу (4 байта
с буквой b - 1 байт, просто регистр - значение.
Функцию b не переводил, там самые обычные вызовы без извратов.
Смысл следующий: на стеке создаётся кусок кода,
который ставит ecx в соответствии с ebp внешней функции и делает jmp.
Точкой входа внутренней функции является этот самый код на стеке.
Вне объемлющей функции данный указатель смысла не имеет.
Кстати, если защищаться от эксплоитов с помощью запрещения
выполнения кода в стеке, то такое работать вообще не будет.


int g {
return [-4(%ecx)]; // parent's y
}
F a (int x) {
// reserve $40 for stack
%eax = %ebp-20)+3) & ~3; // get 20 bytes and round up
%ecx = 10(%eax); // reserve 10 bytes for trampoline
[(%eax)]b = 0xb9; // mov ecx,imm32
[1(%eax)] = %ebp;
[5(%eax)]b = 0xe9; // jmp rel32
[6(%eax)] = (&g - %ecx); // relative g addr
[-4(%ebp)] = [8(%ebp)] + 1; // y = x+1
return %eax = %ebp-20)+3) & ~3; // return trampoline address
}

abrek

Ух, успокоил.
Хоть кложуров нет, а я уж испугался.
> Кстати, если защищаться от эксплоитов с помощью запрещения
> выполнения кода в стеке,
Дурь, кстати

Dasar

> Вне объемлющей функции данный указатель смысла не имеет.
Т.е. вызов такой функции будет убивать стек?
Нда.. весёленькое расширеньеце...

abrek

> Нда.. весёленькое расширеньеце...
Не более и не менее весёлое, чем вполне стандартное:


int *f(int x)
{
int y = x;
return &y;
}

Dasar

Но вот такое тоже умрет, хотя, на первый взгляд, все цивильно.


typedef int (*Fvoid);
void A(F pF)
{
pF;
}
F a (int x)
{
int y = x+1;
int g(void) { return y; }
A(&g);
}

Chupa

почемуйта?

abrek

Почему? Вроде нормально всё.

Dasar

Был не прав. Уже понял в чем фишка.
Оставить комментарий
Имя или ник:
Комментарий: