Что такого привлекательного в Nemerle?
От: Аноним  
Дата: 29.03.10 16:59
Оценка:
Много слышу в последнее время про Немерле. Почитал — кроме хорошего метапрограммирования ничего не пишут.
Можно в нескольких предложениях сказать о плюсах Немерле?
Re: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 29.03.10 17:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Много слышу в последнее время про Немерле. Почитал — кроме хорошего метапрограммирования ничего не пишут.

А>Можно в нескольких предложениях сказать о плюсах Немерле?

1. Простая обучаемость. Не знаешь как правильно — пиши как в c#
2. Модная сейчас парадигма функционального программирования
3. Мощная система метапрограммирования, которая позволяет просто подключать возможности, которые в других языках считаются основным фичами. Например, Design By Contract, ...
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re: Что такого привлекательного в Nemerle?
От: hardcase Пират http://nemerle.org
Дата: 29.03.10 18:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Много слышу в последнее время про Немерле. Почитал — кроме хорошего метапрограммирования ничего не пишут.

А>Можно в нескольких предложениях сказать о плюсах Немерле?

4. А также строгая статическая типизация и вывод типов по Хиндли-Милнеру.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 29.03.10 19:41
Оценка:
Здравствуйте, alvas, Вы писали:

A>1. Простая обучаемость. Не знаешь как правильно — пиши как в c#


Не сказал бы. Была одна попытка, в результате которой приходилось по документации выискивать аналоги конструкций C#. Ну а потом, посмотрев на мой исходник, мне сказали, что я пишу императивно и неправильно. А как правильно не сказали
Re[3]: Что такого привлекательного в Nemerle?
От: hardcase Пират http://nemerle.org
Дата: 29.03.10 20:20
Оценка:
Здравствуйте, Mystic, Вы писали:

M>А как правильно не сказали


Правильно, это когда (в идеале) нету слова mutable в программе и вообще не используются макросы из пространства имен Nemerle.Imperative.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Что такого привлекательного в Nemerle?
От: WolfHound  
Дата: 29.03.10 20:28
Оценка: +1
Здравствуйте, hardcase, Вы писали:

H>4. А также строгая статическая типизация и вывод типов по Хиндли-Милнеру.

Вывод типов там свой. И имеет не много общего с Хиндли-Милнером.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Что такого привлекательного в Nemerle?
От: hardcase Пират http://nemerle.org
Дата: 29.03.10 20:31
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


H>>4. А также строгая статическая типизация и вывод типов по Хиндли-Милнеру.

WH>Вывод типов там свой. И имеет не много общего с Хиндли-Милнером.

Ммм интересно. Я особенно не вникал как оно там, я банально не пойму исходников. Где-то есть человеческая информация?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Что такого привлекательного в Nemerle?
От: hardcase Пират http://nemerle.org
Дата: 29.03.10 20:49
Оценка:
Здравствуйте, hardcase, Вы писали:

H> Где-то есть человеческая информация?


Нашел: Type Inference with Deferral
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 05:18
Оценка: +1
Здравствуйте, Mystic, Вы писали:

A>>1. Простая обучаемость. Не знаешь как правильно — пиши как в c#


M>Не сказал бы. Была одна попытка, в результате которой приходилось по документации выискивать аналоги конструкций C#. Ну а потом, посмотрев на мой исходник, мне сказали, что я пишу императивно и неправильно. А как правильно не сказали


Вот и я об этом. Не знаешь как правильно — пиши императивно. Со временем придет понимание как писать функционально, т.е. правильно
Ваш код давал правильный результат?
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[4]: Что такого привлекательного в Nemerle?
От: Shame Россия funtoo.org
Дата: 30.03.10 05:58
Оценка:
Здравствуйте, alvas, Вы писали:

A> Со временем придет понимание как писать функционально, т.е. правильно


Собственно это один из главных плюсов.
الحقيقة:الشئ الوحيد الذي(لا)يصدقه الناس!ا الزواج : جمع.وطرح.ثم(ضرب)!ولكنه قبل ذلك(قسمة) المحامي:لسان.وحنجرة.وروب!يدافع عن مال موكله (أعزائي)!وهو لا يعرف أحد منّا!الطالب (الأول)على فصله!لولا وجود الأخرين
Re[5]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 09:35
Оценка:
Здравствуйте, Shame, Вы писали:

A>> Со временем придет понимание как писать функционально, т.е. правильно


S>Собственно это один из главных плюсов.


Именно
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[4]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.03.10 14:03
Оценка:
Здравствуйте, alvas, Вы писали:

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


A>>>1. Простая обучаемость. Не знаешь как правильно — пиши как в c#


M>>Не сказал бы. Была одна попытка, в результате которой приходилось по документации выискивать аналоги конструкций C#. Ну а потом, посмотрев на мой исходник, мне сказали, что я пишу императивно и неправильно. А как правильно не сказали


A>Вот и я об этом. Не знаешь как правильно — пиши императивно. Со временем придет понимание как писать функционально, т.е. правильно

A>Ваш код давал правильный результат?

Смотря на чем, на C# на написание кода с отладкой ушло полчаса. На Nemerle я до финишной черты не добрался, умер по пути в поисках эквивалентных конструкций. Сам код я уже приводил тут
Автор: Mystic
Дата: 03.10.09
.
Re[4]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.03.10 14:05
Оценка:
Здравствуйте, hardcase, Вы писали:

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


M>>А как правильно не сказали


H>Правильно, это когда (в идеале) нету слова mutable в программе и вообще не используются макросы из пространства имен Nemerle.Imperative.


Лично мне так писать очень сложно, результат рождается в суках, долго и неуклюже... Если вообще рождается
Re[5]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 30.03.10 14:09
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Смотря на чем, на C# на написание кода с отладкой ушло полчаса. На Nemerle я до финишной черты не добрался, умер по пути в поисках эквивалентных конструкций. Сам код я уже приводил тут
Автор: Mystic
Дата: 03.10.09
.


Честно говоря, не понял, в чем проблема. При желании приведенный код на Шарпе переписывается на Немерле практически один-в-один. Может, проблема была в том, что вы пытались смешивать функциональные типы данных вроде списков, обработку которых удобнее делать с помощью функциональных же конструкций, с чисто императивным стилем основной программы?
Re[5]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 14:17
Оценка:
Здравствуйте, Mystic, Вы писали:

M>>>А как правильно не сказали


H>>Правильно, это когда (в идеале) нету слова mutable в программе и вообще не используются макросы из пространства имен Nemerle.Imperative.


M>Лично мне так писать очень сложно, результат рождается в суках, долго и неуклюже... Если вообще рождается


Ну так не слушайте никого и используйте Nemerle.Imperative.
Опыт придет со временем
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[6]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.03.10 14:21
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Честно говоря, не понял, в чем проблема. При желании приведенный код на Шарпе переписывается на Немерле практически один-в-один. Может, проблема была в том, что вы пытались смешивать функциональные типы данных вроде списков, обработку которых удобнее делать с помощью функциональных же конструкций, с чисто императивным стилем основной программы?


Основная проблема в том, что приходится лазить по документации в поисках того, как та или иная конструкция реализуется средствами Nemerle. Плюс бороться с возникающими ошибками. Что достаточно утомительно и не видно никаких преимуществ. Когда я понял, что в результате код на Nemerle будет полностью идентичный сишарповскому, я задал вопрос: а в чем смысл моих страданий? Этот риторический вопрос окончательно погасил мой энтузиазм.
Re[5]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 14:24
Оценка: +2
Здравствуйте, Mystic, Вы писали:

M>Смотря на чем, на C# на написание кода с отладкой ушло полчаса. На Nemerle я до финишной черты не добрался, умер по пути в поисках эквивалентных конструкций. Сам код я уже приводил тут
Автор: Mystic
Дата: 03.10.09
.


Это Парадокс Блаба. Ничего страшного. Просто продолжайте писать. Захватывая по немногу новые возможности и конструкции. Со временем будете думать в других конструкциях.
У Nemerle, мне кажется, самый плавный переход получается. По сравнению с F# и иже с ним.
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[6]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.03.10 14:25
Оценка:
Здравствуйте, alvas, Вы писали:

A>Ну так не слушайте никого и используйте Nemerle.Imperative.

A>Опыт придет со временем

Тогда возникает другой вопрос: а в чем тогда цимес?
Re[7]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 14:26
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Основная проблема в том, что приходится лазить по документации в поисках того, как та или иная конструкция реализуется средствами Nemerle. Плюс бороться с возникающими ошибками. Что достаточно утомительно и не видно никаких преимуществ. Когда я понял, что в результате код на Nemerle будет полностью идентичный сишарповскому, я задал вопрос: а в чем смысл моих страданий? Этот риторический вопрос окончательно погасил мой энтузиазм.


Это да, с докой не очень.
По поводу второй части см здесь
Автор: alvas
Дата: 30.03.10
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[7]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 30.03.10 14:29
Оценка: 97 (3) +1 :)
Здравствуйте, Mystic, Вы писали:

M>Основная проблема в том, что приходится лазить по документации в поисках того, как та или иная конструкция реализуется средствами Nemerle. Плюс бороться с возникающими ошибками. Что достаточно утомительно и не видно никаких преимуществ. Когда я понял, что в результате код на Nemerle будет полностью идентичный сишарповскому, я задал вопрос: а в чем смысл моих страданий? Этот риторический вопрос окончательно погасил мой энтузиазм.


Отвечу как человек, не знающий Немерле:

using System;
using System.Collections.Generic;
using System.Text;
using Nemerle.Imperative;

namespace PokerTable
{
  class Info
  {
    public mutable Product : int;
    public mutable FlushRank : int;
    public mutable NormalRank : int;
  }

  class Program
  {
    mutable static Primary = array [ 41, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ];

    mutable static rank = 1;
    mutable static Data : Dictionary[int,Info] = Dictionary.[int,Info]();
    
    static public AddFlush(Product : int) : void
    {
      mutable info = Info();
      info.Product = Product;
      info.FlushRank = rank;
      info.NormalRank = -1;
      Data.Add(Product, info);
      rank = rank + 1;
    }

    static public AddNormal(Product : int) : void
    {
      mutable info;
      
      when (!Data.TryGetValue(Product, out info))
      {
        info = Info();
        info.Product = Product;
        info.FlushRank = -1;
      }
      
      info.NormalRank = rank;
      rank = rank + 1;
    }

    static public Straight(isFlush : bool) : void
    {
      mutable Product = Primary[13] * Primary[12] * Primary[11] * Primary[10] * Primary[9];
      if (isFlush) AddFlush(Product); else AddNormal(Product);
      
      for (mutable i = 8; i >= 0; --i)
      {
        Product /= Primary[i + 5];
        Product *= Primary[i];
        if (isFlush) AddFlush(Product); else AddNormal(Product);
      }
    }

    static public Quads() : void
    {
      for (mutable Base = 13; Base >= 1; --Base)
      {
          for (mutable Kicker = 13; Kicker >= 1; --Kicker)
          {
            when (Base == Kicker) 
                continue;
                
            mutable BasePrimary = Primary[Base];
            mutable KickerPrimary = Primary[Kicker];
            AddNormal(BasePrimary * BasePrimary * BasePrimary * BasePrimary * KickerPrimary);
          }
        }
    }

    static public FullHouse() : void
    {
      for (mutable Base = 13; Base >= 1; --Base)
      for (mutable Pair = 13; Pair >= 1; --Pair)
      {
        when (Base == Pair) continue;
        mutable BasePrimary = Primary[Base];
        mutable PairPrimary = Primary[Pair];
        AddNormal(BasePrimary * BasePrimary * BasePrimary * BasePrimary * PairPrimary);
      }
    }

    static public Chanse(isFlush : bool) : void
    {
      for (mutable card1 = 13; card1 >= 1; --card1)
      for (mutable card2 = card1 - 1; card2 >= 1; --card2)
      for (mutable card3 = card2 - 1; card3 >= 1; --card3)
      for (mutable card4 = card3 - 1; card4 >= 1; --card4)
      for (mutable card5 = card4 - 1; card5 >= 1; --card5)
      {
        when (card1 == 13 && card2 == 4) continue;

        mutable isStraight = true  
          && card1 == card2 + 1 
          && card2 == card3 + 1 
          && card3 == card4 + 1 
          && card4 == card5 + 1
        ;
        
        when (!isStraight)
        {
          mutable Product = Primary[card1] * Primary[card2] * Primary[card3] * Primary[card4] * Primary[card5];
          if (isFlush) AddFlush(Product); else AddNormal(Product);
        }  
          
      }
    }
    
    static public ThreeCards() : void
    {
      for (mutable Base=13; Base >= 1; --Base)
      for (mutable Kicker1 = 13; Kicker1 >= 1; --Kicker1)
      for (mutable Kicker2 = Kicker1 - 1; Kicker2 >= 1; --Kicker2)
      {
        when (Base == Kicker1) continue;
        when (Base == Kicker2) continue;
        AddNormal(Primary[Base] * Primary[Base] * Primary[Base] * Primary[Kicker1] * Primary[Kicker2]);
      }
    }

    static public TwoPair() : void
    {
      for (mutable Base1 = 13; Base1 >= 1; --Base1)
      for (mutable Base2 = Base1 - 1; Base2 >= 1; --Base2)
      for (mutable Kicker = 13; Kicker >= 1; --Kicker)
      {
        when (Base1 == Kicker) continue;
        when (Base2 == Kicker) continue;
        AddNormal(Primary[Base1] * Primary[Base1] * Primary[Base2] * Primary[Base2] * Primary[Kicker]);
      }
    }

    static public Pair() : void
    {
      for (mutable Base = 13; Base >= 1; --Base)
      for (mutable Kicker1 = 13; Kicker1 >= 1; --Kicker1)
      for (mutable Kicker2 = Kicker1 - 1; Kicker2 >= 1; --Kicker2)
      for (mutable Kicker3 = Kicker2 - 1; Kicker3 >= 1; --Kicker3)
      {
        when (Base == Kicker1) continue;
        when (Base == Kicker2) continue;
        when (Base == Kicker3) continue;
        AddNormal(Primary[Base] * Primary[Base] * Primary[Kicker1] * Primary[Kicker2] * Primary[Kicker3]);
      }
    }
  
    static Main() : void
    {
      Straight(true);
      Quads();
      FullHouse();
      Chanse(true);
      Straight(false);
      ThreeCards();
      TwoPair();
      Pair();
      Chanse(false);
      System.Console.WriteLine(rank);
    }
  }
}


Данный перевод был сделан мной методами Copy&Paste и Find&Replace в течение где-то минут двух. Если посмотреть на этот код, то видно, что отличие от Шарпа в нюансах.

Т.е. зная Шарп, вы уже можете писать на немерле — достаточно потратить лишь совсем немного времени, чтобы разобраться в небольших отличиях в синтаксисе.

Где здесь "борьба" и что здесь утомительного?

При этом вы можете "плавно" входить в собственно основные немерлианские фичи — практически без отрыва от производства. Можно даже сказать, что Немерле в каком-то плане включает в себя C#, который является его сабсетом.
Re[7]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 14:35
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Тогда возникает другой вопрос: а в чем тогда цимес?


Я его описал выше. Если вы, например, захотите на F# писать, то там тоже все по другому и не так как в c#.
Если вам F# изучить как два пальца об асфальт, то возможно вам Nemerle и не нужен. Хотя, я думаю, что все будет как раз наоборот.
С Nemerle функциональщину изучать намного проще. А дальше или на F# или так и останетесь на Nemerle.
А главный цимес в том что нужно знать как минимум 3-4 языка с разной парадигмой чтобы чувствовать себя профессиональным программистом.
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[3]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 16:03
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Не сказал бы. Была одна попытка, в результате которой приходилось по документации выискивать аналоги конструкций C#. Ну а потом, посмотрев на мой исходник, мне сказали, что я пишу императивно и неправильно. А как правильно не сказали


Ну, так смог же? Пусть не правильно, пусть немного подумать пришлось, но ведь смог?

Ну, а чтобы научиться писать правильно нужно к этому стремиться. Если будет реальная задача, то потихонечку освоишь все премудрости.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 16:14
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Основная проблема в том, что приходится лазить по документации в поисках того, как та или иная конструкция реализуется средствами Nemerle. Плюс бороться с возникающими ошибками. Что достаточно утомительно и не видно никаких преимуществ. Когда я понял, что в результате код на Nemerle будет полностью идентичный сишарповскому, я задал вопрос: а в чем смысл моих страданий? Этот риторический вопрос окончательно погасил мой энтузиазм.


А вот эту статью
Автор(ы): Сергей Туленцев, Владислав Чистяков
Дата: 23.05.2006
Производительность труда программиста в основном зависит от самого программиста. Однако даже самый опытный и знающий программист мало что может без подходящего инструмента. Эта статья открывает цикл статей об одном из таких инструментов, еще мало известном среди программистов, но очень многообещающем. Язык Nemerle, о котором пойдет речь в этих статьях, на первый взгляд очень похож на слегка улучшенный C#, но привносит многое из передовых исследовательских языков. Данная статья рассказывает об отличиях Nemerle от C# (как наиболее близкого языка)и является неформальным введением в язык.
перед тем как начать читал?

В прочем, даже если возникли проблемы, то почему было не задать вопрос в форуме?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 30.03.10 16:16
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А вот эту статью
Автор(ы): Сергей Туленцев, Владислав Чистяков
Дата: 23.05.2006
Производительность труда программиста в основном зависит от самого программиста. Однако даже самый опытный и знающий программист мало что может без подходящего инструмента. Эта статья открывает цикл статей об одном из таких инструментов, еще мало известном среди программистов, но очень многообещающем. Язык Nemerle, о котором пойдет речь в этих статьях, на первый взгляд очень похож на слегка улучшенный C#, но привносит многое из передовых исследовательских языков. Данная статья рассказывает об отличиях Nemerle от C# (как наиболее близкого языка)и является неформальным введением в язык.
перед тем как начать читал?

VD>В прочем, даже если возникли проблемы, то почему было не задать вопрос в форуме?

Он судя по всему спрашивал, причем у тебя
А его в ответ закидали тухлыми помидорами на тему "да у тебя вообще код кривой". Так вот и потерял человек интерес к Немерле
Re[2]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 16:28
Оценка:
Здравствуйте, hardcase, Вы писали:

H>4. А также строгая статическая типизация и вывод типов по Хиндли-Милнеру.


Ага. Только последние два дядьки тут совершенно не причем. Система вывода типов у Nemerle уникальная. Некоторые идеи заимсвованы у авторов Скалы, но алгоритм Nemerle сильно отличается. А если учитывать, что его и дальше развивали (лично я к этому делу руку приложил), то про Хиндли-Милнера можно даже не вспоминать.

Вот в F# используется модифицированный Хиндли-Милнер. Из-за этого они вынуждены требовать от пользователя явно задавать последователь файлов в проекте и кода внутри файла. Я слышал, что из-за в F# даже папки внутри проекта не реализовали.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 16:29
Оценка:
Здравствуйте, hardcase, Вы писали:

H>> Где-то есть человеческая информация?


H>Нашел: Type Inference with Deferral


Ага. Но человеческим это можно назвать только если ты из научной среды .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 16:59
Оценка: 36 (2)
Здравствуйте, Аноним, Вы писали:

А>Много слышу в последнее время про Немерле. Почитал — кроме хорошего метапрограммирования ничего не пишут.

А>Можно в нескольких предложениях сказать о плюсах Немерле?

Нет, нельзя. И не потому, что я злой или не словоохотливый. Просто чтобы понять эти преимущества нужно понять суть тех возможностей которые есть в языке, а это значит нужно понять сам язык.

Тут уже не мало говорилось, что одним из преимуществ Nemerle является то, что на нем можно писать как на C#. Но на самом деле — это само по себе не преимущество. Это упрощает вхождение в язык. Если ты знаешь C#, то начать писать на Nemerle можно за пару вечеров.

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

Второй этап более долгий. Если начать программировать можно уже через 2-3 дня, то на освоение функциональных возможностей уйдет не менее месяца (постоянного программирования). При этом лучше всего иметь под рукой человека который будет производить ревизию твоего кода и подсказывать какие возможности Nemerle можно применить в тех или иных местах, чтобы сделать программу более простой и короткой.

Макросы — это следующий уровень. В прочем простые макросы можно начать писать чуть ли не сразу. Но действительно серьезно поднять уровень абстракции в программе могут только не тривиальные макросы. А они требуют не малого опыта.

Думаю, что средний программист знакомый с C# может освоить Nemerle до уровня "хорошо" где-то за год.

Последовательность действий должна быть такая:
1. Осваиваем программирование на Nemerle в стиле C#. На это обычно уходит от одного дня до пары недель (в зависимости от способностей, отводимого времени и стремления).
2. Изучение маленьких прелестей Nemerle. Где-то 1-3 недели.
3. Изучение функциональных возможностей и изменение стиля кодирования с нарочита императивного на умеренно функциональный. На этом этапе программист начинает понимать, что вместо массивных циклов можно писать очень компактные и удобные контракции. Понимает, что кроме ООП есть варианты и паттерн-матчинг и т.п.
4. Достижение некоторого уровня мастерства в применении ФП и начало баловства с макросами. Главная проблема на этом этапе не увлекаться игрушками. Болезнь все на базе функций высшего порядка нормально на этом этапе, но к сожалению она затагивает .
5. Более глубокое погружение в макросы и осознание того факта, что синтаксические абстракции при грамотном применении могут давать отдачу значительно большую чем ООП или структурное программирование.
6. Программист хорошо владеет ФП, ООП и понимает с чем едят макросы. Далее начинается самосовершенствование которому нет конца.

Ответ на вопрос дойдет ли конкретный человек до шестой ступени во многом определяется желанием (стремлением). Дойдя до шестого пункта человек неизбежно изменяется. Но начинает думать по другому.

Понятно, что если за плечами есть серьезный опыт ФП (любой клон МЛ) и/или Лиспа, то все может выглядеть по другому. Но для человека с C/C#/Java/C++ базой путь будет примерно таким.

О первых преимуществах ты сможешь судить только закончив третий пункт. А реальную мощь языка осознаешь только потратив на Nemerle тот самый год и дойдя до шестого пункта.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.03.10 17:22
Оценка: 1 (1) +2
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Он судя по всему спрашивал, причем у тебя


Он у меня в обсуждении совершенно вводного материала что-то спрашивал. На что я ему резонно заметил, что или он читает не тот материал, или он слишком многого хочет. Введение есть введение оно не позволяет сразу сесть и писать сложные задачи.

ВВ>А его в ответ закидали тухлыми помидорами на тему "да у тебя вообще код кривой".


Ну, это отдельное спасибо нашему горячему парню Синклеру.

ВВ>Так вот и потерял человек интерес к Немерле


Дык здесь вроде не религиозное объединение.
Мы не не превращаем в веру. Мы с удовольствием делимся своими впечатлениями и мыслями. Все кто считает их несостоятельными могут выбрать себе что-то другое. Или не выбирать вовсе.

Парадокс Блаба не позволяет аргументированно убедить программиста в преимуществах языка.

Я конечно могу привести примеры, но они окажутся или каким-то сахаром без которого, по мнению того кто его не пробовал, можно легко пережить или чем-то непонятным.

Такими фичами являются макросы $-строк позволяющие вывести весьма сложно-форматировнный текст в одной короткой строке, или макрос PEG-парсера который позволяет описать грамматику прямо внутри своего кода и получить статически типизированный парсер (пример калькулятора на его основе). Первый пример ($-строки) может показаться легким сахарком, хотя на практике он очень удобен. Второй чем-то сложным и непонятным. Но и то и другое еще можно объяснить, так как это пример расширения языка повышающие его мощность. А вот как объяснить людям преимущества паттерн-матчинга? Я пробовал — это почти бесполезно. Вот когда они проникнутся им, то и объяснять будет ничего не надо. А до тех пор — для непосвященного — это будет "непонятная хреновина без которой он (не посвященный) всю жизнь обходился и дальше спокойно проживет".

Вот такие дела.

По сему убеждать кого-то можно только из спортивного интереса (ради флэйма и задора). Толку от этого ноль. Я для себя решил, что это нужно мне и этого уже достаточно чтобы я этим занимался. C# я перерос. Он мне стал скучен. В С++ я разочаровался полностью. Хаскель слишком заумного и медленно. Лисп слишком уныло и запущено. Пролог пригоден только для ряда задач... В общем, надо просто писать софт на новом языке. Если я окажусь прав (в чем я в общем-то не сомневаюсь), то и сторонники будут только прибывать со временем. Кто-то возможно плюнет, а кто-то со временем вернется. Но если вещь стоящая, то всегда найдутся уверенные в себе люди которые захотят получить конкурентное преимущество.

По сему лучше тратить время не на уговоры и объяснения, а на развитие продукта. Единственное что может остановить Nemerle — это остановка его развития.

Мне кажется, что у многих кто боится использовать Nemerle на практике главная загвоздка не в том, что они не понимают преимуществ Nemerle, а в том, что они боятся, что авторы плюнут на него и он умрет не родившись. Самое смешное, что этот страх и провоцирует такой сценарий. Поляки явно ждали быстрых лавров. Но они ошибались. Языки завоевывают популярность десятилетиями.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Что такого привлекательного в Nemerle?
От: alvas  
Дата: 30.03.10 17:44
Оценка:
Здравствуйте, VladD2, Вы писали:

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


100 %
http://alvas.net — Аудио-инструменты для .Net разработчиков
Re[8]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.03.10 19:17
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Т.е. зная Шарп, вы уже можете писать на немерле — достаточно потратить лишь совсем немного времени, чтобы разобраться в небольших отличиях в синтаксисе.


ВВ>Где здесь "борьба" и что здесь утомительного?


Спасибо большое

А борьба была в том, что прочитав

Nemerle не поощряет императивный стиль


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

Общая идея была такая: заюзать Nemerle при разработке утилит, задача которых генерить код на C++ (Delphi, Ada), возможно на основании некоторого входного файла. Т. е. основная нагрузка в них это парсинг + вычисления. Вроде бы как выбор правильный, но в целом уже на вычислениях возникли проблемы: (1) перевод некоторых императивных конструкций (2) прозраность сообщений об ошибках (3) отладка (4) скорость компиляции... По первому пункту меня все тянуло вместо массивов использовать списки, и большую часть времени я изучал всякие возможности для работы с ним и пытался реализовать все в терминах списков. По второму пункту иногда при опечатке сообщение об ошибке ставило меня в тупик. По четвертому пункту надобыло разбираться с работой ngen.exe, а большого желания не было. Решил мужественно терпеть По третьему возможно интеграция с MS Studio? В общем хватало вывода отладочных сообщений, чтобы не разбираться с чем-то еще...
Re[9]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 30.03.10 19:51
Оценка:
Здравствуйте, Mystic, Вы писали:

ВВ>>Где здесь "борьба" и что здесь утомительного?

M>Спасибо большое
M>А борьба была в том, что прочитав
M>

Nemerle не поощряет императивный стиль


Поощряет или нет, но в императивном стиле на Немерле писать практически так же удобно, как и на Шарпе — особенно по сравнению с тем же F#, который, к слову, тоже позиционируется как гибридный язык.
Да и это, не понимаю, чем императивный код на Немерле хуже точно такого же императивного кода на Шарпе.

M>я решил его и не использовать. Основным документом был этот, но все равно дело шло медленно. Сейчас уже не помню, но вроде сообщения об ошибках часто вызывали недоумение. Более того, постоянно искал, где бы можно было применить какую-нить функциональную фишку, но не находил... Плюс, возможно, отладка...


Вообще сама постановка вопроса — "искал где можно применить какую-нибудь функциональную фишку, но не находил" — довольно странная. На самом деле все наоборот. Как раз в реальных-то проектах зачастую очень сложно найти место, где реально надо применить какую-нибудь "императивную фишку", т.е. где действительно нужно явно указывать последовательность шагов, описывать алгоритм, а не просто декларировать намерения.

Тут Влад в соседнем посте приводил "стадии обучения" Немерле. Если Немерле — первый ФЯ, то его изучение — это в первую очередь изучение новой парадигмы, а описанным тобой методом ее "не взять". Можешь просто писать на Немерле как и на Шарпе — будет по крайней мере не хуже, получишь "сверху" небольшие вкусности, вроде коллекции весьма полезных стандартных макросов.

Но ведь правда — посмотри, отличий не так много. Например, VB.NET в этом плане — как императивный язык — гораздо сильнее отличается от Шарпа. А на моей памяти люди без проблем переключались между выбенетом и шарпом. К тому же идеология Шарпа и Немерле в каком-то плане похожа — если нет 100% уверенности, что программист написал именно то, что хотел — то выдавать ошибку или по крайней мере ворнинг. (В отличие от выбенета, где идеология — непонятно, что хотел программист, так давайте догадаемся).

А ФП лучше, на мой взгляд, изучать по книжкам/статьям. И тут не столь важно, на каком там конкретно языке будут примеры к статьям. По Немерле, конечно, материалов не так много, как по другим языкам. Но ФП оно и в Африке ФП, его нельзя применять как фишку, это просто другое средство для достижения того же, что делается в Шарпе средствами class based OOP.

А "функциональные фишки" — это в C#, где они сделаны через жопу делегаты и прочие радости жизни.
Re[10]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 31.03.10 09:35
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Вообще сама постановка вопроса — "искал где можно применить какую-нибудь функциональную фишку, но не находил" — довольно странная. На самом деле все наоборот.


Наверное тут кроется или большая разница в мышлении, или разные решаемые задачи. Время от времени я делаю набеги на вотчину функциональных языков (Haskell, Nemerle) читаю книги, статьи, и вроде даже все понимаю. Смотря на функциональный код я могу на время стать компилятором и перевести его в результате в набор машинных инструкций, и только тогда понять, что он делает. Могу решать простые упражнения (например из книги Душкина).

Но как только я ставлю перед собой реальную задачу, все функциональные языки уводят меня совсем не туда. Мне везде начинают мерещиться списки, которые я не знаю потом как обрабатывать. Мерещаться ленивые вычисления, которые непонятно как организовать. В случае обычных языков программирования решение задачи у меня совершенно подсознательно переводится в императивные конструкции. В этом отношении мне наиболее нравится Ada: все строго, четко.

Вот приведенный мною пример. Да, конечно его можно императивно один в один реализовать на Nemerle. Но где хоть одно хотя-бы одно маленькое преимущество??? И как этот пример реализовать на чистом ФЯ без mutable? Меня можно расстрелять, но я этого не сделаю. Или это будет очень долгий труд...

Ну а в случае между VB.NET и C# я больших различий в них не вижу, с другой стороны я и не эксперт в .NET Мне больше нравятся C, Delphi, Ada. И при программировании под .NET я обычно использую некоторое подмножество этих языков, которое эквивалентно названным выше.
Re[11]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 11:46
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Здравствуйте, Воронков Василий, Вы писали:

ВВ>>Вообще сама постановка вопроса — "искал где можно применить какую-нибудь функциональную фишку, но не находил" — довольно странная. На самом деле все наоборот.
M>Наверное тут кроется или большая разница в мышлении, или разные решаемые задачи.

Слушай, ну о какой понятности императивного кода может идти речь, если я переделывал на Немерле твой PokerHouse, но при этом ни хрена не понял, что вообще этот код делает. Да и сам бы ты как быстро разобрался в подобном коде от другого программиста, где из всей документации — название пространства имен? Это не камень в твой огород, просто ты написал типичнейший императивный код — есть куча деталей, показывающих как именно нужно решить задачу, какие именно нужно сделать вычисления, каким именно образом их сделать, но что за задача решается при этом не видно

И это типичная проблема с императивщиной.

Если бы мне достался в наследство такой код с заданием, скажем, исправить какой-нибудь баг, то первое, что я бы потребовал — это тех. документацию. Если бы тех. документации вместе с комментариями к коду не было, то потянулись бы к док., описывающему требования (дай бог, чтобы он хоть был). А часто оказывается так, что прочитав требования, просто переписываешь такой код с нуля — может быть, даже в очень похоже стиле — просто потому что в собственном коде ориентироваться проще, и ты в итоге так даже время сэкономишь.
Знаешь легендарная тенденция новых программистов на проекте "все переписать" именно отсюда происходит. И она зачастую вполне оправдано. Потому что часто вообще очень трудно понять, что тут делает какой-то конкретный кусок кода, зачем он нужен — может, он там в каком-нибудь частном случае используется для какой-нибудь хитрой проверки, чтобы в этом частом случае избежать очень хитрого бага. Но без комментария такой код попросту теряет ценность.

Другой вопрос — функциональный подход, который есть подвид декларативного. Где ты не описываешь, как именно тебе нужно производить вычисления, а показываешь *что* конкретно ты хочешь получить. Такой код по определению более понятный

M>Время от времени я делаю набеги на вотчину функциональных языков (Haskell, Nemerle) читаю книги, статьи, и вроде даже все понимаю. Смотря на функциональный код я могу на время стать компилятором и перевести его в результате в набор машинных инструкций, и только тогда понять, что он делает. Могу решать простые упражнения (например из книги Душкина).


Может быть, просто во время таких забегов (Хаскель я бы вообще пока не трогал, честно), ты пропустил какие-то важные концепции и теперь без них понимать код сложно? Хотя бы те же алгебраические типы, паттерн матчинг, операции с фукнциями вроде композиции, каррирования?
В ФП вообще есть достаточно ограниченный набор концепций — можно по пальцам пересчитать — нужно просто в них разобраться, именно *понять*, и все. Все остальное будет сводиться к специфике синтаксиса того или иного языка.

M>Но как только я ставлю перед собой реальную задачу, все функциональные языки уводят меня совсем не туда. Мне везде начинают мерещиться списки, которые я не знаю потом как обрабатывать. Мерещаться ленивые вычисления, которые непонятно как организовать. В случае обычных языков программирования решение задачи у меня совершенно подсознательно переводится в императивные конструкции. В этом отношении мне наиболее нравится Ada: все строго, четко.


Ленивости и в современном Шарпе хватает, причем в Шарпе она почему-то опять сделана через жопу... непонятно даже через что сделана.
Списки проще всего обрабатывать через паттерн матчинг или хотя бы даже обычным перебором.

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


Тебе говорят — как только начнешь писать на Немерле, то поймешь и преимущества.
Ты говоришь — я могу начать писать на Немерле, когда пойму преимущества.
Это нормально. Этакий замкнутый круг. Тут есть два варианта:

1. Забить
2. Поверить на слово тем, кто говорит о преимуществах и начать писать. Учитывая, что и правда для перехода на "императивный Немерле" требуется день от силы.

Решать тебе

M>И как этот пример реализовать на чистом ФЯ без mutable? Меня можно расстрелять, но я этого не сделаю. Или это будет очень долгий труд...


Задача, которую ты описывал, — это по сути реализация компилятора. Это чуть ли не "родная" для ФП задача. Для нее очень очень хорошо подходят алгебраические типы и ПМ. Я думаю несложно нагуглить примеры, показывающие решение схожих задач.
Re[11]: Что такого привлекательного в Nemerle?
От: WolfHound  
Дата: 31.03.10 13:07
Оценка: +2
Здравствуйте, Mystic, Вы писали:

M>Смотря на функциональный код я могу на время стать компилятором и перевести его в результате в набор машинных инструкций, и только тогда понять, что он делает.

Вот в этом и проблема.
Пока не научишся понимать функциюнальщину не компилируя код в машинные инструкции толку от функциональных языков для тебя не будет.
Тебе нужно усвоить разницу между императивщиной и функциональщиной.
Императивщина это последовательность команд изменяющих данные.
Функциональщина это последовательность функций отображающих одни данные в другие данные.
Тебе нужно сменить первый способ мышления на второй. Тогда ты поймешь функциональщину.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 13:37
Оценка: 189 (3)
Здравствуйте, Mystic, Вы писали:

Посмотрел еще раз твой первоначальный код. Все же до конца не уверен, что правильно понял задачу. Есть комбинация карт и надо вычислить некий числовой эквивалент, как бы силу комбинации.
В покере не силен, как и в Немерле, но на функциональный манер получается что-то типа:

using System;
using System.Console;
using CardCombination;
using Card;
using CardSuit;

enum CardSuit
{
    | V = 13
    | Q = 14
    | K = 15
    | T = 16
}

variant Card 
{
    | Plain { v: int }
    | High { s: CardSuit }
    
    public GetRank() : int
    {
        match (this)
        {
            | Plain(v) => v
            | High(s) => s :> int
        }
    }
}

variant CardCombination
{
    | Single { c: Card }
    | Pair { c: Card }
    | TwoPair { p1: Pair; p2: Pair }
    | Three { c: Card }
    | Street { c: Card }
    | Flush { c: Card }
    | Full { c: Card }
    | Four { c: Card }
    | StreetFlush { c: Card }
    
    public GetRank() : int
    {
        match (this)
        {
            | Single(c) => c.GetRank()
            | TwoPair(p1, p2) => p1.GetRank() + p2.GetRank()
            | Pair(c) with r = 0x20 | Three(c) with r = 0x80
            | Street(c) with r = 0x100 | Flush(c) with r = 0x200
            | Full(c) with r = 0x300 | Four(c) with r = 0x400
            | StreetFlush(c) with r = 0x500 => c.GetRank() + r
        }
    }
}

module Program
{
    Main() : void
    {
        def GetRank(c) { 
            | [] => 0 | x::xs => x.GetRank() + GetRank(xs)
        }
    
        def cards = Pair(High(V)) :: Single(High(Q)) :: 
            Single(Plain(6)) :: Single(High(T)) :: [];        
        _ = WriteLine(GetRank(cards));
        
        _ = ReadLine(); //Да, а обновление я так и не скачал
    }    
}
Re[6]: Что такого привлекательного в Nemerle?
От: AngeL B. Россия  
Дата: 31.03.10 16:59
Оценка:
Здравствуйте, VladD2, Вы писали:

H>>Нашел: Type Inference with Deferral

VD>Ага. Но человеческим это можно назвать только если ты из научной среды .

А вот, кстати, совсем не праздный вопрос.
Учитывая куда (на майкрософт) ведет ссылка, описывающая алгоритм вывода типов в языке, не является ли это бомбой под будущем языка? Ведь они там могут и запатентовать его (тьфу-тьфу-тьфу и по дереву постучал).
Re[7]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 17:25
Оценка:
Здравствуйте, AngeL B., Вы писали:

AB>А вот, кстати, совсем не праздный вопрос.

AB>Учитывая куда (на майкрософт) ведет ссылка, описывающая алгоритм вывода типов в языке, не является ли это бомбой под будущем языка? Ведь они там могут и запатентовать его (тьфу-тьфу-тьфу и по дереву постучал).

Я не юрист, но мне кажется, что код, который уже выпущен под опен-сорс лицензией, нельзя "отозвать обратно". Если я, скажем, придумаю некий алгоритм и открою исходники, то все, после этого я могу конечно патентовать, мне никто не мешает, но засудить тех, кто уже использует мои исходники (вместе с алгоритмом) я не могу, так они получили все это добро по вполне законной лицензии.
Но могу ошибаться, тонкостей не знаю
Re[7]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 18:04
Оценка:
Здравствуйте, AngeL B., Вы писали:

AB>А вот, кстати, совсем не праздный вопрос.

AB>Учитывая куда (на майкрософт) ведет ссылка, описывающая алгоритм вывода типов в языке, не является ли это бомбой под будущем языка? Ведь они там могут и запатентовать его (тьфу-тьфу-тьфу и по дереву постучал).

Ссылка ведет на работу Михаля Москаля — одного из авторов Немерле. Эта же работа доступна на сайте Немерла.

Весь код Немерла опубликован под MIT-подобной лицензией и стало быть может меняться как угодно. Что до алгоритмов, то в нашей стране они даже не патентуются.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Что такого привлекательного в Nemerle?
От: Jack128  
Дата: 31.03.10 18:27
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>В покере не силен,


ВВ>enum CardSuit

ВВ>{
ВВ> | V = 13
ВВ> | Q = 14
ВВ> | K = 15
ВВ> | T = 16
ВВ>}
ВВ>[/c#]

не картежник ты -) Валет — Jack, а туз — Ace -)
Re[12]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 18:40
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>В покере не силен, как и в Немерле, но на функциональный манер получается что-то типа:...


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

Кстати, в Немерле особо рулит (на мой взгляд) табличное форматирование. Сравни...
Без него:
variant CardCombination
{
    | Single { c: Card }
    | Pair { c: Card }
    | TwoPair { p1: Pair; p2: Pair }
    | Three { c: Card }
    | Street { c: Card }
    | Flush { c: Card }
    | Full { c: Card }
    | Four { c: Card }
    | StreetFlush { c: Card }
    
    public GetRank() : int
    {
        match (this)
        {
            | Single(c) => c.GetRank()
            | TwoPair(p1, p2) => p1.GetRank() + p2.GetRank()
            | Pair(c) with r = 0x20 | Three(c) with r = 0x80
            | Street(c) with r = 0x100 | Flush(c) with r = 0x200
            | Full(c) with r = 0x300 | Four(c) with r = 0x400
            | StreetFlush(c) with r = 0x500 => c.GetRank() + r
        }
    }
}


С ним:
variant CardCombination
{
    | Single      { card  : Card }
    | Pair        { card  : Card }
    | TwoPair     { pair1 : Pair;  pair2 : Pair }
    | Three       { card  : Card }
    | Street      { card  : Card }
    | Flush       { card  : Card }
    | Full        { card  : Card }
    | Four        { card  : Card }
    | StreetFlush { card  : Card }
    
    public GetRank() : int
    {
        match (this)
        {
            | Single(c)                     => c.GetRank()
            | TwoPair(p1, p2)               => p1.GetRank() + p2.GetRank()
            | Pair(c)        with r = 0x20
            | Three(c)       with r = 0x80
            | Street(c)      with r = 0x100
            | Flush(c)       with r = 0x200
            | Full(c)        with r = 0x300
            | Four(c)        with r = 0x400
            | StreetFlush(c) with r = 0x500 => c.GetRank() + r
        }
    }
}

Ну, и однобуквенные имена полей, на мой взгляд, не плохое решение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 19:02
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>В покере не силен, как и в Немерле, но на функциональный манер получается что-то типа:...

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

Мне, честно говоря, тоже в лом было в императивной разбираться

VD>Ну, и однобуквенные имена полей, на мой взгляд, не плохое решение.


В первоначальном варианте вообще все было в строчку написано. F# в этом плане очень хороший язык, неплохо дисциплинирует.
К слову, вариант на F#:

#light

type CardSuit =
   | V = 13 
   | Q = 14
   | K = 15
   | T = 16

type Card =
    | Plain of int
    | High of CardSuit
with member c.GetRank() =
        match c with
        | Plain(v) -> v
        | High(s) -> (int)s

type CardCombination =
    | Single of Card
    | Pair of Card
    | TwoPair of CardCombination*CardCombination
    | Three of Card
    | Street of Card
    | Flush of Card
    | Full of Card
    | Four of Card
    | StreetFlush of Card
with member c.GetRank() =
        match c with
        | Single(c) -> c.GetRank()
        | TwoPair(p1, p2) -> p1.GetRank() + p2.GetRank()
        | Pair(c) -> c.GetRank() + 0x20 
        | Three(c) -> c.GetRank() + 0x80
        | Street(c) -> c.GetRank() + 0x100 
        | Flush(c) -> c.GetRank() + 0x200
        | Full(c) -> c.GetRank() + 0x300 
        | Four(c) -> c.GetRank() + 0x400
        | StreetFlush(c) -> c.GetRank() + 0x500

let rec getRank (c:list<CardCombination>) = 
    match c with
    | [] -> 0 
    | x::xs -> x.GetRank() + (xs |> getRank)
      
let cards = Pair(High(CardSuit.V)) :: Single(High(CardSuit.Q)) :: Single(Plain(6)) :: Single(High(CardSuit.T)) :: []
let res = getRank cards


По-моему не такие уж большие отличия по синтаксису. Хотя вот почему-то он меня заставил аннотацию типа для функции написать
А вот если писать на F# в стиле class based OOP это будет, конечно, кошмар
Re[14]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 19:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:


ВВ>В первоначальном варианте вообще все было в строчку написано. F# в этом плане очень хороший язык, неплохо дисциплинирует.


В F# табличное форматирование тоже было бы очень полезно.

ВВ>...По-моему не такие уж большие отличия по синтаксису.


Дык ты в основном пользовался алгебраическими типами которые у обоих языков позаимствованы из ML-я. Если в Немерле еще указать "#pragma indent", то вообще очень похоже будет.

ВВ>Хотя вот почему-то он меня заставил аннотацию типа для функции написать


Кто? F#?

ВВ>А вот если писать на F# в стиле class based OOP это будет, конечно, кошмар


Ага. С ФП у него намного лучше чес с ООП и МП. Это следствие того, что язык не проектировался с нуля, а является адаптацией OCaml-а. У создателей OCaml-а был свой, весьма своеобразный взгляд на ООП (функциональный).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Что такого привлекательного в Nemerle?
От: kochetkov.vladimir Россия https://kochetkov.github.io
Дата: 31.03.10 19:57
Оценка:
Здравствуйте, AngeL B., Вы писали:

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


H>>>Нашел: Type Inference with Deferral

VD>>Ага. Но человеческим это можно назвать только если ты из научной среды .

AB>А вот, кстати, совсем не праздный вопрос.

AB>Учитывая куда (на майкрософт) ведет ссылка, описывающая алгоритм вывода типов в языке, не является ли это бомбой под будущем языка? Ведь они там могут и запатентовать его (тьфу-тьфу-тьфу и по дереву постучал).

Они не смогут запатентовать то, что было реализовано и опубликовано не ими до подачи их гипотетической заявки на патент. А если смогут, то такой патент без проблем оспаривается.
... << RSDN@Home 1.2.0 alpha 4 rev. 1446>>

[Интервью] .NET Security — это просто
Автор: kochetkov.vladimir
Дата: 07.11.17
Re[15]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 20:41
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>...По-моему не такие уж большие отличия по синтаксису.

VD>Дык ты в основном пользовался алгебраическими типами которые у обоих языков позаимствованы из ML-я. Если в Немерле еще указать "#pragma indent", то вообще очень похоже будет.

Вот тут есть интересный момент. Как только на Немерле начинаешь писать в функциональном стиле, то он плавным движением руки превращается в ML.
А вот у той же Скалы совсем другая философия — она вообще выглядит так, как будто в ней функциональные конструкции имитируются через ООП. Даже не знаю, как сказать точно. Может быть, некоторых пугает такая двойственность Немерле

ВВ>>Хотя вот почему-то он меня заставил аннотацию типа для функции написать

VD>Кто? F#?

Ну да.

ВВ>>А вот если писать на F# в стиле class based OOP это будет, конечно, кошмар

VD>Ага. С ФП у него намного лучше чес с ООП и МП. Это следствие того, что язык не проектировался с нуля, а является адаптацией OCaml-а. У создателей OCaml-а был свой, весьма своеобразный взгляд на ООП (функциональный).

Да вообще с их явным порядком файлов и плоской структурой проекта что-то большое на F# писать запаришься.

ЗЫ. Кстати, вот как выглядит вышепоказанный пример на моем интерпретаторе:

let (V, Q, K, T) = (13, 14, 15, 16);
type Card = Plain(v) | High(v);
    
let GetCardRank = c -> 
    match (c)
    | Plain(v) -> v
    | High(v) -> v;
        
type Comb =
    Single(c) | Pair(c) | TwoPair(p1, p2) | Three(c) | Street(c)
    | Flush(c) | Full(c) | Four(c) | StreetFlush(c);
    
let GetRank = cc ->
    match (cc)
    | Single(c) -> GetCardRank(c)
    | TwoPair(p1, p2) -> GetRank(p1) + GetRank(p2)
    | Pair(c) with r = 0x20 
    | Three(c) with r = 0x80
    | Street(c) with r = 0x100 
    | Flush(c) with r = 0x200
    | Full(c) with r = 0x300 
    | Four(c) with r = 0x400
    | StreetFlush(c) with r = 0x500 -> GetCardRank(c) + r;

let CalcRank = l -> match(l)
    | [] -> 0 | x::xs -> GetRank(x) + CalcRank(xs);
        
let cards = Comb.Pair(Card.High(V)) ::
    Comb.Single(Card.High(Q)) :: 
    Comb.Single(Card.Plain(6)) :: 
    Comb.Single(Card.High(T)) :: [];    

CalcRank(cards);
Re[13]: Что такого привлекательного в Nemerle?
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 31.03.10 20:48
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кстати, в Немерле особо рулит (на мой взгляд) табличное форматирование.


Однозначно рулит. Делает программирование на Немерле в Виме особенно приятным.
Ce n'est que pour vous dire ce que je vous dis.
Re[16]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 22:04
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>А вот у той же Скалы совсем другая философия — она вообще выглядит так, как будто в ней функциональные конструкции имитируются через ООП. Даже не знаю, как сказать точно. Может быть, некоторых пугает такая двойственность Немерле


На самом деле Скала и Немерл идеологически очень похожи. В немерле тоже ФП выражается через ОО-конструкции. У скалы есть свои преимущество, но у нее нет одной мелочи — макросов. А эта мелочь дорогого стоит.

ВВ>>>Хотя вот почему-то он меня заставил аннотацию типа для функции написать

VD>>Кто? F#?

ВВ>Ну да.


А что говорит?

ВВ>Да вообще с их явным порядком файлов и плоской структурой проекта что-то большое на F# писать запаришься.


Ну, на ОКамле ведь писали? Это конечно неудобно и непривычно но не смертельно. И вообще, главный козырь это не фичи языка, а декларированная поддержка МС.

ВВ>ЗЫ. Кстати, вот как выглядит вышепоказанный пример на моем интерпретаторе:


А зачем ты его создавал?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 22:10
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Однозначно рулит. Делает программирование на Немерле в Виме особенно приятным.


Я напрочь испорчен интеллисенсм. Моя продуктивность без него на порядки ниже.

А в Виме есть фичи облегчающие табличное форматирование?
Как они работают?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 31.03.10 22:11
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>>>Хотя вот почему-то он меня заставил аннотацию типа для функции написать

VD>>>Кто? F#?
ВВ>>Ну да.
VD>А что говорит?

Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.

ВВ>>ЗЫ. Кстати, вот как выглядит вышепоказанный пример на моем интерпретаторе:

VD>А зачем ты его создавал?

Кризис среднего возраста видимо Хочется написать свой язык программирования. Да и 100% managed embeddable script штука вообще полезная.
Re[18]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.03.10 22:39
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.


Попробуй поменять местами строки:
    | [] -> 0 
    | x::xs -> x.GetRank() + (xs |> getRank)


ВВ>Кризис среднего возраста видимо Хочется написать свой язык программирования.


Лучше помог бы нам в работе над Nemerle 2.

ВВ>Да и 100% managed embeddable script штука вообще полезная.


Дык есть железные Питон и Руби же. Плюс джава скрип никто не отменял.

К тому же в качестве такового можно и немерл использовать. Как видишь по количеству кода он очень то уступает скриптам, а по скорости и надежности сильно их превосходит. Макросы позволяют интегрировать в язык нужные DSL-и, что резко повышает уровень скрипта.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Что такого привлекательного в Nemerle?
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 31.03.10 23:32
Оценка: 15 (1)
Здравствуйте, VladD2, Вы писали:

VD>Я напрочь испорчен интеллисенсм. Моя продуктивность без него на порядки ниже.


Я ещё много пишу в С++, где интеллисенс реже работает, чем нет.

VD>А в Виме есть фичи облегчающие табличное форматирование?

VD>Как они работают?

Для Вима есть скрипт Align с широким набором форматов табличного выравнивания. С ним можно выделить блок текста, набрать \tsp и текст будет выравнен в таблицу с колонками разделёнными пробелами; \t= выравнивнивает по знакам =, а \t: по двоеточиям. Есть специальные шаблоны для выравнивания комментариев, объявлений функций, HTML таблиц и многого другого.
Ce n'est que pour vous dire ce que je vous dis.
Re[10]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 07:34
Оценка:
Здравствуйте, Воронков Василий, Вы писали:


ВВ>Поощряет или нет, но в императивном стиле на Немерле писать практически так же удобно, как и на Шарпе — особенно по сравнению с тем же F#, который, к слову, тоже позиционируется как гибридный язык.


А какие проблемы у F# с императивным кодом?
Я вот сейчас на OCaml, гоню сплошной императивный код (оптимизация) никаких неудобств не вижу.
Re[17]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 07:55
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>Да вообще с их явным порядком файлов и плоской структурой проекта что-то большое на F# писать запаришься.


VD>Ну, на ОКамле ведь писали? Это конечно неудобно и непривычно но не смертельно. И вообще, главный козырь это не фичи языка, а декларированная поддержка МС.


Так я опять что-то пропустил?
На OСaml никакой плоской структуры не наблюдается, вложенные модули без проблем. Есть небольшие проблем с линкером при циклических ссылках и все, на F# что опять все испортили?
Re[12]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 01.04.10 08:57
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


ВВ>Посмотрел еще раз твой первоначальный код. Все же до конца не уверен, что правильно понял задачу. Есть комбинация карт и надо вычислить некий числовой эквивалент, как бы силу комбинации.


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

ВВ>        def cards = Pair(High(V)) :: Single(High(Q)) :: 
ВВ>            Single(Plain(6)) :: Single(High(T)) :: [];


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



Но в двух словах про задачу, которую решал я:

Есть такой софт, который называется покерный калькулятор. Задача состоит в том, чтобы подсчитать вероятность победы одного из игроков, если оба дойдут до конца раздачи. Способ решения обычный перебор. Например, у меня есть две карты на руках, у соперника есть две карты на руках. И еще есть пять закрытых карт. Это порядка 1.7M комбинаций. Обычно задача калькулятора состоит в том, чтобы перебрать все эти комбинации и выдать количество побед первого игрока, количество побед второго игрока, количество ничьих и выдать проценты. Естественно, что определение достоинства комбинации должно быть реализовано максимально быстро (в частности PokerStove выполняет указанный перебор за доли секунды).

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

Изначально задача стояла в том, чтобы перечислить все возможные покерные комбинации в порядке от самой сильной к самой слабой, и для каждой из них вычислить уникальный хэш. Список должен быть таким: AKQJTs, KQJT9s, ..., 65432s, A5432s, AAAAK, AAAAQ, ..., AAAA2, KKKKA, KKKKQ, ... (всего 7462 комбинаций, s в конце означает, что все карты одной масти — suited). Это и делает мой код на C#.
Re[13]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 01.04.10 08:59
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Что-то мне кажется, что это совсем разные программы
Re[11]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 10:10
Оценка:
Здравствуйте, FR, Вы писали:

ВВ>>Поощряет или нет, но в императивном стиле на Немерле писать практически так же удобно, как и на Шарпе — особенно по сравнению с тем же F#, который, к слову, тоже позиционируется как гибридный язык.


FR>А какие проблемы у F# с императивным кодом?

FR>Я вот сейчас на OCaml, гоню сплошной императивный код (оптимизация) никаких неудобств не вижу.

Думаю, что он имел в виду ОО-стиль.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 10:14
Оценка:
Здравствуйте, FR, Вы писали:

FR>На OСaml никакой плоской структуры не наблюдается, вложенные модули без проблем. Есть небольшие проблем с линкером при циклических ссылках и все, на F# что опять все испортили?


Разве необходимость объявлять типы перед тем как они используются — это придумка F#-а? Я в ОКамле не силен, но что-то мне казалось, что это из него пошло.

В прочем, может быть это проблемы расширения алгоритма вывода типов сделанного в F#.


Что до модулей, то в F# модуль — это сборка. А сборки в дотнете сильно боше чем модули (юниты) в других языках. И вот в их рамках F# обязывает располагать типы последовательно. А так как он позволяет их разносить по отдельным файлам, то требуют располагать файлы в определенной последовательности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 10:20
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Что-то мне кажется, что это совсем разные программы


Возможно. Но из твоей понять суть алгоритма очень сложно. А из его элементарно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 10:31
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Разве необходимость объявлять типы перед тем как они используются — это придумка F#-а? Я в ОКамле не силен, но что-то мне казалось, что это из него пошло.


Необходимость объявлять есть, но также есть возможность предварительного (неконкретизированного) объявления типов и сигнатур функций. Для этого есть .mli файлы во многом аналог сишных заголовочных файлов.

Например в .mli такое объявление:

type command 

val command: ?doc:string -> string -> Arg.spec -> command


в .ml конкретизация:

type command =
    { doc : string(**The documentation associated to the keyword, possibly empty.*);
      kwd : string(**The keyword. Should start with "-"*);
      spec : Arg.spec (**The behavior associated to the keyword*);
    }

let command ?(doc="") kwd spec =
  { doc = doc;
    kwd = kwd;
    spec= spec }



VD>В прочем, может быть это проблемы расширения алгоритма вывода типов сделанного в F#.



VD>Что до модулей, то в F# модуль — это сборка. А сборки в дотнете сильно боше чем модули (юниты) в других языках. И вот в их рамках F# обязывает располагать типы последовательно. А так как он позволяет их разносить по отдельным файлам, то требуют располагать файлы в определенной последовательности.


В OCaml подобная заморочка есть только у линкера, в исходном же коде можно произвольно располагать.
Re[20]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 10:41
Оценка:
Здравствуйте, FR, Вы писали:

FR>Необходимость объявлять есть,


Ну, вот отсюда ноги и растут. Будучи помноженным на объем дотнетных сборок получается форменная проблема.

FR>но также есть возможность предварительного (неконкретизированного) объявления типов и сигнатур функций. Для этого есть .mli файлы во многом аналог сишных заголовочных файлов.


Да какая разница? Все равно важно файлы в определенной последовательности держать или держать все в одном файле и уже в нем последовательность отслеживать.

В ОКамле, возможно, остроту проблемы снимало тот факт, что модули ОКамла значительно меньше модулей дотнета (сборок).
Зато в ОКамле дургих проблем хватает. Невозможность создать перегрузку и т.п.

FR>Например в .mli такое объявление:


FR>
FR>type command 

FR>val command: ?doc:string -> string -> Arg.spec -> command
FR>


Ужас. Каменный век.

FR>В OCaml подобная заморочка есть только у линкера, в исходном же коде можно произвольно располагать.


Ну, как же произвольно если ты сам выше сказал, что типы должно быть известны заранее?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 01.04.10 11:12
Оценка:
Здравствуйте, VladD2, Вы писали:

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


M>>Что-то мне кажется, что это совсем разные программы


VD>Возможно. Но из твоей понять суть алгоритма очень сложно. А из его элементарно.


Без нужного опыта совсем неэлементарно. Но после некоторого вникания в код у меня возникла мысль, что данный исходник просто считает взвешенную сумму элементов списка.
Re[13]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 01.04.10 12:10
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Изначально задача стояла в том, чтобы перечислить все возможные покерные комбинации в порядке от самой сильной к самой слабой, и для каждой из них вычислить уникальный хэш. Список должен быть таким: AKQJTs, KQJT9s, ..., 65432s, A5432s, AAAAK, AAAAQ, ..., AAAA2, KKKKA, KKKKQ, ... (всего 7462 комбинаций, s в конце означает, что все карты одной масти — suited). Это и делает мой код на C#.


Если речь идет о том, что все карты даны в произвольном порядке и не сгруппированы, то проще всего их вначале отсортировать
Потом ты можешь построить матч по образцу голова-хвост (x::y::xs::..) и перебрать там все основные комбинации (матч эвалюируется последовательно) — пара, тройка, четверка, стрит.
Re[11]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 01.04.10 12:14
Оценка: 1 (1)
Здравствуйте, FR, Вы писали:

FR>А какие проблемы у F# с императивным кодом?

FR>Я вот сейчас на OCaml, гоню сплошной императивный код (оптимизация) никаких неудобств не вижу.

Проблем нет. Но чтобы писать императивно на F#, придется потратить куда больше времени на изучение F#, чем в случае с Немерле, где императивный код очень похож на таковой в шарпе.
Re[14]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 01.04.10 12:30
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Если речь идет о том, что все карты даны в произвольном порядке и не сгруппированы, то проще всего их вначале отсортировать

ВВ>Потом ты можешь построить матч по образцу голова-хвост (x::y::xs::..) и перебрать там все основные комбинации (матч эвалюируется последовательно) — пара, тройка, четверка, стрит.

Это долго. Если, например, я выпущу какой-нить покерный калькулятор, который будет в 10 раз медленнее бесплатных аналогов, то кого он заинтересует? Пусть даже и будут дополнительные возможности В общем максимальная производительность будем считать требованием, прописанным в ТЗ.

В общем случае используется такой трюк: каждому достоинству карты сопоставляется простое число. Например, двойке сопоставляется 2, тройке — 3, четверке — 5, пятерке — 7, шестерке — 11, семерке — 13, восьмерке — 17, девятке — 19, десятке — 23, валету — 29, даме — 31, королю — 37, тузу — 41. Тогда (если не учитывать флеш) одинаковые по старшинству комбинации будут иметь одинаковое произведения этих простых чисел. Т. е. для того, чтобы определить старшинство комбинации надо будет четыре умножений + одно обращение к таблице. В случае возможного флеша (видно по таблице CMP) необходимо будет выполнить проверку на флеш (четыре OR + AND + CMP) и взять из таблицы другое значение. Итого для вычисления достоинства комбинации нам придется потратить от 10 (не флеш) до 20 (флеш) машинных инструкций плюс одно-два ветвления.

Другое дело, что эту таблицу надо сформировать, возможно оптимизировать по размеру... Это некритичная ко времени задача вполне может быть написана на том средстве, которое для этого будет наиболее удобным. Вот эту утилиту я и реализовывал.
Re[21]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 12:32
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, вот отсюда ноги и растут. Будучи помноженным на объем дотнетных сборок получается форменная проблема.


Так я все-таки похоже торможу. В C# (и в Немерли) тоже ведь необходимо предварительное объявление, в чем же разница с F#?

FR>>но также есть возможность предварительного (неконкретизированного) объявления типов и сигнатур функций. Для этого есть .mli файлы во многом аналог сишных заголовочных файлов.


VD>Да какая разница? Все равно важно файлы в определенной последовательности держать или держать все в одном файле и уже в нем последовательность отслеживать.


Все таки непонятно, можно проиллюстрировать на примере?

VD>В ОКамле, возможно, остроту проблемы снимало тот факт, что модули ОКамла значительно меньше модулей дотнета (сборок).


Ну большущие модули там тоже есть например в ocaml-win32.

VD>Зато в ОКамле дургих проблем хватает. Невозможность создать перегрузку и т.п.


Это-то тут причем?

VD>Ужас. Каменный век.


В чем тут каменный век-то?

FR>>В OCaml подобная заморочка есть только у линкера, в исходном же коде можно произвольно располагать.


VD>Ну, как же произвольно если ты сам выше сказал, что типы должно быть известны заранее?


Мы в чем-то друг-друга так и не поняли.
Re[12]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 12:35
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Проблем нет. Но чтобы писать императивно на F#, придется потратить куда больше времени на изучение F#, чем в случае с Немерле, где императивный код очень похож на таковой в шарпе.


Если в F# не расширили императивное подмножество в сравнении с OCaml'ом то там практически нечего изучать, по сути классический паскаль
Re[15]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 01.04.10 13:35
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Если речь идет о том, что все карты даны в произвольном порядке и не сгруппированы, то проще всего их вначале отсортировать

ВВ>>Потом ты можешь построить матч по образцу голова-хвост (x::y::xs::..) и перебрать там все основные комбинации (матч эвалюируется последовательно) — пара, тройка, четверка, стрит.

M>Это долго. Если, например, я выпущу какой-нить покерный калькулятор, который будет в 10 раз медленнее бесплатных аналогов, то кого он заинтересует? Пусть даже и будут дополнительные возможности В общем максимальная производительность будем считать требованием, прописанным в ТЗ.


Тебе же таблицу надо генерить. Так казалось бы зачем производительность коду, который генерит таблицу? Запустил его один раз, отработал — и все.
Плюс ты недооцениваешь производительность ФП-кода. Единственная проблема матчей в том, что они не компилируются в джамп-таблицу, но у тебя самого джамп-таблицей и не пахнет. В остальном Немерле очень неплохо оптимизирует матчи. Наконец он поддерживает оптимизацию хвостовой рекурсии. Так что производительность может быть более чем приемлимая.

Основная философия ФП — никакой premature optimization
Re[19]: Что такого привлекательного в Nemerle?
От: Воронков Василий Россия  
Дата: 01.04.10 13:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Попробуй поменять местами строки:

VD>
VD>    | [] -> 0 
VD>    | x::xs -> x.GetRank() + (xs |> getRank)
VD>


Не помогает. Видимо, не сдюжил таки вывод типов.

ВВ>>Кризис среднего возраста видимо Хочется написать свой язык программирования.

VD>Лучше помог бы нам в работе над Nemerle 2.

Немерле 2? А чем это отличается от просто Немерле? С нуля хотите переделать что ли?

ВВ>>Да и 100% managed embeddable script штука вообще полезная.

VD>Дык есть железные Питон и Руби же. Плюс джава скрип никто не отменял.

Джава скрипт достал К тому же скрипт с полноценной поддержкой ФП все же явление редкое.
Ну и наконец надо же вначале "на собаках" потренироваться

VD>К тому же в качестве такового можно и немерл использовать. Как видишь по количеству кода он очень то уступает скриптам, а по скорости и надежности сильно их превосходит. Макросы позволяют интегрировать в язык нужные DSL-и, что резко повышает уровень скрипта.


Дело не в краткости кода. Во многих случаях компиляция вносит очень сильный оверхед. Это если речь идет именно о встраиваемом скрипте, который можно поменять на лету и перезапустить.
В таком сценарии Немерле мне кажется не очень подойдет, очень уж тяжелая сборка у него.
Re[20]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 14:32
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

VD>>Попробуй поменять местами строки:

VD>>
VD>>    | [] -> 0 
VD>>    | x::xs -> x.GetRank() + (xs |> getRank)
VD>>


ВВ>Не помогает. Видимо, не сдюжил таки вывод типов.


А попробуй уточнить тип у "[]". Просто интересна причина.

ВВ>Немерле 2? А чем это отличается от просто Немерле? С нуля хотите переделать что ли?


Отличия будут не очень большими, но очень полезными. Во-первых, хотим заменить подсистему парсинга сделав ее декларативной на основе PEG. Это позволит снять большинство ограничений и сделать синтаксис более расширяемым. Во-вторых, хотим переписать на бело, так чтобы избавиться от имеющихся проблем. В частности сделать движок компилятора многопоточным, версионным, чтобы не было проблем в интеграции и извлекалась выгода от многоголовых камней современных процессоров. Кроме того попросту нужно переписать компилятор, чтобы он был более понятным и легко изменяемым.

ВВ>Джава скрипт достал К тому же скрипт с полноценной поддержкой ФП все же явление редкое.


Эрланг — весьма популярен в узких кругах.

ВВ>Ну и наконец надо же вначале "на собаках" потренироваться


Тренироваться лучше на кошках. Вот Немерл — отличный пушистый котенок с больным животиком. Можно мучить сколько угодно, хозяева даже не заметят .

ВВ>Дело не в краткости кода. Во многих случаях компиляция вносит очень сильный оверхед. Это если речь идет именно о встраиваемом скрипте, который можно поменять на лету и перезапустить.


Это не проблема. Компилятор полностью менеджед. Мелкие куски компилируются в мгновение ока. Зато скорость на уровне шарпа.

ВВ>В таком сценарии Немерле мне кажется не очень подойдет, очень уж тяжелая сборка у него.


А какая реальная задача то?

ЗЫ

Я (да и многие другие) использую немерл в весьма скриптовых целях уже несколько лет. Получается весьма не плохо. В прочем, я уже неплохо с ним знаком...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[22]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 14:39
Оценка:
Здравствуйте, FR, Вы писали:

FR>Так я все-таки похоже торможу. В C# (и в Немерли) тоже ведь необходимо предварительное объявление, в чем же разница с F#?


Нет, такой необходимости нет. Тип просто должен быть. А где совершенно не важно. Предварительное объявление нужно только для локальных переменных и локальных функций. Но на то они и локальные.

FR>Все таки непонятно, можно проиллюстрировать на примере?


Представ. У тебя два типа в разных файлах. Если один использует второй, то или этот второй должен находиться в файле идущем по порядку раньше, или ты вынужден будешь внести его описание в первый файл. В любом случае получается зависимость от расположения.

В Немерле и Шарпе я могу объявить один тип в одном файле, а другой в другом. И мне будет совершенно все равно где и как расположены файлы. Я всегда смогу использовать один тип из другого (в том числе рекурсивно) без дополнительных объявлений и каких бы то ни было лишних телодвижений.

VD>>Зато в ОКамле дургих проблем хватает. Невозможность создать перегрузку и т.п.


FR>Это-то тут причем?


В F# перегрузка поддерживается. Не так полноценно как в Nemerle или C#, но все же. Это позволяет намного проще интегрироваться с дотнетом и си-подобными языками. Но алгоритм вывода типов при этом резко усложняется.

VD>>Ужас. Каменный век.


FR>В чем тут каменный век-то?


В наличии предеклараций. Это было простительно для С/С++ учитываях дремучесть их просхождения. Но в языке высокого уровня это просто жутко выглядит.

FR>>>В OCaml подобная заморочка есть только у линкера, в исходном же коде можно произвольно располагать.


VD>>Ну, как же произвольно если ты сам выше сказал, что типы должно быть известны заранее?


FR>Мы в чем-то друг-друга так и не поняли.


Видимо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 15:30
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Нет, такой необходимости нет. Тип просто должен быть. А где совершенно не важно. Предварительное объявление нужно только для локальных переменных и локальных функций. Но на то они и локальные.


Вообще-то в OCaml также, просто нужно использовать <имя модуля>.<функция> например Printf.printf никакого предварительного объявления типа open Printf при этом не нужно. Но ограничения на взаиморекурсивность все-таки есть.

FR>>Все таки непонятно, можно проиллюстрировать на примере?


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


Да такое есть, но только для линкера в сборочном файле важен порядок следования модулей, в исходниках этого не видно.

VD>В Немерле и Шарпе я могу объявить один тип в одном файле, а другой в другом. И мне будет совершенно все равно где и как расположены файлы. Я всегда смогу использовать один тип из другого (в том числе рекурсивно) без дополнительных объявлений и каких бы то ни было лишних телодвижений.


Если не рекурсивно то и в Ocaml также.

FR>>В чем тут каменный век-то?


VD>В наличии предеклараций. Это было простительно для С/С++ учитываях дремучесть их просхождения. Но в языке высокого уровня это просто жутко выглядит.


Предекларации опциональны. Не хочешь не используешь.
Re[24]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 16:12
Оценка: +1
Здравствуйте, FR, Вы писали:

FR>Вообще-то в OCaml также, просто нужно использовать <имя модуля>.<функция> например Printf.printf никакого предварительного объявления типа open Printf при этом не нужно. Но ограничения на взаиморекурсивность все-таки есть.


Мне не слышат? В F# модулем является сборка! Так что считай, что большая часть кода программы у тебя в одном модуле.

FR>Да такое есть, но только для линкера в сборочном файле важен порядок следования модулей, в исходниках этого не видно.


Ну, а как это задать в проекте? Или ты мэйком пользуешся?

VD>>В Немерле и Шарпе я могу объявить один тип в одном файле, а другой в другом. И мне будет совершенно все равно где и как расположены файлы. Я всегда смогу использовать один тип из другого (в том числе рекурсивно) без дополнительных объявлений и каких бы то ни было лишних телодвижений.


FR>Если не рекурсивно то и в Ocaml также.


Да не так же. И ты сам об этом говоришь. Я тебе еще раз подчеркиваю, работа ведется в рамках одного модуля. В дотнете видимость типов определяется пространствами иемен. В этом, возможно главное, отличие F#-а от ОКамла.

FR>Предекларации опциональны. Не хочешь не используешь.


Ага. Колхоз дело добровольное. Хочешь вступай, хочешь не вступай. Все равно корову отымим (с).
Так и тут. Хочешь предекларации делай, хочешь описания последовательно выстраивай.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[25]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 01.04.10 16:49
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Мне не слышат? В F# модулем является сборка! Так что считай, что большая часть кода программы у тебя в одном модуле.


Торможу я сегодня
Сижу читаю спецификацию F#, да оказывается не только функторы выкинули

Кстати в OCaml такое вполне легко эмулируется, так как модули не обязаны совпадать с единицами трансляции, в такой единице может быть
сколько угодно (в том числе и взаимно рекурсивных) вложенных модулей. Правда не получится растащить один namespace на несколько разных
единиц трансляции.

FR>>Да такое есть, но только для линкера в сборочном файле важен порядок следования модулей, в исходниках этого не видно.


VD>Ну, а как это задать в проекте? Или ты мэйком пользуешся?


Я да мейком, у меня смесь с С++, а так тот же ocamlbuild все сам разруливает.
Задать просто, определить зависимости и располагать более общие объектники перед их использующими.

VD>Да не так же. И ты сам об этом говоришь. Я тебе еще раз подчеркиваю, работа ведется в рамках одного модуля. В дотнете видимость типов определяется пространствами иемен. В этом, возможно главное, отличие F#-а от ОКамла.


Угу.

VD>Ага. Колхоз дело добровольное. Хочешь вступай, хочешь не вступай. Все равно корову отымим (с).

VD>Так и тут. Хочешь предекларации делай, хочешь описания последовательно выстраивай.

Нет если предеклараций нет, то просто считается что все глобальные объявления ml файла доступны.

.mli позволяет скрыть ненужное. При этом .mli логически это сигнатура (интерфейс модуля):

module A: sig (* содержимое файла a.mli *) end
      = struct (* содержимое файла a.ml *) end;;
Re[26]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.04.10 16:55
Оценка:
Здравствуйте, FR, Вы писали:

FR>Задать просто, определить зависимости и располагать более общие объектники перед их использующими.


Дык это и есть вручную выставить порядок файлов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Что такого привлекательного в Nemerle?
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 01.04.10 18:34
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Тебе же таблицу надо генерить. Так казалось бы зачем производительность коду, который генерит таблицу? Запустил его один раз, отработал — и все.


Я скачу от одной задачи к другой (генерация таблицы и оценивание), отсюда непонятки. Если у нас задача сгенерировать таблицу, то основная проблема не в оценке произвольной руки, а в том, чтобы сгенерировать все возможные 7462 комбинаций. И если мы их сгенерируем в порядке от самой сильной к самой слабой (или наоборот), то у нас автоматически для каждой комбинации будет ее сила. Оценка рук может потребоваться только в том случае, когда мы генерируем все возможные комбинации в произвольном порядке. Но этот вариант мне не очень по душе. Да и как их генерировать все в произвольном порядке я слабо себе представляю, кроме самого лобового решения перебирать все 2598960 сочетаний из 52 по 5.

Если брать конкретно вычисление силы руки на C, то чтобы было понятно, оно ориентировочно будет выглядеть так:

inline int is_flush_5(const card_t* cards)
{
  // Проверяем, все ли карты одной масти. Предполагаем, что масти это степени двойки
  // (например, 0x01 это пики, 0x02 это трефы, 0x04 это бубны и 0x08 это червы

  return cards[0].get_suit() == 
    0
    | cards[1].get_suit()
    | cards[2].get_suit()
    | cards[3].get_suit()
    | cards[4].get_suit()
  ;  
}

inline int evaluate_5(const card_t* cards)
{
  // Вычисляем хэш как произведение простых чисел, которые соответствуют номиналу карты
  // В общем случае номинал карты удобно выражать этим простым числом
  int product = 1
    * cards[0].get_primary_nominal()
    * cards[1].get_primary_nominal()
    * cards[2].get_primary_nominal()
    * cards[3].get_primary_nominal()
    * cards[4].get_primary_nominal()
  ;

  // По хэш-таблице получаем интересующий нас элемент, 
  // MOD используется для оптимизации размера
  // MAGIC_HASH_DIVIDER можно подобрать таким образом, 
  // чтобы все product % MAGIC_HASH_DIVIDER были различны
  hand_info_t* hand_info = magic_hash_table + (product % MAGIC_HASH_DIVIDER);

  // Если не может быть флеша (есть повторы карт), то можно сразу вернуть силу руки
  if (hand_info->no_flush) return hand_info->normal_rank;

  // Может быть флеш, поэтому надо сделать дополнительную проверку
  return is_flush_5(cards) ? hand_info->flush_rank : hand_info->normal_rank;
}


Если, например, предположить, что card_t определен так:

enum nominal_t = 
{
  NOMINAL_2 =  2,
  NOMINAL_3 =  3,
  NOMINAL_4 =  5,
  NOMINAL_5 =  7,
  NOMINAL_6 = 11,
  NOMINAL_7 = 13,
  NOMINAL_8 = 17,
  NOMINAL_9 = 19,
  NOMINAL_T = 23,
  NOMINAL_J = 29,
  NOMINAL_Q = 31,
  NOMINAL_K = 37,
  NOMINAL_A = 41
};

enum suit_t =
{
  SUIT_S = 0x01,
  SUIT_C = 0x02,
  SUIT_D = 0x04,
  SUIT_H = 0x08
};

class card_t
{
public:
  card_t(suit_t suit, nominal_t nominal): _suit(suit), _nominal(nominal) {}
  inline suit_t get_suit() const { return _suit; }
  inline int get_primary_nominal() const { return _nomimal; }
private:
  suit_t _suit;
  nominal_t _nominal;
};


то вычисления сведены к минимуму.



ВВ>Плюс ты недооцениваешь производительность ФП-кода. Единственная проблема матчей в том, что они не компилируются в джамп-таблицу, но у тебя самого джамп-таблицей и не пахнет. В остальном Немерле очень неплохо оптимизирует матчи. Наконец он поддерживает оптимизацию хвостовой рекурсии. Так что производительность может быть более чем приемлимая.


ВВ>Основная философия ФП — никакой premature optimization


Естественно у меня нет никаких match-ей. Мне вообще не нужно вычислять силу комбинации, потому что в том коде, что я приводил раньше, я их сразу генерирую в нужном мне порядке. Вот небольшой анализ:

    
/* Этот код генерирует все 2860 комбинаций "пара" от самой сильной AAKQJ к самой слабой 22543 */

static public void Pair()
{
/* Четыре цикла, каждый в каждом, это самый простой императивный способ генерирования сочетаний. */

  for (int Base = 13; Base >= 1; --Base)
  for (int Kicker1 = 13; Kicker1 >= 1; --Kicker1)
  for (int Kicker2 = Kicker1 - 1; Kicker2 >= 1; --Kicker2)
  for (int Kicker3 = Kicker2 - 1; Kicker3 >= 1; --Kicker3)
  {

    // Небольшие проблемы с порядком (Base учитывается в первую очередь), поэтому
    // надо добавить сравнения
    if (Base == Kicker1) continue;
    if (Base == Kicker2) continue;
    if (Base == Kicker3) continue;

    // Можно добавлять
    AddNormal(Primary[Base] * Primary[Base] * Primary[Kicker1] * Primary[Kicker2] * Primary[Kicker3]);
  }
}


Однажды овладев этим способом генерации сочетаний в лексикографиеском порядке в средней школе я применяю всю жизнь В общем случае, если надо сгенерировать все сочетания c1, c2, c3 в лексикографическом порядке, то самое простое написать

  for(c1 = 0;    c1 <= M; ++c1)
  for(c2 = c1+1; c2 <= M; ++c2)
  for(c3 = c2+1; c3 <= M; ++c3)


В результате мы получим
      0, 1, 2
      0, 1, 3
      0, 1, 4
      ...
      0, 1, M 
      0, 2, 3
      0, 2, 4
      ...
      0, 2, M 

      ...

      M-2, M-1, M


NOTE: Вот в этом случае я особенно надеялся на помощь немерле, как раз в генерации таких сочетаний Например, некоторый могучий макрос

generate_combination(0..M, c1, c2, c3)
{
  Write("{0}, {1}, {2}", c1, c2, c3);
}


где первый параметр список, сочетания (определенной длины) которого мы генерируем. c1, c2, c3 это переменные, куда заносятся текущие значения. Или какой-то трюк со списками... Но ума не хватило Но мой императивный идеал

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

Конечно, небольшой копипаст, но в данном случае он ИМХО оправдан. А в случае императивного Nemerle я представлял в своем больном воображении такой аналог: (синтаксис map взят из головы, вообще больше псевдокод):

generate_combination(map(13..1, x => get_primary(x)), base)
generate_combination(map(13..1, x => get_primary(x)), kicker1, kicker2, kicker3)
{
  if ([base] intersect [kicker1, kicker2, kicker3]) != []) continue; // intersect это пересечение списков
  add_normal(base * base * kicker1 * kicker2 * kicker3); 
}


Ну а до функционального аналога... Я вижу так:

  all_base_combinations = generate_combination_list(map(13..1, x => get_primary(x)), 1);
  // Например, вернули ленивый список всех сочетаний длины 1 в лексикографическом порядке
  // Опять же map беру из головы

  all_kicker_combinations = generate_combination_list(map(13..1, x => get_primary(x)), 3);
  // Например, вернули ленивый список всех сочетаний длины 3 в лексикографическом порядке
  // Результат [ [41, 37, 31], [41, 37, 29], [41, 37, 23], ...]

  foreach(base in all_base_combinations)
    foreach(kickers in all_base_combinations)
    {
      if (intersect(base, kickers) == [])
        add(product(map(base, x => x * x)) * product(kickers));
    }


Хотя есть императивный foreach... Но в принципе от него просто избавиться написав нужные функции обработки списков
Re[27]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 02.04.10 10:53
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Дык это и есть вручную выставить порядок файлов.


Угу если мейком пользуешься, приходится вручную. Системы сборки все сами делают.
Re[26]: Что такого привлекательного в Nemerle?
От: Аноним  
Дата: 02.04.10 14:02
Оценка:
VD>>Мне не слышат? В F# модулем является сборка! Так что считай, что большая часть кода программы у тебя в одном модуле.

FR>Торможу я сегодня

FR>Сижу читаю спецификацию F#, да оказывается не только функторы выкинули

Но модули же есть в спецификации, 10.2 Module definition.
Или это какие-то другие модули?
Re[27]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 02.04.10 15:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Но модули же есть в спецификации, 10.2 Module definition.

А>Или это какие-то другие модули?

Урезанные, как я понял сигнатуры задавать нельзя кроме как в fsi файле (это и понятно без полиморфности модулей они не очень и нужны),
локальных http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc74 и рекурсивных http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc75
модулей тоже нет.
Re[28]: Что такого привлекательного в Nemerle?
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.04.10 15:49
Оценка:
Здравствуйте, FR, Вы писали:

FR>Урезанные, как я понял сигнатуры задавать нельзя кроме как в fsi файле (это и понятно без полиморфности модулей они не очень и нужны),

FR>локальных http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc74 и рекурсивных http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc75
FR>модулей тоже нет.

Я правильно понимаю, что в F# модуль — это просто разновидность типа?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[29]: Что такого привлекательного в Nemerle?
От: FR  
Дата: 02.04.10 16:03
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Я правильно понимаю, что в F# модуль — это просто разновидность типа?


Мне кажется разновидность namespace.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.