Генерируемый код компилятором
От: BOleg Россия  
Дата: 24.08.07 15:50
Оценка:
Привет всем.

Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода).
Дабы получилось нечто вроде:
def tmp=fun(i : ref int):bool
{
//lala
}

Не выйдет! И вот почему. Я залез в код, генерируемый рефлектором, и был сильно удивлён. Я полагал, что указатели на методы или функции — наследники MulticastDelegate.
Оказалось, что на каждую функцию генерируется класс, наследник внутреннего класса Function[n, r] (точнее, есть ещё Function2, Funcrion3 и т.д. — по числу параметров). И указатель на функцию есть ничто иное как экземпляр этого класса-наследника.

То есть код
def tmp=fun(i : int):bool
{
    i>0;
}
Console.WriteLine(tmp(5));


преобразуется в

    private sealed class tmpClass : Function[int, bool]
    {
        public override apply(i : int) : bool
        {
            i>0;
        }
    }
mutable tmp==tmpClass();
Console.WriteLine(tmp.apply(5));


Хотя, на мой взгляд, более логично было бы сделать так:
    private delegate tmpHandler(i : int) : bool;

    private sealed class tmpClass
    {
        public apply(i : int) : bool
        {
            i>0;
        }
    }
mutable tmp==tmpHandler(tmpClass().apply);
Console.WriteLine(tmp.Invoke(5));


Тогда бы можно было и ref-, и, соответственно, out-параметры делать. Да и сами указатели на ф-и выглядели более человечно с точки зрения .NET.

PS: ф-я внутри метода может использовать локальные переменные метода, и тогда генерируется немного больше кода. Но на суть проблемы это не влияет.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Re: Генерируемый код компилятором
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 24.08.07 18:31
Оценка:
Здравствуйте, BOleg, Вы писали:

BO>Привет всем.


Тебе Йодо привет мастер!

BO>Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода).


Зачем тебе нужно это? Чем кортежи не угодили?

BO>Тогда бы можно было и ref-, и, соответственно, out-параметры делать. Да и сами указатели на ф-и выглядели более человечно с точки зрения .NET.


Нету указателей на функцию. Функции в ФЯ — это значения. "Указатель" — это термин, описывающий реализацию, а не саму концепцию.

BO>PS: ф-я внутри метода может использовать локальные переменные метода, и тогда генерируется немного больше кода. Но на суть проблемы это не влияет.


Это называется closure, aka замыкания
... << RSDN@Home 1.2.0 alpha rev. 710>>
Re[2]: Генерируемый код компилятором
От: BOleg Россия  
Дата: 25.08.07 05:22
Оценка:
Здравствуйте, konsoletyper, Вы писали:

K>Тебе Йодо привет мастер!

И тебя приветствую, мой юный подаван!

BO>>Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода).

K>Зачем тебе нужно это? Чем кортежи не угодили?
Странный вопрос довольно-таки. Делать fun(i : int) : (bool, int) вместо fun(i : ref int) : bool. Плюс во втором случае в теле ф-и код будет выглядеть поприятнее.

K>Нету указателей на функцию. Функции в ФЯ — это значения. "Указатель" — это термин, описывающий реализацию, а не саму концепцию.

Принято. Но на суть вопроса это не влияет.
Одно дело — терминология ФП и немерла в частности, другое — код, генерируемый компилятором. Почему бы не сделать класс, отвечающий за значение функции наследником MulticastDelegate?
Тогда бы можно было:
— делать ref-параметры;
— передавать "указатели" на локальные ф-и во внешние сборки, написанные на других языках дотнета.

BO>>PS: ф-я внутри метода может использовать локальные переменные метода, и тогда генерируется немного больше кода. Но на суть проблемы это не влияет.

K>Это называется closure, aka замыкания
Принято.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Re[3]: Генерируемый код компилятором
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 25.08.07 08:45
Оценка: +5
Здравствуйте, BOleg, Вы писали:

K>>Зачем тебе нужно это? Чем кортежи не угодили?

BO>Странный вопрос довольно-таки. Делать fun(i : int) : (bool, int) вместо fun(i : ref int) : bool. Плюс во втором случае в теле ф-и код будет выглядеть поприятнее.

Нет, приятнее код выглядит именно в случае с кортежами.
... << RSDN@Home 1.2.0 alpha rev. 710>>
Re[4]: Генерируемый код компилятором
От: BOleg Россия  
Дата: 25.08.07 17:57
Оценка:
Здравствуйте, konsoletyper, Вы писали:

K>Нет, приятнее код выглядит именно в случае с кортежами.


Ну, я не зна-а-аю...
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Re[5]: Генерируемый код компилятором
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 25.08.07 19:02
Оценка: 1 (1) +1
Здравствуйте, BOleg, Вы писали:

K>>Нет, приятнее код выглядит именно в случае с кортежами.


BO>Ну, я не зна-а-аю...


Понимаешь, в .NET для того есть ref- и out-параметры, чтобы вызвращать из метода несколько значений. Способ, сразу скажу, не универсальный (в том смысле, что ни для чего другого их нельзя юзать) и громоздкий. С другой стороны, кортежи нужны для того же самого, но так же годятся и для других вещей. Да вот хотя бы элементарный пример:

int a;
string b;
foo(p, q, out a, out b);


против

def (a, b) = foo(p, q);


Заодно, можно, например, получить один из параметров без оверхеда. Или тут же передать кортеж функции, совместимой по сигнатуре.
... << RSDN@Home 1.2.0 alpha rev. 710>>
Re[6]: Генерируемый код компилятором
От: BOleg Россия  
Дата: 25.08.07 19:37
Оценка:
Да я только за кортежи. Но так же и за расширение функциональности немерла. В конце концов просто странно зачем обделили локальные ф-и в отличие тех же обычных методов.

Я полностью с тобой согласен в части out-параметров. Их придумали тупо для возвращения нескольких значений и кортежи — достойная им замена.
Но согласись, что если перед тобой ф-я вида foo(/*тут не важно*/): (int*int*int), то поди разберись сходу что означает каждый мембер возвращаемого кортежа? А в случае out-параметров всё ясно из их названий. (Я уже понял, что это противоречит идеологии ФП. Кроме того. out-параметры мне и самому никогда не нравились). Опять же, в таких экстремальных случаях можно заюзать и анонимные классы...

Ну да ладно, сдаюсь. Для лок. ф-и скорее более грамотно использовать вместо ref-параметра кортежи или где возможно замыкание.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Re[7]: Генерируемый код компилятором
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.08.07 08:42
Оценка: 12 (1)
Здравствуйте, BOleg, Вы писали:

BO>Да я только за кортежи. Но так же и за расширение функциональности немерла. В конце концов просто странно зачем обделили локальные ф-и в отличие тех же обычных методов.


Были каке-то трудности в реализация замыканий для яунций с ref/out-парамептрами.

В C# 2.0 вроде бы проблем не возникает. Но Nemerle более сложный язык. В общем, авторам виднее. Можно поднять этот опрос в англоязычной конференции и послушать что скажут авторы. Это что касается технических проблем...


Что же касается использования, то будь моя воля я бы вообще запретил использоание ref/out-параметров, так как они зачастую приводят к неординарным логически ошибкам, замедляют выполнение программ (указатели в середину структру очень болензненны для GC) и делают код плохо читабелным. Если код не является публичным интерфейсом сборки которую нужно использовать в языках отличных от Немерла я бы вообще не использовал ref/out-параметры (даже в методах). Ну, а в локальных функциях сам бог велел использовать ортежи. Это дает более безопасный и более краткий код.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Генерируемый код компилятором
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.08.07 08:42
Оценка:
BO>Хотя, на мой взгляд, более логично было бы сделать так:
BO>
BO>    private delegate tmpHandler(i : int) : bool;

BO>    private sealed class tmpClass
BO>    {
BO>        public apply(i : int) : bool
BO>        {
            i>>0;
BO>        }
BO>    }
BO>mutable tmp==tmpHandler(tmpClass().apply);
BO>Console.WriteLine(tmp.Invoke(5));
BO>


BO>Тогда бы можно было и ref-, и, соответственно, out-параметры делать. Да и сами указатели на ф-и выглядели более человечно с точки зрения .NET.


Делегаты существенно медленнее чем функциональные типы Немерле. К тому же внутри, CLR тоже генерирует невидимые подобия классов для делегатов и анонимных методов. Так что смысла нет.

Проблема ref/out-параметров совсем не в том как реализованы замыкания. Они глубже. Я эти тонкости не помню. Но когда-то авторы объясняли почему это так.

ЗЫ

Запрет на ref/out-параметры в локальных фунциях, я лично, приветствую, так как код с кортежами чище, быстрее и безопаснее.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Генерируемый код компилятором
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.08.07 08:42
Оценка:
Здравствуйте, BOleg, Вы писали:

BO>Тогда бы можно было:

BO>...
BO>- передавать "указатели" на локальные ф-и во внешние сборки, написанные на других языках дотнета.

Функциональные типы и так автоматически приводятся к делегатам. Вот пример:
using System;
using System.Console;
using Nemerle.Utility;

public delegate TestDelegate() : int * string;

module Program
{
  mutable _testDelegate : TestDelegate;
  
  Main() : void
  {
    def testDelegate()
    {
      (1, "Один")
    }
    
    def x : void -> int * string = testDelegate;
    
    _testDelegate = x;
    
    WriteLine(_testDelegate());
    ReadLine();
  }
}


Во внешнем модуле (написанном на Шарпе) такой делегат будет выглядеть как:
public delegate Tuple<int, string> TestDelegate();

и ты без труда сможешь его вызвать. Будет чуть-чуть неудобно в следствии отсуствия в Шарпе средств декомпозиции кортежей, но это не фактальное ограничение.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Генерируемый код компилятором
От: BOleg Россия  
Дата: 27.08.07 08:48
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Делегаты существенно медленнее чем функциональные типы Немерле. К тому же внутри, CLR тоже генерирует невидимые подобия классов для делегатов и анонимных методов. Так что смысла нет.


Да, до этого я уже сам "дошел" на досуге, размышляя над реализацией немерла.
То, что сейчас есть — скорее всего одна из самых быстрых реализаций. Видимо, остальные выводы по поводу ref/out параметров в значительной степени опираются на этот аргумент.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.