it-swarm.it

Funzioni nascoste di Ruby

Continuando il meme "Funzioni nascoste di ...", condividiamo le funzionalità meno note ma utili del linguaggio di programmazione Ruby.

Cerca di limitare questa discussione con il core Ruby, senza alcun Ruby on Rails cose.

Guarda anche:

(Per favore, solo una funzione nascosta per risposta.)

Grazie

160
squadette

From Ruby 1.9 Proc # === è un alias per Proc # call, il che significa che gli oggetti Proc possono essere usati in questi casi:

def multiple_of(factor)
  Proc.new{|product| product.modulo(factor).zero?}
end

case number
  when multiple_of(3)
    puts "Multiple of 3"
  when multiple_of(7)
    puts "Multiple of 7"
end
80
Farrel

Peter Cooper ha una buona lista di Ruby. Forse il mio preferito è quello di consentire l'enumerazione di singoli oggetti e collezioni. (Cioè, trattare un non- oggetto di raccolta come una raccolta contenente solo quell'oggetto.) È simile al seguente:

[*items].each do |item|
  # ...
end
76
James A. Rosen

Non so quanto sia nascosto, ma l'ho trovato utile quando è necessario creare un hash da un array unidimensionale:

fruit = ["Apple","red","banana","yellow"]
=> ["Apple", "red", "banana", "yellow"]

Hash[*fruit]    
=> {"Apple"=>"red", "banana"=>"yellow"}
64
astronautism

Un trucco che mi piace è usare lo splat (*) espansore su oggetti diversi dalle matrici. Ecco un esempio di una corrispondenza di espressioni regolari:

match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)

Altri esempi includono:

a, b, c = *('A'..'Z')

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom
54
tomafro

Wow, nessuno ha menzionato l'operatore di infradito:

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end
52
Konstantin Haase

Una delle cose interessanti di Ruby è che puoi chiamare metodi ed eseguire il codice in luoghi in cui altre lingue non si accorgerebbero, come nelle definizioni di metodi o classi.

Ad esempio, per creare una classe che ha una superclasse sconosciuta fino al runtime, ovvero è casuale, è possibile effettuare le seguenti operazioni:

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.

Questo utilizza il metodo 1.9 Array#sample (Solo in 1.8.7, vedi Array#choice), E l'esempio è abbastanza elaborato ma puoi vedere il potere qui.

Un altro esempio interessante è la possibilità di inserire valori di parametri predefiniti non fissi (come spesso richiedono altre lingue):

def do_something_at(something, at = Time.now)
   # ...
end

Naturalmente il problema con il primo esempio è che viene valutato al momento della definizione, non al momento della chiamata. Quindi, una volta che una superclasse è stata scelta, rimane quella superclasse per il resto del programma.

Tuttavia, nel secondo esempio, ogni volta che chiami do_something_at, La variabile at sarà il momento in cui è stato chiamato il metodo (beh, molto molto vicino ad esso)

49
Bo Jeanes

Un'altra piccola funzione: convertire un Fixnum in qualsiasi base fino a 36:

>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"

>> 1234567890.to_s(8)
=> "11145401322"

>> 1234567890.to_s(16)
=> "499602d2"

>> 1234567890.to_s(24)
=> "6b1230i"

>> 1234567890.to_s(36)
=> "kf12oi"

E come ha commentato Huw Walters, convertire dall'altra parte è altrettanto semplice:

>> "kf12oi".to_i(36)
=> 1234567890
47
tomafro

Hash con valori predefiniti! Un array in questo caso.

parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []

parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"

Molto utile nella metaprogrammazione.

40
August Lilleaas

Scarica Ruby 1.9 e problema make golf, quindi puoi fare cose del genere:

make golf

./goruby -e 'h'
# => Hello, world!

./goruby -e 'p St'
# => StandardError

./goruby -e 'p 1.tf'
# => 1.0

./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/Ruby-svn/src/trunk"

Leggi il golf_prelude.c per nascondere altre cose pulite.

39
manveru

Un'altra aggiunta divertente nella funzionalità Proc 1.9 è il curry Proc # che consente di trasformare un Proc che accetta n argomenti in uno che accetta n-1. Qui è combinato con il suggerimento Proc # === che ho menzionato sopra:

it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]

case Time.now
when it_is_saturday
  puts "Saturday!"
when it_is_sunday
  puts "Sunday!"
else
  puts "Not the weekend"
end
38
Farrel

Operatori booleani su valori non booleani.

&& e ||

Entrambi restituiscono il valore dell'ultima espressione valutata.

Ecco perché il ||= aggiornerà la variabile con il valore restituito espressione sul lato destro se la variabile non è definita. Questo non è esplicitamente documentato, ma conoscenza comune.

Comunque, il &&= non è abbastanza conosciuto.

string &&= string + "suffix"

è equivalente a

if string
  string = string + "suffix"
end

È molto utile per operazioni distruttive che non dovrebbero procedere se la variabile non è definita.

35
EmFi

La funzione Symbol # to_proc che Rails fornisce è davvero interessante.

Invece di

Employee.collect { |emp| emp.name }

Tu puoi scrivere:

Employee.collect(&:name)
29
hoyhoy

Un ultimo - in Ruby puoi usare qualsiasi carattere che desideri delimitare le stringhe. Prendi il seguente codice:

message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"

Se non vuoi sfuggire alle doppie virgolette all'interno della stringa, puoi semplicemente usare un delimitatore diverso:

contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]

Oltre a evitare di dover sfuggire ai delimitatori, puoi utilizzare questi delimitatori per stringhe multilinea più belle:

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}
28
tomafro

Trovo che usare il comando define_method per generare dinamicamente metodi sia abbastanza interessante e non così noto. Per esempio:

((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end

Il codice sopra usa il comando 'define_method' per creare dinamicamente i metodi da "press1" a "press9". Invece di digitare tutti i 10 metodi che contengono essenzialmente lo stesso codice, il comando define method viene utilizzato per generare questi metodi al volo, se necessario.

26

Utilizzare un oggetto Range come un elenco pigro infinito:

Inf = 1.0 / 0

(1..Inf).take(5) #=> [1, 2, 3, 4, 5]

Maggiori informazioni qui: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-Ruby/

26
horseyguy

module_function

I metodi del modulo dichiarati come module_function creeranno copie di se stessi come private metodi di istanza nella classe che include il Modulo:

module M
  def not!
    'not!'
  end
  module_function :not!
end

class C
  include M

  def fun
    not!
  end
end

M.not!     # => 'not!
C.new.fun  # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>

Se si utilizza module_function senza argomenti, tutti i metodi del modulo che seguono la dichiarazione module_function diventeranno automaticamente module_functions stessi.

module M
  module_function

  def not!
    'not!'
  end

  def yea!
    'yea!'
  end
end


class C
  include M

  def fun
    not! + ' ' + yea!
  end
end
M.not!     # => 'not!'
M.yea!     # => 'yea!'
C.new.fun  # => 'not! yea!'
23
newtonapple

Iniezione breve, come tale:

Somma dell'intervallo:

(1..10).inject(:+)
=> 55
23
user130730

Attenzione: questo articolo è stato votato # 1 Hack più orrendo del 2008, quindi usalo con cura. In realtà, evitatelo come la peste, ma è certamente nascosto Ruby.

I superatori aggiungono nuovi operatori a Ruby

Hai mai desiderato un operatore di stretta di mano super-segreto per alcune operazioni uniche nel tuo codice? Ti piace giocare a code golf? Prova operatori come - ~ + ~ - o <--- Quest'ultimo è usato negli esempi per invertire l'ordine di un articolo.

Non ho nulla a che fare con Superators Project oltre ad ammirarlo.

21
Captain Hammer

Sono in ritardo alla festa, ma:

Puoi facilmente prendere due array di uguale lunghezza e trasformarli in un hash con un array che fornisce le chiavi e l'altro i valori:

a = [:x, :y, :z]
b = [123, 456, 789]

Hash[a.Zip(b)]
# => { :x => 123, :y => 456, :z => 789 }

(Funziona perché Array # Zip "comprime" i valori dei due array:

a.Zip(b)  # => [[:x, 123], [:y, 456], [:z, 789]]

E Hash [] può prendere proprio un tale array. Ho visto persone fare anche questo:

Hash[*a.Zip(b).flatten]  # unnecessary!

Il che produce lo stesso risultato, ma lo splat e l'appiattimento sono totalmente inutili - forse non lo erano in passato?)

19
Jordan Running

Hash auto-vivificanti in Ruby

def cnh # silly name "create nested hash"
  Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }

Questo può essere dannatamente utile.

19
Trevoke

Destructuring an Array

(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]

Dove:

a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]

Usando questa tecnica possiamo usare un semplice incarico per ottenere i valori esatti che vogliamo dall'array nidificato di qualsiasi profondità.

16
horseyguy

Class.new()

Crea una nuova classe in fase di esecuzione. L'argomento può essere una classe da cui derivare e il blocco è il corpo della classe. Potresti anche voler guardare const_set/const_get/const_defined? per registrare correttamente la tua nuova classe, in modo che inspect stampi un nome anziché un numero.

Non qualcosa di cui hai bisogno ogni giorno, ma abbastanza utile quando lo fai.

15
Justin Love

creare una matrice di numeri consecutivi:

x = [*0..5]

imposta x su [0, 1, 2, 3, 4, 5]

13
horseyguy

Molta della magia che vedi in Rubyland ha a che fare con la metaprogrammazione, che è semplicemente scrivere codice che scrive codice per te. Ruby attr_accessor, attr_reader, e attr_writer sono tutte semplici metaprogrammazioni, in quanto creano due metodi in una riga, seguendo uno schema standard. Rails esegue molte metaprogrammazioni con i loro metodi di gestione delle relazioni come has_one e belongs_to.

Ma è abbastanza semplice creare i tuoi trucchi di metaprogrammazione usando class_eval per eseguire codice scritto dinamicamente.

L'esempio seguente consente a un oggetto wrapper di inoltrare determinati metodi insieme a un oggetto interno:

class Wrapper
  attr_accessor :internal

  def self.forwards(*methods)
    methods.each do |method|
      define_method method do |*arguments, &block|
        internal.send method, *arguments, &block
      end
    end
  end

  forwards :to_i, :length, :split
end

w = Wrapper.new
w.internal = "12 13 14"
w.to_i        # => 12
w.length      # => 8
w.split('1')  # => ["", "2 ", "3 ", "4"]

Il metodo Wrapper.forwards accetta i simboli per i nomi dei metodi e li memorizza nell'array methods. Quindi, per ognuno di quelli indicati, usiamo define_method per creare un nuovo metodo il cui compito è inviare il messaggio, inclusi tutti gli argomenti e i blocchi.

Una grande risorsa per i problemi di metaprogrammazione è Why "Lucky Seeing Metaprogramming Clearing" .

13
TALlama

usa tutto ciò che risponde a ===(obj) per i confronti di casi:

case foo
when /baz/
  do_something_with_the_string_matching_baz
when 12..15
  do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
  # only works in Ruby 1.9 or if you alias Proc#call as Proc#===
  do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
  do_something_with_the_instance_of_Bar
when some_object
  do_something_with_the_thing_that_matches_some_object
end

Module (e quindi Class), Regexp, Date e molte altre classi definiscono un metodo di istanza: === (altro), e tutti possono essere utilizzato.

Grazie a Farrel per il promemoria di Proc#call essendo alias come Proc#=== in Ruby 1.9.

12
James A. Rosen

Il binario "Ruby" (almeno la risonanza magnetica) supporta molti degli switch che hanno reso molto popolare la battuta del Perl.

Significativi:

  • -n Imposta un ciclo esterno con solo "get" - che funziona magicamente con il nome file o STDIN dato, impostando ogni riga di lettura in $ _
  • -p Simile a -n ma con un puts automatico alla fine di ogni iterazione di loop
  • -a Chiamata automatica a .split su ogni linea di input, memorizzata in $ F
  • -i Modifica i file di input sul posto
  • -l Chiamata automatica a .chomp su input
  • -e Esegue un pezzo di codice
  • -c Controlla il codice sorgente
  • -w Con avvertenze

Qualche esempio:

# Print each line with its number:
Ruby -ne 'print($., ": ", $_)' < /etc/irbrc

# Print each line reversed:
Ruby -lne 'puts $_.reverse' < /etc/irbrc

# Print the second column from an input CSV (dumb - no balanced quote support etc):
Ruby -F, -ane 'puts $F[1]' < /etc/irbrc

# Print lines that contain "eat"
Ruby -ne 'puts $_ if /eat/i' < /etc/irbrc

# Same as above:
Ruby -pe 'next unless /eat/i' < /etc/irbrc

# Pass-through (like cat, but with possible line-end munging):
Ruby -p -e '' < /etc/irbrc

# Uppercase all input:
Ruby -p -e '$_.upcase!' < /etc/irbrc

# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
Ruby -i.bak -p -e '$_.upcase!' /etc/irbrc

Sentiti libero di utilizzare Google "Ruby one-liner" e "Perl one-liner" per tonnellate di esempi più utilizzabili e pratici. In sostanza ti permette di usare Ruby come sostituto abbastanza potente di awk e sed.

11
minaguib

Il metodo send () è un metodo generico che può essere utilizzato su qualsiasi classe o oggetto in Ruby. Se non sovrascritto, send () accetta una stringa e chiama il nome del metodo di cui viene passata la stringa. Ad esempio, se l'utente fa clic sul pulsante "Clr", la stringa "press_clear" verrà inviata al metodo send () e verrà chiamato il metodo "press_clear". Il metodo send () consente un modo divertente e dinamico di chiamare funzioni in Ruby.

 %w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
    button btn, :width => 46, :height => 46 do
      method = case btn
        when /[0-9]/: 'press_'+btn
        when 'Clr': 'press_clear'
        when '=': 'press_equals'
        when '+': 'press_add'
        when '-': 'press_sub'
        when '*': 'press_times'
        when '/': 'press_div'
      end

      number.send(method)
      number_field.replace strong(number)
    end
  end

Parlo di più di questa funzione in Scarpe da blog: l'applicazione Simple-Calc

10
private unless Rails.env == 'test'
# e.g. a bundle of methods you want to test directly

Sembra un fantastico e (in alcuni casi) bello/utile hack/funzionalità di Ruby.

9
Szymon Jeż

Fixnum#to_s(base) può essere davvero utile in alcuni casi. Uno di questi casi sta generando token univoci casuali (pseudo) convertendo un numero casuale in stringa usando una base di 36.

Token di lunghezza 8:

Rand(36**8).to_s(36) => "fmhpjfao"
Rand(36**8).to_s(36) => "gcer9ecu"
Rand(36**8).to_s(36) => "krpm0h9r"

Token di lunghezza 6:

Rand(36**6).to_s(36) => "bvhl8d"
Rand(36**6).to_s(36) => "lb7tis"
Rand(36**6).to_s(36) => "ibwgeh"
9
sickill

Imbrogliamo qualche classe o modulo dicendo che ha richiesto qualcosa che in realtà non ha richiesto:

$" << "something"

Questo è utile ad esempio quando si richiede A che a sua volta richiede B ma non abbiamo bisogno di B nel nostro codice (e A non lo userà nemmeno attraverso il nostro codice):

Ad esempio, bdrb_test_helper requires'test/spec', ma non lo usi affatto, quindi nel tuo codice:

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")
9
olegueret

Definizione di un metodo che accetta un numero qualsiasi di parametri e li scarta tutti

def hello(*)
    super
    puts "hello!"
end

Il precedente metodo hello deve solo puts"hello" sullo schermo e chiama super - ma poiché la superclasse hello definisce anche i parametri, anche se non ha bisogno di utilizzare i parametri in sé - non lo fa dare loro un nome.

9
horseyguy

Per combinare più regex con |, Puoi usare

Regexp.union /Ruby\d/, /test/i, "cheat"

per creare un Regexp simile a:

/(Ruby\d|[tT][eE][sS][tT]|cheat)/
8
J-_-L

Lo trovo utile in alcuni script. Consente di utilizzare direttamente le variabili di ambiente, come negli script Shell e nei Makefile. Le variabili di ambiente vengono utilizzate come fallback per costanti non definite Ruby.

>> class <<Object
>>  alias :old_const_missing :const_missing
>>  def const_missing(sym)
>>   ENV[sym.to_s] || old_const_missing(sym)
>>  end
>> end
=> nil

>> puts Shell
/bin/zsh
=> nil
>> TERM == 'xterm'
=> true
8
Ropez

Che ne dici di aprire un file basato su ARGV [0]?

readfile.rb:

$<.each_line{|l| puts l}

Ruby readfile.rb testfile.txt

È un'ottima scorciatoia per scrivere script unici. C'è un sacco di variabili predefinite che molte persone non conoscono. Usali con saggezza (leggi: non sporcare una base di codice che intendi mantenere con loro, può diventare disordinata).

8
Scott Holden

Sono un fan di:

%w{An Array of strings} #=> ["An", "Array", "of", "Strings"]

È abbastanza divertente quanto spesso sia utile.

5
Judson

Valori di restituzione multipli

def getCostAndMpg
    cost = 30000  # some fancy db calls go here
    mpg = 30
    return cost,mpg
end
AltimaCost, AltimaMpg = getCostAndMpg
puts "AltimaCost = #{AltimaCost}, AltimaMpg = #{AltimaMpg}"

Assegnazione parallela

i = 0
j = 1
puts "i = #{i}, j=#{j}"
i,j = j,i
puts "i = #{i}, j=#{j}"

Attributi virtuali

class Employee < Person
  def initialize(fname, lname, position)
    super(fname,lname)
    @position = position
  end
  def to_s
     super + ", #@position"
  end
  attr_writer :position
  def etype
     if @position == "CEO" || @position == "CFO"
         "executive"
     else
         "staff"
     end
  end
end
employee = Employee.new("Augustus","Bondi","CFO")
employee.position = "CEO"
puts employee.etype    =>  executive
employee.position = "Engineer"
puts employee.etype    =>  staff

method_missing - un'idea meravigliosa

(Nella maggior parte delle lingue quando non è possibile trovare un metodo e viene generato un errore e il programma si arresta. In Ruby puoi effettivamente rilevare quegli errori e forse fare qualcosa di intelligente con la situazione)

class MathWiz
  def add(a,b) 
    return a+b
  end
  def method_missing(name, *args)
    puts "I don't know the method #{name}"
  end
end
mathwiz = MathWiz.new
puts mathwiz.add(1,4)
puts mathwiz.subtract(4,2)

5

Non conosco il metodo sottrarre

zero

5
Ramiz Uddin

La punta di James A. Rosen è interessante ([* items] .each), ma trovo che distrugga gli hash:

irb(main):001:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):002:0> [*h]
=> [[:name, "Bob"]]

Preferisco questo modo di gestire il caso quando accetto un elenco di cose da elaborare ma sono indulgente e consento al chiamante di fornirne uno:

irb(main):003:0> h = {:name => "Bob"}
=> {:name=>"Bob"}
irb(main):004:0> [h].flatten
=> [{:name=>"Bob"}]

Questo può essere combinato con una firma del metodo così bene:

def process(*entries)
  [entries].flatten.each do |e|
    # do something with e
  end
end
4
minaguib

Adoro amo la parola chiave incorporata salvataggio in questo modo:
ESEMPIO MODIFICATO:

@user #=> nil (but I did't know)
@user.name rescue "Unknown"
link_to( d.user.name, url_user( d.user.id, d.user.name)) rescue 'Account removed'

Questo evita di interrompere la mia app ed è molto meglio della funzione rilasciata a Rails . Try ()

4
Fabiano Soriani

Chiamare un metodo definito in qualsiasi punto della catena di ereditarietà, anche se sottoposto a override

Gli oggetti di ActiveSupport talvolta si mascherano come oggetti incorporati.

 richiedono 'active_support' 
 giorni = 5.days 
 days.class # => Fixnum 
 days.is_a? (Fixnum) # => true 
 Fixnum === giorni # => false (eh? Che cosa sei veramente?) 
 Object.instance_method (: class) .bind (days) .call # => ActiveSupport :: Duration (aha!) 
 ActiveSupport :: Durata === giorni # => vero 

Quanto sopra, ovviamente, si basa sul fatto che active_support non ridefinisce l'Oggetto # istanza_metodo, nel qual caso saremmo davvero su un ruscello. Quindi, potremmo sempre salvare il valore restituito di Object.instance_method (: class) prima che venga caricata una libreria di terze parti.

Object.instance_method (...) restituisce un UnboundMethod che puoi quindi associare a un'istanza di quella classe. In questo caso, è possibile associarlo a qualsiasi istanza di Object (sottoclassi incluse).

Se la classe di un oggetto include moduli, è anche possibile utilizzare UnboundMethod da tali moduli.

 modulo Mod 
 def var_add (altro); @ Var + più; end 
 end 
 class Cla 
 include Mod 
 def inizializza (var); @ Var = var; end 
 # override 
 def var_add (altro); @ Var + più + di più; end 
 end 
 cla = Cla.new ('abcdef') 
 cla.var_add ('ghi') # => "abcdefghighi" 
 Mod.instance_method ( : var_add) .bind (cla) .call ('ghi') # => "abcdefghi" 

Questo funziona anche con metodi singleton che sovrascrivono un metodo di istanza della classe a cui appartiene l'oggetto.

 classe Foo 
 def mymethod; 'originale'; end 
 end 
 foo = Foo.new 
 foo.mymethod # => 'original' 
 def foo.mymethod; 'singleton'; end 
 foo.mymethod # => 'singleton' 
 Foo.instance_method (: mymethod) .bind (foo) .call # => 'original' 
 
 # Puoi anche chiamare il metodo #instance su classi singleton: 
 Class << pippo; se stesso; end.instance_method (: mymethod) .bind (foo) .call # => 'singleton' 
4
Kelvin

Ci sono alcuni aspetti dei simboli letterali che le persone dovrebbero conoscere. Un caso risolto da letterali di simboli speciali è quando è necessario creare un simbolo il cui nome causa un errore di sintassi per qualche motivo con la normale sintassi letterale di simboli:

:'class'

Puoi anche eseguire l'interpolazione dei simboli. Nel contesto di un accessorio, ad esempio:

define_method :"#{name}=" do |value|
  instance_variable_set :"@#{name}", value
end
3
Tom

each_with_index metodo per qualsiasi oggetto enumarabile (array, hash, ecc.) forse?

myarray = ["la", "li", "lu"]
myarray.each_with_index{|v,idx| puts "#{idx} -> #{v}"}

#result:
#0 -> la
#1 -> li
#2 -> lu

Forse è più noto di altre risposte ma non così noto per tutti Ruby :)

3
mhd
class A

  private

  def my_private_method
    puts 'private method called'
  end
end

a = A.new
a.my_private_method # Raises exception saying private method was called
a.send :my_private_method # Calls my_private_method and prints private method called'
2
Chirantan

Ruby ha un meccanismo call/cc che consente di salire e scendere liberamente dallo stack.

Segue un semplice esempio. Questo non è certamente il modo in cui si moltiplicherebbe una sequenza in Ruby, ma dimostra come si potrebbe usare call/cc per raggiungere lo stack per cortocircuitare un algoritmo. In questo caso, stiamo moltiplicando ricorsivamente un elenco di numeri fino a quando non abbiamo visto tutti i numeri o non vediamo zero (i due casi in cui conosciamo la risposta). Nel caso zero, possiamo essere arbitrariamente in profondità nell'elenco e terminare.

#!/usr/bin/env Ruby

def rprod(k, rv, current, *nums)
  puts "#{rv} * #{current}"
  k.call(0) if current == 0 || rv == 0
  nums.empty? ? (rv * current) : rprod(k, rv * current, *nums)
end

def prod(first, *rest)
  callcc { |k| rprod(k, first, *rest) }
end

puts "Seq 1:  #{prod(1, 2, 3, 4, 5, 6)}"
puts ""
puts "Seq 2:  #{prod(1, 2, 0, 3, 4, 5, 6)}"

Puoi vedere l'output qui:

http://codepad.org/Oh8ddh9e

Per un esempio più complesso con continuazioni che si muovono nell'altra direzione nello stack, leggi l'origine su Generatore .

2
Dustin

Ho appena letto tutte le risposte ... una notevole omissione è stata la distruzione del compito:

> (a,b),c = [[1,2],3]
=> [[1,2],3]
> a
=> 1

Funziona anche per i parametri di blocco. Ciò è utile quando si hanno array nidificati, ciascun elemento rappresenta qualcosa di distinto. Invece di scrivere codice come "array [0] [1]", puoi suddividere quell'array nidificato e assegnare un nome descrittivo a ciascun elemento, in una singola riga di codice.

2
Alex D
@user #=> nil (but I did't know)
@user.name rescue "Unknown"
2
haoqi

La scorciatoia sprintf

Il mio preferito Ruby. La sintassi è format_string % argument

"%04d"  % 1         # => "0001"
"%0.2f" % Math::PI  # => "3.14"

Funziona anche con array (format_string % array_of_arguments)

"%.2f %.3f %.4f" % ([Math::PI]*3) 
# => "3.14 3.142 3.1416"
1
iblue