Функциональные объекты.

int33h-tm
int33h-tm

Предложение1: функциональные объекты.

В языке С, как и в C++ можно определять указатели на функции, но присвоить одному типу указателя другой невозможно, а самое главное - нельзя получить адрес "сырой функции" в памяти никакими средствами языков(поправьте если я не прав). Так вот, было бы неплохо добавить в эти языки такие возможности, например, вот так:

//Cырые функции

int sumi(int a, int b){
    return a + b;
}

float sumf(float a, float b){
    return a + b;
}

int main(){
    raw_function f() = &sumi; //получение адреса вызова для asm команды call
    int a = 5, b = 8;
    a = f(a, b); //переход по адресу функции
    f = &sumf;
    float c = 0.5, b = 1.2;
    c = f(c, b);
    return 0;
}

//общий алгоритм анализа:
raw_function f(); //не происходит никаких проверок
raw_function f(void, void); //+ контроль числа аргументов
raw_function f(std::string, void) //+ проверка первого типа
raw_function f(std::string, void) -> std::string; //+ проверка возвращаемого значения
//void указывает на вариативность присвоения, т.е. вместо void-а может фигурировать любой тип.
//все проверки делаются на этапе компиляции.
//в случае перегруженных функций надо указывать после имени ее параметры - &sum(int a, int b)
//Объект - функция

...

int main(){
    function f = &sumi;
    ...
}

//общий алгоритм анализа:
//на этапе компиляции для каждой функции которая присваивается f генерится специальный проверяющий метод.
//данный метод занимается жесткой проверкой передаваемых аргуметнов на этапе выполнения, например, с помощью typeid().
//в случае несовпадения бросается исключение...
//если проверка пройдена, делается переход на код функции без всяких дополнительных проверок.
//при присвоении в f записывается указатель на проверяющий метод.

Предложение2: генераторы.

Время добавить в С++ немножечко python-а.

generator natural_numbers(int start_from = 1) -> int{
    int curr = start_from;
    while(true){
        return curr;
        ++curr;
    }
}

Генераторы - особый объект который похож на функцию, при этом ею не являясь.

//Использование

int main(){
    generator g = natural_numbers(); //объявление с инициализацией
    int a = g(); //получение первого значения
}

Ключевое слово static накладывает на генератор следующие ограничения:

  • генератор выделяется до начала работы программы, поэтому не может иметь аргументов.
  • генератор не может вызывать себя рекурсивно.
  • генератор должен быть определен в месте объявления, чтобы исключить случай взаимосвязанных генераторов.
  • все объекты использующие генератор будут разделять его.
  • вызов генератора по имени теперь будет возвращать значение вместо инициализации [b = natural_numbers2();]

P.S. Ограничения static для генераторов можно реализовать и в текущем стандарте с помощью статических переменных.

Предложение3: Над-функции.

Pre.S. В текущем стандарте этот механизм реализуется с помощью специальных классов и то не полно.

Подпрограммы в языке С++ мы умеем вызывать, а что если мы хотим наоборот вставить нашу подпрограмму в некий объемлющий код, как например в циклах for и while. Например, вот так:

int main(){
    int a;
    open("input.txt"){
        fscanf("%d", &a);
        printf("%d", a);
    }
    return 0;
}

Чтож, теперь попробуем представить как должна выглядеть собственно наша над-функция:

over_function open_read(char* name){
    FILE* f = fopen(name, "r");
    code;
    fclose(f);
}

//умышленно не делаю никакик проверок, чтобы не загромаждать код.
//строка code; - обозначение места вставки внутреннего кода.

Отлично. Но как быть с if-конструкцией? Ведь у нее два участка кода. Тоже легко:

//рассмотрим более сложный оператор if из python-a

//cначала определяем
complex over_function:
    if (bool) -> [elif (bool)] [else];
    elif (bool) -> [elif (bool)] [else];

//после if-a может идти либо elif, либо else.
//после elif-а может идти либо elif, либо else.
//квадратные скобки обозначают необязательность дальнейших операторов.(подробнее в форме Бэкуса—Наура)

//теперь реализуем
//Реализация не очень приятная из-за использования ассемблерных вставок, так что опустим
over_function if(bool cond){
    ...
}

over_function elif(bool cond){
    ...
}

over_function else(){
    ...
}

Остается только одна проблема: что делать, когда у над-функции больше одного аргумента... С одной строны, аргументы мы обязаны принимать через [;], а с другой стороны над-функция очень похожа на обычную функцию, поэтому логично принимать аргуметы через [,]. Тут я не знаю, что выбрать.

open("input.txt", "r") {...} //либо так
open("input.txt"; "r") {...} //либо так 
-6
рейтинг
7 комментариев
Михаил Мальцев
> raw_function f(std::string, void) //+ проверка первого типа
> raw_function f(std::string, void) -> std::string; //+ проверка возвращаемого значения
Это невозможно реализовать, т.к. calling convention может сильно зависеть от типа возвращаемого значения.

Про генераторы - см. Coroutines TS open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4649.pdf
Михаил Мальцев
ru.night.beast
Михаил Мальцев> Это невозможно реализовать, т.к. calling convention может сильно зависеть от типа возвращаемого значения.

в виде библиотеки, с рантайм проверками по аналогии с any, возможно.
в язык пихать не нужно.
ru.night.beast
int33h-tm
Михаил Мальцев, да, немного не додумал..., хотя точнее недописал... Понятно, что на стек положить объекты заранее неизвестного размера не лучшая идея, но туда вполне можно положить указатели(типа void*) на сырую дату этих объектов.
int33h-tm
yndx-antoshkka
Подскажите, а RAII с полноценными классами почему вам не подходят?
yndx-antoshkka
int33h-tm
yndx-antoshkka, а как RAII разрешит эту проблему? Эта проблема досталась С++ по наследству от С. RAII, насколько я знаю, помогает решать проблему только для объектов, которыми функции, к сожалению, не являются.
int33h-tm
yndx-antoshkka
int33h-tm, почему

class open_read {
FILE* f;
public:
open_read(char* name) : f(fopen(name, "r")) {}
~open_read() { fclose(f); }
};

...
open_read f("input.txt");
code;

не является заменой вашему предложению с

over_function open_read(char* name){
FILE* f = fopen(name, "r");
code;
fclose(f);
}

?
yndx-antoshkka
int33h-tm
yndx-antoshkka, тогда уж надо f вынести в секцию public... А так в принципе я и писал, что это реализуемо с помощью классов(вроде бы шаблонами функции называются). Проблема в том, что выше...
int33h-tm
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).