質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

1366閲覧

Goの関数のチェインについて

tinoue

総合スコア13

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2019/04/22 08:53

前提・実現したいこと

GO言語を使ったWEBアプリケーションの作成方法を本で勉強しています。
GO言語の関数チェインのやり方で疑問を感じたので教えていただけると助かります。
理解を深めるため、これを参考に自分で簡単なコードを書きました。

発生している問題・エラーメッセージ

sample1はうまく動作しますが、sample2は以下のエラーが出ます。

sample1

1F type is called 25 36

sample2

1prog.go:19:7: undefined: i 2prog.go:23:10: log(hello) used as value

もともとは、sample1のlogという関数で、なんでわざわざ関数型を受け取って関数型を返しているのか疑問に思い、どうせならlog関数の中でhello関数を呼び出せばいいじゃん!と思いsample2を作成しました。
1行目のエラーは引数が引き継げてないのでわかるのですが、2行目のエラーがなぜ起こるのかがわかりません。どなたか教えてくださると幸いです。

該当のソースコード

sample1

1package main 2 3import "fmt" 4 5 6type F func(i int) 7 8func (f F) serveInt(i int){ 9 fmt.Println("F type is called") 10 f(i) 11} 12 13func hello(i int){ 14 fmt.Println(i+1) 15} 16 17func log(h F) F{ 18 return func(i int) { 19 fmt.Println(i) 20 h(i) 21 } 22} 23 24func main() { 25 F(log(hello)).serveInt(5) 26}

sample2

1package main 2 3import "fmt" 4 5 6type F func(i int) 7 8func (f F) serveInt(i int){ 9 fmt.Println("F type is called") 10 f(i) 11} 12 13func hello(i int){ 14 fmt.Println(i+1) 15} 16 17func log(h F) { 18 fmt.Println("log") 19 h(i) 20} 21 22func main() { 23 F(log(hello)).serveInt(5) 24}

試したこと

無名関数、関数チェインなど1日中調べていましたが、同じような事例が見つかりませんでした。

補足情報(FW/ツールのバージョンなど)

以上のコードはGOの公式サイトで実行しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

prog.go:23:10: log(hello) used as valueと出る理由は、

以下のコードだけに注目してみてください。

go

1func log(h F) { 2 fmt.Println("log") 3 h(i) 4} 5 6func main() { 7 F(log(hello)).serveInt(5) 8}

log関数の戻り値がありません。その戻り値をF()でキャストしようとしています。
「存在しない値を値として扱おうとした」というエラーメッセージです。

投稿2019/04/22 14:41

編集2019/04/22 14:46
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tinoue

2019/04/22 15:01

回答ありがとうございます。 つまり、F(log(hello)).serveInt(5)が実行されるときに、まずF(log(hello))が実行されて、その中身のlog(hello)を実行した戻り値がFによって型変換されるという認識で合っていますか? sample1の場合は戻り値があるから大丈夫ということですよね。 でも結局log(hello)を実行した時にhelloに戻り値がないのでsample1も「hello used as value」といったエラーが出ないと辻褄が合わないと思ったのですが、何が間違っていますか?
nobonobo

2019/04/23 00:30 編集

「結局・・辻褄が合わない」と考えた理由を推測するとlog関数が返しているものに着目しきれていない気がします。 sample1ではlog関数が返す「(まだ実行前の)無名関数」をFにキャストしていますのでエラーにはなりません。無名関数を実行した時の戻り値の有無は関係ありませんし、あくまでlog関数の戻り値(つまり無名関数)をFにキャストしているだけであってその内側が何を行なっているかは無関係です。
tinoue

2019/04/24 06:11

return func( i int ) { ... } この時点で無名関数が実行されると勘違いしていました。 だからsample2でも同じことだと考えてしまったんですね。 それが実行されるのはserveInt(5)が実行された時ですよね。 やっと腑に落ちました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問