От статического контроля типов до динамического контроля типов

Я закончил тем, что реализовал обертку для heapq, добавив dict для поддержания уникальных элементов очереди. Результат должен быть довольно эффективным для всех операторов:

class PriorityQueueSet(object):

    """
    Combined priority queue and set data structure.

    Acts like a priority queue, except that its items are guaranteed to be
    unique. Provides O(1) membership test, O(log N) insertion and O(log N)
    removal of the smallest item.

    Important: the items of this data structure must be both comparable and
    hashable (i.e. must implement __cmp__ and __hash__). This is true of
    Python's built-in objects, but you should implement those methods if you
    want to use the data structure for custom objects.
    """

    def __init__(self, items=[]):
        """
        Create a new PriorityQueueSet.

        Arguments:
            items (list): An initial item list - it can be unsorted and
                non-unique. The data structure will be created in O(N).
        """
        self.set = dict((item, True) for item in items)
        self.heap = self.set.keys()
        heapq.heapify(self.heap)

    def has_item(self, item):
        """Check if ``item`` exists in the queue."""
        return item in self.set

    def pop_smallest(self):
        """Remove and return the smallest item from the queue."""
        smallest = heapq.heappop(self.heap)
        del self.set[smallest]
        return smallest

    def add(self, item):
        """Add ``item`` to the queue if doesn't already exist."""
        if item not in self.set:
            self.set[item] = True
            heapq.heappush(self.heap, item)
5
задан Null 12 August 2015 в 20:29
поделиться

7 ответов

This is one of the reasons automated testing/test driven development is even more important in dynamically typed languages. I haven't used Clojure (I mostly use Ruby), so unfortunately I can't recommend a specific testing framework.

8
ответ дан 18 December 2019 в 11:58
поделиться

Первое, что я хотел бы упомянуть, это то, что Брюс Экель написал очень интересную статью под названием Strong Typing vs Strong Testing (ссылка находится по адресу этот момент, к сожалению, но, надеюсь, скоро наступит).

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

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

Итак, я думаю, что первый ответ, который я дам вам, - сосредоточьтесь на своем тестировании, что вы все равно должны делать, и такие изменения не должны сильно на вас повлиять.

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

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

3
ответ дан 18 December 2019 в 11:58
поделиться

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

0
ответ дан 18 December 2019 в 11:58
поделиться

Тим Брей обсуждает его здесь , критика которого Седриком здесь , и сообщение на artima, где это подробно обсуждается.

0
ответ дан 18 December 2019 в 11:58
поделиться

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

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

О, и если ваша программа настолько велика, убедитесь, что у вас есть хорошие тесты (test-is должен сделать ее проще, чем Java)

2
ответ дан 18 December 2019 в 11:58
поделиться

Test coverage is definitely important. But a dynamically typed language will allow you to work in a different way. In a strongly typed language (like Java), a change in the interface needs to modify all the callers. In Ruby, you could do this-- but probably won't. Instead, you'll probably add flexibility to the method on one of a few ways. Namely:

  • you tend to have very few methods that take as many as three parameters in Ruby (as opposed to Java). Because you don't have strong typed interface of Java, you break the problem down into smaller pieces and steps. It's much more common to write methods that take just 1 parameter, and then refactor when it becomes more complex.
  • it's possible-- and common-- to leave the old behavior in place while adding more arguments. For example, if you have to add a third argument to a two argument method, you will set its default value to preserve the old behavior (and save you a refactor). If you are familiar with Javascript libraries like jQuery, they take advantage of this everywhere with "optional" arguments.
  • similar to optional arguments, methods can grow to take a flexible parameter list. With solid test coverage, you can quite easily add a new behavior to an existing method and safely know you haven't broken the existing code. In Rails, methods like "render" take a wide range of options.
1
ответ дан 18 December 2019 в 11:58
поделиться

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

1
ответ дан 18 December 2019 в 11:58
поделиться
Другие вопросы по тегам:

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