Cosa significano le diverse parentesi in Ruby?


85

In Ruby, qual è la differenza tra {}e []?

{} sembra essere utilizzato sia per i blocchi di codice che per gli hash.

Sono []solo per array?

La documentazione non è molto chiara.

Risposte:


72

Dipende dal contesto:

  1. Quando da soli, o assegnando a una variabile, []crea array e {}crea hash. per esempio

    a = [1,2,3] # an array
    b = {1 => 2} # a hash
    
  2. []può essere sovrascritto come metodo personalizzato, ed è generalmente usato per recuperare cose dagli hash (la libreria standard si configura []come un metodo sugli hash che è lo stesso di fetch)
    C'è anche una convenzione secondo cui è usato come metodo di classe nello stesso modo in cui potresti usare un static Createmetodo in C # o Java. per esempio

    a = {1 => 2} # create a hash for example
    puts a[1] # same as a.fetch(1), will print 2
    
    Hash[1,2,3,4] # this is a custom class method which creates a new hash
    

    Vedi la documentazione di Ruby Hash per questo ultimo esempio.

  3. Questo è probabilmente il più complicato - {}è anche la sintassi per i blocchi, ma solo quando viene passato a un metodo FUORI dalle parentesi degli argomenti.

    Quando si invocano metodi senza parentesi, Ruby guarda dove si inseriscono le virgole per capire dove finiscono gli argomenti (dove sarebbero state le parentesi, se le avessi digitate)

    1.upto(2) { puts 'hello' } # it's a block
    1.upto 2 { puts 'hello' } # syntax error, ruby can't figure out where the function args end
    1.upto 2, { puts 'hello' } # the comma means "argument", so ruby sees it as a hash - this won't work because puts 'hello' isn't a valid hash
    

2
nota a margine: Hash # fetch non è esattamente Hash # []. {: a => 1,: b => 2} .fetch (: c) IndexError: chiave non trovata
tokland

@tokland :cnon trovato
yyny

"Esiste anche una convenzione secondo la quale viene utilizzato come metodo di classe nello stesso modo in cui si potrebbe utilizzare un metodo Create statico in C # o Java." Questa è esattamente la risposta che stavo cercando. Anche un classico esempio di ciò che odio di più di Ruby; devi conoscere un sacco di piccoli trucchi oscuri per leggere il codice Ruby.
Tony

22

Un altro, non così ovvio, utilizzo di []è come sinonimo di Proc # call e Method # call. Questo potrebbe creare un po 'di confusione la prima volta che lo incontri. Immagino che il razionale alla base sia che lo fa sembrare più una normale chiamata di funzione.

Per esempio

proc = Proc.new { |what| puts "Hello, #{what}!" }
meth = method(:print)

proc["World"]
meth["Hello",","," ", "World!", "\n"]

9

In generale, hai ragione. Oltre agli hash, lo stile generale è che le parentesi graffe {}vengono spesso utilizzate per i blocchi che possono adattarsi tutti su una riga, invece di utilizzare do/ endsu più righe.

Le parentesi quadre []vengono utilizzate come metodi di classe in molte classi Ruby, tra cui String, BigNum, Dir e, in modo abbastanza confuso, Hash. Così:

Hash["key" => "value"]

è valido quanto:

{ "key" => "value" }

3

Le parentesi quadre [] vengono utilizzate per inizializzare gli array. La documentazione per il caso dell'inizializzatore di [] è in

ri Array::[]

Le parentesi graffe {} vengono utilizzate per inizializzare gli hash. La documentazione per il caso dell'inizializzatore di {} è in

ri Hash::[]

Le parentesi quadre sono anche comunemente usate come metodo in molte classi principali di ruby, come Array, Hash, String e altre.

È possibile accedere a un elenco di tutte le classi che hanno il metodo "[]" definito con

ri []

la maggior parte dei metodi ha anche un metodo "[] =" che consente di assegnare cose, ad esempio:

s = "hello world"
s[2]     # => 108 is ascii for e
s[2]=109 # 109 is ascii for m
s        # => "hemlo world"

Le parentesi graffe possono anche essere usate al posto di "do ... end" sui blocchi, come "{...}".

Un altro caso in cui è possibile vedere le parentesi quadre o le parentesi graffe utilizzate è negli inizializzatori speciali in cui è possibile utilizzare qualsiasi simbolo, come:

%w{ hello world } # => ["hello","world"]
%w[ hello world ] # => ["hello","world"]
%r{ hello world } # => / hello world /
%r[ hello world ] # => / hello world /
%q{ hello world } # => "hello world"
%q[ hello world ] # => "hello world"
%q| hello world | # => "hello world"

2

alcuni esempi:

[1, 2, 3].class
# => Array

[1, 2, 3][1]
# => 2

{ 1 => 2, 3 => 4 }.class
# => Hash

{ 1 => 2, 3 => 4 }[3]
# => 4

{ 1 + 2 }.class
# SyntaxError: compile error, odd number list for Hash

lambda { 1 + 2 }.class
# => Proc

lambda { 1 + 2 }.call
# => 3

2

Nota che puoi definire il []metodo per le tue classi:

class A
 def [](position)
   # do something
 end

 def @rank.[]= key, val
    # define the instance[a] = b method
 end

end

1
Qual è il @rank.?
FeifanZ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.