Pytanie Używanie symboli jako argumentów w metodach ruby


Uczę się szyn i wracam do rubinu, aby zrozumieć, w jaki sposób metody w szynach (i ruby ​​naprawdę działają). Kiedy widzę wywołania metod, takie jak:

validates validates :first_name, :presence => true

Jestem zmieszany. Jak piszesz w ruby, które akceptują symbole lub hashe. Kod źródłowy metody sprawdzania poprawności również jest mylący. Czy ktoś mógłby uprościć ten temat używania symboli jako argumentów w klasie ruby ​​i metod instancji dla mnie?

AKTUALIZACJA:

Dobry jeden @Dave! Ale to, co próbowałem, było coś takiego:

def full_name (:first_name, :last_name)
  @first_name = :first_name
  @last_name = :last_name
  p "#{@first_name} #{last_name}"
end

full_name("Breta", "Von Sustern")

Co oczywiście powoduje błędy. Próbuję zrozumieć: dlaczego przekazywanie takich symboli jest błędne, jeśli symbole są jak każda inna wartość?


12
2017-11-05 16:44


pochodzenie


Symbole i skróty są wartościami jak każde inne - nie ma nic innego w przekazywaniu symbolu lub skrótu niż cokolwiek innego. Co konkretnie cię mylą? - Dave Newton
To, co wprawia mnie w zakłopotanie, to to, że nigdy nie widziałem przykładu skrótów używanych jako wartości w metodach ruby. Więc nie mogę sobie wyobrazić, co mówisz. - Amit Erandole
ty przechodzić symbole, nazwy parametrów są nadal tylko takie - nazwy parametrów i nie powinny mieć wiodącego : postać. - Dave Newton
aah! więc odpowiedzią na moje głupie pytanie jest to, że nie mogę przekazywać symboli jako argumentów podczas konstruowania metod, ale mogę, gdy je nazywam. Czy to jest poprawne? - Amit Erandole
Poprawny. Kiedy definiujesz metodę, nic nie przekazujesz. Nazwiesz argumenty, które zostaną przekazane, gdy ta metoda zostanie wywołana. W twoim przykładzie będzie to po prostu: def full_name (first_name, last_name) Ale to zły przykład, ponieważ nie przekazywałbyś imienia i nazwiska jako symboli, przekazywałbyś je jako ciągi, na przykład person.full_name ("Bruce", "Dickens") - sheldonh


Odpowiedzi:


Symbole i skróty są wartościami jak wszystkie inne i mogą być przekazywane jak każdy inny typ wartości.

Przypomnijmy, że modele ActiveRecord przyjmują wartość mieszającą jako argument; kończy się to podobnym do tego (nie jest to takie proste, ale na końcu jest to ten sam pomysł):

class User
  attr_accessor :fname, :lname

  def initialize(args)
    @fname = args[:fname] if args[:fname]
    @lname = args[:lname] if args[:lname]
  end
end

u = User.new(:fname => 'Joe', :lname => 'Hacker')

To wykorzystuje brak konieczności umieszczania skrótu w nawiasach klamrowych {} chyba że musisz ujednoznacznić parametry (i istnieje również problem z parsowaniem bloku, gdy pomijasz pareny).

Podobnie:

class TestItOut
  attr_accessor :field_name, :validations

  def initialize(field_name, validations)
    @field_name = field_name
    @validations = validations
  end

  def show_validations
    puts "Validating field '#{field_name}' with:"
    validations.each do |type, args|
      puts "  validator '#{type}' with args '#{args}'"
    end
  end
end

t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 })
t.show_validations

To daje wynik:

Validating field 'name' with:
  validator 'presence' with args 'true'
  validator 'length' with args '{min: 2, max: 10}'

Stamtąd możesz zacząć widzieć, jak to działa.


19
2017-11-05 16:57



Rozważ także użycie fetch metoda dostarczania wartości domyślnych podczas pobierania argumentów wewnątrz hasza. - André Barbosa


Pomyślałem, że dodam aktualizację dla Ruby 2+, ponieważ jest to pierwszy wynik dla "symboli jako argumentów".

Od Ruby 2.0.0 możesz także używać symboli podczas definiowania metody. Podczas wywoływania metody symbole te będą działać prawie tak samo, jak nazwane parametry opcjonalne w innych językach. Zobacz przykład poniżej:

def variable_symbol_method(arg, arg_two: "two", arg_three: "three")
  [arg, arg_two, arg_three]
end

result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg"

# result is now equal to:
[:custom_symbol, "two", "Modified symbol arg"]

Jak pokazano w przykładzie, pomijamy arg_two: podczas wywoływania metody i treści metody nadal możemy uzyskać do niej dostęp jako zmienną arg_two. Zwróć także uwagę na zmienną arg_three jest rzeczywiście zmienione przez wywołanie funkcji.


9
2017-09-30 19:43





W Ruby, jeśli wywołasz metodę z garścią name => value pary na końcu listy argumentów, są automatycznie pakowane w Hash i przekazany do twojej metody jako ostatni argument:

def foo(kwargs)
  p kwargs
end

>> foo(:abc=>"def", 123=>456)
{:abc=>"def", 123=>456}

>> foo("cabbage")
"cabbage"

>> foo(:fluff)
:fluff

Nie ma nic "specjalnego" o tym, jak piszesz metodę, tak to nazywasz. Byłoby całkowicie legalne po prostu przekazać zwykły obiekt Hash jako kwargs parametr. Ten skrót syntaktyczny służy do implementacji nazwane parametry w interfejsie API.

Symbol Rubinowy to wartość jak każda inna, więc w twoim przykładzie, :first_name jest zwykłym argumentem pozycyjnym. :presence to symbol używany jako klucz skrótu - dowolny typ może być używany jako klucz skrótu, ale symbole są często wybierane, ponieważ są wartościami niezmiennymi.


4
2017-11-05 17:01



I, co ważniejsze, niż niezmienne, są bardziej komunikatywne, ponieważ działają konkretnie jako nazwa lub etykieta czegoś. - Dave Newton


Symbole nie są ograniczone do skrótów. Są to identyfikatory, bez dodatkowej przestrzeni dyskowej. To tylko sposób na powiedzenie "to jest ..."

Możliwą definicją funkcji dla sprawdzania poprawności może być (tylko po to, aby uprościć, nie wiem z góry, jaka jest naprawdę):

def validates(column, options)
   puts column.to_s
   if options[:presence]
     puts "Found a presence option"
   end
 end

Zwróć uwagę, że pierwszy symbol jest parametrem sam w sobie, a reszta to hash.


2
2017-11-05 17:02



Wciąż są przechowywane, po prostu każda unikatowa etykieta jest przechowywana tylko raz, tak jak internowany ciąg znaków. OTOH, nie kwalifikują się do GC (może są w 1.9), więc pozostają przy życiu. - Dave Newton
Symbole nie mają wartości GC w 1.9. - sheldonh
Ruby 2.2 ma teraz symbol GC - DGM


Sądzę, że wszystkie odpowiedzi pominęły kwestię; i fakt, że pyta go ktoś, kto jest - jak sądzę - nie wiadomo, czym jest symbol?

Jako nowicjusz w Ruby miałem podobne nieporozumienia i dla mnie odpowiedź taka jak ta miała więcej sensu

Argumenty metody są zmiennymi lokalnymi zapełnionymi przez przekazane wartości.

Nie możesz używać symboli jako Argumenty same, ponieważ nie możesz zmienić wartości symbolu.


2
2018-03-30 13:43



Nie jestem pewien, co masz na myśli mówiąc "nie możesz używać symboli jako argumentów przez siebie", ponieważ możesz ... foo(:bar) jest całkowicie uzasadnionym wywołaniem funkcji. Być może źle mnie zrozumiałem? - Dave Newton