Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода).
Дабы получилось нечто вроде:
def tmp=fun(i : ref int):bool
{
//lala
}
Не выйдет! И вот почему. Я залез в код, генерируемый рефлектором, и был сильно удивлён. Я полагал, что указатели на методы или функции — наследники MulticastDelegate.
Оказалось, что на каждую функцию генерируется класс, наследник внутреннего класса Function[n, r] (точнее, есть ещё Function2, Funcrion3 и т.д. — по числу параметров). И указатель на функцию есть ничто иное как экземпляр этого класса-наследника.
Тебе Йодо привет мастер!
BO>Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода).
Зачем тебе нужно это? Чем кортежи не угодили?
BO>Тогда бы можно было и ref-, и, соответственно, out-параметры делать. Да и сами указатели на ф-и выглядели более человечно с точки зрения .NET.
Нету указателей на функцию. Функции в ФЯ — это значения. "Указатель" — это термин, описывающий реализацию, а не саму концепцию.
BO>PS: ф-я внутри метода может использовать локальные переменные метода, и тогда генерируется немного больше кода. Но на суть проблемы это не влияет.
Здравствуйте, konsoletyper, Вы писали:
K>Тебе Йодо привет мастер!
И тебя приветствую, мой юный подаван!
BO>>Сначала предыстория. Хотел было написать функцию с ref-параметрами (точно не знаю как они называются, но имею в виду ф-я, объявляемая внутри метода). K>Зачем тебе нужно это? Чем кортежи не угодили?
Странный вопрос довольно-таки. Делать fun(i : int) : (bool, int) вместо fun(i : ref int) : bool. Плюс во втором случае в теле ф-и код будет выглядеть поприятнее.
K>Нету указателей на функцию. Функции в ФЯ — это значения. "Указатель" — это термин, описывающий реализацию, а не саму концепцию.
Принято. Но на суть вопроса это не влияет.
Одно дело — терминология ФП и немерла в частности, другое — код, генерируемый компилятором. Почему бы не сделать класс, отвечающий за значение функции наследником MulticastDelegate?
Тогда бы можно было:
— делать ref-параметры;
— передавать "указатели" на локальные ф-и во внешние сборки, написанные на других языках дотнета.
BO>>PS: ф-я внутри метода может использовать локальные переменные метода, и тогда генерируется немного больше кода. Но на суть проблемы это не влияет. K>Это называется closure, aka замыкания
Принято.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Здравствуйте, BOleg, Вы писали:
K>>Зачем тебе нужно это? Чем кортежи не угодили? BO>Странный вопрос довольно-таки. Делать fun(i : int) : (bool, int) вместо fun(i : ref int) : bool. Плюс во втором случае в теле ф-и код будет выглядеть поприятнее.
Нет, приятнее код выглядит именно в случае с кортежами.
Здравствуйте, BOleg, Вы писали:
K>>Нет, приятнее код выглядит именно в случае с кортежами.
BO>Ну, я не зна-а-аю...
Понимаешь, в .NET для того есть ref- и out-параметры, чтобы вызвращать из метода несколько значений. Способ, сразу скажу, не универсальный (в том смысле, что ни для чего другого их нельзя юзать) и громоздкий. С другой стороны, кортежи нужны для того же самого, но так же годятся и для других вещей. Да вот хотя бы элементарный пример:
int a;
string b;
foo(p, q, out a, out b);
против
def (a, b) = foo(p, q);
Заодно, можно, например, получить один из параметров без оверхеда. Или тут же передать кортеж функции, совместимой по сигнатуре.
Да я только за кортежи. Но так же и за расширение функциональности немерла. В конце концов просто странно зачем обделили локальные ф-и в отличие тех же обычных методов.
Я полностью с тобой согласен в части out-параметров. Их придумали тупо для возвращения нескольких значений и кортежи — достойная им замена.
Но согласись, что если перед тобой ф-я вида foo(/*тут не важно*/): (int*int*int), то поди разберись сходу что означает каждый мембер возвращаемого кортежа? А в случае out-параметров всё ясно из их названий. (Я уже понял, что это противоречит идеологии ФП. Кроме того. out-параметры мне и самому никогда не нравились). Опять же, в таких экстремальных случаях можно заюзать и анонимные классы...
Ну да ладно, сдаюсь. Для лок. ф-и скорее более грамотно использовать вместо ref-параметра кортежи или где возможно замыкание.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.
Здравствуйте, BOleg, Вы писали:
BO>Да я только за кортежи. Но так же и за расширение функциональности немерла. В конце концов просто странно зачем обделили локальные ф-и в отличие тех же обычных методов.
Были каке-то трудности в реализация замыканий для яунций с ref/out-парамептрами.
В C# 2.0 вроде бы проблем не возникает. Но Nemerle более сложный язык. В общем, авторам виднее. Можно поднять этот опрос в англоязычной конференции и послушать что скажут авторы. Это что касается технических проблем...
Что же касается использования, то будь моя воля я бы вообще запретил использоание ref/out-параметров, так как они зачастую приводят к неординарным логически ошибкам, замедляют выполнение программ (указатели в середину структру очень болензненны для GC) и делают код плохо читабелным. Если код не является публичным интерфейсом сборки которую нужно использовать в языках отличных от Немерла я бы вообще не использовал ref/out-параметры (даже в методах). Ну, а в локальных функциях сам бог велел использовать ортежи. Это дает более безопасный и более краткий код.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
BO>Тогда бы можно было и ref-, и, соответственно, out-параметры делать. Да и сами указатели на ф-и выглядели более человечно с точки зрения .NET.
Делегаты существенно медленнее чем функциональные типы Немерле. К тому же внутри, CLR тоже генерирует невидимые подобия классов для делегатов и анонимных методов. Так что смысла нет.
Проблема ref/out-параметров совсем не в том как реализованы замыкания. Они глубже. Я эти тонкости не помню. Но когда-то авторы объясняли почему это так.
ЗЫ
Запрет на ref/out-параметры в локальных фунциях, я лично, приветствую, так как код с кортежами чище, быстрее и безопаснее.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Делегаты существенно медленнее чем функциональные типы Немерле. К тому же внутри, CLR тоже генерирует невидимые подобия классов для делегатов и анонимных методов. Так что смысла нет.
Да, до этого я уже сам "дошел" на досуге, размышляя над реализацией немерла.
То, что сейчас есть — скорее всего одна из самых быстрых реализаций. Видимо, остальные выводы по поводу ref/out параметров в значительной степени опираются на этот аргумент.
В человечишке все должно быть прекрасненьким: и одёжка, и душенка, и мордочка, и мыслишки.