คำตอบ:
import StdEnvเมื่อเป็นไปได้ในการเข้าถึงฟังก์ชั่นแม้กระทั่งขั้นพื้นฐานดูเหมือนจะชอบ(==)หรือmapคำสั่งนำเข้าเป็นสิ่งจำเป็นมักจะimport StdEnvเพราะมันนำเข้าโมดูลที่พบมากที่สุดเช่นStdInt, StdBoolและอื่น ๆ (ดูที่นี่สำหรับข้อมูลเพิ่มเติมเกี่ยวStdEnv)
อย่างไรก็ตามอาจเป็นไปได้ที่จะหลีกเลี่ยงการนำเข้านี้สำหรับความท้าทายบางอย่างและใช้คุณลักษณะภาษาหลักเช่นความเข้าใจในรายการและการจับคู่รูปแบบ
ตัวอย่างเช่นแทนที่จะเป็น
import StdEnv
map f list
หนึ่งสามารถเขียน
[f x\\x<-list]
ฟังก์ชันหรือการเรียกใช้ฟังก์ชันบางอย่างที่ต้องการimport StdEnvทางเลือกที่ไม่ต้องการการนำเข้าและการประมาณคร่าวๆของไบต์ที่บันทึกไว้
hd-> (\[h:_]=h), ~ 6 ไบต์tl-> (\[_:t]=t), ~ 6 ไบต์map f list-> [f x\\x<-list], ~ 10 ไบต์filter p list-> [x\\x<-list|p x], ~ 11 ไบต์(&&)-> %a b|a=b=a;%, ~ 6 ไบต์(||)-> %a b|a=a=b;%, ~ 6 ไบต์not-> %a|a=False=True;%, ~ 1 ไบต์and-> %[a:r]|a= %r=a;%_=True, ~ 0 ไบต์or-> %[a:r]|a=a= %r;%_=False, ~ 0 ไบต์ไม่กี่คนสุดท้ายที่ไม่น่าจะบันทึกไบต์ได้จริงเนื่องจากการแทนที่โดยตรงให้ผลตอบแทนมากกว่าไบต์ที่นำเข้า แต่อาจเป็นไปได้ในกรณีที่จำเป็นต้องมีการเรียกซ้ำในรายการ
map f list -> [f x\\x<-list] (11 bytes saved)(หรือบางอย่างที่คล้ายกัน))
ท้ายที่สุดแล้วทุกคนสามารถเล่นกอล์ฟในภาษาที่พวกเขาไม่สามารถใช้!
ออนไลน์
ทำความสะอาดไม่ใช่ภาษาที่รู้จักกันดีหรือมีเอกสารดีและชื่อไม่ได้ทำให้ง่ายต่อการค้นหาแหล่งข้อมูลที่จำเป็นมากในการแก้ไขปัญหาเหล่านี้ ... หรือไม่
Clean เดิมเรียกว่าConcurrent Cleanซึ่งยังคงใช้ในส่วนนำหน้าของเอกสารเกือบทั้งหมดที่เกี่ยวข้องกับ Clean - ดังนั้นหากคุณกำลังมองหา Clean ให้มองหา Clean พร้อมกันแทน
หนึ่งในความคล้ายคลึงที่น่าทึ่งยิ่งกว่าของ Clean คือ Haskell (ซึ่งมีอยู่มากมาย) คือการมีอยู่ของCloogleซึ่งเป็นเครื่องมือค้นหาฟังก์ชั่นที่ครอบคลุมไลบรารีที่ Clean มาพร้อมกับ
ในท้องถิ่น
ไลบรารีที่ Clean จัดส่งด้วยนั้นอยู่ในรูปแบบของไฟล์ซอร์ส Clean ที่มีการติติงด้วยความคิดเห็นที่ค่อนข้างเหมาะสมซึ่งสามารถเรียกดูผ่านการใช้ IDE
(นอกจากนี้ยังมาพร้อมกับโปรแกรมตัวอย่างแบบเต็มภายใต้$INSTALL/Examples)
เมื่อพูดถึง Clean เวอร์ชัน Windows มาพร้อมกับ IDE - แม้ว่ามันจะถูก จำกัด ด้วยมาตรฐานที่ทันสมัย แต่โลกก็ยังดีกว่าการใช้เท็กซ์เอดิเตอร์และบรรทัดคำสั่ง
คุณสมบัติที่มีประโยชน์มากที่สุดสองประการ (ในบริบทของการเรียนรู้) คือ:
[Ctrl]+[D]เพื่อเปิดไฟล์คำจำกัดความ (หรือใช้[Ctrl]+[I]สำหรับไฟล์การนำไปใช้) และสลับระหว่างคำจำกัดความและไฟล์การนำไปปฏิบัติด้วย[Ctrl]+[/]คอมไพเลอร์ของ Clean ไม่สนใจว่าการเข้ารหัสใดที่คุณคิดว่าคุณได้บันทึกไฟล์ต้นฉบับไว้เช่นเดียวกับค่าไบต์ในไฟล์ สิ่งนี้มีผลตามมาอย่างเรียบร้อย
ในร่างกายของรหัสที่มาเพียงไบต์ด้วยรหัสจุดที่สอดคล้องกับตัวอักขระ ASCII \t\r\nได้รับอนุญาตนอกจากนั้นสำหรับ
ตัวอักษร:
ในStringและ[Char]ตัวอักษร ( "stuff"และ['stuff']ตามลำดับ) ไบต์ใด ๆ ยกเว้น 0ได้รับอนุญาตด้วยข้อแม้ที่"และ'จะต้องหลบหนี (สำหรับStringและ[Char]ตามลำดับ) และการขึ้นบรรทัดใหม่และผลตอบแทน carraige จะต้องถูกแทนที่ด้วย\nและ\r(ยังตามลำดับ)
ในCharตัวอักษรไบต์ใด ๆ ยกเว้น 0ได้รับอนุญาตหมายความว่า:
'\n'
'
'
เหมือนกัน แต่ที่สองคือหนึ่งไบต์ที่สั้นกว่า
หนี:
นอกเหนือจากการ\t\r\nหลีกเลี่ยงจดหมายมาตรฐาน(ฯลฯ ) ลำดับการหลีกเลี่ยงที่ไม่ใช่ตัวเลขทั้งหมดใน Clean จะใช้สำหรับเครื่องหมายทับหรือสำหรับเครื่องหมายคำพูดที่ใช้เพื่อกำหนดขอบเขตตัวอักษรที่อยู่ภายใน
สำหรับลำดับ escape ตัวเลขตัวเลขจะถือว่าเป็นค่าฐานแปดที่ถูกยกเลิกหลังจากสามหลัก ซึ่งหมายความว่าหากคุณต้องการโมฆะตามด้วยตัวอักษร1ในStringคุณจำเป็นต้องใช้"\0001"(หรือ"\0\61") และไม่ได้ "\01"อย่างไรก็ตามถ้าคุณทำตามการหลบหนีด้วยอะไรก็ได้ยกเว้นตัวเลขคุณสามารถละเว้นเลขศูนย์นำหน้าได้
ผลกระทบ:
การเล่นโวหารด้วยวิธีที่ Clean จัดการกับไฟล์ต้นฉบับช่วยให้Stringและ['Char']กลายเป็นลำดับของตัวเลขหลักเดียว 256 หลักได้อย่างมีประสิทธิภาพซึ่งมีการใช้งานมากมายสำหรับ code-golf เช่นการจัดเก็บดัชนี (สูงสุด 255 รายการ)
เมื่อกำหนดฟังก์ชั่นมักจะสั้นกว่าที่จะใช้การรวมกันบางส่วนของ!@$%^&*~-+=<:|>.?/\กว่าจะใช้ตัวอักษรและตัวเลขเพราะมันช่วยให้คุณสามารถเว้นช่องว่างระหว่างตัวระบุ
ตัวอย่างเช่น: ?a=a^2สั้นกว่าf a=a^2และการเรียกใช้จะสั้นกว่าเช่นกัน
อย่างไรก็ตาม :
หากมีการใช้ฟังก์ชั่นตัวระบุติดกับสัญลักษณ์อื่น ๆซึ่งสามารถรวมกันเป็นรูปแบบที่แตกต่างกัน แต่ตัวระบุที่ถูกต้องพวกเขาทั้งหมดจะถูกแยกวิเคราะห์เป็นหนึ่งตัวบ่งชี้และคุณจะเห็นข้อผิดพลาด
ตัวอย่างเช่น: ?a+?bแยกวิเคราะห์เป็น? a +? b
นอกจากนี้:
มันเป็นไปได้ที่จะเขียนทับตัวบ่งชี้ที่นำเข้าในที่สะอาดและอื่น ๆ เพียงตัวเดียวตัวระบุสัญลักษณ์ที่ไม่ได้ใช้แล้วในการเป็นStdEnv @$?การเขียนทับ^-+(ฯลฯ ) อาจมีประโยชน์หากคุณต้องการตัวระบุสัญลักษณ์เพิ่มเติม แต่ระวังว่าคุณไม่ได้เขียนทับสิ่งที่คุณกำลังใช้อยู่
บางส่วนของโครงสร้างที่แข็งแกร่ง (สำหรับการเล่นกอล์ฟ) let ... in ...ในภาษาที่ทำงานได้ดี
สะอาดของหลักสูตรมีนี้และสิ่งที่ดีกว่า - #The
โหนดคืออะไร
ทั้งสะอาด#และแพร่หลาย|(ยามรูปแบบ) เป็นที่รู้จักกันทั้งสองเป็น 'การแสดงออกโหนด'
โดยเฉพาะอย่างยิ่งพวกเขาช่วยให้คุณสามารถตั้งโปรแกรม imperatively- ishในที่สะอาด (Clean ซึ่งเป็นสิ่งที่ดีจริงๆที่นี่!)
#(ขอก่อน):
ทั้งสองนี้คำนวณค่าของจำนวนเต็มที่กำหนดเป็นสตริงคูณด้วยผลรวมของตัวอักษร
f s=let i=toInt s;n=sum[toInt c\\c<-:s]in n*i
f s#i=toInt s
#s=sum[toInt c\\c<-:s]
=s*i
โปรดทราบว่ารุ่นที่มี#จะสั้นลงอย่างไรและเราจะกำหนดใหม่sได้อย่างไร สิ่งนี้มีประโยชน์หากเราไม่ต้องการค่าที่ตัวแปรมีเมื่อเราได้รับดังนั้นเราจึงสามารถใช้ชื่อได้อีกครั้ง ( letสามารถพบปัญหาเมื่อคุณทำเช่นนั้น)
แต่การใช้letจะง่ายกว่าเมื่อคุณต้องการบางสิ่งflip f = let g x y = f y x in g
The |(รูปแบบการป้องกัน):
รูปแบบการป้องกันของ Clean สามารถใช้งานได้เหมือนกับภาษาอื่น ๆ ที่มีฟังก์ชั่นการใช้งานif ... else ...มากมาย และเวอร์ชันที่สั้นกว่าของนิพจน์ประกอบไปด้วย
ตัวอย่างเช่นสิ่งเหล่านี้ทั้งหมดส่งคืนสัญลักษณ์ของจำนวนเต็ม:
s n|n<>0|n>0=1= -1
=0
s n=if(n<>0)if(n>0)1(-1)0
s n|n>0=1|n<0= -1=0
แน่นอนคนสุดท้ายที่ใช้ยามมากกว่าเดิมคือสั้นที่สุด แต่คนแรกแสดงให้เห็นว่าคุณสามารถซ้อนมันได้ (แต่เพียงสองประโยคที่ไม่มีเงื่อนไขกลับสามารถปรากฏในบรรทัดเดียวกันในรูปแบบกฎ) และที่สองแสดงสิ่งที่ คนแรกไม่มีเหตุผล
หมายเหตุ:
คุณสามารถใช้นิพจน์เหล่านี้ได้ทุกที่ ใน lambdas, case ... of, let ... inฯลฯ
Stringคุณควรใช้งานTextการแปลงเป็นสายอักขระและการจัดการกับสายอักขระ (ตัว{#Char}/ Stringไม่ใช่[Char]แบบชนิด) ค่อนข้างยาวและไม่ดีสำหรับการเล่นกอล์ฟ Textเยียวยาโมดูลนี้
การแปลง:
Textกำหนดผู้ประกอบการ<+สำหรับสองประเภทใด ๆ ที่ได้toStringกำหนดไว้
ผู้ประกอบการนี้ใช้เป็นa<+bเป็นเช่นเดียวกับtoString a+++toString b- ประหยัดอย่างน้อย 19 ไบต์ แม้ว่าคุณจะรวมการนำเข้าเพิ่มเติม,Textและใช้เพียงครั้งเดียวก็ยังบันทึกได้ 14 ไบต์!
การจัดการ:
Textกำหนดลวดเย็บกระดาษการจัดการสตริงที่หายไปจากStdEnv:
+สำหรับสตริงซึ่งสั้นกว่า+++(จากStdEnv)indexOfโดยมีพฤติกรรมคล้าย C ในการส่งคืน-1แทนที่จะเป็นNothingความล้มเหลวconcatซึ่งจะเชื่อมโยงรายการสตริงjoinซึ่งรวมรายการของสตริงโดยใช้สตริงตัวคั่นsplitซึ่งแยกสตริงเป็นรายการสตริงบนสตริงย่อยบางครั้งคุณพบว่าตัวเองใช้แลมบ์ดาแสดงออก (เพื่อส่งต่อmapหรือsortByฯลฯ ) เมื่อคุณทำเช่นนี้ (เขียน lambdas) มีหลายวิธีที่คุณสามารถทำได้
ทางที่ถูก:
นี่คือsortByรายการเรียงลำดับแลมบ์ดาที่มีสำนวนยาวที่สุดถึงสั้นที่สุด
sortBy (\a b = length a > length b)
อีกวิธีที่ถูกต้อง:
หากคุณกำลังใช้Data.Funcงานคุณสามารถทำได้
sortBy (on (>) length)
ทางสั้น ๆ :
นี่คือสิ่งเดียวกัน แต่มีไวยากรณ์นักกอล์ฟ
sortBy(\a b=length a>length b)
วิธีอื่น ๆ :
การใช้การแต่งเพลงไม่ได้สั้นลงในครั้งนี้ แต่บางครั้งอาจสั้นกว่านี้ได้
sortBy(\a=(>)(length a)o length)
วิธีอื่น ๆ :
ในขณะที่มันถูกประดิษฐ์ขึ้นเล็กน้อยที่นี่คุณสามารถใช้การ์ดใน lambdas
sortBy(\a b|length a>length b=True=False)
และยังให้นิพจน์โหนดก่อน
sortBy(\a b#l=length
=l a>l b)
หมายเหตุ:
มีอีกสองรูปแบบของแลมบ์ดามี(\a b . ...)และ(\a b -> ...)หลังซึ่งเป็นเหมือน=ที่แตกต่างและอดีตซึ่งมีอยู่ด้วยเหตุผลบางอย่างและมักจะดูเหมือนว่าคุณกำลังพยายามที่จะเข้าถึงทรัพย์สินของบางสิ่งบางอย่างแทนการกำหนดแลมบ์ดาเพื่อ don ใช้งานไม่ได้
\a=... คือไวยากรณ์แลมบ์ดาของ Clean: P
on(<)lengthแม้ว่าData.Funcการนำเข้าจะทำให้คุณเลิกเว้นแต่ว่าคุณต้องการมันอยู่แล้ว
#) เป็น lambdas ได้ด้วย
ตัวอักษรรายชื่อตัวละครเป็นวิธีที่จดชวเลขการเขียนสิ่งที่ต้องการเป็น['h','e','l','l','o']['hello']
นี่ไม่ใช่ขีด จำกัด ของสัญกรณ์ตัวอย่างเช่น:
repeat'c'กลาย['c','c'..]เป็น['cc'..]['z','y'..'a'] กลายเป็น ['zy'..'a']['beginning']++[a,b,c]++['end'] กลายเป็น ['beginning',a,b,c,'end']['prefix']++suffix กลายเป็น ['prefix':suffix]งานเหล่านี้ในการจับคู่เกินไป:
['I don't care about the next character',_,'but I do care about these ones!']codeก็สั้นClean มีฟังก์ชั่นที่มีประโยชน์มากมายในไลบรารีมาตรฐานซึ่งบางฟังก์ชั่นใช้งานได้อย่างไม่น่าเชื่อ *Worldและการใช้*Worldcode-golf เป็นความคิดที่ไม่ดีอยู่แล้ว
เพื่อแก้ไขปัญหานี้บ่อยครั้ง ccallคุณสามารถใช้codeบล็อกภายในแทน
ตัวอย่างบางส่วน:
เวลาของระบบ
import System.Time,System._Unsafe
t=toInt(accUnsafe(time))
ด้านบนคือ 58 ไบต์ แต่คุณสามารถบันทึก 17 ไบต์ (ลงไปที่ 40 + 1) ด้วย:
t::!Int->Int
t _=code{ccall time "I:I"
}
ตัวเลขสุ่ม
อันนี้ไม่ได้บันทึกไบต์ด้วยตัวเอง แต่หลีกเลี่ยงการต้องผ่านรายการ genRandInt
s::!Int->Int
s _=code{ccall time "I:I"ccall srand "I:I"
}
r::!Int->Int
r _=code{ccall rand "I:I"
}
ใช้อื่น ๆ
นอกเหนือจากสองสิ่งนี้ซึ่งอาจใช้เป็นหลักในการเขียนโค้ดกอล์ฟคุณสามารถเรียกใช้ฟังก์ชันที่มีชื่อใด ๆ (รวมถึง แต่ไม่ จำกัด เฉพาะ syscall ทุกแห่ง) ฝังแอสเซมบลีตามอำเภอใจด้วยinstruction <byte>และฝังโค้ดสำหรับเครื่อง ABC
import StdEnv+a and b(21 ไบต์) เล็กกว่า%[a:r]|a= %r=a;%_=True(22 ไบต์) ใช่ไหม หรือจะเป็นimport StdEnv+a=True and b=True(31 ไบต์) ซึ่งในกรณีนี้มันสั้นกว่านี้อย่างแน่นอน (ผมไม่เคยโปรแกรมในสะอาดครับ.)