На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (495) « Первая ... 441 442 [443] 444 445 ...  494 495  ( Перейти к последнему сообщению )  
> Delphi vs C++ vs C# , ну и Java немножко, где-то ближе к старшему байту номеров страниц
    Особо упоротые могут делать так:
    ExpandedWrap disabled
      public interface Box<A> {
       
          A get();
       
          void set(A a);
      }
       
      public class BoxImpl<A> implements Box<A> {
       
          private A value;
       
          public BoxImpl (A a) {
              set(a);
          }
       
          public A get() {
              return value;
          }
       
          public void set(A a) {
              value = a;
          }
       
          public String toString() {
              return value.toString();
          }
      }

    И юзать везде, где надо Box'ы
    ExpandedWrap disabled
      import java.util.Date;
       
      interface IntBox extends Box<Integer> {}
       
      class IntBoxImpl extends BoxImpl<Integer> implements IntBox {
       
          public IntBoxImpl() {
              super(0);
          }
      }
       
      public class App {
       
          private static void decodeDate(Date date, IntBox year, IntBox month, IntBox day) {
              year .set(getYear (date));
              month.set(getMonth(date));
              day  .set(getDay  (date));
          }
       
          public static void main(String[] args) {
              IntBox year  = new IntBoxImpl();
              IntBox month = new IntBoxImpl();
              IntBox day   = new IntBoxImpl();
       
              decodeDate(new Date(), year, month, day);
              System.out.printf("%02d.%02d.%d", day.get(), month.get(), year.get());
          }
      }


    только я согласен со Смайком, у меня и в делфи-то не возникало необходимости и желания использовать var-параметры, да еще и несколько.
    А вот вернуть кортеж из нескольких значений (обычно не больше двух) в том же Go или Хаскелле -- вполне нормально и удобно.

    Добавлено
    Цитата trainer @
    Очевидно в неочевидности. Из вызова функции в Delphi с var/out-аргументом не видно, что аргумент может модифицироваться.

    P.S. Хотя в Delphi надо просто сразу считать, что вызов функции модифицирует аргументы, если не доказано обратное

    Вообще достаточно навести мышку на вызов функции и тебе в подсказке отобразится ее сигнатура, ну да ладно...

    Цитата trainer @
    :D Фишку с неконстантностью аргументов с атрибутом const мы уже обсуждали.

    const в делфи полностью константен в соответствием со своим смысом -- передача константной (не-var) ссылки.

    http://liveworkspace.org/code/16oxEH$16

    То же самое и в делфи:
    ExpandedWrap disabled
      program Project1;
       
      {$APPTYPE CONSOLE}
       
      uses
        SysUtils;
       
      type Foo = class
        value : Integer;
      public
        procedure Incr;
        function  Get : Integer;
      end;
       
      procedure Foo.Incr;
      begin
        Inc(self.value);
      end;
       
      function Foo.Get : Integer;
      begin
        Result := value;
      end;
       
      procedure int_inc(const x : Integer);
      begin
        // x := x + 1; // Error: E2064 Left side cannot be assigned to
        // Inc(x);     // Error: E2064 Left side cannot be assigned to
      end;
       
      procedure foo_inc(const f : Foo);
      begin
        f.Incr;
        // f := Foo.Create; f.Free; // Error: E2064 Left side cannot be assigned to
      end;
       
      var x : Integer;
      var f : Foo;
       
      begin
        f := Foo.Create;
        int_inc(x);
        foo_inc(f);
        WriteLn(f.Get);
        f.Free;
        ReadLn;
      end.

    ExpandedWrap disabled
      1
    Сообщение отредактировано: korvin -
      Цитата trainer @
      Фишку с неконстантностью аргументов с атрибутом const мы уже обсуждали.

      Там проблема не в const, а в ссылочной семантике(грубо говоря, ты делаешь константным не объект, а указатель на него, если пользоваться терминологией С++). Для нее "глубокую" константность в стиле С++ не сделаешь.

      Добавлено
      Цитата korvin @
      То же самое и в делфи

      Да, но в С++ я могу еще сделать
      ExpandedWrap disabled
        void foo(const Foo * const f)
        // И
        void foo(const Foo * f)

      А в Delphi - нет.
        Цитата D_KEY @
        Да, но в С++ я могу еще сделать
        ExpandedWrap disabled
          void foo(const Foo * const f)
          // И
          void foo(const Foo * f)

        А в Delphi - нет.

        Ради бога, делай. В делфи нельзя неконстантные данные сделать вдруг константными. Хотя во всяких питонах и рубях есть методы а ля freeze.
          Цитата korvin @
          В делфи нельзя неконстантные данные сделать вдруг константными.

          Дело не в данных, а контрактах. Я говорю, что не изменю логическое состояние объекта.

          Цитата
          Хотя во всяких питонах и рубях есть методы а ля freeze.

          Костыль, ИМХО.
            Цитата D_KEY @
            Да, но в С++ я могу еще сделать
            ExpandedWrap disabled
              void foo(const Foo * const f)
              // И
              void foo(const Foo * f)

            А в Delphi - нет.

            Первый вариант, IMHO, бессмысленный, но читал, что некоторые так себя контролируют...
              Цитата MyNameIsIgor @
              Первый вариант, IMHO, бессмысленный

              В случае передачи параметров - да.

              Цитата
              но читал, что некоторые так себя контролируют...

              В данном случае проще воспользоваться ссылками :) Или ты вообще о константности передаваемых по значению аргументов?
                Цитата D_KEY @
                Дело не в данных, а контрактах. Я говорю, что не изменю логическое состояние объекта.

                Какая разница? Ты не изменишь -- кто-то другой изменит. Надежней делать иммутабельные объекты/структуры с нужными свойствами или копии для таких случаев.

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

                То же самое и с IO в Хаскелле, только еще хуже.
                Сообщение отредактировано: korvin -
                  Цитата korvin @
                  Какая разница? Ты не изменишь -- кто-то другой изменит.

                  И в чем проблема? Изменения - естественная штука в ОО-мире.

                  Цитата
                  Надежней делать иммутабельные объекты/структуры с нужными свойствами или копии для таких случаев.

                  Тебе никто не мешает это делать, если нужно :-?
                  Вопрос в том, как мне написать функцию, принимающую объект с гарантией того, что я не буду дергать методы, изменяющие его состояние? Сам объект при этом может быть изменяемым.
                  Можно делать это через интерфейсы/абстрактные классы, но часто это является просто введением лишних сущностей, да и заставляет использовать полиморфизм на ровном месте.

                  Цитата
                  если мне вдруг захотелось, чтобы немутирующий метод в моем классе вдруг стал мутирующим, то это поломает весь код, который его использует.

                  Нет. Это не поломает весь код. Но будет означать, что ты плохо спроектировал что-либо. Если ты о кэшировании и т.п., то для этого есть mutable, позволяющий менять "физическое" состояние без изменения логического.
                    Цитата D_KEY @
                    В яве скоро будут(уже есть?) лямбды. Так что тоже можно будет фактически создавать локальные функции

                    Так с помощью анонимных классов можно уже сейчас это делать. Но главное отличие в том, что все джава-иде такие классы нормально показывают.
                      Цитата MyNameIsIgor @
                      Первый вариант, IMHO, бессмысленный, но читал, что некоторые так себя контролируют...

                      Я какое-то время так делал. Потом забил, ибо решил, что бессмысленно :D
                        Цитата D_KEY @
                        И в чем проблема? Изменения - естественная штука в ОО-мире.

                        И в чем тогда смысл явного указания в функции, что она не меняет состояние объекта?

                        Цитата D_KEY @
                        Тебе никто не мешает это делать, если нужно :-?

                        Какие тогда претензии к Делфи? =)

                        Цитата D_KEY @
                        Вопрос в том, как мне написать функцию, принимающую объект с гарантией того, что я не буду дергать методы, изменяющие его состояние?
                        Сам объект при этом может быть изменяемым.

                        Так и не надо писать такие функции. ;-) Зачем она тебе? Зачем она кому-то другому?

                        Цитата D_KEY @
                        Можно делать это через интерфейсы/абстрактные классы, но часто это является просто введением лишних сущностей

                        Да, гораздо лучше взять одно слово const и позволить пихать его чуть ли не везде, при этом каждый раз это имеет какой-то свой эффект.
                        Как там было у Пайка или кого там про Foo
                        ExpandedWrap disabled
                          foo::Foo *myFoo = new foo::Foo(foo::FOO_INIT);

                        Теперь еще и
                        ExpandedWrap disabled
                          const Foo * copy(const Foo * const foo) const;

                        =)

                        Цитата D_KEY @
                        да и заставляет использовать полиморфизм на ровном месте.

                        А что плохого в полиморфизме? =)

                        Цитата D_KEY @
                        Нет. Это не поломает весь код. Но будет означать, что ты плохо спроектировал что-либо.

                        Сфига ли? Реализация метода -- это мое дело. Если я изначально методом ничего не мутирую и повешу на него const, то я резко ограничу возможность будущей модификации этого метода.

                        Цитата D_KEY @
                        Если ты о кэшировании и т.п., то для этого есть mutable, позволяющий менять "физическое" состояние без изменения логического.

                        Цитата
                        Костыль, ИМХО.

                        =)

                        Добавлено
                        Цитата [S]mike @
                        Цитата D_KEY @
                        В яве скоро будут(уже есть?) лямбды. Так что тоже можно будет фактически создавать локальные функции

                        Так с помощью анонимных классов можно уже сейчас это делать. Но главное отличие в том, что все джава-иде такие классы нормально показывают.

                        Не, анонимные классы -- это куча лишнего мусора. Когда нужен всего-лишь один метод, то лямбды намного удобней и читабельеней:
                        ExpandedWrap disabled
                          button.addActionListener(new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                  model.doSomething();
                              }
                          });

                        ExpandedWrap disabled
                          button.actionListeners += (ActionEvent e) => { model.doSomething() };


                        А когда нужно (пере)определить несколько, то гораздо удобней и читабельней создать отдельный класс.

                        Так что ждем восьмую джаву с лямбдами или юзаем нормальные jvm-языки =)
                          Цитата korvin @
                          Вообще достаточно навести мышку на вызов функции и тебе в подсказке отобразится ее сигнатура, ну да ладно...

                          не ладно, возможность изменения входных параметров - это критично и должно быть видно безо всяких движений мыши.

                          Цитата D_KEY @
                          В С++ нет out/var параметров. Если ты имеешь в виду ссылки/указатели - то это отдельные типы данных.

                          только смысла это не меняет, так как можно неявно преобразовать значение в ссылку. если бы было только явное преборазование (
                          что нить типа void foo(int & i) {}

                          int j;
                          foo((auto&)j); тогда явно было бы видно, что параметр меняется. Но синтаксис конечно убог. Впрочем для с++ нутых - сойдет :-D


                          А по поводу константности в дельфе:

                          ExpandedWrap disabled
                            type
                              TRec = record
                                 Arr: array[0..10] of Integer; // чтоб оптимизатор не мутил воду
                                 Value: Integer;
                                 procedure Inc;
                              end;
                             
                            procedure TRec.Inc;
                            begin
                              Value := Value + 1;
                            end;
                             
                            procedure Foo(const R: TRec);
                            begin
                              R.Inc;
                            end;
                             
                             
                            procedure TForm11.FormCreate(Sender: TObject);
                            var
                              R: TRec;
                              I: Integer;
                            begin
                              for I := Low(R.Arr) to High(R.Arr) do R.Arr[I] := I; // чтоб оптимизатор не мутил воду
                              R.Value := 1;
                              Foo(R);
                              if R.Value <> 1 then
                                raise Exception.Create('ХА-ХА-ХА');  //  Злобный смех супер-злодея
                            end;
                            Цитата korvin @
                            Цитата D_KEY @
                            И в чем проблема? Изменения - естественная штука в ОО-мире.

                            И в чем тогда смысл явного указания в функции, что она не меняет состояние объекта?

                            В этом и смысл - указать, что мы не будем изменять состояние :-? Это делает код более понятным, избавляет от ошибок и пр.

                            Цитата
                            Какие тогда претензии к Делфи? =)

                            Не к делфи, а к языкам с параллельным существованием двух семантик - ссылочной и значений, которые определяются неявным образом и зависят от "вида" типа(класс/структура/встроенный тип и пр.) :)

                            Цитата
                            Так и не надо писать такие функции. ;-) Зачем она тебе? Зачем она кому-то другому?

                            :wacko:

                            Цитата
                            Да, гораздо лучше взять одно слово const и позволить пихать его чуть ли не везде, при этом каждый раз это имеет какой-то свой эффект.

                            Один и тот же :)

                            Цитата
                            Как там было у Пайка или кого там про Foo
                            ExpandedWrap disabled
                              foo::Foo *myFoo = new foo::Foo(foo::FOO_INIT);

                            Теперь еще и
                            ExpandedWrap disabled
                              const Foo * copy(const Foo * const foo) const;

                            =)

                            Ничего не понял.

                            Цитата
                            А что плохого в полиморфизме? =)

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

                            Цитата
                            Сфига ли? Реализация метода -- это мое дело. Если я изначально методом ничего не мутирую и повешу на него const, то я резко ограничу возможность будущей модификации этого метода.

                            Ничего ты не ограничишь. const или не const - это не твое дело, это декларация наличия/отсутствия логического изменения состояния.

                            Цитата
                            Цитата D_KEY @
                            Если ты о кэшировании и т.п., то для этого есть mutable, позволяющий менять "физическое" состояние без изменения логического.

                            Цитата
                            Костыль, ИМХО.

                            =)

                            В чем костыльность-то? Хочешь изменять объект, не изменяя логического состояния - делай это явно и для определенных полей.

                            Добавлено
                            Цитата jack128 @
                            только смысла это не меняет, так как можно неявно преобразовать значение в ссылку. если бы было только явное преборазование (
                            что нить типа void foo(int & i) {}

                            int j;
                            foo((auto&)j); тогда явно было бы видно, что параметр меняется.

                            Если это действительно нужно, то:
                            ExpandedWrap disabled
                              void foo(int *const i) {}
                              // ...
                              int j;
                              foo(&j);

                            :-?
                            Сообщение отредактировано: D_KEY -
                              Цитата jack128 @
                              только смысла это не меняет, так как можно неявно преобразовать значение в ссылку. если бы было только явное преборазование (

                              Как бы тогда работали операторы и их переопределение?
                                korvin, вот тебе кусочек нашего вектора:
                                ExpandedWrap disabled
                                  // не меняем передаваемый нам объект(т.к. копируем его), меняем свое состояние
                                  void push_back (const value_type& val);
                                  // удаляем у себя объект с конца, меняем свое состояние
                                  void pop_back();
                                  // возвращаем неизменяемую ссылку на наш последний элемент
                                  // (позволительно и для константного объекта, т.к. клиент не изменит наши данные)
                                  const_reference back() const;
                                  // возвращаем изменяемую ссылку на наш последний элемент,
                                  // (возможно только для неконстантного объекта)
                                  reference back();

                                Может так будет понятнее...
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (495) « Первая ... 441 442 [443] 444 445 ...  494 495


                                Рейтинг@Mail.ru
                                [ Script execution time: 0.6116 ]   [ 15 queries used ]   [ Generated: 29.07.26, 10:52 GMT ]