ジェネリクスを使うと、同じコードを複数の型で使い回せます。いちいち同じことを書き直す必要はありません。ジェネリックな型は、山括弧(<>)を使って、たとえば<T>のように定義します。ここでTは、任意の型のプレースホルダーです。
fn largest_list<T>(l1: Array<T>, l2: Array<T>) -> Array<T> {
if l1.len() > l2.len() {
l1
} else {
l2
}
}
Cairoでは、ジェネリック型がどんな操作に対応している必要があるかを指定するために、トレイト境界が必要です。制約は、+の構文で追加できます。
fn process_data<T, +Drop<T>, +Copy<T>>(value: T) -> T {
// Function body
}
構造体もジェネリックにできます。
#[derive(Drop)]
struct Container<T> {
value: T,
}
トレイトもジェネリックにできます。これにより、さまざまな型に対応できるようになります。
trait Processor<T> {
fn process(self: @T) -> ByteArray;
}
impl MyProcessor<T, +Drop<T>> of Processor<T> {
fn process(self: @T) -> ByteArray {
"processed"
}
}
関数でも、トレイト境界を付けたジェネリックな型を入力として受け取れます。こうすると、必要なトレイトを実装したどんな型でも扱えるようになります。
fn use_processor<T, +Processor<T>, +Drop<T>>(item: T) -> ByteArray {
item.process()
}
ベルリンの新しい空港が、ロボット研究所のエンジニアとして採用されました。 その空港には、ぎこちなく、どことなく人型に見えるロボットがいて、接客サービスの向上に役立てようとしています。
最初の仕事は、セルフチェックインカウンターでパスポートをスキャンした利用者に、その人の母語であいさつするようロボットをプログラムすることです。
ロボットは自分の能力に誇りを持っているので、必ず自分が話せる言語を先に言ってから、その人にあいさつします。 たとえば、ドイツのパスポートがスキャンされると、ロボットはこう言います。
I can speak German: Hallo Dietrich!
自分も他のエンジニアも言語を簡単に追加できるように、コードを構成する必要があります。
まずは、2つの関数を持つGreeter traitを定義します。
language_name:ロボットが利用者へのあいさつに使う言語(ByteArray)を返す。greet:利用者の名前(ByteArray)を受け取り、その言語のあいさつメッセージ(ByteArray)を返す。次に、利用者の名前と、Greeter traitを実装したものを受け取り、目的のあいさつ(ByteArray)を返す関数say_helloを実装します。
たとえば、language_nameが"German"を返し、greetが"Hallo {name}!"を返すドイツ語のGreeter実装を考えてみましょう。
say_hello("Dietrich", germanGreeter)
// => "I can speak German: Hallo Dietrich!"
では、イタリアのパスポートをスキャンした人にも対応できるようにロボットを動かしましょう。
Italian structを作成し、タスク1のGreeter traitを満たすように2つの関数を実装します。
イタリア語では、"Ciao {name}!"のようにあいさつできます。
今日の仕事を終える前に、フランス語であいさつする機能を追加しておくことになっています。
French structを作成し、Greeter traitを満たすように2つの関数を実装します。
フランス語では、"Bonjour {name}!"のようにあいさつできます。