Tulis fungsi (bukan program lengkap), sehingga jika fungsi dipanggil dengan variabel global tunggal (atau bahasa terdekat terdekat Anda) sebagai argumennya, ia mengeluarkan (yaitu mencetak atau mengembalikan) nama variabel itu. Jika argumennya bukan variabel, output nilai falsey sebagai gantinya. (Anda tidak harus menangani kasus di mana argumennya adalah variabel, tetapi bukan global.)
Tidak boleh ada koneksi waktu kompilasi antara pemanggilan fungsi dan definisi fungsi (terutama, definisi fungsi tidak boleh makro atau konstruksi serupa yang menerima argumen dalam bentuk fragmen literal dari kode sumber, baik dalam teks maupun pohon sintaksis abstrak bentuk). Yaitu: dalam bahasa yang mendukung kompilasi terpisah, program harus bekerja bahkan jika pemanggilan fungsi dikompilasi terlebih dahulu (tanpa pengetahuan tentang definisi fungsi tetapi mungkin tipe tanda tangan atau setara), maka definisi fungsi dikompilasi setelahnya. Jika bahasa tidak memiliki kompilasi terpisah, Anda harus tetap bertujuan untuk pemisahan yang sama antara panggilan dan definisi.
Jika menggunakan bahasa yang dikompilasi, Anda dapat membaca formulir yang dikompilasi dari program lengkap dari disk, dan dapat berasumsi bahwa program itu dikompilasi dengan informasi debug. (Dengan demikian, solusi yang berfungsi dengan melampirkan debugger dari suatu program ke program itu sendiri diperbolehkan.)
Perhatikan bahwa tugas ini mungkin tidak dapat dilakukan dalam setiap bahasa.
Contoh:
var apple = "Hello"
p(apple) // apple
var nil = "Nothing"
p(nil) // nil
var SOMETHING = 69
p(SOMETHING) // SOMETHING
function foo(){}
p(foo) // foo
p(3.14159) // false
p(function foo(){}) // false
sumber
Jawaban:
Jawa
Ini saat ini bekerja dengan beberapa gotcha:
javac
dengan-g
bendera. Ini menghasilkan semua informasi debugging termasuk nama variabel lokal di file kelas yang dikompilasi.com.sun.tools.javap
yang mem-parsing bytecode dari classfile dan menghasilkan hasil yang dapat dibaca manusia. API ini hanya dapat diakses di perpustakaan JDK sehingga Anda harus menggunakan runtime java JDK atau menambahkan tools.jar ke classpath Anda.Ini sekarang harus bekerja bahkan jika metode ini dipanggil beberapa kali dalam program. Sayangnya itu belum berfungsi jika Anda memiliki banyak pemanggilan dalam satu baris. (Untuk yang melakukannya, lihat di bawah)
Cobalah online!
Penjelasan
Bagian pertama ini mendapat beberapa informasi umum tentang kelas apa kita berada dan apa nama fungsinya. Ini dilakukan dengan membuat pengecualian dan mem-parsing 2 entri pertama dari jejak stack.
Entri pertama adalah baris di mana pengecualian dilemparkan di mana kita dapat mengambil methodName dari dan entri kedua adalah tempat fungsi dipanggil.
Pada baris ini kita mengeksekusi javap executable yang datang dengan JDK. Program ini mem-parsing file kelas (bytecode) dan menyajikan hasil yang dapat dibaca manusia. Kami akan menggunakan ini untuk "parsing" yang belum sempurna.
Kami melakukan beberapa hal berbeda di sini. Pertama, kita membaca baris keluaran javap demi baris ke dalam daftar. Kedua kita membuat peta indeks garis bytecode ke indeks garis javap. Ini membantu kita nanti untuk menentukan metode doa mana yang ingin kita analisis. Akhirnya kita menggunakan nomor baris yang diketahui dari jejak tumpukan untuk menentukan indeks garis bytecode yang ingin kita lihat.
Di sini kita mengulangi garis javap sekali lagi untuk menemukan tempat di mana metode kita dipanggil dan di mana Tabel Variabel Lokal dimulai. Kita perlu baris tempat metode dipanggil karena baris sebelum itu berisi panggilan untuk memuat variabel dan mengidentifikasi variabel mana (berdasarkan indeks) untuk memuat. Tabel Variabel Lokal membantu kita mencari nama variabel berdasarkan indeks yang kita ambil.
Bagian ini sebenarnya mengurai panggilan beban untuk mendapatkan indeks variabel. Ini dapat membuang pengecualian jika fungsi tersebut tidak benar-benar dipanggil dengan variabel sehingga kita dapat mengembalikan nol di sini.
Akhirnya kita menguraikan nama variabel dari baris di Tabel Variabel Lokal. Kembalikan nol jika tidak ditemukan walaupun saya tidak melihat alasan mengapa ini harus terjadi.
Menyatukan semuanya
Ini pada dasarnya adalah apa yang kita lihat. Dalam kode contoh pemanggilan pertama adalah baris 17. baris 17 di LineNumberTable menunjukkan bahwa awal baris itu adalah bytecode indeks baris 18. Itu adalah
System.out
beban. Kemudian kita memilikiaload_2
tepat sebelum pemanggilan metode sehingga kita mencari variabel dalam slot 2 dari LocalVariableTable yangstr
dalam hal ini.Untuk bersenang-senang, inilah yang menangani beberapa panggilan fungsi pada saluran yang sama. Ini menyebabkan fungsi tidak idempoten tapi itu intinya. Cobalah online!
sumber
System.out.println(e.getParamName(str));System.out.println(e.getParamName(str2));System.out.println(e.getParamName(str4));
ke satu baris di tautan TIO.javap
lokasi seperti ini:Paths.get(System.getProperty("java.home"), "bin", "javap")
.Python 2
Ini tentang kode paling kotor yang saya tulis tetapi berfungsi. ¯ \ _ (ツ) _ / ¯ Melempar kesalahan pada variabel yang tidak ada karena Python akan segera membenci Anda karena memanggil fungsi dengan satu. Juga melempar kesalahan pada non-variabel tetapi ini bisa diperbaiki dengan coba / kecuali jika diperlukan.
Cobalah online!
Jika kami diizinkan untuk mengambil argumen sebagai string, ini memenuhi persyaratan untuk menghasilkan nilai palsu pada input yang tidak valid.
Cobalah online!
sumber
Mathematica
The
HoldFirst
atribut mencegahf
dari mengevaluasi argumen sebelum memanggil fungsi.ValueQ @ x
kemudian memeriksa apakah argumen yang diberikan adalah variabel yang telah diberi nilai. Jika tidak, kami hanya kembaliFalse
karena hubungan arus pendek. Jika tidak, kami memperoleh nama variabel denganToString @ HoldForm @ x
.sumber
And
... Saya suka bagaimana argumen yang tepat dariAnd
bahkan tidak harus menjadi ekspresi Boolean.f[x_] := ValueQ @ x && HoldForm @ x
? Jika bukan karena persyaratan untuk memeriksa apakah input adalah variabel,HoldForm
dengan sendirinya akan berfungsi.HoldAll
bukanHoldFirst
?HoldForm[a]
dan tidak"a"
. Sementara mereka ditampilkan sama di notebook Mathematica, fungsinya ada secara independen dari frontend, jadi saya ingin memiliki solusi yang mengembalikan string.Mathematica
Mathematica suka mengevaluasi semuanya , jadi untuk menghentikannya, kita harus berjuang melawannya. Dalam bahasanya sendiri.
Bagaimana?
Memberitahu Mathematica bahwa setiap kali fungsi
f
dipanggil, argumennya tidak harus dievaluasi (yaitu diadakan).Ketika
f
dipanggil dengan argumen, outputFalse
. (?!)Ketika
f
dipanggil dengan Simbol yang ditentukan (yang memiliki nilai), keluarkan nama simbol input.Baris sebelumnya tidak diutamakan, meskipun telah didefinisikan sebelumnya, karena definisi ini lebih spesifik. Seperti yang dinyatakan oleh Dokumentasi Wolfram: Mathematica "mencoba untuk menempatkan definisi spesifik sebelum definisi yang lebih umum."
Mathematica sangat keras kepala dan terus berusaha mengevaluasi variabel kapan pun memungkinkan. Ekstra
Unevaluated
menangani itu.sumber
C #
Versi Lengkap / Terformat:
Cara lain untuk melakukan ini adalah dengan merefleksikan tipe seperti ini:
Namun, Anda harus menyebutnya seperti:
Kemudian gagal juga
3.14159
dengan mengembalikanLength
dan untuk itu Anda juga harus menyebutnya seperti berikut ini sebagai gantinya:Dalam C # 6.0 kami juga memiliki:
Tetapi ini tidak akan dikompilasi jika Anda memberikan sesuatu yang bukan variabel misalnya
3.14159
. Saya percaya itu juga mengevaluasi input pada waktu kompilasi jadi sepertinya gagal juga persyaratan itu.sumber
Expression
). Anda juga harus menghitungusing System.Linq.Expressions;
.MATLAB
Dalam suatu fungsi ada beberapa variabel preset seperti
varargin
ataunargin
, di antara yang juga kita milikiinputname
.dicuri dari sini
sumber
x=42;y=54; f=@(x)eval(inputname(1));f(x),f(y)
eval==evil
= D (ini benar-benar bekerja denganx=42;y=54; f=@(x)eval('inputname(1)');f(x),f(y)
)x
, dan kemudianeval
-menggunakan argumen fungsi, bukan variabel ruang kerja.R
substitute
mengembalikan pohon parse untuk ekspresi yang tidak dievaluasi. Theidentical
merek bersyarat yakin bahwa ekspresi unevaluated ini tidak identik dengan ekspresi itu sendiri; yaitu bahwa parameter yang dikirimkan bukan literal.sumber
Python 2
Beberapa penelitian telah dilakukan. Dan sepertinya itu bisa dilakukan dengan python, tapi saya masih berharap beberapa masalah dapat ditemukan.
Solusi tidak sempurna, karena mengasumsikan beberapa struktur kode. Namun saya tidak mematahkannya.
Ini menggunakan inspeksi untuk melihat lingkup surround dan menemukan di mana fungsi
get_name
dipanggil. Misalnyainspect...[1]
akan kembaliDan
inspect...[1][4]
akan menampilkan daftar dengan kode, di mana fungsinya disebut:Setelah itu saya menggunakan regex untuk mengambil nama argumen
Dan
.lstrip().rstrip()
untuk menghapus semua spasi putih yang dapat ditempatkan ke dalam gelang.Contoh dengan beberapa input yang rumit
sumber
PowerShell
Tapi itu tidak bekerja dengan baik, ini belum sempurna.
sumber
PHP
Perlu bahwa nilai variabel unik dalam array variabel global
Cobalah online!
PHP , 96 byte
Cobalah online!
Perlu bahwa variabel diinisialisasi langsung ke pemanggilan fungsi.
Cek apakah variabel global terakhir sama dengan variabel penyerahan
sumber
JavaScript (ES6)
Untuk semua nama properti di
window
(Object.getOwnPropertyNames(w)
), coba tetapkan pengambil untuk properti yang mengembalikan nama properti.Kemudian, tambahkan entri ke Peta
M
mana kuncinya adalah nilai (mungkin diganti) properti, dan nilai tersebut adalah nama properti.Fungsi
f
hanya mengambil variabel (yaitu properti dariwindow
) dan mengembalikan entriM
untuk nilai itu.Ini berfungsi untuk semua variabel global bawaan kecuali
window
sendiri, karena tidak ada cara untuk membedakannyatop
(kecuali dijalankan dalam bingkai):sumber
L not a function
. Mengapa itu terjadi?Perl 5 + Devel :: Caller
Kami menggunakan Devel :: Caller (modul mirip debugger) untuk menjalankan tumpukan panggilan, mencari panggilan ke fungsi, dan mengembalikan semua operan dalam argumen, mengembalikannya sebagai nama variabel. Jika ada lebih (atau kurang) dari satu operan, kami tidak dipanggil dengan variabel. Jika operan bukan variabel, itu tidak akan memiliki nama dan kami dapat mendeteksi itu juga.
Kasus paling sulit adalah jika kita mendapatkan ekspresi satu operan yang melibatkan variabel, seperti
~$x
. Kita dapat mencari tahu apakah ini telah terjadi dengan mengambil referensi ke variabel langsung dari tabel simbol (menggunakan${…}
sintaks referensi simbolik) dan membandingkan alamat memorinya dengan nilai yang kami berikan sebagai argumen (yang, mudah, dilewatkan dengan referensi ). Jika mereka berbeda, kami memiliki ekspresi daripada variabel tunggal.Perhatikan bahwa jika kita memanggil fungsi ini dengan ekspresi preincrement atau predecrement pada variabel tunggal, seperti pada
v(--$x)
, kita akan$x
kembali. Ini karena sebenarnya variabel itu sendiri yang diteruskan ke fungsi dalam kasus ini; itu hanya akan bertambah atau dikurangi sebelumnya. Saya harap ini tidak mendiskualifikasi jawabannya. (Di satu sisi, itu membuatnya lebih baik, karena itu menunjukkan bahwa kita memeriksa argumen itu sendiri daripada hanya membaca kode sumber.)sumber
PHP
Sementara pengiriman PHP lainnya hanya menguji jika nilai yang diberikan cocok dengan nilai global, versi ini berfungsi dengan mengambil referensi ke nilai:
Ini sekarang harus bekerja bahkan jika variabel global adalah referensi ke nilai lain pada saat menelepon.
Uji di sini .
sumber
Rosda
Cobalah online!
Rosda memiliki fungsi bawaan untuk ini -
name
. Sayangnya, itu tidak mengembalikan nilai palsu ketika tidak diberi variabel.Kode ini menyalahgunakan beberapa fitur semantik referensi. Penjelasan baris demi baris:
f(&a...) {
Fungsi mengambil sejumlah variabel argumen referensi (
&a...
). Ini adalah satu-satunya cara di Raeda untuk membuat daftar referensi.a() | name(_) | for str do
Pada baris kedua elemen-elemen
a
didorong ke aliran (a()
). Elemen-elemen ini adalah referensi jika fungsi diberi variabel dan nilai normal sebaliknya.Elemen-elemen diulang menggunakan loop garis bawah. Sintaks garis bawah adalah sintaksis gula untuk
for
loop, jadiname(_)
sama denganname(var) for var
. Nama variabel yang digunakan dalamfor
loop adalah bentuk di<sfvN>
mana N bervariasi. (Yaitu. "name(<sfv1>) for <sfv1>
") Adalah ilegal untuk mengandung variabel yang ditentukan pengguna<
atau>
, jadi nama yang dihasilkan tidak bertabrakan dengan nama variabel yang ada.The
name()
fungsi mengembalikan nama variabel yang diberikan. Jika elemen dalama
iterasi adalah referensi, maka itu adalah variabel yang diberikan kepadaname
. Jika tidak, jika elemen adalah nilai normal, variabel yang diberikanname
adalah variabel garis bawah<sfvN>
. Hal ini disebabkan oleh semantik referensi dalam Röda: jika suatu fungsi menerima referensi dan fungsi tersebut meneruskan variabel referensi, nilai yang diteruskan tidak menunjuk ke variabel referensi tetapi ke variabel yang ditunjuk oleh variabel referensi.false if [ "<" in str ] else [str]
Pada baris ketiga kami memeriksa apakah nama variabel dalam aliran berisi
<
karakter. Jika demikian, itu adalah variabel garis bawah dan nilai yang diteruskan kef
bukan referensi. Kalau tidak, kami menampilkan nama referensi.Solusi ini tidak berfungsi jika variabel yang diberikan ke fungsi adalah referensi atau variabel garis bawah. Namun, pertanyaannya menentukan bahwa hanya variabel global yang harus ditangani, dan mereka tidak dapat menjadi referensi atau menggarisbawahi variabel dalam Rda.
sumber
Rubi , 46 byte
Terasa seperti kode paling kotor yang pernah saya tulis untuk Ruby.
Mengharuskan bahwa variabel global yang Anda panggil memiliki nilai unik yang tidak ada pada variabel global lainnya, karena satu-satunya cara untuk melakukan tantangan ini di Ruby adalah dengan melakukan pencarian pada semua variabel global dan mengembalikan kecocokan pertama. OP mengatakan tidak apa-apa, dan bebas menilai apakah solusi saya valid.
Perhatikan bahwa variabel global dimulai dengan
$
di Ruby, karena jika Anda ingin menambahkan hal-hal kasus tes tambahan.Cobalah online!
sumber
PHP
jika ditemukan nilai, cetak nama variabel dan keluar. cetak apa-apa dan jangan keluar lagi.
61 byte untuk mengembalikan nama variabel atau
NULL
:Itu tidak akan menemukan fungsi bernama, hanya yang ditugaskan ke variabel.
Dan fungsi PHP tidak dapat mendeteksi apakah parameter diberikan oleh referensi atau nilai. Fungsi hanya akan mengembalikan nama depan di mana nilainya sesuai dengan nilai parameter fungsi.
Uji secara online
sumber
PowerShell
Versi baru tetapi bekerja mulai dari PowerShell 3.0
Cobalah secara Online!
Versi sebelumnya
Cobalah secara Online!
sumber
tcl
demo
sumber
JavaScript (ES6)
Mengharuskan nilai variabel yang diteruskan ke fungsi unik untuk variabel itu. Mengembalikan
undefined
jika variabel tidak lulus.Cobalah
Untuk beberapa alasan, ia melempar kesalahan asal-silang ke dalam Snippet ketika "literal" dilewatkan.
Penjelasan
Loop melalui semua entri dalam objek global (
this
), memeriksa apakah nilai masing-masing secara ketat sama dengan nilai argumen yang diteruskan ke fungsi. Jika entri yang cocok ditemukan maka kuncinya (nama) dikembalikan, keluar dari fungsinya.Alternatif
Dengan persyaratan yang sama seperti di atas
sumber
hello--
). Selain itu, Anda harus menggunakanvar
daripadalet
.let
danvar
. Untuk pertanyaan kedua Anda: Itu terjadi karena Anda memiliki variabel bernamaIN_GLOBAL_SCOPE
dalam lingkup global Anda dan memiliki nilai1
. Anda dapat memeriksa variabel yang ada dalam lingkup global Anda dan nilainya dengan menjalankan ini sebelum menguji yang di atas:for(x in this)console.log(x+": "+this[x])
Swift, 45 byte
sumber
value of type 'Mirror' has no member 'label'