Nemerle vs C#: array[object] and arrya[string] are not compa
От: Ilya10k Россия  
Дата: 20.09.06 02:08
Оценка:
А это баг?

Код на C# работает отлично:
using System;
using System.Windows.Forms;

namespace Test
{
    class Form1: Form
    {
        static void Main()
        {
            Application.Run(new Form1());
        }

        private Form1()
        {
            string[] strings = new string[]{"test1", "test2", "test3"};
            ComboBox comboBox1 = new ComboBox();
            comboBox1.Items.AddRange(strings);
            this.Controls.Add(comboBox1);
        }
    }
}


D:>csc test.cs
Версия компилятора Microsoft (R) Visual C# 20058.00.50727.42
для Microsoft (R) Windows (R) 2005 Framework версии2.0.50727
Авторские права (C) Microsoft Corporation 2001-2005. Все права защищены.


D:>



Код на Nemerle не компилируется:
using System;
using System.Windows.Forms;

namespace Test
{
    class Form1: Form
    {
        static Main() :  void
        {
            Application.Run( Form1());
        }

        private this()
        {
            def strings = array["test1", "test2", "test3"];
            def comboBox1 = ComboBox();
            comboBox1.Items.AddRange(strings);
            this.Controls.Add(comboBox1);
        }
    }
}


D:>ncc -r System.Windows.Forms test.n
test.n:17:1:17:25: <[01;31merror<[0m: in argument #1 (items) of comboBox1.Items.AddRange, needed a array [System.Object], got array [string]: the types System.Object and string are not compatible [simple unify]

D:>



Workaround:
using System;
using System.Windows.Forms;

namespace Test
{
    class Form1: Form
    {
        static Main() :  void
        {
            Application.Run( Form1());
        }

        private this()
        {
            def strings = array["test1", "test2", "test3"];
            def arr = Array.ConvertAll(strings, Converter.[string, object](fun(from){from}));
            def comboBox1 = ComboBox();
            comboBox1.Items.AddRange(arr);
            this.Controls.Add(comboBox1);
        }
    }
}


D:>ncc -r System.Windows.Forms test1.n


D:>test1.exe


D:>


30.01.07 18:14: Перенесено модератором из 'Декларативное программирование' — IT
Re: Nemerle vs C#: array[object] and arrya[string] are not c
От: ie Россия http://ziez.blogspot.com/
Дата: 20.09.06 03:12
Оценка: 1 (1)
Здравствуйте, Ilya10k, Вы писали:

I>А это баг?


Не совсем, это фитча
Если я не ошибаюсь, авторы столкнулись с какой-то проблемой связаной с парой: ковариантность массивов — вывод типов.

Варианты:

    def strings = array["test1" : object, "test2", "test3"];
    def comboBox1 = ComboBox();
    comboBox1.Items.AddRange(strings);

    def strings = array["test1", "test2", "test3"];
    def comboBox1 = ComboBox();
    comboBox1.Items.AddRange((strings : object) :> array[object]);


Ну и тот, что ты предложил
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re: Nemerle vs C#: array[object] and arrya[string] are not c
От: Vermicious Knid  
Дата: 20.09.06 05:54
Оценка: 1 (1) +1
Здравствуйте, Ilya10k, Вы писали:

На твой вопрос уже ответили, а я сделаю небольшое замечание по поводу анонимных функций.
Вместо этого кошмара:
Array.ConvertAll(strings, Converter.[string, object](fun(from){from}));

Можно было написать так:
Array.ConvertAll(strings, x => x : object);

Кстати Nemerle приводит функции к делегатам автоматически, так что в данном случае никакого смысла создавать делегат по имени не было. Если это для того, чтобы указать тип функции, то можно было проще:
Array.ConvertAll(strings, fun(from) : object { from });
Re: Nemerle vs C#: array[object] and arrya[string] are not c
От: Ilya10k Россия  
Дата: 20.09.06 11:35
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:

VK>Вместо этого кошмара:

VK>
VK>Array.ConvertAll(strings, Converter.[string, object](fun(from){from}));
VK>

Протупил. Скопировал с MSDN даже не задумавшись, что это делегат. А про вывод функций к делегатам знал.


VK>Можно было написать так:

VK>
VK>Array.ConvertAll(strings, x => x : object);
VK>


Здесь не очень понятно, почему можно так написать.

Правильно ли я рассуждаю, что можно вот так сократить:

1. Первоначальный максимальный вариант — конструктор делегата с анонимной функцией в качестве параметра:
Converter.[string, object](fun(from){from})

сокращается до
2. Только собственно функция с паттерн-матчингом:
fun(x: string): object {match(x){| x => x: object} }

сокращается до
3. Типы функции и параметров выводятся, единственный match в функции можно сократить:
fun(x) {| x => x: object}

сокращается до
4. Саму функцию сокращаем до просто ее тела (на каком основании сокращаем и куда исчезает токен "|"? С чего компилятор догадывается, что "x => x : object" — функция?).
| x => x: object

5. Результат:
Array.ConvertAll(strings, x => x : object);



Глянул рефлектором. Действительно, создается функция:
private Form1()
{
      string[] textArray1 = new string[] { "test1", "test2", "test3" };
      object[] objArray1 = Array.ConvertAll<string, object>(textArray1, new Converter<string, object>(Form1._N__N_l44205270));
      ComboBox box1 = new ComboBox();
      box1.Items.AddRange(objArray1);
      this.Controls.Add(box1);
}

private static object _N__N_l44205270(string x)
{
      return (object) x;
}
Re[2]: Nemerle vs C#: array[object] and arrya[string] are no
От: Vermicious Knid  
Дата: 20.09.06 12:40
Оценка: 31 (2) +1
Здравствуйте, Ilya10k, Вы писали:

I>Здесь не очень понятно, почему можно так написать.

I>Правильно ли я рассуждаю, что можно вот так сократить:
Нет, не правильно. Паттерн-мэтчинг здесь не причем, просто внешне напоминает. x => y это нотация для анонимных функций, позаимствованная из C# 3.0. Во многих языках есть что-то похожее. Например в Haskell это \x -> y.

Если интересно, почему и как компилятор это понимает, то можно и пояснить.
В стандартной библиотеке макросов есть бинарный макро-оператор @=>.
x => x он раскрывает в fun(x) { x }
(x,y) => x + y в fun(x, y) { x + y }

В качестве списка параметров он(макрос) воспринимает только имена параметров(или _ если параметр игнорируется) с опциональной аннотацией типов. Это поведение кстати отличается от методов и локальный функций. Параметры методов можно еще помечать атрибутами. В параметрах локальных, анонимных функций и методов можно использовать паттерны. Например так:
def f = fun((a,b), (x::xs)) {}

Т.е. это просто сильно облегченный синтаксис для анонимных функций. Меньше функциональности, но зато и меньше "оверхеда".
Re: Nemerle vs C#: array[object] and arrya[string] are not c
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 13:39
Оценка: 10 (2)
Здравствуйте, Ilya10k, Вы писали:

I>А это баг?


Да, это извесный баг компилятора о котором известно разработчикам. Но у них никак не дойдут руки до этого дела. Я с ними как-то об этом говорил.

Как решить проблему тебе уже написали, я же для упрощения проблемы добавил Extention method с именем To.Base(). Так что моно писать так:

I>Код на Nemerle не компилируется:

using Nemerle.Utility;
...
def strings = array["test1", "test2", "test3"];
...
comboBox1.Items.AddRange(strings.ToBase());
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle vs C#: array[object] and arrya[string] are no
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 13:39
Оценка: 2 (1)
Здравствуйте, Ilya10k, Вы писали:

VK>>Можно было написать так:

VK>>
VK>>Array.ConvertAll(strings, x => x : object);
VK>>


Скажу больше использовать Array.ConvertAll() тоже смысла нет. Вместо него можно использовать метод-расширение NArray.ConvertAll(). Вот пример преобразования массива целых в массив строк:
using System.Console;
using Nemerle.Utility;

def ary1 = array[1, 2, 3, 4];
def ary2 = ary1.ConvertAll(elem => elem.ToString());

WriteLine(ary2.ToString(", "))

Можно даже еще короче:
def ary2 = ary1.ConvertAll(_.ToString());

"_.ToString()" — это так называемое частичное применение. Оно преобразовывается в анонимную функцию (лямбду) анлогичную "elem => elem.ToString()".

Кстати, в функциональном мире методы аналогичные ConvertAll() принято называть Map(). Правда Map

НО в твоем случае, вообщен не стоит вызвать ConvertAll(). Здесь требуется приведение типов (описанное ie
Автор: ie
Дата: 20.09.06
), вместо которого удобнее применять метод ToBase(). Метод ToBase обеспечивает так же и дополнительный контроль, так как на его параметры типов наложено ограничение. Так что пользоваться лучше именно им. Ну, а там глядишь и компилятор поправят.

I>Здесь не очень понятно, почему можно так написать.

I>Правильно ли я рассуждаю, что можно вот так сократить:
Нет не правльно.
x => x : object

это описание анонимной функции. Просто другой синтаксис (реализованный в виде макроса). Этот код полностью аналогичен коду:
fun (x) { x : object }

В свою очередь "x : object" просто приказывает компилятору трактовать x как переменную типа object. С тем же умпехом можно было бы написать так:
fun (x) : object { x }

или так
(x) : object => x

Задание уточнения типа нужно только потому, что иначе компилятор выведет функцию как
(x) : string => x
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle vs C#: array[object] and arrya[string] are no
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 13:39
Оценка: 2 (1)
Здравствуйте, ie, Вы писали:

ie>Не совсем, это фитча

ie>Если я не ошибаюсь, авторы столкнулись с какой-то проблемой связаной с парой: ковариантность массивов — вывод типов.

По-моему — это баг. Просто не учитывается ковариантность массивов. Причем на фоне того, что ковариантность реализована для интерфейсов — версия проблемы выглядит еще более сомнительной. Так что проблема тут тольк одна — промазали с логикой.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Nemerle vs C#: array[object] and arrya[string] are not c
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 15:57
Оценка: +1
Здравствуйте, Ilya10k, Вы писали:

I>А это баг?


I>Код на C# работает отлично:

I>
I>            string[] strings = new string[]{"test1", "test2", "test3"};
I>            ComboBox comboBox1 = new ComboBox();
I>            comboBox1.Items.AddRange(strings);
I>


Подумалось... Есть смысл создать extension-методы вроде:
using Nemerle.Utility;
using System.Windows.Forms;
using System.Collections.Generic;

namespace System.Windows.Forms
{
  module ExtensionMethods
  {
    public AddRange[T](this items : ComboBox.ObjectCollection, args : array[T]) : void
      where T: class
    {
      items.AddRange((args : object) :> array[object]);
    }

    public AddRange[T](this items : ComboBox.ObjectCollection, args : IEnumerable[T]) : void
      where T: class
    {
      items.AddRange((args.ToArray() : object) :> array[object]);
    }
  }
}

def strings = array["test1", "test2", "test3"];
def comboBox1 = ComboBox();
comboBox1.Items.AddRange(strings);
System.Console.WriteLine(comboBox1.Items.Count);

def strings = ["test1", "test2", "test3"]; // список!
def comboBox1 = ComboBox();
comboBox1.Items.AddRange(strings);
System.Console.WriteLine(comboBox1.Items.Count);

Тогда никакого "шума" не будет. Добавил файлик к проекту и живи спокойно. А то и вообще в библиотечку положить можно.

Причем в этом случае мы получаем контроль времени компиляции, так как передать этому методу массив вэлью-типов уже не дастся.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle vs C#: array[object] and arrya[string] are no
От: ie Россия http://ziez.blogspot.com/
Дата: 20.09.06 16:54
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Подумалось... Есть смысл создать extension-методы вроде:

VD>Тогда никакого "шума" не будет. Добавил файлик к проекту и живи спокойно. А то и вообще в библиотечку положить можно.

Ну уж коль разработчики признают баг и планируют его поправить, то в библиотечку класть ИМХО смысла не имеет. Тем более, что на все коллекции, экстеншенов не напасешься. А как воркараунд, отличное решение!

VD>Причем в этом случае мы получаем контроль времени компиляции, так как передать этому методу массив вэлью-типов уже не дастся.


Что-то не вкурил, а зачем нужна такая дескриминация вэлью-типов?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Превратим окружающую нас среду в воскресенье.
Re[3]: Nemerle vs C#: array[object] and arrya[string] are no
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 02:36
Оценка: +1
Здравствуйте, ie, Вы писали:

ie>Ну уж коль разработчики признают баг и планируют его поправить, то в библиотечку класть ИМХО смысла не имеет. Тем более, что на все коллекции, экстеншенов не напасешься. А как воркараунд, отличное решение!


Исправят уберем. Да и если не уберем, то тоже проблем не будет.

ie>Что-то не вкурил, а зачем нужна такая дескриминация вэлью-типов?


Массмвы вэлью-типов не ковариантны. Их так приводить нельзя.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Nemerle vs C#: array[object] and arrya[string] are no
От: Ilya10k Россия  
Дата: 24.09.06 23:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Скажу больше использовать Array.ConvertAll() тоже смысла нет. Вместо него можно использовать метод-расширение NArray.ConvertAll().


NArray.ConvertTo()

VD>[/c#]

VD>Можно даже еще короче:
VD>
VD>def ary2 = ary1.ConvertAll(_.ToString());
VD>

VD>"_.ToString()" — это так называемое частичное применение. Оно преобразовывается в анонимную функцию (лямбду) анлогичную "elem => elem.ToString()".

А почему не работает "_:> Class1"? Пришлось писать "x => x:> Class1":

using Nemerle.Utility;

class Class1 {}
    
def arr1: array[object] = array[Class1(), Class1(), Class1()];
def _arr2: array[Class1] = arr1.ConvertTo(_:> Class1);
//def _arr2: array[Class1] = arr1.ConvertTo(x => x:> Class1);


>C:\Program Files\Nemerle\ncc.exe -no-color -r System.Windows.Forms -r System.Data -t winexe test.n -o test.exe
test.n:6:43:6:44: error: found pattern expression (_ ) inside a raw expression
test.n:6:28:6:42: error: in argument #2 (f) of Nemerle.Utility.NArray.ConvertTo.[System.Object, ?], needed a System.Object -> ?, got Class1: Class1 is not a subtype of System.Object -> ? [simple require]
test.n:6:1:6:4: error: expected array [Class1], got array [Class1]+ in type-enforced expression
>Exit code: 1
Re[4]: Nemerle vs C#: array[object] and arrya[string] are no
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.09.06 00:08
Оценка:
Здравствуйте, Ilya10k, Вы писали:

I>А почему не работает "_:> Class1"? Пришлось писать "x => x:> Class1":


Самому интересно. По уму хорошо бы чтобы работало. В общем, я лучше за багрепортю это дело, а там послушает что неперловцы скажут. А вось исправят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Nemerle vs C#: array[object] and arrya[string] are no
От: Ilya10k Россия  
Дата: 25.09.06 00:47
Оценка:
Здравствуйте, VladD2, Вы писали:

I>>А почему не работает "_:> Class1"? Пришлось писать "x => x:> Class1":


VD>Самому интересно. По уму хорошо бы чтобы работало. В общем, я лучше за багрепортю это дело, а там послушает что неперловцы скажут. А вось исправят.


Елы-палы. Я думал, чего-то недопонимаю. А тут опять баг-репорт... snks


P.S. Я нигде не указывал версию Nemerle. Но все и так понимают, что речь идет о последней официальной версии на день отправки сообщения (ждем, не дождемся первого релиза):
D:\>ncc -V
Nemerle Compiler (ncc) version 0.9.3.99 (SVN)
(c) 2003-2005 University of Wroclaw, All rights reserved.


P.P.S. Что я пытаюсь сейчас сделать — так это ради изучения переписать свой старый проект на новый язык. И создаю новые — на Nemerle. Эх, не смогу ж назад перейти...
Re[6]: Nemerle vs C#: array[object] and arrya[string] are no
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.09.06 15:38
Оценка:
Здравствуйте, Ilya10k, Вы писали:

I>Елы-палы. Я думал, чего-то недопонимаю. А тут опять баг-репорт... snks


Дык свежая голова со свежими паттернами вот баги и полезли. Каждый раз когда к языку приобщается кто-то дейятельный сразу вылезают некотоые проблемы. Радует, что все же они в последнее время не критичны и то что их довольно быстро фиксях. Как с МС ждать по три года не надо.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.