LINUX.ORG.RU

Муки выбора первого юзабельного языка (pascal за язык не считается). Есть два ООП ЯП: лиспы точеные и питоны золоченые...

 , ,


2

5

Решил изучать первый (после псевоязыка: паскаля) ООП ЯП. Всё думаю, куда сесть то: на лиспы точеные или на питоны золоченые? Цели: нейронные сети, работа с БД, ФС, мелкие поделки школьного уровня (типа машинного обучения на SVM).

Какие преимущества и недостатки у того и другого ЯП?

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



Последнее исправление: ymn (всего исправлений: 1)
Ответ на: комментарий от somequest

зато в реболе были диалекты — почти как в ракетке #lang mylang-syntax

anonymous
()
Ответ на: комментарий от anonymous

Почему пистон тормозит — это вообще *загадка*.

1. Бинарные операции, как правило, вызов двух методов (__add + __radd, например).

2. Объекты позволяют менять свои поля и методы. И перед чтением/записью поля выполняются __getattribute__, __getattr__, __setattr__, __get__, __set__

monk ★★★★★
()
Ответ на: комментарий от somequest

Ъ функциональный подход с чистыми ф-циями, осложнит проектирование и раздует код еще раз в 10, как минимум.

class AccountClass a where
  withdraw :: a -> Rational -> a
  deposit :: a -> Rational -> a

data Account = Account Rational | AccountError String
  deriving Show

instance AccountClass Account where
  withdraw (Account balance) amount = 
    if balance >= amount 
    then Account (balance - amount)
    else AccountError "Insufficient funds"

  deposit (Account balance) amount = Account (balance + amount)

data AccountWithCredit = AccountWithCredit Rational Rational | AccountWithCreditError String
  deriving Show

instance AccountClass AccountWithCredit where
  withdraw (AccountWithCredit balance credit) amount = 
    if balance + credit >= amount 
    then AccountWithCredit (balance - amount) credit
    else AccountWithCreditError "Insufficient funds"

  deposit (AccountWithCredit balance credit) amount = Account (balance + amount) credit
monk ★★★★★
()
Ответ на: комментарий от anonymous

http://www.sbcl.org/manual/#Package_002dLocal-Nicknames

Это только для имён пакетов. А проблема возникает с именами символов.

Можно, конечно, в текущем пакете дублировать. Типа (setf (macro-function do-iter) (macro-function iterate:iter)). Но многословно.

monk ★★★★★
()
Ответ на: комментарий от monk

То что ты привел — это только подтверждение моих слов. Ты, во первых, полностью реализацию не сделал. Во-вторых, основную мысль ты подтвердил. Ты вместо того чтобы отнаследовать класс реализовал все заново, продублировал весь функционал. А теперь представь, что в Account не 3, а 100 методов. Там, по-ходу, даже не в 10 раз получается, а экспонцеально, lol

somequest
()
Ответ на: комментарий от somequest

Ты, во первых, полностью реализацию не сделал.

Если ты про метод show, то сделал. «deriving Show» именно это делает. Или что пропустил?

А теперь представь, что в Account не 3, а 100 методов.

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

Так для упомянутой задачи было бы правильней:

class AccountClass a where
  changeBalance :: a -> Rational -> a

withdraw a i | i > 0 = changeBalance a (-i)

deposit a i | i > 0 = changeBalance a i

data Account = Account Rational | AccountError String
  deriving Show

instance AccountClass Account where
  changeBalance (Account balance) change = 
    if balance + change > 0
    then Account (balance + change)
    else AccountError "Insufficient funds"

data AccountWithCredit = AccountWithCredit Rational Rational | AccountWithCreditError String
  deriving Show

instance AccountClass AccountWithCredit where
  changeBalance (AccountWithCredit balance credit) amount = 
    if balance + credit + change >= 0
    then AccountWithCredit (balance + amount) credit
    else AccountWithCreditError "Insufficient funds"

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Или что пропустил?

Ты больше половины пропустил. В моем коде AccountWithCredit нследует от Account, AccountWithCredit10 и AccountWithCredit20 от AccountWithCredit, account1 — от Account, account2 — от AccountWithCredit10, account3 — от AccountWithCredit20

то сделал. «deriving Show» именно это делает

Угу, я понял, это финт ушами для впечатления более лучшей краткости. Я вообще мог его не писать, можно было просто account balance print

то, скорее всего, ошибка в архитектуре.

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

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

somequest
()
Ответ на: комментарий от somequest

account1 — от Account, account2 — от AccountWithCredit10, account3 — от AccountWithCredit20

account1 = Account 0

accountWithCredit10 = AccountWithCredit 0 10
accountWithCredit20 = AccountWithCredit 0 20

account2 = accountWithCredit10
account3 = accountWithCredit20

Я думал, то просто пример испоьзования

monk ★★★★★
()
Ответ на: комментарий от somequest

Я вообще мог его не писать, можно было просто account balance print

Если явно писать будет что-то вроде

class AccountClass a where
  changeBalance :: a -> Rational -> a
  printAccount :: a -> IO ()
  printAccount = putStrLn . show


вместо
class AccountClass a where
  changeBalance :: a -> Rational -> a
monk ★★★★★
()
Ответ на: комментарий от monk

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

AccountWithCredit20 foo := method("bar")
account3 = accountWithCredit20
account3 foo print // --> bar
И кстати, я что-то не вижу там у тебя стейт.

somequest
()
Ответ на: комментарий от somequest

ты написал совершенно другой код,

Естественно, если объектов нет, то код другой. Мы же задачу решаем, а не объекты рисуем.

продемонстрировал отсутствие гибкости, и подтвердил то, что утверждалось изначально.

С чего это? Вроде строки примерно как у тебя. Задача решается так же.

Кстати, что будешь делать если при твоих условиях (уже написанное менять нельзя) появится необходимость добавить метод ко всей иерархии?

То есть, например,

withdrawBalanceKurs a i k = withdraw a (i*k)

Твой код?

monk ★★★★★
()
Ответ на: комментарий от monk

Вроде строки примерно как у тебя

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

появится необходимость добавить метод ко всей иерархии?

Это взаимоисключающие понятия. Надо будет добавить хотя бы одну строку к главному классу.

somequest
()
Ответ на: комментарий от monk

Мы же задачу решаем

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

somequest
()
Ответ на: комментарий от monk

Задача решается так же.

Она не так же у тебя решается. У меня:


class[1000 lines here]
subClass [1 line here]
subSubClass [1 line here]

//у тебя
class[1000 lines here]
anotherClass [1000 lines here]
anotherClass [1000 lines here]

Надеюсь, понятно. И я вообще не уверен, что ты реализовал аккаунт. Где там стейт у тебя?

somequest
()
Ответ на: комментарий от monk

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

somequest
()
Ответ на: комментарий от somequest

появится необходимость добавить метод ко всей иерархии?

Это взаимоисключающие понятия. Надо будет добавить хотя бы одну строку к главному классу.

Теперь ты «продемонстрировал отсутствие гибкости» ООП подхода.

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

В гипотетической же ситуации с 100 независимыми методами просто будет 100 классов типов по одному методу с реализацией по-умолчанию. И если тебе надо переопределить 1 метод, то просто определяешь экземпляр типа для этого класса типов.

Примерно так:

class Printable a where
  showP :: a -> IO ()
  showP = putStrLn . show

class AccountClass a where
  changeBalance :: a -> Rational -> a

instance AccountClass a => Printable a

withdraw a i | i > 0 = changeBalance a (-i)

deposit a i | i > 0 = changeBalance a i

data Account = Account Rational | AccountError String
  deriving Show

instance AccountClass Account where
  changeBalance (Account balance) change = 
    if balance + change > 0
    then Account (balance + change)
    else AccountError "Insufficient funds"

data AccountWithCredit = AccountWithCredit Rational Rational | AccountWithCreditError String
  deriving Show

instance AccountClass AccountWithCredit where
  changeBalance (AccountWithCredit balance credit) amount = 
    if balance + credit + change >= 0
    then AccountWithCredit (balance + amount) credit
    else AccountWithCreditError "Insufficient funds"

account1 = Account 0

accountWithCredit10 = AccountWithCredit 0 10
accountWithCredit20 = AccountWithCredit 0 20

account2 = accountWithCredit10
account3 = accountWithCredit20

monk ★★★★★
()
Ответ на: комментарий от somequest

subClass [1 line here]

anotherClass [1000 lines here]

Ну нет же.

У тебя

AccountWithCredit := Account clone do(
  credit ::= 0
  withdraw = method(amount, 
    if((balance + credit) >= amount, balance = balance - amount, "Insufficient funds" )
  )
)

у меня

data AccountWithCredit = AccountWithCredit Rational Rational | AccountWithCreditError String
  deriving Show

instance AccountClass AccountWithCredit where
  changeBalance (AccountWithCredit balance credit) amount = 
    if balance + credit + change >= 0
    then AccountWithCredit (balance + amount) credit
    else AccountWithCreditError "Insufficient funds"

Не сказал бы, что сильно больше

monk ★★★★★
()
Ответ на: комментарий от somequest

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

Ты же сам просил чистые функции.

Где там стейт у тебя?

Стейт в функциональных языках снаружи. Вот переданная переменная изменяет своё значение

makeDeposit :: STRef s Account -> Fractional -> ST s ()
makeDeposit account i = 
  modifySTRef account $ \v -> deposit v i
monk ★★★★★
()
Ответ на: комментарий от monk

В гипотетической же ситуации с 100 независимыми методами просто будет 100 классов типов по одному методу с реализацией по-умолчанию. И если тебе надо переопределить 1 метод, то просто определяешь экземпляр типа для этого класса типов. Примерно так:

То же самое можно сделать и в ООП, создаешь класс, затем от него наследуешь 100 классов, хоть с собственными методами, хоть с наследуемыми, и затем переопределяешь один этот метод в суперклассе. Это все настолько элементарно, что даже удивительно, что с виду адекватные люди выдают это за фичу. Детский сад.

somequest
()
Ответ на: комментарий от monk

Ты же сам просил чистые функции.

Я имел в виду с монадами и прочим говном, которое обеспечивает стейт. Какой аккаунт ты без стейта взялся показывать? Ты в своем уме вообще? Ты завел в банке счет, положил туда 1000 баксов, а как ты снимать их будешь? Ты может перегрелся? Отдохнуть надо?

somequest
()
Ответ на: комментарий от monk

Естественно, я не стал писать 100/1000/10000 методов, для демонстрации принципа этого достаточно было. А это рассуждение в стиле акына, что вижу о том пою.

somequest
()

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

lovesan ★★★
()
Ответ на: комментарий от Virtuos86

Занимались

По сравнению с v8 - нет:

«Томас Воутерс (Thomas Wouters), Джеффри Ясскин (Jeffrey Yasskin) и Коллин Винтер (Collin Winter) сами являются штатными сотрудниками Google[2], однако большинство участников проекта не являются сотрудниками Google

Главный спонсор проекта Google потерял интерес дальнейшему развитию проекта»

Но, в некотором смысле, Unladen жив под именем Pyston.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Занимались

По сравнению с v8 - нет

Хочешь сказать, что при должном подходе питон возможно, принципиально, ускорить?

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Конечно. Мало того, что нет никаких принципиальных отличий Python от JS, так PyPy является живым доказательством.

tailgunner ★★★★★
()
Ответ на: комментарий от somequest

он не чисто объектно-ориентированный язык

нихренасибе, это с каких пор недостаток?

и он не полностью свободный

поэтому речь и идет про Red.

loz ★★★★★
()
Ответ на: комментарий от DarkEld3r

Ты ведь нимом интересуешь - на твой взгляд Red перспективнее или как?

Да, Red точно перспективнее в плане высокоуровневого программирования, рантайма, интроспекции и тд. А на низком уровне диалект Red/System примерно соответствует ниму.

loz ★★★★★
()
Ответ на: комментарий от somequest

определяешь экземпляр типа для этого класса типов

затем переопределяешь один этот метод в суперклассе

Здесь у нас терминологическая путаница. «определяешь экземпляр типа» в ООП будет «указываешь, что класс является наследником данного суперкласса и определяешь в нём необходимые методы», а не изменение суперкласса

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от somequest

Я имел в виду с монадами и прочим говном, которое обеспечивает стейт.

www.linux.org.ru/add_comment.jsp?topic=12156738&replyto=12162753

Какой аккаунт ты без стейта взялся показывать?

Account — это и есть стейт банковского счёта. Если мне надо их различать (у меня несколько счетов в коллекции), то могу добавить в структуру данных номер счёта.

Ты завел в банке счет, положил туда 1000 баксов, а как ты снимать их будешь?

Так и буду: newAccount = withdraw account 1000. Результатом будет новое состояние этого счёта в банке.

monk ★★★★★
()
Ответ на: комментарий от somequest

Какой аккаунт ты без стейта взялся показывать? Ты в своем уме вообще?

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

ovk48 ★★★
()
Ответ на: комментарий от monk

Так и буду:

ЯННП. Давай, для ясности, выкинем все лишнее, и перепишем вот так.

Account := Object clone do(
   balance ::= 0
   withdraw := method(amount, balance = balance - amount)
   deposit := method(amount, balance = balance + amount)
)

Person := Object clone

John := Person clone do(
   account := Account clone
)

Jack := Person clone do(
   account := Account clone
)

John account deposit(100)
Jack account deposit(300)

John account withdraw(10)
Jack account withdraw(50)

Jack account balance println // 250
John account balance println // 90

Как будет выглядеть вариант без стейта? В какую такую структуру ты собрался добавлять что-то? Где это видано?

Ведущие ученые из области CS говорят, что аккаунт — это то что не может чистое ФП. Может ты открытие важное сделал? Может тебе нобелевскую премию вручат?

somequest
()
Ответ на: комментарий от monk

«указываешь, что класс является наследником данного суперкласса и определяешь в нём необходимые методы», а не изменение суперкласса

Ну и что? От этого что суть меняется? Разница в том, что я и в рантайме смогу переопределить или добавить метод, а ты — нет.

somequest
()
Ответ на: комментарий от ovk48

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

somequest
()

этих уродливых отступов.

Рукожоп.

ggrn ★★★★★
()
Ответ на: комментарий от somequest

Для меня больше важна возможность пользоваться ООП и не пользоваться им когда мне надо.

loz ★★★★★
()
Ответ на: комментарий от monk

Но многословно.

Одна из задач макросов - уменьшение многословности

(defmacro alias (nick name)
  `(setf (macro-function ,nick) (macro-function ,name)))

(alias do-iter iterate:iter)

anonymous
()
Ответ на: комментарий от somequest
class AccountClass a where
  changeBalance :: a -> Rational -> a

withdraw i a | i > 0 = changeBalance a (-i)

deposit i a | i > 0 = changeBalance a i

data Account = Account Rational | AccountError String
  deriving Show

instance AccountClass Account where
  changeBalance (Account balance) change = 
    if balance + change > 0
    then Account (balance + change)
    else AccountError "Insufficient funds"

balance (Person (Account a)) = a

data Person = Person Account

withPerson f (Person a) = Person $ f a

main = do
  john <- newIORef $ Person $ Account 0
  jack <- newIORef $ Person $ Account 0
  modifyIORef john $ withPerson $ deposit 100
  modifyIORef jack $ withPerson $ deposit 300
  modifyIORef john $ withPerson $ withdraw 10
  modifyIORef jack $ withPerson $ withdraw 50
  readIORef jack >>= putStrLn . show . balance  -- // 250
  readIORef john >>= putStrLn . show . balance  -- // 90
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Как будет выглядеть вариант без стейта?

newIORef

modifyIORef

readIORef

Я, конечно хаскель особо не понимаю, но создается ощущение, что ты меня за идиота держишь.

somequest
()
Ответ на: комментарий от monk

К слову, в clojure с алиасами из коробки все в порядке.

zz ★★★★
()
Ответ на: комментарий от somequest

Как будет выглядеть вариант без стейта?

но создается ощущение, что ты меня за идиота держишь.

Account без стейта. Даже Person без стейта. Стейт есть только у переменных john и jack.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от somequest

Похоже, ты начинаешь что-то подозревать.

anonymous
()
Ответ на: комментарий от Gentooshnik

Всё гуглится, если уж решили меряться количеством правил в BNF.

CL: http://cui.unige.ch/isi/bnf/LISP/BNFlisp.html В Common Lisp есть ещё макросы чтения, которые вызывают произвольную функцию, чтобы прочитать следующий за ним список, но без них BNF такой. Стандартные ридер-макросы для процесса разработки не принципиальны. Tcl: http://rosettacode.org/wiki/Category:Tcl#Grammar Тут кое чего не хватает, но он будет даже не в два раза больше. Кроме того, аргумент expr и первый аргумент if - арифметическое выражение с другой BNF, вроде этой: https://en.wikipedia.org/wiki/Syntax_diagram#Example Только ещё есть квадратные скобки, которые имеют такой же смысл как и в основном синтаксисе Tcl.

И да, в обоих языках ключевых слов нет.

Java вообще один из самых простых языков с «обычным» инфиксным синтаксисом, если не самый простой. https://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html

Python: https://docs.python.org/3/reference/grammar.html

Erlang: Не знаю для чего это (intelij-erlang? o_O) Но похоже на правду. Даже новый синтаксис хеш-таблиц из 18.0 есть.

Ок, по количеству правил Erlang всё же сложнее.

Gentooshnik ★★★★★
()
Ответ на: комментарий от Gentooshnik

Всё гуглится, если уж решили меряться количеством правил в BNF.

А как еще более-менее объективно оценить сложность синтаксиса? На глазок, что ли?

Ок, по количеству правил Erlang всё же сложнее

На лисп с тиклем изначально надежды было мало.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Gentooshnik

CL: http://cui.unige.ch/isi/bnf/LISP/BNFlisp.html В Common Lisp есть ещё макросы чтения, которые вызывают произвольную функцию, чтобы прочитать следующий за ним список, но без них BNF такой.

Там даже правил для кавычек нет. Реальная бнф CL раз в 20 больше.

anonymous
()
Ответ на: комментарий от anonymous

Да, я уже посмотрел внимательно. :) Но не в 20. Там не хватает строк («кавычек»), float (1.234) и rational (12/34) чисел, буквы (#\a) символа в пакете (пакет:символ) и символа вне пакетов (#:символ). Это всё по одному правилу. Кейворд с точки зрения синтаксиса - частный случай символа в пакете, когда пакет не указан явно. Своё правило для этого не нужно.

Gentooshnik ★★★★★
()
Ответ на: комментарий от anonymous

И нет, в Tcl действительно правил для никаких чисел нет. С точки зрения парсера это строки.

Gentooshnik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.