はじめに
後述のコードはGolangで書かれていますが、全言語において気になっていたので多言語のタグをつけさせていただきます。
回答コードは、Go,python , C#ないしCだと助かりますが、その他言語でも問題ありません
正直「そんな方法はありません」
という回答が来る気もしています
特にGoとC#の回答を求めています!
やりたいこと
関数
call1
call2
call3
call4
を定義しておいて、末尾の数字だけを変えて連続実行する際に、綺麗にまとめる方法はありますか?
以下、動かないですが、やろうとしてることが伝わるように、イメージを書いておきます。。
go
1func main() { 2 for i:=1;i<4;i++{ 3 call+i() 4 } 5} 6 7func call1() { 8 fmt.Println("I am call1") 9} 10 11func call2() { 12 fmt.Println("I am call2") 13} 14 15func call3() { 16 fmt.Println("I am call3") 17} 18 19func call4() { 20 fmt.Println("I am call4") 21}
追記
みなさん多彩な回答ありがとうございます。
現状Goで困っていたため、Goで回答を作ってくださった方をベストアンサーとさせていただきますが、他言語を使うことになった際は、ここを参考にさせていただきます。
ありがとうございました!
- Goは関数の配列を作って、forで回す, あるいはreflectを使う(非推奨)
- pythonはevalを使う
- phpは可変関数, call_user_func, あるいはevalを使う(非推奨)
- JSは関数を配列に入れる, あるいはevalを使う(非推奨)
- C#はデリゲートを作る, リフレクションを使う
Cとswift, objective-cにも回答がついていました。
募集から1日未満にもかかわらず、たくさんの回答、ありがとうございました。
私のみならず、他の人の参考にもなれば幸いと思います。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 08:11
2017/09/06 23:42
回答13件
0
追記:
コメントでご指摘頂きましたが、eval()
は脆弱性につながる恐れがありますので、他の手段がある場合は使わないほうが良いようです。PHPにはcall_user_func()
という専用関数が、Pythonならばglobals()
またはlocals()
で定義済みの関数・変数のディクショナリを取得することで文字列での呼び出しができます。
PHP:call_user_func - Manual
2. 組み込み関数 ー Python 3.6.1 ドキュメント
参考までに、PHPの公式ドキュメントには下記のように記載されています。
警告
eval() は非常に危険な言語構造です。 というのも、任意の PHP コードを実行できてしまうからです。 これを使うことはおすすめしません。 いろいろ検討した結果どうしても使わざるを得なくなった場合は、細心の注意を払って使いましょう。 ユーザーから受け取ったデータをそのまま渡してはいけません。 渡す前に、適切な検証が必要です。
肝心のGolangについては門外漢ですので、pythonと、聞かれてないですがPHPの例です。
eval()を使えばなんでもできます(是非はともかくとして)。
pyth
1def call1(): print('spam') 2def call2(): print('ham') 3def call3(): print('sausage') 4 5for i in range(1, 4): 6 eval('call' + str(i) + '()') 7
php
1<?php 2function call1(){ echo "call1"; } 3function call2(){ echo "call2"; } 4function call3(){ echo "call3"; } 5 6foreach (range(1, 3) as $i){ 7 eval('call' . $i . '();'); 8}
投稿2017/08/31 19:27
編集2017/09/03 07:55総合スコア663
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/09/01 01:03
退会済みユーザー
2017/09/01 07:55 編集
退会済みユーザー
2017/09/01 07:50
退会済みユーザー
2017/09/01 07:51
退会済みユーザー
2017/09/01 07:57
2017/09/03 07:57
退会済みユーザー
2017/09/04 09:31
0
ベストアンサー
Go言語の関数は変数に格納できるという特徴を持っています。(第一級関数という特徴です。JavaScript等も同様)
この特徴を利用し、例えば配列に関数を追加して、イテレータ(i)で呼び出した関数を順次実行するということが出来ます。
このような方法でなくとも、「Go言語の関数は変数に格納できる」という特徴を上手く利用すれば似たようなことはかなり自由自在にできます。
是非考えてみて下さい。
以下、手直ししてみました。
私の環境では動作することを確認しています。
Go
1func main() { 2 3 var funcList [4]func() 4 funcList[0] = call1 5 funcList[1] = call2 6 funcList[2] = call3 7 funcList[3] = call4 8 9 for i:=0;i<4;i++{ 10 f := funcList[i] 11 f() 12 } 13} 14 15func call1() { 16 fmt.Println("I am call1") 17} 18 19func call2() { 20 fmt.Println("I am call2") 21} 22 23func call3() { 24 fmt.Println("I am call3") 25} 26 27func call4() { 28 fmt.Println("I am call4") 29}
投稿2017/09/01 03:16
総合スコア1947
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:54
2017/09/01 07:59
0
c言語で書いてみました。綺麗とは言えませんが。
c
1#include <stdio.h> 2 3int call1(int a) { return(a+10); } 4int call2(int a) { return(a+20); } 5int call3(int a) { return(a+30); } 6int call4(int a) { return(a+40); } 7 8void main() 9{ 10 int (*po[])() = { call1, call2, call3, call4 }; 11 12 int i; 13 for (i=0;i<4;i++){ 14 printf("Call Func call%d\n",(*po[i])(i)); 15 } 16}
投稿2017/09/01 00:07
編集2017/09/01 00:41総合スコア4070
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:55 編集
0
PHPなら可変関数が使えるのですが、他の言語(JavaScript/Python)であれば eval とかを使う方法があるようです。JavaScriptであればそもそも配列に関数自体を入れることができるので、evalを使わなくても良いと思います。
JavaScript
1const func = [ 2 i=>{ console.log( 1, i ); } 3 , i=>{ console.log( 2, i ); } 4 , i=>{ console.log( 3, i ); } 5]; 6func.map( ( f, i )=>{ f( i ); } ); 7/* 81 0 92 1 103 2 11*/
【PHP: 可変関数 - Manual】
http://php.net/manual/ja/functions.variable-functions.php
【JavaScriptでPHPの可変関数のような事をしたい時は | nkymemo】
http://nkymemo.blogspot.jp/2011/02/javascriptphp.html
【Python - 関数を文字列から動的に呼び出す - Qiita】
http://qiita.com/Chan_moro/items/9b0105e4c18bb76ed4e9
【python - Pythonで可変関数の書き方を教えてください。 - スタック・オーバーフロー】
https://ja.stackoverflow.com/questions/32744/pythonで可変関数の書き方を教えてください/32748
投稿2017/08/31 19:20
総合スコア69583
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:55 編集
0
Objective-C
objectivec
1- (void)call1 {NSLog(@"call1");} 2- (void)call2 {NSLog(@"call2");} 3- (void)call3 {NSLog(@"call3");} 4- (void)call4 {NSLog(@"call4");} 5 6for (int i = 1; i <= 4; i++) { 7 NSString *name = [NSString stringWithFormat:@"call%zd", i]; 8 SEL sel = NSSelectorFromString(name); 9 if ([self respondsToSelector:sel]) { 10 [self performSelector:sel]; 11 } else { 12 NSLog(@"'%@' does not exist.", name); 13 } 14}
Swift (with Objective-C)
swift
1@objc func call1() {print("@call1")} 2@objc func call2() {print("@call2")} 3@objc func call3() {print("@call3")} 4@objc func call4() {print("@call4")} 5 6for i in 1...4 { 7 let name = "call\(i)" 8 let sel = Selector(name) 9 if self.responds(to: sel) { 10 self.perform(sel) 11 } else { 12 print("'\(name)' does not exist.") 13 } 14}
Swift
akabeeさんの回答を書き直してみました。
swift
1func call1() {print("call1")} 2func call2() {print("call2")} 3func call3() {print("call3")} 4func call4() {print("call4")} 5 6let funcList = [call1, call2, call3, call4] 7funcList.forEach {$0()} 8 9//もしくは、 10 11let funcList = [call1(), call2(), call3(), call4()] 12funcList.forEach {$0}
投稿2017/09/01 01:07
編集2017/09/01 08:25総合スコア16733
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:55 編集
0
PHPでは専用関数がよういされています
PHP
1for($i=1;$i<=3;$i++){ 2call_user_func("call".$i); 3} 4function call1(){ 5 print "a"; 6} 7function call2(){ 8 print "b"; 9} 10function call3(){ 11 print "c"; 12} 13
投稿2017/09/01 01:02
総合スコア116412
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:55 編集
0
デリゲートtestを作成して、そこに呼び出したい関数を設定する。
test()にてすべての関数を実行する。
C#
1 public Form1() 2 { 3 InitializeComponent(); 4 5 Action test = null; 6 test += Call1; 7 test += Call2; 8 test += Call3; 9 test += Call4; 10 test(); 11 } 12 13 void Call1() 14 { 15 System.Diagnostics.Debug.WriteLine("call1"); 16 } 17 18 void Call2() 19 { 20 System.Diagnostics.Debug.WriteLine("call2"); 21 } 22 23 void Call3() 24 { 25 System.Diagnostics.Debug.WriteLine("call3"); 26 } 27 28 void Call4() 29 { 30 System.Diagnostics.Debug.WriteLine("call4"); 31 }
投稿2017/09/01 04:28
総合スコア529
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:40
0
こうですか?
C#
1using System; 2using System.Linq; 3 4namespace ConsoleApplication1 5{ 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 Enumerable.Range(1, 4) 11 .Select(n => "Call" + n) 12 .Select(m => typeof(Hoge).GetMethod(m)) 13 .ToList() 14 .ForEach(m => m.Invoke(null, null)); 15 } 16 17 class Hoge 18 { 19 public static void Call1() 20 { 21 Console.WriteLine("call1"); 22 } 23 24 public static void Call2() 25 { 26 Console.WriteLine("call2"); 27 } 28 29 public static void Call3() 30 { 31 Console.WriteLine("call3"); 32 } 33 34 public static void Call4() 35 { 36 Console.WriteLine("call4"); 37 } 38 } 39 } 40}
投稿2017/09/01 04:16
総合スコア4152
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:41
0
英文ですが、実現できるようです。
https://stackoverflow.com/questions/8103617/call-a-struct-and-its-method-by-name-in-go
構造体の値(メソッド)をreflectパッケージによって取り出して実行しています。
ただ、reflectパッケージはプログラムを複雑にするだけでなく実行速度の低下にもつながるので、むやみな使用は避けましょう。
以下のようにしたほうが無難かと思われます。
go
1funcs := []func(){call1, call2, call3, call4} 2for _, f := range funcs { 3 f() 4}
投稿2017/09/01 04:03
総合スコア868
0
例だけ見るとこうすればできますが。
C#
1static void Main(string[] args) 2{ 3 for (int i = 1; i <= 4; i++) 4 { 5 Call(i); 6 } 7} 8 9static void Call(int i) 10{ 11 Console.WriteLine("I am call{0}", i); 12}
リフレクションで動的に関数名を指定したいということでしょうか。
C#
1class Program 2{ 3 static void Main(string[] args) 4 { 5 TestClass tc = new TestClass(); 6 Type t = tc.GetType(); 7 for (int i = 1; i <= 4; i++) 8 { 9 MethodInfo mi = t.GetMethod(string.Format("Call{0}", i)); 10 mi.Invoke(tc, new object[] { }); 11 } 12 13 Console.ReadLine(); 14 } 15} 16 17class TestClass 18{ 19 public void Call1() 20 { 21 Console.WriteLine("I am call1"); 22 } 23 public void Call2() 24 { 25 Console.WriteLine("I am call2"); 26 } 27 public void Call3() 28 { 29 Console.WriteLine("I am call3"); 30 } 31 public void Call4() 32 { 33 Console.WriteLine("I am call4"); 34 } 35}
投稿2017/09/01 02:13
編集2017/09/01 05:56総合スコア559
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:54 編集
0
多言語ということで
call4までしかないけど 5,6,7って増えたら forの数字を修正しないといけないですよね。
どうせコードをいじるのであれば、、、
callをすべて関数ポインタ(およびそれに準じるもの)にしておいて関数ポインタの配列をforで回して実行。
うまくplugin形式にしておいてメイン実装修正しなくても実行できるようにしてみるといいね。
投稿2017/08/31 20:02
総合スコア1408
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/01 07:48
0
;;; Common Lispでのケースです。
Lisp
1(defun call1() 2 (print "call1")) 3 4(defun call2() 5 (print "call2")) 6 7(defun call3() 8 (print "call3")) 9 10(defun join (str lst &optional (jstr "")) 11 (cond 12 ((null lst) jstr) 13 (t (let ((news (concatenate 'string jstr 14 (first lst) 15 (if (null (rest lst)) 16 "" 17 str)))) 18 (join str (rest lst) news))))) 19 20(defun call-fn() 21 (dolist(a '("1" "2" "3")) 22 (funcall 23 (read-from-string 24 (join "" `("call" ,a)))))) 25 26(call-fn) 27
投稿2017/09/07 00:39
総合スコア71
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
解決済みだけれど、Rubyでの回答が無かったので参考までに。
ruby
1def call1 2 puts 'call1' 3end 4def call2 5 puts 'call2' 6end 7def call3 8 puts 'call3' 9end 10 11(1..3).each {|i| send("call#{i}") } #
投稿2017/09/06 08:48
編集2017/09/06 08:49総合スコア267
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/09/06 10:31
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。