Gleyzer両氏によって共同開発されました。2019で、同言語の発表を行いました。InfoQはPurdy氏に言語と、氏らが解決を目指した問題について聞きました。設計/アーキテクチャアジャイルマニュフェスト:ソフトウェアアーキテクトの視点ソフトウェアアーキテクトの役割と責任はアジャイルソフトウェア開発のためのマニフェストの価値と矛盾していると見えますが、優れたアーキテクトはアジャイル開発チームをサポートするテクニックを見つけています。Streamingは、ストリーミングデータのためのSQLライクなインターフェースを提供します。Streamsによって、Redisがストリーミングデータを複数のプロデューサとコンシューマの間で消費、保持、配信することができるようになります。ソフトウェア開発のマニフェストたゆまず息もつかずに市場に突進することで、会社を静かに消滅の崖っぷちへと追い込みます。それは設計してコードを書く方法を再考する時です。簡単さへの投資は、速さへの投資です。簡単さは知的財産の主鉱脈でもあります。競争上の優位性は、一度失ったら、もう一度手に入れることはほとんど不可能です。Buytaerts氏が過去10年間にわたって、企業がDevOps採用のハイプサイクルをくぐり抜け、変革に対する誤解を解消する過程を支援してきた経験について語ります。8に含まれる新しいアイディアをかなり具体化しています。8に含まれる新しい機能の概要を紹介しました。Lambdaが含まれます。Lambdaでしょう。Lambdaはラムダ式と仮想拡張メソッドとサポートし、並列コレクションによってマルチコアプラットフォームのサポートを強化します。関連スポンサーコンテンツこれらの新しい機能の多くはJVM上で動く多くの言語で既にサポートされています。Scalaもそのひとつです。8で採用された手法の多くはScalaに驚くほどにています。8でのプログラミングがどのようなものがわかります。8の新しい機能を、Scalaと比較しながら紹介します。コレクション、想拡張メソッドを紹介します。8に導入された、関数型言語のような新しいパラダイムを考察します。8に導入された新しい概念がどのようなものかわかるでしょう。Scalaにはすでに導入されている機能ですが、ただの飾りではなく、パラダイムシフトを起こす可能性のあるのがわかるでしょう。ソフトウエア開発に大きな可能性をもたらすでしょう。8はついにラムダ式を導入します。Lambdaで利用することができました。Closuresと言われていました。サンプルコードを紹介する前に、ラムダ式がJavaプログラマにとってなぜ歓迎すべき機能なのかを説明しましょう。ラムダ式を使うのかラムダ式の一般的な使い方はGUI開発においてです。一般的に、GUIプログラミングではイベントと結びつく振る舞いを解決する必要があります。プログラミングは何らかの処理を実行する必要があります。Swingでは、次のコードで示すようにActionListenersを使います。}}この例ではクラスButtonHandlerがコールバックの受取手として設定されています。ButtonHandlerはひとつのメソッドしか保持しません。actionPerformedです。このメソッドはActionListenerインターフェイスで定義されています。この例は匿名クラスを使うことでコードをシンプルにできます。}}この方がいくらかきれいです。コードをより詳しく見ると、ひとつのメソッドを呼ぶためだけにインスタンスを作っていることがわかります。この問題はラムダ式を導入することで解決することができます。関数としてラムダ式ラムダ式は関数リテラルで、パラメータと関数の本体を定義します。8のラムダ式の構文はまだ検討中ですが、下記のようになるでしょう。function_body具体的には次のようになります。s2.length();このラムダ式は2つの文字列長の差を計算します。}を使って文をまとめることで複数行定義をサポートするなど構文を拡張しています。Collections.sort()メソッドはラムダ式の理想的な使い方です。このメソッドを使えばStringsのコレクションの要素を文字列の長さでソートすることができます。"looooong".現在のJavaのバージョンを使った場合のようにsortメソッドにComparatorの実装を与える代わりに、ラムダ式を与えれば同じ結果を得られます。クロージャとしてのラムダ式ラムダ式には興味深い特徴があります。ひとつはクロージャです。クロージャを使うと関数は現在の構文スコープの外の変数にアクセスすることができます。outerにアクセスしていますが、この変数はスコープの外に定義されています。インラインで処理を実施する場合、このクロージャはとても便利です。7で導入されましたが、ラムダ式にも適用されます。簡単に言えば、型推論を使うことでプログラマは、コンパイラが型を推測できる箇所ならどこでも型の宣言を省略できます。ソート処理のラムダ式で型推論を使うと次のようになるでしょう。s2.length());パラメータs1とs2の型の宣言が省略されています。コンパイラがリストがStringsのコレクションであり、ラムダ式を比較処理に使う場合2つのString型のパラメータが必要だということを知っているから省略できるのです。明示的に型を宣言する必要はありません。明示的に宣言することもできます。型推論の利点は定型的なコードを削減できることです。コンパイラが型を推論してくれるのなら、どうしてわざわざ宣言する必要があるのでしょうか。ハロー、ラムダ式、さようなら匿名内部クラスさて、最初に見たコールバックの実装をラムダ式と型推論を使うとどのようにシンプルになるのか見てみましょう。}}コールバックメソッドを保持するクラスを定義する代わりに、ラムダ式を直接addActionListenerメソッドに渡します。定型的なコードを削除できる上、読みやすくなり、イベントをハンドルするという関心事だけをはっきりと表現できます。ラムダ式の利点をさらに詳述する前に、Scalaのラムダ式を見てみましょう。関数型プログラミングでは関数は基本的な構成要素のひとつです。Scalaはオブジェクト指向と関数型プログラミングの両方の特徴を合わせています。Scalaではラムダ式は‘関数’または‘関数リテラル’と呼ばれる基本的な構成要素です。ラムダ式はvalsまたはvarsに割り当てることができます。他の関数に引数として渡すこともできますし、新しい関数を作るために合成することもできます。Scalaでは関数リテラルは下記のように記述されます。body例えば、上でJavaのラムダ式でふたつの文字列の長さの差を計算しましたが、Scalaで書くと次のようになります。s2.lengthScalaでは、関数リテラルはクロージャでもあります。構文スコープの外で定義した変数にアクセスできます。20この例の結果は20です。この例ではmyFuncLiteralという変数に関数リテラルを割り当てています。8のラムダ式とScalaの関数は構文的にも意味的にもとても似ています。意味的には両者は全く同じです。簡易表記も違いますがここでは触れません。関数リテラルの大きな利点はStringやObjectなど他のリテラルと同じように、様々な処理に引き回せるということです。この利点には様々な用途があり、コンパクトで再利用可能なコードを書くことができます。関数リテラルをメソッドに渡す場合、メソッドを引数に取るメソッドが必要です。このようなメソッドを高階関数と言います。前述のSwingのコードで見たaddActionListenerメソッドはまさに高階関数です。独自の高階関数を定義することもできます。次の例を見てください。result}measureメソッドはfuncという関数リテラルを実行するのに費やした時間を計測します。funcのシグネチャは、引数を取らず、ジェネリック型Tの結果を返します。Scalaの関数は実際に引数を取る場合も引数を宣言する必要はありません。measureメソッドには関数リテラル(メソッド)を渡すことができます。ns概念的な視点から考えると、この方法は実際の処理からメソッド呼び出しの時間を計測するという関心事を分離したと言えます。2つの再利用可能なコード(時間計測処理とコールバック)は疎結合になります。高階関数を使った再利用2つの再利用可能なコードが強く結合している例を見てみましょう。}}doWithContactメソッドはファイルからvCardのような連絡情報を読み取り、連絡情報ドメインオプジェクトに変換します。このドメインオブジェクトは関数リテラルのコールバックhandleに渡されます。doWithContactメソッドとhandleの戻り値はUnit型です。これはJavaのvoidメソッドと同じです。doWithContactメソッドに渡すことができる様々なコールバックを定義することができます。combinedCallback)コールバックはインラインで渡すこともできます。8の高階関数もとても似ています。ContactDao.save(c))高階関数の利点ご覧の通り、関数を使うことでドメインオブジェクトの作成と処理をきれいに分離できます。することで連絡情報ドメインオブジェクトの新しい処理方法をドメインオブジェクトの作成処理と分離したまま追加することができます。Yourself)に保つことができ、プログラマが細かい粒度のコードを適切に再利用できるということです。高階関数はコレクションを処理するのに極めて効率的な方法を提供します。すべてのプログラムがコレクションを使うので、コレクション処理が効率的になるのは大きな利点です。コレクションのフィルタリングコレクションを使った一般的な例を見ましょう。コレクションの各要素に処理を適用したいとします。写真オブジェクトのリストがあり、あるサイズの写真オブジェクトだけ抽出したいとします。}このコードには定型的なコードがたくさん含まれています。処理結果のコレクションを作成したり、リストに新しい要素を追加したりするコードです。これ以外の書き方としては、Functionクラスを使う方法があります。Functionクラスは関数の振る舞いを抽象化します。}Guavaを使うとこの結果は次のように書けます。});この書き方は定型的なすが、まだ汚いです。8で書き直すとラムダ式の強力さとエレガントさがわかるでしょう。10)両方ともエレガントで簡潔な実装です。両方とも型推論が使えるということに注意してください。関数の引数pの型Photoは明示的に宣言されていません。これまで見てきたように、Scalaでは型推論は標準的な機能です。Scalaの関数連鎖これまで、少なくとも6行のコードを削減し可読性を改善しました。面白いのは複数の高階関数を連鎖させる方法です。これを説明するためにScalaでPhotoクラスを作り、属性を追加してみましょう。ratesの3つインスタンス変数を宣言しているだけです。変数ratesにはこの写真のユーザの評価を持ちます。取り得る値は1から10です。次のようにPhotoクラスを作ります。...)Photoクラスのインスタンスのリストに対して、複数の高階関数を連鎖させることで様々な問い合わせ処理を定義できます。10MB以上の写真の名前を抽出する処理です。問題になるのはPhotoクラスのリストをファイル名のリストに変換する方法です。これを実現するために高階関数を使います。使うのはmapと呼ばれる最も強力な高階関数のひとつです。p.name)mapメソッドはコレクションの各要素をmapメソッドに渡された関数に定義されている型に変換します。この例ではPhotoオブジェクトを受け取り、画像の名前であるStringを返す関数が定義されています。mapをfilterメソッドと連鎖させることで目的の処理を実現できます。p.name)NullPointerExceptionsの心配はありません。各メソッド(filter、mapなど)は常にコレクションを返します。空のコレクションの場合はありますが、nullにはなりません。Photoのコレクションが始めから空であれば、計算結果も空のコレクションになるでしょう。関数連鎖は‘関数合成’とも言われます。関数合成を使うことで、コレクションのAPIから問題を解決するための処理を探すことができます。先進的な例を見てみましょう。"平均評価が6よりも高い写真の名前を取得せよ。評価の合計値順にソートすること。p.name)この処理を実現するには、sortByメソッドを使います。このメソッドは入力としてコレクションの要素の型を受け取り(この場合はPhoto)、Ordered型のオブジェクト(この場合はInt)を返します。Listには平均を算出するメソッドはありません。したがって、与えられたIntのListの平均を算出する関数リテラルavgを定義しています。この関数リテラルは匿名関数としてfilterメソッドに渡されます。8のコレクションクラスがどのような高階関数を提供するのか現時点では明確ではありません。mapがサポートされる可能性は高いです。8で書くと下記のようになるでしょう。p.name)特筆すべきは、Scalaの場合と構文的な違いがほとんどないことです。コレクションと組み合わせた高階関数はとても強力です。簡潔で読みやすいだけでなく、たくさんの定型的なコードを省けます。それゆえ、少ないテストで済み、バグも少なくなります。並列コレクションこれまで、高階関数を使ったコレクションの処理の最も強力な利点を紹介していませんでした。簡潔さと読みやすさに加えて、高階関数はとても重要な抽象レイヤを提供します。前述した例はすべてループがありません。フィルタ処理やマップ処理、ソート処理のために一度もコレクションに対して反復処理をしていません。反復処理は隠されています。別の言い方をすれば抽象化されているのです。この抽象化レイヤはマルチコア環境を利用するための鍵です。いうのは、抽象レイヤの下にあるループの実装はどのように反復処理をするかを選択できるからです。反復処理は順次実行されるだけでなく、並列で実行することもできるのです。マルチコア環境において、並列処理はもはや「可能であれば実装したい」という段階ではありません。今日のプログラミング言語は並列環境の要求に答える必要があります。理論的には、並列処理のコードを自前で書くことはできます。実際には自前で書くのは賢いやり方ではありません。第一に、しっかりとした並列処理を書くのはとても難しいです。状態を共有し、処理の中間結果を最終的に統合する場合は大変です。第二に、多くの異なる並列処理実装が生まれるのは望ましくありません。Java7にはFork/Joinがありますが、データの分解処理と統合処理はクライアント側で書かなければなりません。ここには私たちが求める抽象レイヤはありません。第三に、関数型プログラミングに既に答えがあるのに、これ以上悩む必要はありません。賢い人々に並列反復処理のコードを書いてもらい、高階関数を使ってそのコードの使い方を抽象化すればいいのです。Scalaの並列コレクションScalaの並列処理の簡単な例を見ましょう。heavyComputation)まず、heavyComputationメソッドを定義します。このメソッドは重い処理を実行します。クアッドコアのラップトップではこの処理は実行するのに4秒かかります。10)をインスタンス化し、parメソッドを実行します。parメソッドは並列処理の実装を返却します。この並列処理の実装は並列でない処理と全く同じインターフェイスを持っています。ほとんどのScalaのコレクション型はparメソッドを持ちます。これだけで並列処理が実現できます。クアッドコアのマシンでどのくらい性能が改善するか確認して見ましょう。先に取り上げたmeasureメソッドを使い、性能調査をそます。s驚くべきことは、並列処理の場合、4つのコアを使っているにも関わらず、たった2.5倍だけしか速くならないということです。これは、並列処理をすることで新たなオーバーヘッド、つまり、スレッドを起動する処理と中間の結果を統合する処理にかかるオーバヘッドが生まれるからです。したがって、どのような処理でも並列コレクションを使うというのは得策ではありません。重い処理にのみ適用するのがいいでしょう。8の並列コレクションのインターフェイスはほとんどScalaと同じです。->heavyComputation())パラダイムはScalaと全く同じです。並列コレクションを作成するメソッドの名前がparではなくparallel()であるのがわずかな違いです。高階関数/ラムダ式と並列コレクションの組み合わせを、より大きな例を使って簡単にまとめてみましょう。この例では、Scalaで上述した概念を組み合わせて使っています。この例では、美しい壁紙を提供するサイトから、画像のURLを抽出し画像を並列処理でダウンロードします。Scalaの標準ライブラリ以外に2つのライブラリを使いました。HTTP通信のためのライブラリDispatchとApacheのFileUtilsです。この記事では紹介しないScalaの特徴が出てきますが、何をしようとしているかは理解できると思います。}コードの説明scrapeWallpapersメソッドは処理の流れを制御し、htmlから画像を取り出してダウンロードします。fetchWallpaperImgURLsOfPageメソッドはすべての壁紙の画像URLをhtmlから取り出します。HttpオブジェクトはDispatchライブラリのクラスです。このクラスはApacheのhttpclientライブラリ関連のDSLを提供します。as_tagsoupedメソッドはhtmlをxmlに変換します。xmlはScalaに組み込まれているデータ型です。as_tagsouped)xhtmlからダウンロードしたい画像に関連するhrefを探します。使ってノードを選択できます。すべてのhrefを検索したら、画像のURLを抽出し、hrefをURLオブジェクトに変換します。この処理に使うのがmapやfilterのようなScalaのコレクションAPIの高階関数の連鎖です。結果は画像URLのリストになります。URL(href))次に画像を並列処理でダウンロードします。並列でダウンロードするために画像の名前のリストを並列コレクションに変換します。することで、foreachメソッドは複数のスレッドを立ち上げてコレクションに同時にループ処理を適用します。各スレッドは最終的にはcopyToDirメソッドを呼びます。CommonのライブラリFileUtilsを使います。FileUtilクラスの静的メソッドcopyURLToFileを静的にインポートしているので直接呼び出すことができます。処理を明確にするために処理を実行したスレッドの名前を表示しています。実際に並列処理を実行してみると複数のスレッドが忙しく処理を実行しているのがわかります。url.getFile.split("/").last))}このメソッドでわかるのは、ScalaはJavaの既存のライブラリを利用できるということです。Scalaの関数的な特徴とコレクションに対する高階関数の利点、並列処理を使うことで、データを解析し、入出力を扱い、データを変換する並列処理をわずか数行で実行できるのです。仮想拡張メソッド/traitJavaの仮想拡張メソッドはScalaの‘trait’と似ています。traitと何でしょう。Scalaのtraitはインターフェイスを提供しますが、実装も提供することができます。この構造は大きな可能性を生み出します。traitを使ってクラスを構成してみるとよくわかるでしょう。8と同じように、Scalaは多重継承をサポートしていません。JavaもScalaもサブクラスが継承できるスパークラスはひとつだけです。traitを使えば違います。in"することができます。興味深いのはtraitを使うとクラスはそのtraitの型やメソッドや状態をすべて利用できるということです。このような特性からtraitはmixinとも呼ばれます。