Ten film mówi ci wszystko, co musisz wiedzieć o symbolach.
totymedli
Odpowiedzi:
249
:footo symbol o nazwie „foo”. Symbole mają wyraźną cechę polegającą na tym, że dowolne dwa takie same symbole będą identyczne:
"foo".equal?"foo"# false:foo.equal?:foo # true
To sprawia, że porównywanie dwóch symboli jest naprawdę szybkie (ponieważ chodzi tylko o porównanie wskaźnika, w przeciwieństwie do porównywania wszystkich znaków jak w łańcuchu), a ponadto nie będziesz mieć pływających wokół zillionowych kopii tego samego symbolu.
Ponadto, w przeciwieństwie do łańcuchów, symbole są niezmienne.
Zastanawiam się, dlaczego dosłowny ciąg nie obsługuje internowania łańcucha?
onmyway133,
5
@ onmyway133 Ponieważ ciągi Ruby są zmienne. Internowanie dotyczy tylko niezmiennych wartości.
Chris Jester-Young,
3
a) Dlaczego "foo".equal? "foo"fałsz? b) Czy możesz odwołać się do symbolu w dowolnym miejscu, zasadniczo czyniąc go podobnym do zmiennych globalnych?
Arc676,
2
@ Arc676 1. equal?w Ruby dokonuje porównania tożsamości. Każdy literał łańcuchowy, podobnie jak "foo", tworzy nową instancję łańcucha. Działa to w ten sposób, ponieważ ciągi w Rubim są zmienne. 2. Symbole są globalne, ale bardziej przypominają stałe globalne niż zmienne globalne, ponieważ symbole nie mają stanu. Zatem używanie symboli nie jest antypatternem tak jak zmienne globalne.
Chris Jester-Young
2
@ Arc676 "foo" == "foo"# => true
Filip Bartuzi
44
Aby zademonstrować niektóre rzeczy wymienione w odpowiedziach:
Porównywanie łańcucha z ciągiem przy użyciu equal?kończy się niepowodzeniem, ponieważ są to różne obiekty, nawet jeśli mają równą zawartość. ==porównuje zawartość, a kontrole równoważne z symbolami są znacznie szybsze.
user system total real
string 0.3700000.0000000.370000(0.371700)
str == str 0.3300000.0000000.330000(0.326368)
symbol 0.1700000.0000000.170000(0.174641)
sym == sym 0.1800000.0000000.180000(0.179374)
Oba testy symboli są zasadniczo takie same pod względem prędkości. Po 1 000 000 iteracji jest tylko 0,004733 sekundowa różnica, więc powiedziałbym, że to pranie pomiędzy, których należy użyć.
Niezwykle pomocny! W moim systemie wynik ==był szybszy niż w .equal?przypadku porównań ciągów i symboli. Porównanie symboli było ponad 3 razy szybsze niż porównywanie ciągów.
melvynkim
33
Symbole są sposobem na reprezentowanie ciągów i nazw w rubinie.
Główną różnicą między symbolami i łańcuchami jest to, że symbole o tej samej nazwie są inicjowane i istnieją w pamięci tylko raz podczas sesji ruby.
Są przydatne, gdy trzeba użyć tego samego słowa do przedstawienia różnych rzeczy
Szyny używają symboli do identyfikacji rzeczy. W szczególności używa ich jako kluczy podczas nazywania parametrów metody i wyszukiwania rzeczy w haszach.
redirect_to :action =>"edit",:id => params[:id]
Możesz myśleć o symbolach jak o literałach łańcuchowych, które są magicznie przekształcane w stałe. Alternatywnie możesz uznać, że dwukropek oznacza „rzecz o nazwie”, więc: id to „rzecz o nazwie id”.
W Ruby każdy obiekt ma unikalny identyfikator obiektu, jeśli napiszesz puts "hello".object_idw swoim irb i naciśniesz return 2 razy, otrzymasz 2 różne wartości zwracane, ale jeśli napiszesz :hello.object_id2 razy, otrzymasz tylko tę samą zwracaną wartość. To powinno było wyjaśnić różnicę.
To jest symbol. Zasadniczo mówisz, że dwa elementy skrótu mają klucze blai bloop, tak jakbyś użył ciągów "bla"i "bloop". Jednak zajmują mniej pamięci niż łańcuchy i są łatwiejsze do pisania.
Wszystkie te odpowiedzi pomijają jeden dodatkowy kuszący szczegół ... jeśli skreślisz symbol: foo, otrzymasz ... zgadnij co ... ciąg "foo". W związku z tym
Jeśli znasz język Java, możesz mieć świadomość, że ciągi w języku Java są niezmienne. Symbole są podobne pod tym względem w języku Ruby. Są niezmienne, tzn. Dowolna liczba wystąpień określonego symbolu :symbolzostanie zmapowana tylko na jeden adres pamięci. Dlatego zaleca się używanie symboli tam, gdzie to możliwe, ponieważ optymalizuje wykorzystanie pamięci.
Mówię o twojej analogii do Javy. Ciągi Java nie są analogiczne do symboli. Literały ciągów Java są, ale nie wszystkie ciągami.
smartnut007
Być może moje oświadczenie nie było wystarczająco jasne. Są do siebie analogiczni tylko pod tym względem, że są niezmienni.
Dhruva Sagar
@DhruvaSagar: Analogia byłoby lepiej, jeśli używane c-Celu NSString. Nie "foo"zawsze będzie równa "foo", ponieważ wewnętrznie struny, które są takie same są tylko wskazał. Odpowiedź byłaby jednak myląca.
Odpowiedzi:
:foo
to symbol o nazwie „foo”. Symbole mają wyraźną cechę polegającą na tym, że dowolne dwa takie same symbole będą identyczne:To sprawia, że porównywanie dwóch symboli jest naprawdę szybkie (ponieważ chodzi tylko o porównanie wskaźnika, w przeciwieństwie do porównywania wszystkich znaków jak w łańcuchu), a ponadto nie będziesz mieć pływających wokół zillionowych kopii tego samego symbolu.
Ponadto, w przeciwieństwie do łańcuchów, symbole są niezmienne.
źródło
"foo".equal? "foo"
fałsz? b) Czy możesz odwołać się do symbolu w dowolnym miejscu, zasadniczo czyniąc go podobnym do zmiennych globalnych?equal?
w Ruby dokonuje porównania tożsamości. Każdy literał łańcuchowy, podobnie jak"foo"
, tworzy nową instancję łańcucha. Działa to w ten sposób, ponieważ ciągi w Rubim są zmienne. 2. Symbole są globalne, ale bardziej przypominają stałe globalne niż zmienne globalne, ponieważ symbole nie mają stanu. Zatem używanie symboli nie jest antypatternem tak jak zmienne globalne."foo" == "foo"
# => trueAby zademonstrować niektóre rzeczy wymienione w odpowiedziach:
Uruchomienie go powoduje:
Porównywanie łańcucha z ciągiem przy użyciu
equal?
kończy się niepowodzeniem, ponieważ są to różne obiekty, nawet jeśli mają równą zawartość.==
porównuje zawartość, a kontrole równoważne z symbolami są znacznie szybsze.Oba testy symboli są zasadniczo takie same pod względem prędkości. Po 1 000 000 iteracji jest tylko 0,004733 sekundowa różnica, więc powiedziałbym, że to pranie pomiędzy, których należy użyć.
źródło
==
był szybszy niż w.equal?
przypadku porównań ciągów i symboli. Porównanie symboli było ponad 3 razy szybsze niż porównywanie ciągów.Symbole są sposobem na reprezentowanie ciągów i nazw w rubinie.
Główną różnicą między symbolami i łańcuchami jest to, że symbole o tej samej nazwie są inicjowane i istnieją w pamięci tylko raz podczas sesji ruby.
Są przydatne, gdy trzeba użyć tego samego słowa do przedstawienia różnych rzeczy
źródło
Jest kilka cytatów ze słynnej książki Agile Web Development with Rails , które mogą być pomocne w zrozumieniu tego symbolu :
źródło
W Ruby każdy obiekt ma unikalny identyfikator obiektu, jeśli napiszesz
puts "hello".object_id
w swoim irb i naciśniesz return 2 razy, otrzymasz 2 różne wartości zwracane, ale jeśli napiszesz:hello.object_id
2 razy, otrzymasz tylko tę samą zwracaną wartość. To powinno było wyjaśnić różnicę.źródło
Jeśli użyjesz
:foo => bar
, foo będzie symbolem. Zaletą symboli jest to, że są wyjątkowe. Kiedy wywołujesz element w skrócie, robiszhash[:foo]
.Symbole wymagają mniej pamięci niż łańcuchy, co czyni je również przydatnymi, jeśli chcesz, aby twój program był nieco szybszy.
źródło
To jest symbol. Zasadniczo mówisz, że dwa elementy skrótu mają klucze
bla
ibloop
, tak jakbyś użył ciągów"bla"
i"bloop"
. Jednak zajmują mniej pamięci niż łańcuchy i są łatwiejsze do pisania.źródło
Wszystkie te odpowiedzi pomijają jeden dodatkowy kuszący szczegół ... jeśli skreślisz symbol: foo, otrzymasz ... zgadnij co ... ciąg "foo". W związku z tym
Stąd… dla programistów Perla… to odpowiedź Ruby na „gołe słowo”.
źródło
Jeśli znasz język Java, możesz mieć świadomość, że ciągi w języku Java są niezmienne. Symbole są podobne pod tym względem w języku Ruby. Są niezmienne, tzn. Dowolna liczba wystąpień określonego symbolu
:symbol
zostanie zmapowana tylko na jeden adres pamięci. Dlatego zaleca się używanie symboli tam, gdzie to możliwe, ponieważ optymalizuje wykorzystanie pamięci.źródło
NSString
. Nie"foo"
zawsze będzie równa"foo"
, ponieważ wewnętrznie struny, które są takie same są tylko wskazał. Odpowiedź byłaby jednak myląca.