идея переключения / сопоставления с образцом

В g ++ 5.2 (например, g ++ 4.9 это отличается) строка в основном определяется как:

class string {
  char* bufferp;
  size_t length;
  union {
    char local_buffer[16];
    size_t capacity;
  };
};

На обычном компьютере это добавляет до 32 байтов (8+ 8 + 16).

Фактическое определение, конечно,

typedef basic_string<char> string;

, но идея одинаков.

147
задан Marc Gravell 1 October 2008 в 06:47
поделиться

8 ответов

Я думаю, что это выглядит действительно интересным (+1), но одна вещь остерегаться: компилятор C# довольно хорош в оптимизации операторов переключения. Не только для того, чтобы сорвать - Вы получаете совершенно другой IL в зависимости от того, сколько случаев Вы имеете и так далее.

Ваш определенный пример действительно делает что-то, что я нашел бы очень полезным - нет никакого синтаксиса, эквивалентного для преобразования регистра типом, поскольку (например) typeof(Motorcycle) не константа.

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

3
ответ дан Keith 1 October 2008 в 06:47
поделиться

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

у меня нет подсказки, если это, когда-либо, вероятно, будет функцией языка C# (кажется сомнительным, но кто видит будущее?).

Для ссылки, соответствующий F# приблизительно:

let getRentPrice (v : Vehicle) = 
    match v with
    | :? Motorcycle as bike -> 100 + bike.Cylinders * 10
    | :? Bicycle -> 30
    | :? Car as car when car.EngineType = Diesel -> 220 + car.Doors * 20
    | :? Car as car when car.EngineType = Gasoline -> 200 + car.Doors * 20
    | _ -> failwith "blah"

принятие Вы определили иерархию классов вроде

type Vehicle() = class end

type Motorcycle(cyl : int) = 
    inherit Vehicle()
    member this.Cylinders = cyl

type Bicycle() = inherit Vehicle()

type EngineType = Diesel | Gasoline

type Car(engType : EngineType, doors : int) = 
    inherit Vehicle()
    member this.EngineType = engType
    member this.Doors = doors
22
ответ дан Brian 1 October 2008 в 06:47
поделиться

Bart Де-Смет превосходный блог имеет 8 серий при выполнении точно, что Вы описываете. Найдите первую часть здесь .

82
ответ дан mancaus 1 October 2008 в 06:47
поделиться

Хотя это не очень 'C-sharpey' для включения типа, я знаю, что конструкция была бы довольно полезна во всеобщем употреблении - у меня есть по крайней мере один персональный проект, который мог использовать его (хотя его managable ATM). Есть ли большая часть проблемы производительности компиляции с перезаписью дерева выражений?

4
ответ дан Simon Buchan 1 October 2008 в 06:47
поделиться

Возможно причина, что C# не делает простым включить тип, состоит в том, потому что это - прежде всего, объектно-ориентированный язык и 'корректный' способ сделать, это в объектно-ориентированных терминах должно было бы определить метод GetRentPrice на Механизме и переопределить его в производных классах.

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

[Редактирование: Удаленная часть о представлении в качестве Marc указала, что это могло быть закорочено]

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

А путем я склонен использовать для решения этого вида проблемы, должен использовать поле словаря с типом как ключ и лямбда как значение, которое является довольно кратким для построения синтаксиса инициализатора объекта использования; однако, это только составляет конкретный тип и не позволяет дополнительные предикаты, так может не подойти для более сложных случаев. [Примечание стороны - при рассмотрении вывода компилятора C# это часто преобразовывает операторы переключения в основанные на словаре таблицы переходов, таким образом, кажется, нет серьезного основания, это не могло поддерживать включение типов]

25
ответ дан Edward Brey 1 October 2008 в 06:47
поделиться

После попытки сделать такие "функциональные" вещи в C# (и даже попытка книги по нему), я пришел к выводу, что не, за немногим исключением, такие вещи не помогают слишком много.

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

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

"проблема" состоит в том, что, как только Вы начинаете использовать некоторые функциональные понятия, естественно хотеть продолжиться. Однако усиливая кортежи, функции, частичное приложение метода и приправление карри, сопоставление с образцом, вложенные функции, дженерики, поддержка монады, и т.д. в C# становится очень ужасной, очень быстро. Интересно, и некоторые очень умные люди сделали некоторые очень прохладные вещи в C#, но на самом деле использование это чувствует себя тяжелым.

, Что я закончил тем, что использовал часто (через проекты) в C#:

  • функции Последовательности, с помощью дополнительных методов для IEnumerable. Вещи как ForEach или Процесс ("Применяются"? - делают действие с объектом последовательности, поскольку это перечисляется), вписываются, потому что синтаксис C# поддерживает его хорошо.
  • шаблоны совместного заявления Абстракции. Сложные блоки попытки/выгоды/наконец или другой включенный (часто в большой степени универсальный) кодируют блоки. Расширение LINQ к SQL вписывается здесь также.
  • Кортежи, в некоторой степени.

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

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

Некоторые другие ссылки:

37
ответ дан MichaelGG 1 October 2008 в 06:47
поделиться

ИМХО объектно-ориентированный способ делать такие вещи - это шаблон Visitor. Методы ваших посетителей-членов просто действуют как конструкции case, и вы позволяете самому языку обрабатывать соответствующую отправку без необходимости «заглядывать» в типы.

5
ответ дан 23 November 2019 в 22:32
поделиться

Сопоставление с образцом (как описано здесь ), его цель - деконструировать значения в соответствии со спецификацией их типа. Однако концепция класса (или типа) в C # с вами не согласуется.

В дизайне языков с несколькими парадигмами замечено неправильное, наоборот, очень приятно иметь лямбды в C #, а Haskell может делать что-то императивное, например, для ввода-вывода. Но это не очень элегантное решение, не в стиле Haskell.

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

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

9
ответ дан 23 November 2019 в 22:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: