Lời khuyên cho việc chơi golf ở Scala


24

Bạn có lời khuyên chung nào cho việc chơi golf ở Scala? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về golf nói chung ít nhất là cụ thể đối với Scala (ví dụ: "xóa bình luận" không phải là một câu trả lời). Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.

(Đây là một bản sao không biết xấu hổ của ... trong Python)

Câu trả lời:


5

từ chối trách nhiệm: các phần của câu trả lời này là khái quát của các câu trả lời khác được tìm thấy ở đây.

Sử dụng lambdas mà không chỉ định loại đối số của họ

Nó được phép gửi một cái gì đó như thế này: a=>a.sizethay vì (a:String)=>a.size.

Sử dụng ký hiệu ascii làm định danh.

Chúng bao gồm !%&/?+*~'-^<>|. Bởi vì chúng không phải là chữ cái, chúng được phân tách tách biệt khi chúng nằm cạnh các chữ cái.

Ví dụ:

a=>b       //ok
%=>%        //error, parsed as one token
% => %      //ok
val% =3     //ok
&contains+  //ok
if(x)&else* //ok

Sử dụng Set thay vì chứa

if (Seq(1,2,3,'A')contains x)... //wrong
if (Set(1,2,3,'A')(x))...         //right

Điều này là có thể bởi vì Set[A] extends (A => Boolean).

Sử dụng hàm curried khi bạn cần hai đối số.

(a,b)=>... //wrong
a=>b=>...  //right

Sử dụng _-syntax khi có thể

Các quy tắc cho điều này là hơi mơ hồ, đôi khi bạn phải chơi một chút xung quanh để tìm ra con đường ngắn nhất.

a=>a.map(b=>b.size)) //wrong
a=>a.map(_.size)     //better
_.map(_.size)        //right

Sử dụng một phần ứng dụng

a=>a+1 //wrong
_+1    //better, see above
1+     //right; this treats the method + of 1 as a function

Sử dụng ""+thay vìtoString

a=>a.toString //wrong
a=>a+""       //right

Sử dụng chuỗi làm chuỗi

"" đôi khi là cách ngắn nhất để tạo một chuỗi trống nếu bạn không quan tâm đến loại Actula

Sử dụng BigInt để chuyển đổi số đến và từ chuỗi

Cách ngắn nhất để chuyển đổi một số thành một chuỗi trong một cơ sở khác với cơ sở 10 là thông qua toString(base: Int)phương thức của BigInt

Integer.toString(n,b) //wrong
BigInt(n)toString b   //right

Nếu bạn muốn chuyển đổi một chuỗi thành một số, hãy sử dụng BigInt.apply(s: String, base: Int)

Integer.parseInt(n,b) //wrong
BigInt(n,b)           //right

Xin lưu ý rằng điều này trả về một BigInt, có thể sử dụng như một số lượng hầu hết thời gian, nhưng không thể được sử dụng làm chỉ mục cho một chuỗi, ví dụ.

Sử dụng Seq để tạo chuỗi

a::b::Nil   //wrong
List(...)   //also wrong
Vector(...) //even more wrong
Seq(...)    //right
Array(...)  //also wrong, except if you need a mutable sequence

Sử dụng Chuỗi cho Seqences of chars:

Seq('a','z') //wrong
"az"         //right

Sử dụng Stream cho chuỗi vô hạn

Một số thách thức yêu cầu yếu tố thứ n của một chuỗi vô hạn. Stream là ứng cử viên hoàn hảo cho việc này. Hãy nhớ rằng Stream[A] extends (Int => A), đó là một luồng là một hàm từ một chỉ mục đến thành phần tại chỉ mục đó.

Stream.iterate(start)(x=>calculateNextElement(x))

Sử dụng các toán tử tượng trưng thay vì các đối tác dài dòng của họ

:\:/thay vì foldRightfoldLeft

a.foldLeft(z)(f) //wrong
(z/:a)(f)        //right
a.foldRight(z)(f) //wrong
(a:\z)(f)         //right

hashCode -> ##

throw new Error() -> ???

Sử dụng &|thay vì &&||

Chúng hoạt động giống nhau đối với booleans, nhưng sẽ luôn đánh giá cả hai toán hạng

Bí danh phương thức dài như hàm

def r(x:Double)=math.sqrt(x) //wrong
var r=math.sqrt _            //right; r is of type (Double=>Double)

Biết các chức năng trong thư viện tiêu chuẩn

Điều này đặc biệt áp dụng cho các phương pháp của bộ sưu tập.

Các phương pháp rất hữu ích là:

map
flatMap
filter
:/ and :\ (folds)
scanLeft and scanRight
sliding
grouped (only for iterators)
inits
headOption
drop and take
collect
find
zip
zipWithIndex3
distinct and/or toSet
startsWith

11

Cách ngắn nhất để lặp lại một cái gì đó là với Seq.fill.

1 to 10 map(_=>println("hi!")) // Wrong!
for(i<-1 to 10)println("hi!") // Wrong!
Seq.fill(10)(println("hi!")) // Right!

10

định danh đáng ngờ :?

Bạn có thể dùng ? như định danh:

val l=List(1,2,3)
val? =List(1,2,3)

Ở đây nó không giúp bạn tiết kiệm được gì, vì bạn không thể dán nó vào dấu bằng:

val ?=List(1,2,3) // illegal

Nhưng sau này, nó thường lưu một ký tự, vì bạn không cần một dấu phân cách:

print(?size)  // l.size needs a dot
def a(? :Int*)=(?,?tail).zipped.map(_-_)

Tuy nhiên, nó thường rất khó sử dụng:

       print(?size)
3
       print(?size-5)
<console>:12: error: Int does not take parameters
       print(?size-5)
              ^

9

Bộ sưu tập

Sự lựa chọn đầu tiên cho một bộ sưu tập ngẫu nhiên thường là Danh sách . Trong nhiều trường hợp, bạn có thể thay thế nó bằng Seq , giúp lưu một ký tự tức thời. :)

Thay vì

val l=List(1,2,3)
val s=Seq(1,2,3)

và, trong khi s.head và s.tail thanh lịch hơn trong mã thông thường, s(0)lại là một ký tự ngắn hơn s.head.

Thậm chí ngắn hơn trong một số trường hợp - tùy thuộc vào chức năng cần thiết là một tuple:

val s=Seq(1,2,3)
val t=(1,2,3)

lưu 3 ký tự ngay lập tức và để truy cập:

s(0)
t._1

nó là như nhau cho truy cập chỉ mục trực tiếp. Nhưng đối với các khái niệm được xây dựng, bộ dữ liệu thất bại:

scala> s.map(_*2)
res55: Seq[Int] = List(2, 4, 6)

scala> t.map(_*2)
<console>:9: error: value map is not a member of (Int, Int, Int)
       t.map(_*2)
         ^

cập nhật

def foo(s:Seq[Int])
def foo(s:Int*)

Trong khai báo tham số, Int * lưu 4 ký tự trên Seq [Int]. Nó không tương đương, nhưng đôi khi, Int * sẽ làm.


8

Bạn thường có thể sử dụng mapthay vì foreach:

List("a","b","c") foreach println

có thể được thay thế bằng

List("a","b","c") map println

Sự khác biệt duy nhất là loại trả về ( Unitvs List[Unit]), dù sao bạn không quan tâm đến việc sử dụng foreach.


7

định nghĩa các loại ngắn hơn:

Nếu bạn có nhiều khai báo của một loại, như

def f(a:String,b:String,c:String) 

nó ngắn hơn để xác định một bí danh loại và sử dụng nó thay thế:

type S=String;def f(a:S,b:S,c:S)

Độ dài ban đầu là 3 * 6 = 18 Mã thay thế là 8 (loại S =;) + 6 + 3 * 1 (= chiều dài mới) = 17

if (n * length <8 + length + n), thì đó là một lợi thế.

Đối với các lớp được khởi tạo thông qua một nhà máy, chúng ta có thể đặt một tên biến ngắn hơn để trỏ đến đối tượng đó. Thay vì:

val a=Array(Array(1,2),Array(3,4))

chúng tôi có thể viết

val A=Array;val a=A(A(1,2),A(3,4))

Điều này cũng áp dụng cho C ++ #define, nhưng tôi thừa nhận nó rất hay defvalngắn hơn.
Matthew Đọc

Hừm. deflà từ khóa để định nghĩa một phương thức và một bản dịch đơn giản sang c ++ cho vallà 'const' và nó là một khai báo, nhưng kiểu này thường được suy ra. Việc rút ngắn là trong trường hợp đầu tiên type=gần hơn typedef- phải không? Ví dụ thứ hai không phải từ tôi và nó mới đối với tôi. Tôi phải coi chừng, sử dụng nó ở đâu.
người dùng không xác định

typedef long long ll;là giống như #define ll long longvậy, vì vậy cái sau ngắn hơn 1. Nhưng vâng, typedefkhông hoạt động. Nhìn vào valví dụ một lần nữa tôi chắc chắn đọc sai nó. Nó dường như thậm chí ít cụ thể hơn Scala. x = thingWithAReallyLongComplicatedNameForNoReasonlà một chiến lược khá chung: P
Matthew Đọc

@userunknown Khi bạn khởi tạo một Listhoặc Arrayvv với cú pháp, val x = List(1,2,3)bạn chỉ cần gọi applyphương thức trên Listđối tượng. (Kỹ thuật tạo đối tượng này được gọi là "phương thức nhà máy", ngược lại với việc sử dụng một hàm tạo với new.) Vì vậy, ở trên, chúng ta chỉ tạo một biến mới trỏ đến cùng một đối tượng singleton như tên biến Array. Vì đó là điều tương tự, tất cả các phương pháp, bao gồm apply, đều có sẵn.
Luigi Plinge

7

Sử dụng cú pháp infix để loại bỏ sự cần thiết của các .ký tự. Bạn không cần khoảng trắng trừ khi các mục liền kề có cả chữ và số hoặc cả ký tự toán tử (xem tại đây ) và không được phân tách bằng các ký tự dành riêng (dấu ngoặc, dấu phẩy, v.v.).

Ví dụ

List(1,2,3,4).filter(_ % 2 == 0) // change to:
List(1,2,3,4)filter(_%2==0)


7

Gọi hai lần cùng chức năng để khởi tạo:

val n,k=readInt

(Nhìn thấy ở một nơi khác, nhưng không thể tìm thấy nó bây giờ).


6

Đổi tên các Phương thức, nếu tên của chúng dài và nếu chúng được sử dụng nhiều lần - ví dụ trong thế giới thực:

 x.replaceAll(y,z)

 type S=String; def r(x:S,y:S,z:S)=x.replaceAll(y,z)

Tùy thuộc vào khả năng lưu 'S = String' ở các vị trí khác nhau, điều này sẽ chỉ có hiệu quả kinh tế, nếu bạn thay thế ít nhất 3 lần thay thế.


3

Khởi tạo một số biến cùng một lúc bằng cách sử dụng một tuple:

var(a,b,c)=("One","Two","Three") //32 characters

so với

var a="One";var b="Two";var c="Three" //37 characters

0

Bạn cũng có thể sử dụng thay vì sử dụng =>cho các định nghĩa hàm.


1
Xin chào và chào mừng đến với PPCG. Vì hầu hết thời gian, câu trả lời được tính bằng byte thay vì ký tự, mẹo của bạn chỉ có phạm vi giới hạn. Tôi sẽ giải quyết vấn đề này và cũng thêm một tiêu đề mẹo như Rút ngắn định nghĩa hàm trong các thử thách chơi gôn dựa trên số ký tự .
Jonathan Frech
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.