Действительно ли Clojure объектно-ориентирован в своей основе? (Полиморфизм в seqs)

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

class Thing(object):

    def __init__(self, x, y_add):
        self.x = x
        self.y_add = y_add

    @property
    def y(self):
        return self.x + self.y_add

In use:

>>> t = Thing(2, 10)
>>> t.x
2
>>> t.y
12
>>> t.x = 3
>>> t.y
13

В противном случае вам нужно будет вызвать функцию (y() вместо y) или использовать что-то вроде sympy .

26
задан Steve 10 October 2009 в 15:20
поделиться

4 ответа

Идиоматический Clojure поддерживает определение независимых функций, которые работают с очень небольшим набором основных структур данных; такое разделение методов и данных является сильным заявлением против объектной ориентации и в пользу функционального стиля. Рич Хики (создатель Clojure) неоднократно заявлял о важности этого; например, здесь: «Clojure избегает традиционного объектно-ориентированного подхода к созданию нового типа данных для каждой новой ситуации, вместо этого предпочитая создавать большую библиотеку функций на небольшом наборе типов». .

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

27
ответ дан 28 November 2019 в 06:55
поделиться

Я предполагаю следствие этого вопроса - когда полиморфизм можно считать отличным от ориентации объекта?

Полиморфизм не имеет абсолютно никакого отношения к объектной ориентации. Это просто означает, что одна и та же операция может вести себя по-разному в зависимости от типа (типов) ее операндов.

Функциональные языки, такие как ML или Haskell, имеют полиморфизм более 30 лет, и кто-то, кто лучше знает историю PL, может указать на некоторые примеры до 1962 года (то есть до OO).

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

18
ответ дан Jörg W Mittag 15 October 2019 в 07:51
поделиться

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

больше добра в: http://clojure.org/multimethods

4
ответ дан Arthur Ulfeldt 15 October 2019 в 07:51
поделиться

Вы должны использовать Grandpa :: __ construct () , другого ярлыка для него нет. Кроме того, это нарушает инкапсуляцию класса Papa - при чтении или работе с Papa можно с уверенностью предположить, что метод __ construct () будет вызывается во время строительства, но класс Kiddo этого не делает.

t сначала вызывается в seq, вы сначала вызываете с аргументом seq). Все основные функции языка Clojure работают с коллекциями, последовательностями или примитивными типами. В открытых интерфейсах нет данных, связанных с методами. Таким образом, реализация Clojure находится на Java, и все взаимодействие с JVM будет включать классы / объекты, а сам язык Clojure - нет.

Объединение методов со структурами данных - это то, что Clojure не рекомендует.

Сказав все это. ... на самом деле у функций есть ограничения на то, с какими аргументами они будут работать. first rest и nth будут работать только с тем, что может быть seq. С этой точки зрения нет большой разницы, связаны ли структуры данных с методами или нет - вам все равно нужно правильно сопоставить их. Большая выгода от гибкости. Функции могут быть написаны так, чтобы принимать любые аргументы, а затем составляться из функций более высокого порядка без определения классов и т. Д.:

(def farms [{:name "Swansea", :value 100}
            {:name "Broadmarsh", :value 200, :produce [:corn :wheat :rye]}
            {:name "Snug", :value 50, :animals [:goats :pigs]}])
(reduce + (map :value farms))
-> 350
(reduce + (map :value (filter :animals farms)))
-> 50
6
ответ дан 28 November 2019 в 06:55
поделиться