LINUX.ORG.RU

Полнота парадигм в Ruby

 , , , ,


1

3

Доброго времени суток ананимусы и аналитики ЛОР'а! В связи с последним г*ом, которое заявил Гвидо решил окончательно сползать с Python 3.x на что-то более вменяемое. Полностью переходить на tcl пока не хочу (много слишком веществ надо потреблять), хочется немного батареек побольше. Ранее использовал Ruby в разрезе ООП. Заинтересовало вот что:

1. Как обстоят дела на Ruby с ФП? Насколько он поддерживает данную парадигму? Хотя бы на уровне Scheme или Clojure оно или на том же уровне, что и Python?

2. Как обстоят дела с меттапрограммированием? Можно ли писать такие же классные вещи как на tcl или lisp-family (макросы, программирование синтаксиса, etc.)? Насколько хорошо с этим в рубине?



Последнее исправление: iMushroom (всего исправлений: 1)

1. Как обстоят дела на Ruby с ФП? Насколько он поддерживает данную парадигму? Хотя бы на уровне Scheme или Clojure оно или на том же уровне, что и Python?

В отличие от питона лямбды не однострочные, в остальном всё то же самое, т.е. также как в scheme. Тебе чего конкретно нужно-то?

2. Как обстоят дела с меттапрограммированием?

Норм, eval и exec во все поля. Да, не стыдясь eval-им голые строки, хотя часто можно обойтись блоками.

как на tcl или lisp-family (макросы, программирование синтаксиса, etc.)?

Нет. Последнее — слава богу нет.

Что в питоне не понравилось-то? По-сути-то то же самое.

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

В отличие от питона лямбды не однострочные, в остальном всё то же самое, т.е. также как в scheme. Тебе чего конкретно нужно-то?

Что-то на вроде tcl, только с «батарейками». Т.е. есть бооольшой проект (сейчас живет на тикле, уже за первые две недели под 3000 строк кода), который хочется переписать на что-то имеющее большее количество библиотек, дабы не плодить свои велосипеды с квадратными колесами на гусенечной тяге.

Норм, eval и exec во все поля. Да, не стыдясь eval-им голые строки, хотя часто можно обойтись блоками.

Радует.

Нет. Последнее — слава богу нет.

Т.е. нельзя даже переопределить класс стандартной библиотеки и все его методы? О_О Или Вы про служебные слова? В Ruby, кстати, они вообще есть или вообще все - объекты?

Что в питоне не понравилось-то? По-сути-то то же самое.

Не понравилось, то, что для проекта мне удобнее мета+ФП+примеси ООП (достаточно серьезные). При этом удобнее держать проект в виде .tcl/.rb/.py файлов, т.к. программа должна сама себя модифицировать при определенных обстоятельствах. Очень большая доля программы - работа со списками, которые передает сервер. Причем списки очень объемные. Одна из задач - по спискам выстраивать интерфейс программы и менять ее функционал...и обрабатывать списки, отсылаю их на сервер))

iMushroom
() автор топика
Ответ на: комментарий от vladimir-vg

Нет. Последнее — слава богу нет.

Если ты про невозможность DSL, то ты же неправ! Или что такое программирование синтаксиса?

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

Можно пример DSL на Ruby? (в смысле где почитать)

Ну как пример - если в языке А есть оператор jopa и он уничтожает объекты, то программируемый синтаксис - возможность в любой момент jopa присвоить действие, скажем, расчета факториала.

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

Радует.

А если почитать про tainted objects, то будет совсем хорошо. Можно эвалить без особых опасений, если строка признается за безопасную. (там неск. уровненй паранойи). Плюс еще ручное управление этим.

Библиотек хватает, но всякий сайпи, нампи и т. д. нет - всев глубоких альфах. Остальное есть в большинстве своем.

Т.е. нельзя даже переопределить класс стандартной библиотеки и все его методы? О_О Или Вы про служебные слова? В Ruby, кстати, они вообще есть или вообще все - объекты?

Конечно можно, там же манки патчинг. Прямо посреди скрипта можешь написать class Integer #...; end и юзать свой класс. Кстати, в 2 будет немного не так, почитай про Ruby Refinements.

Можешь даже в модуле Kernel крутить гайки. Например, там есть предопределенные штуки вроде BigInteger(«2») (чтоб не писать b = BigInteger.new(«1234»)), так вот, ты можешь свое такое доопределять прямо в кернел, тот же самый манки патчинг:

module Kernel
	def MyShort(a)
		a.next
	end
end
# а потом:
puts MyShort(500)
В руби вообще все объект, даже текущий контекст работы.

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

Т.е. нельзя даже переопределить класс стандартной библиотеки и все его методы? О_О Или Вы про служебные слова? В Ruby, кстати, они вообще есть или вообще все - объекты?

Я говорил про синтаксис. В рубях слава богам, синтаксис расширять низя.

Классы, объекты легко модифицируются, можно безнаказанно доопределять методы. Можно получить доступ к приватным членам объектов через instance_exec/instance_eval.

Служебных слов хватает.

Можно делать конструкции вроде:

foo arg1, arg2 do |param1, param2|

end

где foo — вызов метода и блок-лямбда идёт третьим неявным аргументом. Так и мутят новые конструкции, kinda dsl

мета+ФП+примеси ООП (достаточно серьезные)

звучит непонятно. Особенно про примеси

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

Звучит странно.

Чем тебе не понравился питон? Всем же подходит.

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

Чем тебе не понравился питон? Всем же подходит.

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

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

И да, мой пример немного корявый и непонятно, к чему. Я имел в виду, что таким способом можно делать так:

module Kernel
	def MyClass(a)
		MyClass.initialize(a)
	end
end
# а потом:
a = MyClass(500)
# эквивалентно
a = MyClass.new(500)

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

В питоне есть simple statement - зарезервированное слово, типа print, for, import, if, try, lambda, для которых существуеют особые синтаксические правила, и которые не являются методами никакого класса. Соответственно, их переопределение невозможно или делается слишком нетривиальным образом.

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

= это не оператор присваивания. Это оператор привязывания значения к переменной, что в питоне, что в рубях.

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

Я приводил абстрактный пример :) И все - же, можно ему задать что-то иное, нежели привязываение значения к переменной?

iMushroom
() автор топика

В связи с последним г*ом, которое заявил Гвидо

~/work$ find . -name '*.py' | xargs grep reduce | wc -l
1
~/work$ cloc .
--------------------------------------------------------------------------------
Language                      files          blank        comment           code
--------------------------------------------------------------------------------
Python                          144           4641           1184          14735

Ты тупая белка-истеричка.

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

Я имею в виду, для переменных своего класса. «=» в руби не перегружается как метод, потому что, как говорил, нет логичных юзкейсов.

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

Смотри-ка, неосиляторы грепа подтянулись.

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

anonymous
()

И вообще, погоди. Ты спросил про полноту парадигм, а сам задаешься не теми вопросами. Перегрузка методов - это не к ФП, это ООП в чистом виде.

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

def from_expr(e)
	%w[** / * + -].map {|op| String.send(:define_method, op) {|n| "(#{op=='**'??^:op} #{self} #{n})"}}
	s = eval e.gsub(/\w/, '?\0').gsub ?^,'**'
end

p from_expr("1+2")

Из инфиксной в префиксную нотацию без всяких там рекурсий!

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

Расскажи мне что-нибудь еще о юниксвее

Зафиксированным на комбайнах этого всё равно не понять, такие дела.

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

мета

Ну во-первых, есть метаклассы, во-вторых есть объект интепритатора самого и в третьих доступ к ast + внешние библиотеки

ФП

Конкретней? Рекурсия есть, модуль functools и опять же внешие либы

ООП

Чего же нет в ООП Питона что нужно Вам?

pylin ★★★★★
()
Ответ на: комментарий от special-k

Нет, он о плюсовых operator=, видимо. Чтоб вот можно было писать t = something, и это давало какое-то неожиданное поведение. ТС не знает сам, чего хочет.

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

Скажем в выражении a=2, «=» - это оператор присваивания.
теперь точно вкурил

Не вкурил ты. Если а - инстанс класса, = отработает только так, как положено, т. е. содержимое объекта справа станет и содержимым объекта слева. А special-k привел пример того, что можно - сеттеры переменных инстанса, когда ты внутрях у а какие-то переменные, опять же, стандартным поведением = изменяешь. Ты должен сам себе понять, что переопределение = в стиле

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

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

def a=(arg)
  puts "#{a}, #{arg}"
end
но это уже совсем лютый пи$#ец.

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

содержимое объекта справа станет и содержимым объекта слева

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

но это уже совсем лютый пи$#ец.

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

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

Почему же? Слева объект, и справа объект.

irb(main):001:0> s1 = 's1'
=> "s1"
irb(main):002:0> s2 = s1
=> "s1"
irb(main):005:0> s1.hash==s2.hash
=> true
Выполню, например, s2.clear, в s1 тоже ничего не останется. Как это расходится с утверждением «содержимое объекта справа станет и содержимым объекта слева»?

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

Полезно, но никак не согласуется с идеей «один метод - одно действие». Я бы уж тогда вынес в отдельный метод и дергал, но это уже дело архитектуры. И, в любом случае, = будет, так или иначе, выполнять то, что должно, т. е. не «что-то иное, нежели».

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

iMushroom

хочу обратить внимание

сеттеры переменных инстанса

Это, как бы, не так.. в руби нет понятия сеттера в принципе - есть имитация (частный случай вызова метода). Но смотрите, выглядит так, словно a - это локальная переменная, для которой переопределен оператор = (единственное отличие - необходимость использования self при присвоении). Методы a и a= даже нельзя вызвать снаружи объекта. И это не какие-то космические костыли, это элементарнейшая конструкция языка, это гибкость.

class A
  def inc_a!
    self.a += 1
    a
  end

  protected
  def a= v
    @a = v * 2
  end
  def a
    @a ||= 0
  end
end

t = A.new
p t.inc_a! #2
p t.inc_a! #6
t.a #NoMethodError
t.a = 1 #NoMethodError
special-k ★★★
()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от special-k

1) А что такое сеттер, если не метод, который устанавливает переменную объекта? Если уж на то пошло, то в тривиальных случаях проще писать attr_writer :a, не так ли?

2) В том-то и суть, что a= - это просто метод, а не перегрузка = для типа переменной а. ТС же как раз спрашивал про перегрузку = вообще, чего нельзя сделать.

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

Или, если уж на то пошло, то совсем так:

irb(main):001:0> class C
irb(main):002:1> attr_accessor :a
irb(main):003:1> end
=> nil
irb(main):004:0> b = C.new
=> #<C:0x00000002311210>
irb(main):005:0> b.a = 1
=> 1
irb(main):006:0> b
=> #<C:0x00000002311210 @a=1>
irb(main):007:0> b.instance_variable_set("@a", 2)
=> 2
irb(main):008:0> b
=> #<C:0x00000002311210 @a=2>
Это же все одно, что а=, что attr_writer, что instance_variable_set. Последний-то случай вы за сеттер признаете?

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

А что такое сеттер

Просто когда говорят сеттер, то у меня в голове возникает какая-то специфичная конструкция, тесно связанная с понятием «свойство», а в руби нет свойств, следовательно нет и сеттеров. А указанное выше - абсолютно типичный вызов метода.

a= - это просто метод, а не перегрузка = для типа переменной а.

Кто спорит, но ведь выглядит именно так. Так какая разница.

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

Ага, какая разница. Сегодня ты показал тсу, что можно сделать что-то подобное перегрузке, а завтра он попробует сделать это для класса в целом, не сможет, и будет на лоре обсирать уже не питон, а руби. Нет пути!

cdshines ★★★★★
()

1. Как обстоят дела на Ruby с ФП?

Плохо. Даже в python лучше.

2. Как обстоят дела с меттапрограммированием?

Никак. Метапрограммирования в рубях нету.

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

Последний-то случай вы за сеттер признаете?

мм.. не знаю.. это важно?) Это больше метапрограммирование чем сеттер)

для меня эталонный сеттер вот:

  public class ScheduleTask
  {
    private int hours;
    public int Hours
    {
      set
      {
         if ( (value >= 0) && (value < 24) )
         {
           hours = value;
         }
      }
    }
  }

ИМХО бесполезная штука, аналог, по функционалу, которой в руби будет выглядеть и лаконичнее, и красивее, и логичнее, и органичнее.

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

Во-первых, в самом общем смысле: In computer science, a mutator method is a method used to control changes to a variable. И только In programming languages that support them, properties offer a convenient alternative without giving up the utility of encapsulation.

http://en.wikipedia.org/wiki/Accessor. Особенно #Ruby_example часть:)

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

ах.. руби часть.. такая нормальная) Да, я говорю о собственных ассоциациях, на основе собственного опыта работы с языками. Просто я не работал с языками без пропертей кроме руби..

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

Кстати, bang'и использовать, если нету метода без него, не по феншую. Правильно было бы назвать inc_a.

drakmail ★★★★
()
Ответ на: комментарий от special-k

Спасибо за пояснения, рассматриваю возможность того, что понаписал полностью на рубин. У вас есть опыт написания больших приложений на руби? (не рельсы)

iMushroom
() автор топика

Ruby слишком мейнстримно для тебя. LISP, впрочем, тоже.

Если хочешь труЪ нонконформизма — твой выбор Coq, Agda2, Omega, Epigram, APL, J, K, Smalltalk.

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

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

LISP же, ну!

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

Не скажу за 1 и 3-4, но 2 же даже не тьюринг-полный, что на нем писать, кроме матановых штук для окунания хаскелистов в говно?

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

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

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