Apakah sintaksis duplikat untuk mendefinisikan fungsi yang dinamai merupakan keputusan desain bahasa yang buruk?

9

Saya memodelkan bahasa pemrograman untuk bersenang-senang, dan sintaksisnya sangat dipengaruhi oleh Scala - khususnya definisi fungsi.

Saya telah mengalami masalah desain karena bahasa saya tidak membedakan antara fungsi yang didefinisikan melalui defsintaks (metode kelas) dan fungsi anonim yang ditugaskan ke nilai (dibuat menggunakan =>) - ini menghilangkan perbedaan dalam implementasi dan perilaku .

Hasilnya adalah bahwa dua definisi berikut memiliki arti yang sama:

def square(x: Int) = x*x

val square = (x: Int) => x*x

Tidak ada alasan untuk bentuk yang terakhir (penugasan fungsi anonim langsung) untuk digunakan dalam situasi normal - sangat mungkin untuk menggunakannya daripada defformulir.

Apakah memiliki sintaks duplikat untuk mendefinisikan fungsi-fungsi yang disebutkan akan merusak ortogonalitas bahasa atau aspek desain lainnya?

Saya lebih suka solusi ini karena memungkinkan untuk definisi pendek dan intuitif dari metode dan fungsi bernama (via def), dan definisi pendek dari fungsi anonim (menggunakan =>).

Sunting: Scala memang membedakan antara dua - fungsi anonim tidak sama dengan metode yang didefinisikan defdalam Scala. Perbedaannya relatif halus - lihat posting yang saya tautkan sebelumnya.

jcora
sumber
However, assigning existing functionstampaknya tidak ada akhir kalimat
Izkata
1
Bisakah Anda mendefinisikan fungsi rekursif menggunakan valnotasi Anda ?
Giorgio
2
Saya memverifikasi bahwa ini mungkin di Scala juga. Di SML tidak dan Anda harus menggunakan fununtuk mendefinisikan fungsi rekursif.
Giorgio
3
Bentuk kedua sebenarnya bukan struktur sintaksis khusus, caranya def. Ini hanya efek samping dari fakta bahwa fungsi anonim, katakanlah (x : Int) => x + 1adalah objek, dan objek dapat ditugaskan ke nilai val f = .... Desainer bahasa harus keluar dari jalan mereka untuk melarang sintaksis. Ini tidak persis sama dengan secara eksplisit menempatkan upaya untuk mendukung dua sintaks berbeda yang melakukan (kurang-lebih) hal yang sama.
KChaloux
3
Manfaat utama melakukan sesuatu lebih dari satu cara dalam suatu bahasa adalah cara yang bagus untuk memulai perdebatan agama yang tidak produktif yang mengalihkan perhatian dari masalah nyata (Berpikir C ++ di sini) .......
mattnz

Jawaban:

3

Saya pikir memiliki dua konstruksi yang berarti hal yang sama tetapi terlihat berbeda harus dijaga agar tetap minimum dalam suatu bahasa. Duplikasi apa pun meningkatkan betapa sulitnya untuk membaca (dan dengan demikian menulis / memodifikasi kode) bahasa Anda. Menghilangkan semua duplikasi tidak dapat dihindari dalam bahasa yang dapat membuat konstruksi sewenang-wenang (misalnya, kesetaraan iterasi vs rekursi).

Jadi dalam hal ini, saya pikir itu bisa dirancang lebih baik di sini. Satu cara untuk mendefinisikan fungsi paling masuk akal bagi saya. Dalam hal ini, kedengarannya seperti dua pernyataan scala yang sebenarnya Anda miliki memiliki implikasi yang sedikit berbeda, yang lagi-lagi mungkin bukan desain yang baik (mungkin yang terbaik untuk memiliki sesuatu yang jelas yang menyatakan perbedaan apa, seperti kata kunci).

Bahkan, Anda dapat menerapkan prinsip ini tidak hanya untuk fungsi yang disebutkan, tetapi untuk fungsi apa pun . Mengapa ada perbedaan dalam mendefinisikan fungsi bernama dan fungsi anonim? Di Lima , fungsi selalu didefinisikan seperti ini: fn[<arguments>: <statements>]. Jika Anda ingin menjadi "bernama" Anda dapat menetapkan ke variabel: var x = fn[<arguments: <statements>], dan jika Anda ingin lulus ke fungsi lain anonim: function[fn[<arguments: <statements>]]. Jika Anda ingin mengangkatnya, buatlah konstan const var x = fn[<arguments: <statements>]. Bentuk tunggal membuatnya jelas bahwa mereka berarti hal yang sama.

BT
sumber
Itu cukup menarik yang constmenyebabkan pengangkatan, tetapi itu masuk akal. Dalam JS function myFuncmenyebabkan pengangkatan, tetapi var myFunc =tidak, yang mungkin sedikit kurang intuitif karena mereka berperilaku kurang lebih sama.
mpen
1
@mpen Ya, sebenarnya javascript pada dasarnya melakukan hal yang sama. yang function fnName()...bentuk tidak sebenarnya membuat konstan, yang adalah apa yang membuat mengangkat hal yang sah untuk dilakukan dengan itu. Javascript membuat hal-hal yang cukup membingungkan ketika Anda menggunakan formulir var fn = function anotherFnName()...karena itu membuat nama anotherFnName tidak mengerek, bahkan itu jelas konstan.
BT
2

Apa yang Anda posting adalah scala yang valid dan berfungsi dengan baik.

Mengingat bahwa penggandaan tidak menyebabkan masalah dengan scala (setahu saya), saya akan mengatakan bahwa itu tidak akan menjadi masalah bagi bahasa Anda juga.

Daenyth
sumber
1
Ini valid dalam Scala, sebagian besar kerjanya sama, tetapi itu tidak berarti hal yang sama - dan jika Anda akan membuat contoh yang lebih kompleks (tipe polimorfisme tidak tersedia untuk fungsi anonim misalnya) - perbedaan akan menjadi lebih jelas.
jcora
2

Saya telah menemukan perbedaan mendasar antara lambdas dan defmetode di Scala - bahwa saya masih tidak yakin apakah saya ingin menerapkannya. Saya harus melakukan penelitian lebih lanjut tentang hal itu dan kemudian saya akan melaporkan kembali keputusan saya.

Pada dasarnya, hanya metode yang bisa return- dan ketika kata kunci digunakan dari lambda, sebenarnya kembali dari metode yang mencakup.

Seperti yang sudah saya katakan, saya tidak yakin apakah saya menginginkan ini. Tapi itu bisa menjadi pembenaran yang cukup untuk sintaksis ini. Atau mungkin terlalu berbahaya karena perbedaan yang tidak disengaja dapat menyebabkan kerusakan.

Detail

jcora
sumber