В C# нельзя писать функцию в функции, вас это не напрягает?
меня не напрягает
Когда я хочу написать функцию в функции, я беру OCAML, отрываюсь, так сказать, на все 100.
А разве где-н можно?
А нафик это надо?
pascal
в C
ps. На С/C++ не писал
это плохой стиль, так делать не нужно
а смысл, без 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
можно продемонстрировать эффект?
main написать и printf'ы расставить?
delegate void Inner;
...
Inner i = delegate{
Console.WriteLine("8237489721489");
Console.ReadLine;
};
i; // вызов
я нифига не понял:
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)"
АФАИК, можно делать только локальные декларации функций.
вот так можно:
bool a
{
bool b;
return b;
}
bool b {return true;}
а вот так уже нельзя:
bool a
{
bool b {return true;}
return b;
}
приведите пример, когда это нужно - функция в функции...
Примерно для таких случаев.
void Func
{
double goodValue = GetGoodValue;
bool IsGood(Item item)
{
return item.Value > goodValue;
}
Items items = Filter (&IsGood);
}
Т.е. когда у нас есть некий алгоритм, который в качестве настройки хочет функцию.
если я правильно понял, твой пример на C# делается через делегаты, они для этого и придуманы (хотя краткости там не будет )
А разве не для улучшения этой характеристики изобретаются все новые языки?
зато нет указателей
Что мешает вложенную функцию описать снаружи?
Потому что не получается.
Вот попробуй сам это сделать для следующего примера:
void Func(ICriterion criterion)
{
double goodValue = criterion.GetGoodValue;
bool IsGood(Item item)
{
return item.Value > goodValue;
}
Items items = Filter (&IsGood);
Output(items);
}
void f1
{
void f2
{
f3;
}
void f3
{
с1=a*2;
}
double a=3;
f2;
}
переменная a локальная, больше нигде она не нужна. Что новый класс заводить: новое имя, открывать закрывать скобочки -- некрасиво. И функции f2 b f3 больше нигде не нужны.
Причем тут указатели?
return item.Value > goodValue;
Можно и обойти... например передать еще один параметр.. или завернуть все это в класс...
Ведь не всегда следует до такой степени извращаться?
у тебя там передается указатель на функцию
Кто-нибудь может разобраться, что происходит в моём примере?
По большому счету получается ведь тоже самое, только написаное через попу..
В таком коде потом разбираться сложнее, в классе все будет более наглядно.
void Func(ICriterion criterion)
{
double goodValue = criterion.GetGoodVallue;
Items items = Filter (delegate bool(Item item){return item.Value > goodValue;});
Output(items);
}
И чем это поможет?
Filter-то берет только функцию, и ни о каких твоих дополнительных параметрах, и классах ничего не знает.
а вот какое жопное имя этому классу придумывать? и где его описывать?
эти функции испльзуются толко здесь, тут им и место. Зачем загромождать и так не маленький список классов?
Да, согласен. Вот именно, что не хочется извращаться, и придумывать что-то страшное для решения простенькой задачки.
Хочется иметь простое стандартное решение для стандартных задач
f1 + что-нибудь типа utils, hlp и т.д.
> и где его описывать?
рядом с функцией.
private class f1_utils
{
double a;
void f2;
void f3;
void f1;
}
void f1
{
new f1_utils.f1;
}
вот вот, этото как раз через то место. И не смотриться как единый блок, а по смыслу это единый блок
да и вопрос про быстродействие, каждый раз в куче выделяется память, а это не быстро. К меня эта функция стоит в цикле 1 000 000 итераций.
d = (D)delegate{
Console.WriteLine("Second variant");
Inn e = delegate {
Console.WriteLine("345435234");
return 2;
};
e(23); //вызов e
};
d(4); // вызов d
В таком коде потом разбираться сложнее
читать вот такие _utils имена напрягает. Что за фигня имя функции диктуется ограничениями языка.
Но в C/C++ есть объективные проблемы с реализацией таких вещей, есть проблемы со стековыми переменными.
Java - как язык, консервативна, и почти не меняется
C# - пока молод, чтобы говорить о том, что будет в нем, а что не будет.
ps
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.
Всем устраивает.
Только такой код можно будет писать не раньше лета.
Так ставь сейчас .net framework 1.2 - там вроде бы все уже работает...
Сам Framework сейчас alpha, beta или FinalRelease?
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.
Такие языки есть - Lisp. Что-то не заметно, чтобы он широко распространился среди программистов. Зато С++, где синтаксические конструкции самые ужасающие и труднопонимаемые, распространился дай боже.
Самое большое число программистов - это VB-ешники.
Потом скорее всего идут Java-программисты
И только потом C++.
Сам framework непонятно в каком состоянии. К лету обещали бету; финальный релиз возможно будет только в составе Whidbey. Сейчас у меня стоит 1.2 версия от Yukon'a,- все новые фичи C# уже реально работают - сам проверял.
Кстати уже есть приличная документация + 2 книжки от Addison Wesley с обзором возможностей ASP.NET 2.0 & ADO.NET
> Потом скорее всего идут Java-программисты
> И только потом C++.
Это не программисты.
Программисты Лисп знают, естественно. И используют, когда нужно.
с beta-ми обычно уже получше, но риск все равно остается.
Псевдокод, думаю, будет понятен, квадратные скобки - обращение по адресу (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
}
Хоть кложуров нет, а я уж испугался.
> Кстати, если защищаться от эксплоитов с помощью запрещения
> выполнения кода в стеке,
Дурь, кстати
Т.е. вызов такой функции будет убивать стек?
Нда.. весёленькое расширеньеце...
Не более и не менее весёлое, чем вполне стандартное:
int *f(int x)
{
int y = x;
return &y;
}
typedef int (*Fvoid);
void A(F pF)
{
pF;
}
F a (int x)
{
int y = x+1;
int g(void) { return y; }
A(&g);
}
почемуйта?
Почему? Вроде нормально всё.
Был не прав. Уже понял в чем фишка.
Оставить комментарий
6yrop
Сабж. В Java кажеться тоже.....