оператор ?. не работает с option
От: _Claus_  
Дата: 08.12.11 01:53
Оценка:
собственно интуитивно ожидается, что должен работать и возвращать Value, однако же нет.
недоработка или что-то другое?
Re: оператор ?. не работает с option
От: hardcase Пират http://nemerle.org
Дата: 08.12.11 06:18
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>собственно интуитивно ожидается, что должен работать и возвращать Value, однако же нет.


Value возвращает "null coalescing operator": ??.

_C_>недоработка или что-то другое?


Скорее недоработка. Оператор ?. не проверяет на option[T] и nulable[T].
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: оператор ?. не работает с option
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.12.11 19:15
Оценка:
Здравствуйте, hardcase, Вы писали:

_C_>>недоработка или что-то другое?


H>Скорее недоработка. Оператор ?. не проверяет на option[T] и nulable[T].


Зачем там что-то проверять? И в чем недоработка?

Товарищ просто интуитивно что-то понял не так.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: оператор ?. не работает с option
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.12.11 19:27
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>собственно интуитивно ожидается, что должен работать и возвращать Value, однако же нет.

_C_>недоработка или что-то другое?

?. защищает доступ к членам. Откровенно говоря я не предполагал, что кто-то будет использовать его с option[T] для обхода None.

С другой стороны ?? родственный оператор и он работает с option[T]. Так что даже не знаю.

К тому же option[T] — это сам по себе ссылочный тип и члены возвращающие этот тип могут содержать null. Так что если изменить его поведение, то могут быть проблемы в других местах.

В общем, хотелось бы услышать другие мнения. Нужно ли прикручивать поддержку option[T] к "?.", и что при этом делать с проверкой на null самого члена типа option[T]?

ЗЫ

Чем больше думаю над option[T], тем больше понимаю, что надо было его структурой делать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: оператор ?. не работает с option
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.12.11 19:27
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>собственно интуитивно ожидается, что должен работать и возвращать Value, однако же нет.

_C_>недоработка или что-то другое?

Да. Забыл добавить. Ты можешь использовать метод WithDefault. Он делает ровно что тебе нужно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: оператор ?. не работает с option
От: _Claus_  
Дата: 09.12.11 12:11
Оценка:
VD>В общем, хотелось бы услышать другие мнения. Нужно ли прикручивать поддержку option[T] к "?.", и что при этом делать с проверкой на null самого члена типа option[T]?

VD>ЗЫ


VD>Чем больше думаю над option[T], тем больше понимаю, что надо было его структурой делать.


хотел вот именно это все сразу написать, но потом подумал, что это как бы очевидно и так, и не стоит.
но ессно option[T] должна быть структурой по реализации, даже если ее удобно показывать как вариант.
иначе накладные расходы и странности в использовании.
соответственно и ?. должен вести себя предсказуемо.
Re[2]: оператор ?. не работает с option
От: hardcase Пират http://nemerle.org
Дата: 10.12.11 06:10
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Да. Забыл добавить. Ты можешь использовать метод WithDefault. Он делает ровно что тебе нужно.


Это несовсем верно. У ?. ленивая семантика, тогда как у WithDefault — энергичная.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: оператор ?. не работает с option
От: catbert  
Дата: 11.12.11 10:10
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Это несовсем верно. У ?. ленивая семантика, тогда как у WithDefault — энергичная.


Это как? Если я передам a?.b в метод, оно не будет вычисляться пока аргумент не понадобится?
Re[4]: оператор ?. не работает с option
От: hardcase Пират http://nemerle.org
Дата: 11.12.11 11:34
Оценка:
Здравствуйте, catbert, Вы писали:

C>Здравствуйте, hardcase, Вы писали:


H>>Это несовсем верно. У ?. ленивая семантика, тогда как у WithDefault — энергичная.


C>Это как? Если я передам a?.b в метод, оно не будет вычисляться пока аргумент не понадобится?


Речь идет не о передачи значения всего выражения, но о вычислении правого аргумента. Праый аргумент операторов ?. и ?? вычисляется лишь при условии.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: оператор ?. не работает с option
От: BogdanMart Украина  
Дата: 11.12.11 23:32
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>но ессно option[T] должна быть структурой по реализации, даже если ее удобно показывать как вариант.


По моему надо с любым вариантом сделать что то подобное -- запретить любым вариантам принимать значение null.

В хаскеле, например, Алгебраические типы (читай варианты) по поределению не могут быть null, собственно и понятия такого как null там нет.
Но у нас есть пережиток .NET'a как NULL.

Ну вообще исключать null из языка -- гемор в использовании, но в случаи с вариантами null не нужен. Например как list может быть null? по логике он должен быть либо [], либо [a1..an]. То же можно сказать про любой другой вариант, там где нужно неопределенное значение можно использовать option.

Поясню по другому: где видим класса -- понимаем что это может быть, либо null, либо экземпляр. В случае с вариантами -- подразумеваем, что это один из вариантов(извините за тавтологию)
Re[4]: оператор ?. не работает с option
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.12.11 23:40
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>По моему надо с любым вариантом сделать что то подобное -- запретить любым вариантам принимать значение null.


В дотнете это физически невозможно. Например, null-ссылка может быть получена внутри массива или внутри структуры созданной дефолтным конструктором.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: оператор ?. не работает с option
От: BogdanMart Украина  
Дата: 12.12.11 00:04
Оценка:
Здравствуйте, BogdanMart, Вы писали:

BM>Ну вообще исключать null из языка -- гемор в использовании


Если оборачивать все либы в опции, то гемор, но внешние либы не гарантируют что поля не будут null, даже если это означает ошибку либы. Но лепить визде опшины тоже не дело.
То есть в кошерном коде null не будет по определению(либо варианты, либо свой класс с объявленным контрактом). Ну а там где иидет взаимодейтсвие сс внешним кодом могут быть нулы.
То есть объявить святотатство класса notnull

BM>По моему надо с любым вариантом сделать что то подобное -- запретить любым вариантам принимать значение null.


Наделе можно так сделать:

[NotNull]
class A{};
class B:A{};

class C
{
  this()
  { 
    a = A();
  }  // Error: nonnul immutable field a' must be initialized
  public a:A;
  public a':A;
  public mutable a'':A;  // Error: public fieelds can't expose  non-null types
  private mutable a''':A = A(); // All ok, check for non-null contract will be emited by compiler  on use cases
  public mutable a'''':A = A(); // Error: public fieelds can't expose  non-null types

  internal setA(A aa):void
  {
    a''' = aa; // поскольку метод internal , то мы уверены что здесь нету нулл'а
  }
  public setA2(A aa):void // поскольку метод public , то если аа == Null -- бросаем ArgumentException
  {
    a''' = aa;
  }
}


это создаст следующий код(то что не скомпилится выбросил):

[NotNull]
class A{};
[NotNull]
class B:A{};

class C
{
  this()
  { 
    a = A();
  }

  public a:A;
  private mutable a''':A = A(); 

  internal setA(A aa):void
  {
    a''' = aa; 
  }

  internal setA_Internal_N_35483(A aa):void
  {
    a''' = aa;
  }
  public setA2(A aa):void
  {
    if (aa == null)
      throw ArgumentException(...)
    else
      setA_Internal_N_35483(aa)
  }

}


// ну и напоследок сладость для доступа  к такому методу из другой сборки написанной на немерле

public NonNullInteropHelper_Ϡ
{
  public static C__setA_Internal_Ϡ_35483(C c, A aa):void   // иероглиф, чтобы ненароком с C# не вызвали
  {
    c.setA_Internal_N_35483(aa)
  }

}


можно вообще какой то непечатаемый символ ( обфускатор использует символ конца строки в имени метода,так как CLR просто транслирует Unicode, то ему по фиг, а ни один компилер такое не распарсит

Вопрос целесообразно ли делать такой трюк, чтобы обойти проверку на Null при вызове из другой либы на Nemerle? думаю не очень, не такие большие накладные расходы.
Но если прикрутить нативную поддержку компилятором и других контрактов, то тогда есть смысл.


PS. скорее хотелка для Н2
Re[5]: оператор ?. не работает с option
От: BogdanMart Украина  
Дата: 12.12.11 00:14
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>В дотнете это физически невозможно. Например, null-ссылка может быть получена внутри массива или внутри структуры созданной дефолтным конструктором.

Да с массивом и структурой действительно лажа..

Но подобную штуку видел в С++/CIL

struct A
{
   int i;
   String^ s; //Error  can't use managed pointer inside unmanged struct
   char Cs[20];
}

struct val B
{
   int i;
   String^ s; //All ok
   char Cs[20]; //Critical warning  -- mixed types not allowed
 // светится как ошибка, но прагмой специальной можно отключить, но тогда эта  струкутра не будет CLS Compilant
}


Так что для таких типов можно запретить массивы/структы.
Ты часто видел массивы варантов? а не листы, например.

можно:
  • вставлять проверки на Null и исключение по несоотвтесвию контарктов в точах соприкосовения NonNull типов и внешних дотнетовских тпов
  • запретить использовать наши типы с внешними, небезопасными
  • какой то свой, "безоасный" тип структа, как в С++/CLI
  • Re[3]: оператор ?. не работает с option
    От: BogdanMart Украина  
    Дата: 12.12.11 00:19
    Оценка:
    Здравствуйте, _Claus_, Вы писали:

    _C_>но ессно option[T] должна быть структурой по реализации, даже если ее удобно показывать как вариант.


    Можно ввести понятие варианта "по умолчанию" для вариантных типов, это может быть любой не гиперболизированный вариант указанный разработчиком.
    Например для option это None а для list[T] это Nil итд.

    И когда идет матч по варианту, если видим null обрабытваем как вариант по умолчанию.
    (подводный камень -- если есть какие то методы)
    Re[3]: оператор ?. не работает с option
    От: Uriel Россия  
    Дата: 12.12.11 06:21
    Оценка: 3 (1)
    Здравствуйте, _Claus_, Вы писали:

    _C_>но ессно option[T] должна быть структурой по реализации, даже если ее удобно показывать как вариант.

    _C_>иначе накладные расходы и странности в использовании.

    Заинтересовался вопросом накладных расходов на класс по сравнению со структурой ещё из прошлого обсуждения в какой-то другой теме.
    В некоторых модулях в рабочем проекте (правда на C#) активно используется самодельный Option вида:

    public abstract class Option<T>: IEnumerable<T> {
        public abstract bool HasValue { get; }
        public abstract T Value { get; }
    }
    
    public sealed class Some<T>: Option<T> {
        ...
    }
    
    public sealed class None<T>: Option<T> {
        ...
    }


    Из любопытства проверил следующие варианты:
    1. Option в реализации, приведённой выше
    2. Option без наследования (то есть пустое поле под Value будет даже у None)
    3. Option в виде структуры
    4. Алгоритм вообще без Option

    Дело было недели 3 назад, поэтому конкретных цифр, к сожалению, не осталось.
    В целом, первые три варианта отличались совсем незначительно и по большей части разница была только в объёме используемой памяти и количестве сборок мусора.
    Можно даже сказать, что вариант со структурами был несколько медленнее с точки зрения затраченного времени, но эффективнее в плане нагрузки на память и сборщик.
    Вариант без Option'ов работал где-то процентов на 30-40 быстрее, чем с оными, но код при этом стал раза в 3 страшнее.
    Re[4]: оператор ?. не работает с option
    От: hardcase Пират http://nemerle.org
    Дата: 12.12.11 06:46
    Оценка:
    Здравствуйте, Uriel, Вы писали:

    U>Дело было недели 3 назад, поэтому конкретных цифр, к сожалению, не осталось.

    U>В целом, первые три варианта отличались совсем незначительно и по большей части разница была только в объёме используемой памяти и количестве сборок мусора.
    U>Можно даже сказать, что вариант со структурами был несколько медленнее с точки зрения затраченного времени, но эффективнее в плане нагрузки на память и сборщик.
    U>Вариант без Option'ов работал где-то процентов на 30-40 быстрее, чем с оными, но код при этом стал раза в 3 страшнее.

    Talk is cheap
    Было бы интересно посмотеть на бенчмарки и реализацию структуры. Особенно меня смущает реализация IEnumerable<T>.
    /* иЗвиНите зА неРовнЫй поЧерК */
    Re[5]: оператор ?. не работает с option
    От: Uriel Россия  
    Дата: 12.12.11 07:19
    Оценка:
    Здравствуйте, hardcase, Вы писали:

    H>Talk is cheap

    H>Было бы интересно посмотеть на бенчмарки и реализацию структуры. Особенно меня смущает реализация IEnumerable<T>.

    Да я понимаю, просто привычка поганая есть удалять всё после того, как оно уже не актуально.
    Вечером гляну, может быть остались исходники, с которыми я баловался.

    А IEnumerable<T> навеяно реализацией Option'ов в Scala, где их можно пользовать в конструкции for.
    Ну и к тому же очень удобно иногда впихивать операции над Option'ами в портянку вызовов LINQ, a-la:
    public Option<T> Foo(Bar input);
    
    IEnumerable<T> foo = SomeCollection.SelectMany(_ => Foo(_));
    Re[6]: оператор ?. не работает с option
    От: Jack128  
    Дата: 12.12.11 07:49
    Оценка:
    Здравствуйте, Uriel, Вы писали:

    U>А IEnumerable<T> навеяно реализацией Option'ов в Scala, где их можно пользовать в конструкции for.

    U>Ну и к тому же очень удобно иногда впихивать операции над Option'ами в портянку вызовов LINQ, a-la:
    U>
    U>public Option<T> Foo(Bar input);
    
    U>IEnumerable<T> foo = SomeCollection.SelectMany(_ => Foo(_));
    U>


    Не лучше ли такой метод использовать:
    IEnumerable<TResult> Choose<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, Option<TResult>> selector) { return source.Select(selector).Where(Option.IsSame); }
    ?
    Ну и вообще в качестве примера http://msdn.microsoft.com/en-us/library/ee370544.aspx
    Re[4]: оператор ?. не работает с option
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 12.12.11 11:39
    Оценка:
    Здравствуйте, Uriel, Вы писали:

    U>В целом, первые три варианта отличались совсем незначительно и по большей части разница была только в объёме используемой памяти и количестве сборок мусора.


    Конечно, сперва нужно смотреть на код. Так ничего сказать нельзя.

    Но "отличались совсем незначительно" скорее всего является следствием синтетичности тесто. По видимому в этих тестах объем работы с option был незначителен по сравнению с основном объемом работы.

    Но бывают и другие ситуации. Например, в компиляторе немерла option используется очень плотно. При этом каждый раз создаются новые экзепляры. Уверен, что замена его на структуру заметно повысит производительность.

    U>Можно даже сказать, что вариант со структурами был несколько медленнее с точки зрения затраченного времени, но эффективнее в плане нагрузки на память и сборщик.


    Это зависит от особенностей применения. Если будет создаваться большое количество экземпляров option-а, то структура должна быть значительно шустрее. Плюс на скорость влияет и способ ее возврата. К сожалению CLR генерирует медленный код когда из метода возвращается структура размер которой больше размера указателя.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[3]: оператор ?. не работает с option
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 12.12.11 11:41
    Оценка:
    Здравствуйте, hardcase, Вы писали:

    VD>>Да. Забыл добавить. Ты можешь использовать метод WithDefault. Он делает ровно что тебе нужно.


    H>Это несовсем верно. У ?. ленивая семантика, тогда как у WithDefault — энергичная.


    "ленивая" тут не совсем точный термин. Но я понял твою мысль. WithDefault больше похож на ??. Это да.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.