Почему пакет изображений Go вырезает + вставляет циклы по пикселям? - PullRequest
4 голосов
/ 11 июля 2011

Если вы посмотрите на пакет изображений здесь http://golang.org/src/pkg/image/image.go, то увидите, что реализация Opaque () для каждого изображения делает одно и то же, отличаясь только логикой, специфичной для пикселя.

Есть ли причина для этого? Будет ли какое-либо общее решение менее эффективным? Это просто недосмотр? Есть ли какое-то ограничение (я не вижу такого) в системе типов, которое затруднило бы полиморфный подход [was: generic]?

[edit] Тип решения, о котором я думал (для которого не нужны обобщения в смысле Java), будет выглядеть следующим образом:


type ColorPredicate func(c image.Color) bool;

func AllPixels (p *image.Image, q ColorPredicate) bool {
  var r = p.Bounds()
  if r.Empty() {
    return true
  }
  for y := r.Min.Y; y < r.Max.Y; y++ {
    for x := r.Min.X; x < r.Max.X; x++ {
      if ! q(p.At(x,y)) {
        return false
      }
    }
  }
  return true
}

но у меня возникают проблемы с компиляцией (все еще очень плохо для Go - он будет компилироваться с изображением, но не с указателем изображения!).

Это слишком сложно для оптимизации? (вам нужно иметь встроенную функцию, но тогда не будет ли какая-либо проверка типов выведена из цикла?). Кроме того, теперь я понимаю, что не должен был использовать слово «универсальный» ранее - я имел в виду только общий (ха).

Ответы [ 2 ]

4 голосов
/ 11 июля 2011

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

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

func opaque(pix []Color, stride int, rect Rectangle) bool

Вы бы хотели вызвать эту функцию следующим образом:

func (p *RGBA) Opaque() bool {
    return opaque([]Color(p.Pix), p.Stride, p.Rect)
}

Ноты не можешьp.Pix не может быть преобразован в [] Color, потому что эти типы имеют разные представления в памяти, и спецификация запрещает это.Мы могли бы выделить новый фрагмент, преобразовать каждый отдельный элемент p.Pix и передать его, но это было бы очень неэффективно.

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

func opaque(pix []RGBAColor, stride int, rect Rectangle) bool

func (p *NRGBA) Opaque() bool {
    return opaque([]RGBAColor(p.Pix), p.Stride, p.Rect)
}

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

Это похоже на область, где дженерики пригодятся, но нет решения для дженериковна ходу пока.

1 голос
/ 11 июля 2011

Почему в Go нет универсальных типов?

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

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

Этот вопрос остается открытым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...