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

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

pascal
в C 

В новой спецификации по С# есть что-то подобное
ps. На С/C++ не писал
ps. На С/C++ не писал
это плохой стиль, так делать не нужно
а смысл, без lexical scoping?
> без 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'ы расставить?
main написать и printf'ы расставить?
Вот пример на C# - с делегатами, но эффект такой же.
delegate void Inner;
...
Inner i = delegate{
Console.WriteLine("8237489721489");
Console.ReadLine;
};
i; // вызов
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)"
Ты уверен, что стандарт C позволяет определять локальные функции?
АФАИК, можно делать только локальные декларации функций.
вот так можно:
а вот так уже нельзя:
АФАИК, можно делать только локальные декларации функций.
вот так можно:
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);
}
Моя задача разбивается на три процедурки
переменная a локальная, больше нигде она не нужна. Что новый класс заводить: новое имя, открывать закрывать скобочки -- некрасиво. И функции f2 b f3 больше нигде не нужны.
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-то берет только функцию, и ни о каких твоих дополнительных параметрах, и классах ничего не знает.
И чем это поможет?
Filter-то берет только функцию, и ни о каких твоих дополнительных параметрах, и классах ничего не знает.
это почему через попу?
а вот какое жопное имя этому классу придумывать? и где его описывать?
эти функции испльзуются толко здесь, тут им и место. Зачем загромождать и так не маленький список классов?
а вот какое жопное имя этому классу придумывать? и где его описывать?
эти функции испльзуются толко здесь, тут им и место. Зачем загромождать и так не маленький список классов?
> Ведь не всегда следует до такой степени извращаться?
Да, согласен. Вот именно, что не хочется извращаться, и придумывать что-то страшное для решения простенькой задачки.
Хочется иметь простое стандартное решение для стандартных задач
Да, согласен. Вот именно, что не хочется извращаться, и придумывать что-то страшное для решения простенькой задачки.
Хочется иметь простое стандартное решение для стандартных задач
> а вот какое жопное имя этому классу придумывать?
f1 + что-нибудь типа utils, hlp и т.д.
> и где его описывать?
рядом с функцией.
f1 + что-нибудь типа utils, hlp и т.д.
> и где его описывать?
рядом с функцией.
private class f1_utils
{
double a;
void f2;
void f3;
void f1;
}
void f1
{
new f1_utils.f1;
}
вот вот, этото как раз через то место. И не смотриться как единый блок, а по смыслу это единый блок
да и вопрос про быстродействие, каждый раз в куче выделяется память, а это не быстро. К меня эта функция стоит в цикле 1 000 000 итераций.
А чем Вам аналогичный код на C# не нравится.
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
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.
Но в C/C++ есть объективные проблемы с реализацией таких вещей, есть проблемы со стековыми переменными.
Java - как язык, консервативна, и почти не меняется
C# - пока молод, чтобы говорить о том, что будет в нем, а что не будет.
ps
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.
> А чем Вам аналогичный код на C# не нравится.
Всем устраивает.
Только такой код можно будет писать не раньше лета.
Всем устраивает.
Только такой код можно будет писать не раньше лета.
Так ставь сейчас .net framework 1.2 - там вроде бы все уже работает...
Сам Framework сейчас alpha, beta или FinalRelease?
Но есть еще мнения, что язык должен иметь минимум синтаксических конструкций. Это позволяет быстрее языку распространятся среди программистов.
Такие языки есть - Lisp. Что-то не заметно, чтобы он широко распространился среди программистов. Зато С++, где синтаксические конструкции самые ужасающие и труднопонимаемые, распространился дай боже.
Могу тебя обрадовать.
Самое большое число программистов - это VB-ешники.
Потом скорее всего идут Java-программисты
И только потом C++.
Самое большое число программистов - это VB-ешники.
Потом скорее всего идут Java-программисты
И только потом C++.
Сам framework непонятно в каком состоянии. К лету обещали бету; финальный релиз возможно будет только в составе Whidbey. Сейчас у меня стоит 1.2 версия от Yukon'a,- все новые фичи C# уже реально работают - сам проверял.
Кстати уже есть приличная документация + 2 книжки от Addison Wesley с обзором возможностей ASP.NET 2.0 & ADO.NET
> Самое большое число программистов - это VB-ешники.
> Потом скорее всего идут Java-программисты
> И только потом C++.
Это не программисты.
Программисты Лисп знают, естественно. И используют, когда нужно.
> Потом скорее всего идут Java-программисты
> И только потом C++.
Это не программисты.
Программисты Лисп знают, естественно. И используют, когда нужно.
alpha-у использовать для серьезных проектов страшно, потому что в release-е может очень многое поменяться. Тем более, что сейчас вводятся довольно серьезные расширения.
с beta-ми обычно уже получше, но риск все равно остается.
с beta-ми обычно уже получше, но риск все равно остается.
> Кто-нибудь может разобраться, что происходит в моём примере?
Псевдокод, думаю, будет понятен, квадратные скобки - обращение по адресу (4 байта
с буквой b - 1 байт, просто регистр - значение.
Функцию b не переводил, там самые обычные вызовы без извратов.
Смысл следующий: на стеке создаётся кусок кода,
который ставит ecx в соответствии с ebp внешней функции и делает jmp.
Точкой входа внутренней функции является этот самый код на стеке.
Вне объемлющей функции данный указатель смысла не имеет.
Кстати, если защищаться от эксплоитов с помощью запрещения
выполнения кода в стеке, то такое работать вообще не будет.
Псевдокод, думаю, будет понятен, квадратные скобки - обращение по адресу (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 кажеться тоже.....