Programmering

Hva REPL betyr for Java

Kanskje du er en Clojure eller Scala-utvikler, eller kanskje du har jobbet med LISP tidligere. I så fall er det en god sjanse for at du har brukt en REPL som en del av din daglige rutine. REPL, eller read-eval-print-loop, er et skallgrensesnitt som leser hver linje av inndata, evaluerer den linjen og deretter skriver ut resultatet. Øyeblikkelig tilbakemelding, hyggelig!

Når du bruker en REPL, skriver du kode interaktivt og utfører den uten forsinkelse. Utgivelsen av Java 9 i 2016 vil levere et fullt funksjonelt REPL-miljø som heter JShell (kodenavnet Kulla). Denne artikkelen gir en oversikt over Java REPL og diskuterer noen muligheter for hvordan du kan bruke den i Java-programmering - ja, du!

Vent, Java har ikke allerede en REPL?

Sikkert et etablert språk som Java må ha en REPL! Vel, faktisk, ikke alle språk har dem, og Java er et av de som har savnet det. Uten tvil, med mer seremoni og kokeplate enn de fleste språk, er Java et av språkene som utviklerne har fortjent det mest. Java har hatt noe litt REPL-aktig en stund i form av Java BeanShell, men dette prosjektet var aldri en fullverdig REPL på nivå med andre språk. Det var bare et delsett av den fulle Java-syntaksen.

REPL reduserer snuoperasjonen

Å forkorte behandlingstiden og tilbakemeldingsløkkene så mye som mulig er utrolig viktig for sunnheten til en utvikler. En REPL er et flott verktøy for utviklere som ønsker å oppnå nettopp det. Utviklere er mest produktive når de umiddelbart kan se resultatene av arbeidet sitt. Med en Java REPL vil utviklere være i stand til å skrive kode, utføre den koden, og deretter fortsette å utvikle koden sin på farten uten å måtte avslutte for å kjøre en build og så videre. Mens mange av systemene som bruker Java, er utenfor kompleksiteten til det som kan håndteres av en interaktiv REPL, betyr bare tilstedeværelsen av en REPL i JDK at noen, et eller annet sted, vil finne et fantastisk brukstilfelle for det på kort tid. Det faktum at JShell avslører et API, sørger i utgangspunktet for at IDE-utviklere skal integrere denne REPL i verktøyene vi bruker til å skrive kode. Bare vent til Java REPL er en del av hver IDE!

Kom i gang med JShell

Det er viktig å innse at bruk av REPL, Project Kulla, ikke er for svak av hjertet. Kulla, aka JShell, er ikke en del av forhåndsvisningspakken JDK 9 i skrivende stund, så du må klone et Mercurial-prosjekt, kompilere JDK og kompilere JShell selv. Sett av en time til denne prosessen, spesielt hvis du vanligvis ikke kaster rundt JDK-kildekoden. Du må deaktivere advarsler som feil, og hvis du bygger videre på OSX, må du sørge for at du har installert XCode sammen med XQuartz for freetype-biblioteket. Følg instruksjonene nedenfor for å installere og kjøre Project Kulla i Java-utviklingsmiljøet ditt.

1. Installer Java 9

For å kjøre JShell, må du laste ned og installere den siste forhåndsversjonen av tidlig tilgang for Java 9. Når du har lastet ned Java 9, må du angi din JAVA_HOME miljøvariabel og kjør java –versjon for å bekrefte installasjonen. Dette kan være vondt, spesielt på OSX, så det er verdt å sjekke det dobbel!

2. Installer Mercurial og Project Kulla

Project Kulla er et OpenJDK-prosjekt, så du må klone Mercurial-depotet for å kompilere det.

Deretter kloner du Kulla-depotet:

 hg klone //hg.openjdk.java.net/kulla/dev kulla 

Deretter konfigurerer du bygningen:

 cd kulla bash ./configure - deaktiver-advarsler-som-feil lager bilder 

3. Kompilere og kjør REPL

Her er koden for å kompilere REPL:

 cd langtools / repl; bash ./scripts/compile.sh 

Og her er koden for å kjøre den:

 bash ./scripts/run.sh 

Som jeg bemerket, er Java's REPL-funksjon ikke klar for generelt forbruk ennå, men vi kan fortsatt ta den med på en tidlig prøvekjøring!

Du gjør matte

For et første eksempel på hva JShell kan gjøre, la oss evaluere noen enkle uttrykk ved hjelp av java.lang.Math:

Oppføring 1. Evaluering av matematiske uttrykk med REPL

 $ bash ./scripts/run.sh | Velkommen til JShell - Versjon 0.710 | Skriv / hjelp for hjelp -> Math.sqrt (144.0f); | Uttrykkverdi er: 12,0 | tilordnet midlertidig variabel $ 1 av typen dobbel -> $ 1 + 100; | Uttrykkverdi er: 112.0 | tilordnet den midlertidige variabelen $ 2 av typen dobbelt -> / vars | doble $ 1 = 12,0 | doble $ 2 = 112.0 -> dobbel val = Math.sqrt (9000); | Lagt til variabel verdi av typen dobbelt med startverdi 94.86832980505137 

Her vurderer vi uttrykk, finner kvadratroten til et tall og legger deretter to tall sammen. Dette er ikke den mest komplekse koden, men du bør merke deg at / vars kommando gir oss muligheten til å liste opp variablene som ble opprettet i JShell-økten. Vi kan referere til verdier av ikke tildelte uttrykk ved å bruke en dollartegn ($). Til slutt kan vi opprette en ny variabel og tildele den en verdi.

Definer en metode

Nå blir det mer interessant. I dette eksemplet definerer vi en metode for å beregne Fibonacci-sekvensen. Etter at metoden er definert, sjekker vi for å se hvilke metoder som er definert med / metoder kommando. Til slutt utfører vi et kodebit for å gå gjennom en matrise og skrive ut de første tallene i sekvensen.

Oppføring 2. Beregn Fibonacci-sekvensen

 $ bash ./scripts/run.sh | Velkommen til JShell - Versjon 0.710 | Skriv / hjelp for hjelp -> langfibre (langt tall) >> hvis ((tall == 0) | Lagt til metode fibreg (lang) -> / metoder | Fibonacci (lang) lang -> Fibonacci (12) | Uttrykkingsverdi : 144 | tilordnet midlertidig variabel $ 1 av typen long -> int [] array = {1,2,3,4,5,6,7,8}; | Lagt til variabel array av typen int [] med startverdi [I @ 4f4a7090 -> for (long i: array) {System.out.println (Fibonacci (i));} 1 1 2 3 5 8 13 21 

I samme JShell-økt kan jeg omdefinere definisjonen av Fibonacci-metoden og utføre den samme koden. På denne måten kan du bruke REPL til raskt å utføre, modifisere og teste ut nye algoritmer.

Oppføring 3. REPL for gjenbruk

 -> langfibrat (langt tall) {>> retur 1; >>} | Modifisert metode Fibonacci (lang) -> for (lang i: array) {System.out.println (Fibonacci (i)); } 1 1 1 1 1 1 1 

Definer en klasse

Følgende eksempel viser hvordan du definerer en hel klasse i JShell og deretter refererer til den klassen i et uttrykk - alt uten å forlate REPL. Evnen til å dynamisk opprette og teste kode frigjør deg til å raskt eksperimentere og gjenta med ny kode.

Oppføring 4. Dynamisk klassedefinisjon

 MacOSX: repl tobrien $ bash ./scripts/run.sh | Velkommen til JShell - Versjon 0.710 | Skriv / hjelp for hjelp -> klasse Person {>> offentlig Strengnavn; >> offentlig alder; >> offentlig strengbeskrivelse; >> >> offentlig person (strengnavn, alder, strengbeskrivelse) {>> dette.navn = navn; >> this.age = alder; >> denne.beskrivelse = beskrivelse; >>} >> >> offentlig String toString () {>> returner dette.navn; >>} >>} | Lagt til klasse Person -> Person p1 = ny person ("Tom", 4, "Liker Spiderman"); | Lagt til variabel p1 av typen Person med startverdi Tom -> / vars | Person p1 = Tom 

Selv om muligheten til å definere klasser dynamisk er kraftig, er det ikke som utviklere klager på å skrive store, flerlinjedefinisjoner i et interaktivt skall. Det er her konseptet med historie og det å være i ferd med å laste og lagre tilstanden til REPL begynner å bli viktig. Med /historie kommando kan du liste alle utsagnene og uttrykkene som er evaluert i en REPL.

Oppføring 5. Kjenn din / historie

 -> / historie klasse Person {public Strengnavn; offentlig alder; offentlig strengbeskrivelse; offentlig person (strengnavn, alder, strengbeskrivelse) {this.name = navn; this.age = alder; denne.beskrivelse = beskrivelse; } offentlig streng til streng () {returner dette.navn; }} Person p1 = ny person ("Tom", 4, "Liker Spiderman"); Person p2 = ny person ("Zach", 10, "Bra på matematikk"); / vars p1 p2 / historie 

Deretter kan du lagre REPL-historikken din i en fil og gi den navnet, slik at den kan lastes inn igjen senere. Her er et eksempel:

 -> / lagre output.repl -> / reset | Tilbakestiller tilstand. -> / vars -> / open output.repl -> / vars | Person p1 = Tom | Person p2 = Zach 

De /lagre kommandoen lagrer REPL-historikken i en fil, /nullstille kommandoen tilbakestiller tilstanden til REPL og /åpen kommandoen leser i en fil og utfører stater mot REPL. Lagre og åpne funksjoner gjør det mulig å sette opp svært komplekse REPL-skript som du kan bruke til å konfigurere forskjellige REPL-scenarier.

Redigering av klassedefinisjon på farten

JShell gjør det også mulig å angi en oppstartsdefinisjonsfil og laste definisjoner automatisk. Du kan hoppe rundt i REPL-historikken din og redigere navngitte kildeoppføringer. For eksempel hvis jeg ønsket å endre definisjonen av Person klasse fra dette eksemplet kunne jeg bruke /liste og /redigere kommandoer.

Oppføring 6. Endring av person

 -> / l 1: klasse Person {offentlig Strengnavn; offentlig alder; offentlig strengbeskrivelse; offentlig person (strengnavn, alder, strengbeskrivelse) {this.name = navn; this.age = alder; denne.beskrivelse = beskrivelse; } offentlig streng til streng () {returner dette.navn; }} 2: Person p1 = ny person ("Tom", 4, "Liker Spiderman"); 3: Person p2 = ny person ("Zach", 10, "Good at Math"); 4: p1 5: p2 -> / rediger 1 

Kjører dette /redigere kommandoen laster en enkel redaktør der jeg kan endre klassedefinisjonen og få klassen oppdatert umiddelbart.

Hva er problemet?

Snakk med en Clojure- eller LISP-programmerer om hvordan de utvikler seg hver dag, så ser du at de koder i en REPL. De skriver ikke skript og utfører dem så mye som de bruker mesteparten av sin utviklingstid på å endre kode interaktivt. Hvis du har noen timer til overs, spør en Scala- eller Clojure-utvikler om deres REPL. Det er slik de fungerer.

Java er et annet språk enn Scala eller Clojure. Java-utviklere bruker ikke dager fokusert på enkeltlinjer med LISP som kan inneholde hele programstrukturer i noen få uttalelser. De fleste Java-programmer krever oppsett for å fungere skikkelig, og mens nylige endringer i språket har redusert antall linjer som er skrevet på Java, måler vi fortsatt kompleksiteten til systemene våre i tusenvis av kodelinjer. Det enkle Person eksemplet som er oppført ovenfor er ikke nyttig kode, og den mest nyttige koden i Java bærer med seg en kompleksitet som det blir vanskelig å passe inn i et REPL-basert programmeringsmiljø.

Scala og Clojure-utviklere praktiserer noe som Programmering av Clojure forfatteren Chas Emerick kaller "iterativ utvikling" som ikke er avhengig av en filbasert arbeidsflyt. Java-utviklere er avhengige av titalls biblioteker, komplekse avhengighetshierarkier og containere som Tomcat eller TomEE. Av denne grunn forutser jeg ikke at REPL-orientert programmering vil innhente tradisjonell Java-utvikling i en IDE. I stedet ser jeg at Java REPL gir noen forskjellige fordeler og muligheter.

1. Lære Java: Fordi Java-programmer krever så mye oppsett, kan det være utfordrende for utviklere som lærer språket å forstå syntaksen raskt. Java 9s REPL vil bli den primære måten nye utviklere får tak i den grunnleggende syntaksen.

2. Eksperimentere med nye biblioteker: Java har hundrevis av nyttige open source-biblioteker for alt fra dato og klokkeslett til mattebiblioteker. Uten REPL, når en utvikler ønsker å forstå et nytt bibliotek, oppretter de uunngåelig noen kasserte klasser med det vanlige "offentlig statisk ugyldig hoved"seremoni. Med en REPL kan du bare skyte den opp og spille uten dette overhead.

3. Rask prototyping: Dette er nærmere hvordan de fleste Clojure- og Scala-utviklere jobber iterativt, men hvis du jobber med et fokusert problem, gjør en REPL det enkelt å itere raskt på endringer i klasser og algoritmer. Med en REPL trenger du ikke vente på at en bygging skal fullføres; du kan tilpasse definisjonen av en klasse raskt, tilbakestille REPL og prøve den på nytt.

4. Integrasjon med byggesystemer: Gradle tilbyr en interaktiv "shell" -modus, og Maven-samfunnet har sendt lignende verktøy tidligere. Utviklere som ønsker å redusere byggekompleksiteten, kan utforske å bruke en REPL som et verktøy for å ordne andre systemer.

Min siste 2c

Jeg ser Java REPL som noe som vil begynne å påvirke den daglige utviklingen de neste årene, for de som oppgraderer til Java 9. Jeg tror også at Java-samfunnet kommer til å trenge tid til å tilpasse seg ny utviklingsstil og forstå både utfordringene og mulighetene som en REPL gir. Jeg forventer ikke at de fleste Java-utviklere vil gå over til REPL-orientert utvikling slik deres fettere til Clojure-programmering har, men jeg tror at vi vil se REPL påvirke måten nye utviklere lærer Java på. Når nye Java-utviklere møter Java for første gang i en REPL, er det ingen tvil om at det vil begynne å påvirke hvordan vi bygger og prototype Java-baserte systemer.

Denne historien, "Hva REPL betyr for Java" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found