Any fool can make things bigger, more complex, and more violent. It takes a touch of genius and a lot of courage to move in the opposite direction. Albert Einstein

o Ruby

Super-operatory w Rubym

5 komentarzy | Kategorie: Ruby, Techblog, Tips & tricks | trackback
Tagi:

Ostatnim razem pisałem o zabawie z unicode w Rubym. Podkreślam słowo "zabawie" bo raczej nie jest to praktyczne. Chciałem jeszcze pokazać jeden dosyć ciekawy trick, który można uznać także za niezbyt praktyczny, choć niekoniecznie (o tym za chwilę).

Być może nieraz brakowało Wam operatorów w języku programowania? Może chcieliście wprowadzić swój, unikalny operator? A co byś powiedział na coś takiego:

puts "Tangy" ++ "Erlangy"    #=> TANGYERLANGY
puts "Super" -~+~- "ators"   #=> Superators

p ["jay"] <--- "spillihp"    #=> ["jay", "phillips"]

rocket = Rocket.new
fuel = Fuele.new
rocket <=- fuel              #=> rocket is full!

puts 1 /~ 2                  #=> 0.5

p ["a", "b"] <~ ["c"]        #=> ["a", "b", "c"]

Nie potrzebujesz do tego nowego parsera Rubiego, aktualny poradzi sobie z tym jak najbardziej. A wszystko dzięki temu jak Ruby interpretuje takie wiązanki. Otóż taki kod

foo ++- bar
jest równoważny temu
foo.+(bar.-@().+@())

Czyli są to wywołania zwykłych metod, które można odpowiednio przesłonić. Ten fakt wykorzystał jeden z hackerów Rubiego (co opisał na swoim blogu), zapakował ładnie do gema i nazwał go dumnie "superators".

Instalacja jest standardowa: gem install superators. Poniżej prezentuję uzupełniony kod o definicję superatorów

require 'rubygems'
require 'superators'

class Array
  superator "<---" do |operand|
    self << operand.reverse
  end

  superator "<~" do |operand|
    self.concat(operand)
    sort!
  end
end

class String
  superator "++" do |operand|
    upcase + operand.upcase
  end

  superator "-~+~-" do |operand|
    self + operand
  end
end

class Rocket
  superator "<=-" do |operand|
    puts "rocket is full!"
  end
end

class Fuel
end

puts "Tangy" ++ "Erlangy"    #=> TANGYERLANGY
puts "Super" -~+~- "ators"   #=> Superators

p ["jay"] <--- "spillihp"    #=> ["jay", "phillips"]

rocket = Rocket.new
fuel = Fuel.new
rocket <=- fuel              #=> rocket is full!

p ["b", "z", "y"] <~ ["c", "a"]     #=> ["a", "b", "c", "y", "z"]

Sposób tworzenia operatorów nie jest dowolny i podlega pewnej zasadzie. Prawidłowy superator to:
-na pierwszym miejscu jeden z binarnych operatorów: ** * / % + – << >> & | ^ <=> >= <= < > === == =~
-potem dowolna ilość operatorów unarnych: – ~ +

A co z wykorzystaniem tego w praktyce? Otóż może to się przydać przy tworzeniu jakiegoś DSL-a, w czym Ruby jest po prostu genialny. Można też pokusić się o wykorzystanie tej metody w jakimś naszym osobistym, superwypaśnym skrypcie :). Albo żeby wkurzyć innego programistę...

Jeśli spodobał Ci się wpis to może umieścisz ten blog w swoim czytniku RSS?

Komentarze

1. avatar icon Khorne napisał(a) 06 Lis 2007 o godz. 01:28:

Jakby nie wystarczyło Perla używać ;-)
A poważnie: DSLe są zajebiste. http://www.generative-programming.org/

2. avatar icon wijet napisał(a) 06 Lis 2007 o godz. 14:09:

Heh, super sprawa, Ruby chyba nigdy nie przestanie mnie zadziwiac.

3. avatar icon Radarek napisał(a) 06 Lis 2007 o godz. 14:19:

@Khorne, czy aby na pewno mówimy o tym samym znaczeniu DSL?:)

@wijet, otóż to! Od samego początku Ruby mnie zadziwia i wciąż to robi :).

4. avatar icon Khorne napisał(a) 06 Lis 2007 o godz. 14:23:

@Radarek, owszem. Czarnecki i Eisenecker pociągneli to po prostu dalej.

Na marginesie chodzi Ci nie tyle o DSL co o DSEL (embedded). Ładnym przykładem jest C++owy http://spirit.sourceforge.net/

5. avatar icon Radarek napisał(a) 06 Lis 2007 o godz. 14:36:

@Khorne, rzeczywiście, ja raczej myślę kategoriami embedded DSL. W sumie na dzień dzisiejszy tylko one mnie iteresują, bo: – są embedded, więc nie muszę się martwić o zewn. środowisko, parsowanie itp – mogę je tworzyć w Rubym – więcej do szczęścia mi nie trzeba ;)

Dodaj coś od siebie

Możesz korzystać ze składni Textile.

Pola oznaczone * są wymagane.

Proszę o dodawanie komentarzy związanych z tematem postu, sprawy osobiste proszę załatwiać przez maila bądź gg.

Zastrzegam sobie prawo do moderacji komentarzy (edycja, usuwanie).