ฟังก์ชั่นการเขียนโปรแกรมเป็นไปได้ใน Java? [ปิด]


42

ฉันถูกเรียกดูผ่าน Amazon.com ร้านหนังสือและฉันมาข้ามหนังสือ"หน้าที่ Programming สำหรับ Java Developers"

ฉันรู้ว่าการเขียนโปรแกรมฟังก์ชั่นพื้นฐานบางอย่างและได้รับการเขียนโปรแกรมใน Java เป็นเวลา 3 ปี

ฉันต้องการที่จะรู้ว่าฟังก์ชั่นการเขียนโปรแกรมเป็นไปได้แม้ใน Java?


2
สไตล์เป็นไปได้ แต่ verbosity อาจมากเกินไปที่จะรับไวยากรณ์ของ Java: functionaljava.org
Yuriy Zubarev

7
@nCdy ทำไมต้องตรวจสอบ JRuby โปรดระบุคำอธิบายเพิ่มเติม
Chiron

1
ตรวจสอบ groovy :-)
Ant's

6
ฉันคิดว่านี่เป็นคำถามที่ทำให้เกิดความแตกต่างระหว่าง Java-the-language และ Java-the-platform
Thomas Owens

2
@ ThorbjørnRavnAndersen: อะไรทำให้คุณคิดว่า "การวางโปรแกรมเชิงปฏิบัติการ" ถูกกำหนดโดย "การประเมินแบบสันหลังยาว" ดูเหมือนว่าเป็นตัวอย่างที่แปลกที่จะเลือก ...
John Bartholomew

คำตอบ:


70

มันขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "การเขียนโปรแกรมการทำงาน" และ "เป็นไปได้"

เห็นได้ชัดว่าคุณสามารถใช้สิ่งต่าง ๆ ตามกระบวนทัศน์การทำงาน อย่างไรก็ตามภาษาจาวาไม่ได้ให้น้ำตาลเชิงประโยคสำหรับมันดังนั้นบางสิ่งจะน่าเบื่อที่สุดและบางอันจะมีความคลาดเคลื่อนอย่างมาก

ในทำนองเดียวกันคุณสามารถเขียนโค้ดเชิงวัตถุในภาษาที่ไม่ใช่ OO เช่น C

ไลบรารี Java

มีห้องสมุดที่สามารถช่วยคุณทำสิ่งนี้ได้โดยทำสิ่งที่ถูกต้องให้กับคุณแล้วซ่อนสิ่งที่ลึกลับ:

สิ่งเหล่านี้จะช่วยให้คุณสามารถเขียนโค้ด Java ด้วยวิธีการทำงานที่มากขึ้นและอาจมีความคุ้นเคยกับไวยากรณ์และความหมายมากขึ้นตามที่คุณคาดหวังจากภาษาที่มีความเชี่ยวชาญของ FP ภายในเหตุผลนั่นคือ

ภาษา JVM

และแน่นอนคุณสามารถใช้ภาษาทำงานได้บน Java เพื่อให้คุณสามารถใช้ภาษานั้นเป็นภาษา FP ของคุณ ซึ่งเป็นระดับที่สูงกว่าสิ่งที่เป็นนามธรรมของสิ่งที่คุณถาม แต่ในบริบท (แม้ว่าฉันจะโกงที่นี่เล็กน้อยได้รับ)

ตัวอย่างเช่นตรวจสอบ:

ภาษา JVM ใช้งานได้มากกว่าหรือน้อยกว่า

แม้ว่าภาษาเหล่านี้อาจไม่ตรงตามที่คุณต้องการ แต่ก็มีภาษาอื่นอีกจำนวนหนึ่งที่ถูกย้ายไปยังแพลตฟอร์ม Java และอาจทำให้คุณหลุดพ้นจากธรรมชาติของ Java ซึ่งไม่ใช่แนวสนุก (ใช่, ตั้งใจ) และให้คุณมากกว่า มีความยืดหยุ่น คู่หูที่มีชื่อเสียงเช่นJRuby , JythonและRhino (ตามลำดับสำหรับRuby , PythonและJavaScript / ECMAScript ) ยังมีศักยภาพที่น่าสนใจสำหรับการเขียนโปรแกรมการทำงานแม้ว่าเนื้อหานั้นไม่ใช่ภาษาโปรแกรมที่ใช้งานได้จริงตามธรรมชาติ JetBrains ' Kotlinในขณะที่การยอมรับอย่างชัดเจนว่าไม่ใช่ภาษาที่ใช้งานได้จะรองรับโครงสร้างที่ใช้งานได้บางอย่างและคุ้มค่าที่จะดู

อ่านเพิ่มเติม

คุณอาจต้องการอ่านหรือดูบทความหรือวิดีโอเหล่านี้:


2
ตอนนี้ซอร์สโค้ด Clojure ถูกโฮสต์บน Github github.com/clojure/clojure
Chiron

@ The Legend of 1982: ฉันเร็วกว่าความคิดเห็นของคุณฉันได้เปลี่ยนลิงค์ไปยังเว็บไซต์อย่างเป็นทางการของ clojure.org :) แต่ขอบคุณสำหรับการจับมันอย่างรวดเร็ว! เหมาะที่จะเห็นคนตอบสนองอย่างรวดเร็ว
haylem

นอกจากนี้ยังมี ABCL ( common-lisp.net/project/armedbear ) แต่ฉันไม่รู้ว่ามันอยู่ตรงไหนในระดับที่เป็นผู้ใหญ่ / ไม่ได้เป็นผู้ใหญ่
Vatine

@Vatine: น่าสนใจไม่เคยได้ยินมาก่อน จะมีรูปลักษณ์ที่รวดเร็วและเพิ่มเข้าไป
haylem

1
ฉันชอบคำของ Alan Perlis "Turing Tarpit" ที่พยายามทำสิ่งที่ languge สามารถทำได้ (เพราะมันทำให้สมบูรณ์) แต่ด้วยความเจ็บปวดและความซับซ้อนที่ไม่ควรทำ
itsbruce

11

ฉันกำลังอ่านหนังสือที่คุณพูดถึง มันดีจริงๆ BTW

ใช่เป็นไปได้ที่จะใช้งานได้ใน Java ฉันไม่รู้ว่าคุณจะสำเร็จระดับไหน แต่คุณสามารถใช้สำนวนการเขียนโปรแกรมที่ใช้งานได้หลายอย่าง

หนึ่งในสิ่งที่สำคัญที่สุดคือความพยายามในการเขียนโค้ดด้วยความคิด "อย่ากลายพันธุ์"

ตัวอย่างเช่นคุณใช้คำหลักสุดท้ายเพื่อให้บรรลุความไม่สามารถเปลี่ยนแปลงได้ หากคุณกำลังจะใช้โครงสร้างข้อมูลคุณควรเขียนโค้ดในโครงสร้างข้อมูลที่ไม่เปลี่ยนรูป ห้องสมุด Google Guava กำลังทำสิ่งนี้อยู่

นอกจากนี้สำหรับการเขียนโปรแกรมพร้อมกันคุณสามารถพึ่งพากรอบของ Akka (โมเดลนักแสดง)

เป็นมูลค่าการกล่าวขวัญว่า JVM bytecode ไม่สนับสนุน (อย่างน้อยที่สุด) การเพิ่มประสิทธิภาพ Tail-call ซึ่งเป็นคุณสมบัติที่สำคัญมากสำหรับภาษาโปรแกรมที่ใช้งานได้


"เป็นเรื่องที่ควรกล่าวถึงว่า JVM bytecode ไม่สนับสนุน (อย่างน้อยที่สุด) การปรับให้เหมาะสมแบบ tail-call ซึ่งเป็นคุณสมบัติที่สำคัญมากสำหรับภาษาโปรแกรมที่ใช้งานได้": คุณหมายถึงอะไร สกาล่าไม่มี TCO
Giorgio

@Giorgio: Scala ทำ TCO ในเวลารวบรวม
scrwtp

@scrwtp: มีโทษประสิทธิภาพเพราะสิ่งนั้นหรือไม่ หรืออะไรคือข้อเสียของการรวบรวมเวลา TCO?
Giorgio

@Giorgio: สิ่งที่ฉันหมายถึงคือ java bytecode ไม่สนับสนุนมันเหมือน Chiron ที่ระบุไว้ในตอนแรก ภาษาที่ใช้งานได้ทำงานได้รอบ ๆ มันรวบรวมการเรียกแบบเรียกซ้ำเข้าไปในลูป แต่มันเป็นคุณสมบัติของภาษา -> bytecode คอมไพเลอร์ไม่ใช่ JVM
scrwtp

@scrwtp: คำตอบของ Chiron กล่าวว่า "เป็นมูลค่าการกล่าวขวัญว่า JVM bytecode ไม่สนับสนุน (อย่างน้อยที่สุด) การปรับให้เหมาะสมแบบ tail-call ซึ่งเป็นคุณสมบัติที่สำคัญมากสำหรับภาษาโปรแกรมที่ใช้งานได้" ทำให้ดูเหมือนว่าการติดตั้งภาษาที่ใช้งานได้บน JVM นั้นถูกลงโทษ แต่ (และเราเห็นด้วยกับเรื่องนี้) สิ่งนี้ไม่เป็นความจริงเนื่องจากการเพิ่มประสิทธิภาพการโทรหางสามารถจำลองในโค้ดที่คอมไพล์ได้ ดังนั้นฉันเห็นด้วยกับคำสั่งของ Chiron แต่ฉันคิดว่ามันทำให้เข้าใจผิดเล็กน้อย
Giorgio

6

ใช่มันเป็นไปได้อย่างแน่นอนในลักษณะเดียวกับที่เป็นไปได้ในการรวมกันของสภาพแวดล้อมภาษา / การดำเนินการทัวริงที่สมบูรณ์ คุณสามารถทำให้มันทำงานได้ค่อนข้างดีถ้าคุณรู้ว่าคุณกำลังทำอะไรอยู่

ไม่แน่ใจว่ามันสมเหตุสมผลแค่ไหน โดยเฉพาะอย่างยิ่งระวังว่ามันไม่ได้เป็นสำนวนโดยเฉพาะ (เช่นมันจะดูแปลกมากคุณจะต้องทำสิ่งที่แปลกใหม่และสับสนคนที่เคยชินกับ Java ปกติ)

คุณจะได้รหัสแปลก ๆ เช่นเพื่อกำหนดฟังก์ชั่นใหม่:

Function twoStrings=new Function() {
  public Object apply(Object param1) {
    // do something to param1 and return a result
  }
}

หากต้องการเขียนโปรแกรมเชิงฟังก์ชันคุณต้อง:

  • ฟังก์ชั่นชั้นหนึ่ง - ง่ายต่อการสร้างใน Java โดยการกำหนดคลาสนามธรรมหรืออินเตอร์เฟซที่แสดงถึง "ฟังก์ชั่น" ของคุณและมีวิธี "ใช้" ซึ่งใช้ฟังก์ชั่นกับพารามิเตอร์หนึ่งหรือมากกว่า
  • Closures - สร้างอินสแตนซ์ของวัตถุฟังก์ชันของคุณด้านบนด้วยค่าปิดที่เก็บไว้ในฟิลด์สุดท้าย คุณสามารถใช้คลาสภายในแบบไม่ระบุชื่อสำหรับสิ่งนี้
  • ห้องสมุดที่มีฟังก์ชั่นการสั่งซื้อที่สูงกว่ามาตรฐาน - นี่เป็นเรื่องยากกว่า แต่คุณยังสามารถเขียนภาษาของคุณเองเพื่อบู๊ตภาษาที่ใช้งานได้ง่ายในเวลาไม่กี่ชั่วโมง หากคุณต้องการสิ่งที่ชื่นชอบคุณสามารถตรวจสอบไลบรารี่การทำงานอื่น ๆ ที่ผู้คนสร้างขึ้นใน Java

ดังนั้นจึงเป็นไปได้ในการออกกำลังกายและแม้แต่งานอดิเรกที่น่าสนใจ แต่คุณต้องการที่จะทำการเขียนโปรแกรมการทำงานอย่างจริงจังในขณะที่รักษาข้อดีของ JVM / การเข้าถึงไลบรารี Java จากนั้นClojureเป็นตัวเลือกที่ดีที่สุดของคุณในความคิดของฉัน

ป.ล. เนื่องจากแก่นแท้ของ Clojure เขียนด้วยภาษาจาวาเป็นตัวอย่างที่น่าสนใจอย่างมากเกี่ยวกับวิธีการเขียนโปรแกรมการทำงานใน Java ในขณะที่ซ่อนรายละเอียดที่ยุ่งเหยิงไว้เบื้องหลังไวยากรณ์ภาษาใหม่ที่ทันสมัย รหัสที่มา Clojure อยู่บน GitHubสำหรับผู้ที่สนใจ


น่าสนใจฉันสังเกตเห็นว่า IntelliJ IDEA รุ่นล่าสุดจะพับคนที่ไม่ระบุตัวตนเหล่านี้ให้เป็นรูปแบบกะทัดรัดยิ่งขึ้นเพื่อแสดงในเครื่องมือแก้ไข การทำงานที่เหมาะสมของการซ่อน cruft ซ้ำซ้อนหรือไม่ แน่นอนว่าทั้งหมดนี้จะไม่เกี่ยวข้องกับ Java 8
Ben Hardy

4

มันเป็นไปได้ที่จะใช้งานได้ค่อนข้างใน Java การทำเช่นนั้นเจ็บปวดอย่างมาก แทน

myList.each { doSomething(it); }

คุณมีสิ่งที่ชอบ:

myList.each(new Function() { public void do(Object arg) { something(); }})

และถ้าคุณต้องการการเขียนโปรแกรมการใช้งานจริงด้วยการปิดและฟังก์ชั่นเป็นวัตถุชั้นหนึ่งให้เลือกภาษาอื่น Scala, Clojure, Groovy ทั้งหมดทำงานบน JVM และสามารถโต้ตอบกับคลาส Java ดั้งเดิม .


ฟังก์ชั่นการเขียนโปรแกรมไม่ได้เกี่ยวกับการใช้บล็อกแทนคลาสที่ไม่ระบุชื่อ Java 8 กำลังจะมีบล็อกดังนั้นโค้ดที่โพสต์ของคุณจะดูหรูหรามากขึ้น แต่มันจะไม่เป็นโปรแกรมที่ใช้งานได้
Chiron

@ ตำนาน: ฉันเข้าใจ แต่เห็นได้ชัดว่าไม่ได้อธิบายได้ดี
วินไคลน์

นี่คือการกำกับดูแล / ใต้ ด้วยภาษาใด ๆ คุณต้องกำหนดฟังก์ชั่นจริง ๆ แล้วคุณไม่สามารถข้ามส่วนนั้นได้ ดังนั้นจาวาเกือบจะกระชับสิ่งที่คุณต้องทำคือทำให้วัตถุฟังก์ชั่นไม่มีชื่อ คุณสามารถทำได้: Function f = new Function () {public void do () {}}; .... จากนั้น ... เรียกใช้ฟังก์ชันนั้น ... myMethodToCallAFunction (ฟังก์ชัน f) {f.do ()} ... นั่นแหละคือ bros และ brolinis จัดการกับมัน
Alexander Mills

3

คำตอบคือ "ใช่แน่นอน" ดังก้อง แต่ในความคิดของฉันหนึ่งในคุณสมบัติที่สำคัญที่สุดในภาษาที่ใช้งานได้หลายอย่างเป็นระบบประเภทที่ยอดเยี่ยม คุณจะไม่สามารถจัดการสิ่งนี้ใน Java ด้วยตัวเอง

หากคุณต้องการที่จะเขียนโปรแกรมการทำงานและยังอยู่กับ JVM ฉันสามารถขอแนะนำในหมู่ผู้ต้องสงสัยตามปกติ Scala และ Clojure จะมองไปที่Frege Frege มีระบบไวยากรณ์และระบบพิมพ์ที่ใกล้เคียงกับ Haskell มาก แต่โปรแกรมจะถูกแปลโดยตรงเป็นโค้ดจาวาและสามารถโต้ตอบกับโค้ดจาวาอื่น ๆ ได้


2

ทุกสิ่งเป็นไปได้ เป็นไปได้ที่จะทำการเขียนโปรแกรมเชิงวัตถุใน C; มันไม่ใช่ความคิดที่ดีนัก

Java ไม่ได้ออกแบบมาสำหรับ FP ดังนั้นถ้าคุณกำลังพยายามทำทุกอย่างในแบบ FP ล้วนๆคุณจะมีปัญหา คุณจะต้องต่อสู้กับภาษาแทนที่จะทำงานกับมัน และไม่ใช่แค่ภาษาเท่านั้น - ยังมีห้องสมุด Java ที่ยอดเยี่ยมฟรีอีกด้วย ดังนั้นอย่าไปหา FP บริสุทธิ์ รับแนวคิดบางอย่างที่อยู่เบื้องหลัง FP และรวมเข้ากับโค้ด Java ของคุณ แต่เข้าใจว่าคุณไม่สามารถทำตามแนวคิดทั้งหมดได้


0

คุณได้รับการสนับสนุนจากทีม OpenJDK เพื่อดาวน์โหลด OpenJDK 8 ไบนารีล่าสุดของพวกเขาและเล่นกับนิพจน์แลมบ์ดาใหม่และสำนวนการใช้งานใหม่ที่ได้รับการแนะนำใน Collections API (ท่ามกลางคนอื่น ๆ ) คุณสามารถโปรแกรมในสไตล์การทำงานที่ชัดเจน ดู"ฟังก์ชั่นการเขียนโปรแกรมใน Java?" สำหรับการเปรียบเทียบคอลเลกชัน JDK8 กับ libs Java8 ก่อนเช่น Guava, FunctionalJava และ LambdaJ


-3

ดูเหมือนว่าจะเป็นไปได้ แต่จะไม่เป็นโปรแกรมที่ใช้งานได้จริง มันอาจส่งผลให้การเขียนโปรแกรมที่จำเป็น

ไม่มีการถามว่าทำไมเขาถึงหมายถึงโดยการเขียนโปรแกรมการทำงานที่เป็นไปได้ดังกล่าวโดยเฮย์เล็ม นี่มันคือ:

มันขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "การเขียนโปรแกรมการทำงาน" และ "เป็นไปได้"

ฟังก์ชั่นการเขียนโปรแกรมไม่สามารถมีคำจำกัดความหรือความหมายที่แตกต่างกันแม้ว่ามันอาจมีคำอธิบายมากมาย
เช่นเดียวกับ OOP เราสามารถถาม "คุณหมายถึงอะไรโดย OOP"
แน่นอนว่าจะมีคำอธิบายมากมาย แต่มันจะเกี่ยวข้องกับหนึ่งวัตถุประสงค์วัตถุประสงค์ของ OOP
เช่นเดียวกับการเขียนโปรแกรมการทำงาน

เมื่อเราพูดถึงฟังก์ชั่นหมายถึงโปรแกรมประกอบด้วยฟังก์ชั่น
บทบาทของฟังก์ชันคือส่งคืนอาร์กิวเมนต์ / พารามิเตอร์ที่ประเมิน (อาร์กิวเมนต์คือตัวแปรคือนิพจน์ที่มาเมื่อเรียกใช้ฟังก์ชันในขณะที่พารามิเตอร์เป็นตัวแปรที่เป็นส่วนหนึ่งของการประกาศฟังก์ชัน)

นอกจากนี้ฟังก์ชั่นจะส่งกลับผลลัพธ์เดิมเสมอเมื่อมีการโต้แย้งกัน ด้วยวิธีนี้จะง่ายกว่าในการหลีกเลี่ยงข้อบกพร่องหรือแก้ไขข้อบกพร่องในอนาคต โดยการเขียนโปรแกรมการทำงานเราสามารถหลีกเลี่ยงผลข้างเคียงเช่นการแก้ไขตัวแปรทั่วโลก

ตัวอย่างใน JavaScript:

function increment(lis){
    return lis.map(
        function (x){
            return x+2;
        }
    );
}

var myList = [4, 7, 2, 3];
console.log(increment(myList));
console.log(myList);

การเพิ่มฟังก์ชันจะเพิ่ม 1 ค่าให้กับองค์ประกอบภายในวัตถุและส่งคืนผลลัพธ์ ค่าของ myList ไม่เปลี่ยนแปลง แต่เมื่อเราเรียกใช้ฟังก์ชันที่เราเห็นมูลค่าเพิ่มให้กับองค์ประกอบของวัตถุนั้น

ตามการตอบสนองของฉันต่อการเขียนโปรแกรมฟังก์ชั่นเป็นไปได้ใน Java? ฉันเชื่อว่าเป็นไปไม่ได้ที่จะมีการเขียนโปรแกรมใช้งานได้จริงใน java เพราะจาวาได้รับการออกแบบให้เป็น OOP ซึ่งจะขยายการเขียนโปรแกรมที่จำเป็นและปรับปรุงเพื่อการบำรุงรักษา เมื่อสถานะของวัตถุตัวแปร ฯลฯ เปลี่ยนแปลงไปแล้วนั่นคือการเขียนโปรแกรมที่จำเป็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.