[C] как функцией вернуть функцию?

erotic

 
double GetFunctions(unsigned char fn) (double, double)
{
return f1;
}

Выдает ошибку - error C2091: function returns function.
Как оформить по другому - не знаю. Можно ли вообще функцией возвращать указатель на другую функцию?
Дело в том, что ошибка выдается независимо от того, что содержится в теле функции - не нравится сам факт, что одна функция возвращает другую.

kruzer25

double GetFunctions(unsigned char fn) (double, double)
Эээ... во-первых, что означает "(double,double)"?
А во-вторых - наверное, ей не нравится факт того, что ты возвращаешь какую-то функцию, когда она должна возвращать double...

erotic

Все. Рюхнул. Вот так надо:

double (*GetFunctions(unsigned char fn (double,double)
{
return f2;
}

Где f2 есть
double f2 (double, double);

kruzer25

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

yolki

правильнее так:

typedef double (*PFundouble, double);
PFun GetFunction(int k)
{
...
}

так сделан signal, например. он возвращает тип signal_t и принимает аргумент такого типа..

erotic

Да, так, пожалуй, красивше. Я просто стормозил, как typedef написать.
Пробовал typedef double * (double,double) PFun, но ничего не вышло, и я забил.

rosali

hint: Синтаксис typedef такой же как объявление переменной.

yolki

ещё больший хинт: typedef - это спецификатор, синтаксически эквивалентный "extern", "register", "auto", "static" итп
просто объект, который объявляется при помощи typedef становится не переменной, а типом.

Maurog

еще больше запутал своим "большим" хинтом лучше бы не писал

kruzer25

А я всё понял... что я делаю не так

vook

Си это не Лисп, там функции - второсортные объекты и с ними ничего интересного нельзя сделать

rosali

boost::lambda

lilia_rass

указатель можно, функцию - нет. возврат функции возможет только в языках с lazy evaluation (нестрогих функциональных, например). в остальных функция вычисляется сразу, как только встречается, поэтому вернуть её никак не получится.

erotic

Гы, это-то понятно, но как заковыристо ты выразился =)

ppplva

а в чем разница ?

zzzzzzzzzzz

C не ведает «::»

lilia_rass

разница? указатель - адрес, бишь число, функция - отнюдь не число.
в чём разница между функционалом и оператором над некоторым пространством?

lilia_rass

да вроде нет

ppplva

в чём разница между функционалом и оператором над некоторым пространством?
Это для меня слишком сложно.
В чем функциональная разница ? Что можно сделать с указателем на функцию, что нельзя с функцией ? И вообще, что такое функция ?
функция - отнюдь не число.
Неужели набор чисел ?

lilia_rass

у указателя можно узнать адрес. у функции - нет.
нет, функция - это отображение из одного множества в другое.

maggi14

ты не прав имхо. Указатель - это не адрес, это переменная, хранящая адрес. Функция - условно говоря, это просто адрес. Именно поэтому у указателя адрес взять можно, а у функции нет.

zzzzzzzzzzz

В каком смысле у функции нельзя взять адрес?

ppplva

у указателя можно узнать адрес. у функции - нет.
Указатель - это и есть адрес. Адрес функции.

erotic

Разница... Ну, насколько я понял глубокую мысль 'a, можно вернуть указатель на уже существующую функцию. При этом функция жестко вбита в код и не изменяется на этапе выполнения программы.
В PHP, к примеру, ты можешь создать динамическую функцию string create_function (string args, string code). Эта функция вернет тебе имя для твоей новой функции, по которому и можешь ее вызвать.

rosali

можно вернуть указатель на уже существующую функцию
Ну вобщем все правильно. Указатель на функцию оотличается от "настоящей" функции тем, что указателей на функции в любой программе конечное число, а функций хотелось бы иметь потенциально неограниченное количество. В Си чтобы это выразить всегда приходится вместе c указателем на функцию тоскать с собой (void * то есть контекст, какие-то данные, параметризующие эту функцию. А в "нормальных" языках код вместе с контекстом объединяются вместе и называются просто функцией.
PS. Правда совершенно не ясно какое отношение имеют к этому ленивые вычисления? Просто язык должен поддерживать данные высшего порядка, он не обязан для этого быть ни ленивым (SML) ни даже функциональным (perl, PHP даже вот тут говорят).

ppplva

Первый раз слышу, чтобы замыкание называли "функцией", а функцию - "указателем".

lilia_rass

я и не говорил, что указатель - это адрес.

lilia_rass

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

lilia_rass

А причём замыкание?

ppplva

код вместе с контекстом
или ты другое имел в виду ?

rosali

Первый раз слышу, чтобы замыкание называли "функцией"
Серьезно? Я знаю много языков, в которых "функцией" называется именно замыкание. Ты нет? По-моему ты это написал просто чтобы все знали что ты знаешь слово "замыкание"

rosali

 
Указатель - это не адрес, это переменная
почему это указатель обязан храниться в переменной?
 
some_t * f;
void g(some_t *);
g(f;

Что, "та штука" которую вернула f и "съела" g - это был не указатель что ли? Указатель это как раз таки адрес. Он может храниться в переменной. А может и не храниться.

ppplva

По-моему ты это написал просто чтобы все знали что ты знаешь слово "замыкание"
Незачот по телепатии. Во-первых, не для этого, во-вторых, не знаю (как выяснилось)

lilia_rass

Первый раз просто слышу подобный термин в отношении к программированию - только применительно к анализу знаю

rosali

In programming languages, a closure is an abstraction representing a function, plus the lexical environment (see static scoping) in which the function was created.
http://en.wikipedia.org/wiki/Closure_(programming)

lilia_rass

Благодарю

lilia_rass

В Си чтобы это выразить всегда приходится вместе c указателем на функцию тоскать с собой (void * то есть контекст, какие-то данные, параметризующие эту функцию.
Насколько я понял из статьи про замыкания, в Си как раз не существует контекста функций, собственно поэтому и замыкания не существует. Можно только эмулировать контекст при помощи статических переменных.

erotic

Простите за мою необразованность, но что означает конструкция
 some_t * f;  

lilia_rass

функция возвращает указатель на some_t.

erotic

Бля. До чего же тупым делает меня бессоница

lilia_rass

rosali

Можно только эмулировать контекст при помощи статических переменных.
Так по той ссылке написано? Ну это уже совсем извращение!.. Посмотрим как это делают профессионалы
 
extern int pthread_create (pthread_t *__restrict __threadp,
__const pthread_attr_t *__restrict __attr,
void *(*__start_routine) (void *
void *__restrict __arg) __THROW;

То есть __start_routine + __arg это и есть замыкание.
Или вот пример из "другого мира"

BOOL EnumWindows(
WNDENUMPROC lpEnumFunc,
LPARAM lParam
);

Здесь колбацка lpEnumFunc имеет прототип

BOOL CALLBACK EnumWindowsProc(
HWND hwnd,
LPARAM lParam
);

То есть lpEnumFunc + lParam замыкание в чистом виде.
А qsort, например, в этом смысле "спроектирован" неправильно, не позволяет параметризовать компаратор:

extern void qsort (void *__base, size_t __nmemb, size_t __size,
__compar_fn_t __compar) __nonnull 1, 4;

lilia_rass

То есть lpEnumFunc + lParam замыкание в чистом виде
Ну это-то всё понятно, только это ведь тоже эмуляция. Если я, например, вместо контекста передам NULL, или нагажу в него между вызовами? В контексте, как я понял, смысл именно такой, что никто туда гадить не может, он относится только к замыканию, которому он принадлежит.
Оставить комментарий
Имя или ник:
Комментарий: