tl; dr: Apakah akan ada definisi bahasa-agnostik dari Simbol dan alasan untuk memilikinya dalam bahasa lain?
Jadi, mengapa pembuat Ruby menggunakan konsep symbols
dalam bahasa?
Saya menanyakan ini dari sudut pandang programmer non-ruby. Saya telah belajar banyak bahasa lain, dan tidak menemukan satu pun dari mereka, kebutuhan untuk menentukan apakah saya berurusan atau tidak dengan apa yang disebut Ruby symbols
.
Pertanyaan utamanya adalah, apakah konsep symbols
di Ruby ada untuk kinerja, atau hanya sesuatu yang diperlukan karena cara bahasa ditulis?
Apakah program di Ruby lebih ringan dan / atau lebih cepat daripada, katakanlah, Python atau Javascript? Jika demikian, apakah karena symbols
?
Karena salah satu niat Ruby adalah agar mudah dibaca dan ditulis untuk manusia, tidak dapatkah pembuatnya mempermudah proses pengkodean dengan mengimplementasikan peningkatan itu dalam juru bahasa itu sendiri (seperti dalam bahasa lain)?
Sepertinya semua orang hanya ingin tahu apa symbols
dan bagaimana menggunakannya, dan bukan mengapa mereka ada di tempat pertama.
sumber
Jawaban:
Pencipta Ruby, Yukihiro "Matz" Matsumoto, memposting penjelasan tentang bagaimana Ruby dipengaruhi oleh Lisp, Smalltalk, Perl (dan Wikipedia mengatakan Ada dan Eiffel juga):
Di kompiler mana pun, Anda akan mengelola pengidentifikasi untuk fungsi, variabel, blok bernama, jenis, dan sebagainya. Biasanya Anda menyimpannya di kompiler dan melupakannya di executable yang dihasilkan, kecuali ketika Anda menambahkan informasi debug.
Di Lisp, simbol-simbol tersebut adalah sumber daya kelas satu, dihosting dalam paket yang berbeda, yang berarti Anda dapat menambahkan simbol baru saat runtime, mengikatnya ke berbagai jenis objek. Ini berguna ketika meta-pemrograman karena Anda bisa yakin Anda tidak akan memiliki tabrakan penamaan dengan bagian lain dari kode.
Juga, simbol diinternir pada waktu membaca dan dapat dibandingkan dengan identitas, yang merupakan cara yang efisien untuk memiliki jenis nilai baru (seperti angka, tetapi abstrak). Ini membantu menulis kode tempat Anda menggunakan nilai simbolik secara langsung, alih-alih menentukan jenis enum Anda sendiri yang didukung oleh bilangan bulat. Juga, setiap simbol dapat menampung data tambahan. Begitulah cara, misalnya, Emacs / Slime dapat melampirkan metadata dari Emacs langsung ke daftar properti simbol.
Gagasan tentang simbol adalah sentral dalam Lisp. Lihat misalnya di PAIP (Paradigma Pemrograman Kecerdasan Buatan: Studi Kasus di Common Lisp, Norvig) untuk contoh terperinci.
sumber
Yah, mereka tidak benar-benar "harus", mereka memilih untuk. Juga, perhatikan bahwa secara tegas
Symbol
s bukan bagian dari bahasa, mereka adalah bagian dari perpustakaan inti. Mereka memang memiliki sintaksis tingkat bahasa, tetapi mereka akan bekerja dengan baik jika Anda harus membangunnya dengan meneleponSymbol::new
.Anda tidak mengatakan apa itu "banyak bahasa lain", tapi ini hanya kutipan kecil dari bahasa yang memiliki
Symbol
tipe data seperti Ruby:Ada juga bahasa lain yang menyediakan fitur
Symbol
s dalam bentuk yang berbeda. Di Jawa, misalnya, fitur RubyString
dibagi menjadi dua (sebenarnya tiga) jenis:String
danStringBuilder
/StringBuffer
. Di sisi lain, fiturSymbol
tipe Ruby dilipat ke dalamString
tipe Java : JavaString
s dapat diinternir , string literal danString
s yang merupakan hasil kompilasi waktu ekspresi konstan dievaluasi secara otomatis diinternir, yang dihasilkan secara dinamisString
dapat diinternir dengan memanggil yangString.intern
metode. DiinternirString
di Jawa persis sepertiSymbol
di Ruby, tapi itu tidak diimplementasikan sebagai tipe terpisah, itu hanya keadaan berbeda bahwa JavaString
bisa masuk. (Catatan: di versi Ruby yang lebih lama,String#to_sym
dulu dipanggilString#intern
dan metode itu masih ada sampai sekarang sebagai alias warisan.)Symbol
s adalah datatype pertama dan terpenting dengan semantik tertentu . Semantik ini juga memungkinkan untuk mengimplementasikan beberapa operasi performan (mis. Pengujian cepat O (1)), tetapi itu bukan tujuan utama.Symbol
Karena tidak diperlukan dalam bahasa Ruby sama sekali, Ruby akan bekerja dengan baik tanpa mereka. Mereka murni fitur perpustakaan. Tepat ada satu tempat dalam bahasa yang terkait denganSymbol
s:def
ekspresi definisi metode mengevaluasi ke yangSymbol
menunjukkan nama metode yang sedang didefinisikan. Namun, itu adalah perubahan yang agak baru, sebelum itu, nilai kembali hanya dibiarkan tidak ditentukan. MRI hanya dievaluasinil
, Rubinius dievaluasi keRubinius::CompiledMethod
objek, dan sebagainya. Juga mungkin untuk mengevaluasi keUnboundMethod
... atau hanya aString
.Saya tidak yakin apa yang Anda tanyakan di sini. Kinerja sebagian besar adalah masalah kualitas implementasi, bukan bahasa. Plus, Node bahkan bukan bahasa, ini adalah kerangka kerja I / O untuk ECMAScript. Menjalankan skrip yang setara pada IronPython dan MRI, IronPython kemungkinan akan lebih cepat. Menjalankan skrip yang setara pada CPython dan JRuby + Truffle, JRuby + Truffle cenderung lebih cepat. Ini tidak ada hubungannya dengan
Symbol
s tetapi dengan kualitas implementasinya: JRuby + Truffle memiliki kompiler yang mengoptimalkan secara agresif, ditambah seluruh mesin optimisasi JVM berkinerja tinggi, CPython adalah penerjemah sederhana.Tidak.
Symbol
S bukan optimasi kompiler. Mereka adalah tipe data terpisah dengan semantik tertentu. Mereka tidak seperti flonum YARV , yang merupakan optimasi internal pribadi untukFloat
s. Situasinya tidak sama dengan untukInteger
,Bignum
danFixnum
, yang seharusnya merupakan detail optimasi internal pribadi yang tidak terlihat, tetapi sayangnya tidak. (Ini akhirnya akan diperbaiki di Ruby 2.4, yang menghapusFixnum
danBignum
dan meninggalkan hanyaInteger
.)Melakukannya dengan cara Jawa melakukannya, sebagai keadaan khusus dari
String
s normal berarti bahwa Anda selalu perlu waspada tentang apakah AndaString
berada dalam keadaan khusus dan di bawah keadaan apa mereka secara otomatis dalam keadaan khusus itu dan kapan tidak. Itu beban yang jauh lebih tinggi daripada hanya memiliki tipe data terpisah.Symbol
adalah tipe data yang menunjukkan konsep nama atau label .Symbol
s adalah objek bernilai , tidak berubah, biasanya langsung (jika bahasa membedakan hal semacam itu), tanpa kewarganegaraan, dan tidak memiliki identitas. TwoSymbol
s yang sama juga dijamin identik, dengan kata lain, duaSymbol
s yang sama sebenarnya samaSymbol
. Ini berarti bahwa persamaan nilai dan persamaan referensi adalah hal yang sama, dan dengan demikian persamaan tersebut efisien dan O (1).Alasan untuk memilikinya dalam suatu bahasa benar-benar sama, terlepas dari bahasa tersebut. Beberapa bahasa lebih mengandalkan mereka daripada yang lain.
Dalam keluarga Lisp, misalnya, tidak ada konsep "variabel". Sebaliknya, Anda telah
Symbol
dikaitkan dengan nilai-nilai.Dalam bahasa dengan kemampuan reflektif atau introspektif,
Symbol
s sering digunakan untuk menunjukkan nama-nama entitas tercermin dalam API refleksi, misalnya di Ruby,Object#methods
,Object#singleton_methods
,Object#public_methods
,Object#protected_methods
, danObject#public_methods
mengembalikanArray
dariSymbol
s (meskipun mereka bisa juga mengembalikanArray
dariMethod
s).Object#public_send
mengambilSymbol
denoting nama pesan untuk dikirim sebagai argumen (meskipun ia juga menerimaString
,Symbol
lebih tepat secara semantik).Dalam ECMAScript,
Symbol
s adalah blok bangunan mendasar untuk membuat kapabilitas ECMAScript aman di masa depan. Mereka juga memainkan peran besar dalam refleksi.sumber
Simbol berguna di Ruby, dan Anda akan melihatnya di seluruh kode Ruby karena setiap simbol digunakan kembali setiap kali direferensikan. Ini adalah peningkatan kinerja atas string karena setiap penggunaan string yang tidak disimpan dalam variabel menciptakan objek baru di memori. Misalnya, jika saya menggunakan string yang sama beberapa kali sebagai kunci hash:
String "a" dibuat 101.000 kali dalam memori. Jika saya menggunakan simbol sebagai gantinya:
Simbol
:a
masih satu objek di memori. Ini membuat simbol jauh lebih efisien daripada string.PEMBARUAN Berikut ini adalah patokan (diambil dari Codecademy ) yang menunjukkan perbedaan kinerja:
Inilah hasil saya untuk MBP saya:
Ada perbedaan yang jelas dalam menggunakan string vs simbol untuk hanya mengidentifikasi kunci dalam hash.
sumber
"a"
memang merupakan string baru, saya pikir dalam contoh Anda akan ada tepat dua"a"
(dan implementasi bahkan dapat berbagi memori sampai salah satu dari mereka bermutasi). Untuk membuat jutaan string, Anda mungkin perlu menggunakan String.new ("a"). Tapi saya tidak berpengalaman dalam Ruby, jadi mungkin saya salah.string_AZ[String.new("r")]
untuk melihat apakah itu membuat perbedaan. Saya mendapatkan 21ms untuk string (versi asli), 7ms dengan simbol dan 50ms dengan string segar setiap kali. Jadi saya akan mengatakan bahwa string tidak dialokasikan sebanyak dengan"r"
versi literal .