2017-07-05 5 views
1

私はGolangにスーパーで新しく、言語の周りの大きな話題が同時性と思われるのを見て、私のつま先を濡らす良い方法が一般化されたマップ関数。 psudoコードで:空のインタフェースを持つコンカレントマップ関数をGOlangで一般化する

map(F funtion,A array){ 
    return([F(k) for k in A]) 
} 

明らかに私は各F(k)の計算が同時に起こりたいと思います。組織のために、私の実装にはメインファイルがあり、必要な定義にはサポートファイルがあります。

. 
├── main.go 
└── Mr 
   └── Mr.go 

主な結果の各メンバーは、入力配列内の対応する文字列の長さintの配列に文字列の配列を変換する必要があり、単純なテストの実装です。

package main 

import(
    "fmt" 
    "./Mr" 
) 

func exfunc(i int, c chan int){ 
    c<-i 
} 

func main(){ 
    data := make(map[int]string) 
    data[1]="these" 
    data[2]="are" 
    data[3]="some" 
    data[4]="words" 
    data[5]="and a few more..." 
    f := func(w string)int{ 
     return(len(w)) 
    } 
    testMr := Mr.Map(f,data) // this is line 22 (matters later) 
    fmt.Println(testMr) 
} 

すべての型を明示的に指定すると、私のMr.Map関数にはうまくいきます。

package Mr 

type result struct{ 
    key,value int 
} 

func wrapper(f func(string) int,k int,v string, c chan result){ 
    c <- result{k,f(v)} 
} 

func Map(f func(string) int,m map[int]string) map[int]int{ 
    c := make(chan result) 
    ret := make(map[int]int) 
    n := 0 
    for k := range m{ 
     go wrapper(f,k,m[k],c) 
     n++ 
    } 
    for ;n>0; { 
     r := <-c 
     ret[r.key]=r.value 
     n-- 
    } 
    return(ret) 
} 

しかし、私は空のインターフェイスでこのマッピングを一般化することができると期待していました。

package Mr 

type T interface{} 

type result struct{ 
    key,value T 
} 

func wrapper(f func(T) T,k T,v T, c chan result){ 
    c <- result{k,f(v)} 
} 

func Map(f func(T) T,m map[T]T) map[T]T{ 
    c := make(chan result) 
    ret := make(map[T]T) 
    n := 0 
    for k := range m{ 
     go wrapper(f,k,m[k],c) 
     n++ 
    } 
    for ;n>0; { 
     r := <-c 
     ret[r.key]=r.value 
     n-- 
    } 
    return(ret) 
} 

残念ながら、私はこのgeneralize Mr.Mapでmainを実行すると、次のエラーが発生します。

# command-line-arguments 
./main.go:22: cannot use f (type func(string) int) as type func(Mr.T) Mr.T in argument to Mr.Map 
./main.go:22: cannot use data (type map[int]string) as type map[Mr.T]Mr.T in argument to Mr.Map 

はそうそう、明らかに私はエラーが私に言っているか理解が、それは私がキーと値の種類の組み合わせごとにマイマップ機能を再書き込みしなければならない野生のようです。

Is there a work around here, or is this just the nature of the beast?

+0

あなたのカウンタは正常に機能しますが、これを管理するための組み込み型があります。['sync.WaitGroup'](https://golang.org/pkg/sync/#WaitGroup) 。 – Adrian

答えて

1

ありません本当の問題を回避するには、それは獣の性質です。

言語はC++で苦労して設計されたもので、クリエイターのアイデアは重要ではないものをすべて簡素化すると同時に、言語をより表現力豊かにするための重要な追加機能です。

あなたは私はあなたが彼らが作ったすべての決定に同意しない場合でも、非常に興味深いものであると信じている、ここではその推論について少しを読むことができます:あなたが望んだ場合、あなたの例では

https://commandcenter.blogspot.com.ar/2012/06/less-is-exponentially-more.html

あなたはあなたのマップと関数をinterface{}(これは空のインターフェイスであり、 "nil"インターフェイスではありません)とします。

もちろん、コンパイル時の型チェックが失われ、キャストをすべて追加する必要があります。

使用したいタイプの共通点を表現するためのインターフェースを見つけることもできます(これは簡単ではないかもしれません)。

+0

それは私が望んでいた答えではありませんでしたが、それは私が期待したものです...空のインターフェースと呼ぶべきものを指摘してくれてありがとう! – kpie

+0

@kpie:ええ、私は想像しました...このスレッドを読むことができれば、この種の機能を言語に正確に追加しないという考え方がかなりわかります:https://groups.google.com/forum/ #!topic/golang-nuts/RKymTuSCHS0 – eugenioy

+0

実際に私はmap reduceとfilterを探していません。これはすべて既に作成済みです(https://blog.gopheracademy.com/advent-2015/glow-map-reduce-for-golang/)。私が探しているのはunsafe.go(https://github.com/golang/go/blob/master/src/unsafe/unsafe.go)ですが、まだ完全には調べていません。 – kpie

1

Goの哲学は、一般的な動的言語のスタイルなどの一般化された関数と互換性がありません。コンパイラにあなたがしようとしていることを正しく伝えるためには、必要なマップをインターフェイスで表現するか、それを使用している各タイプごとに記述するだけです。

マッピングでは、配列を割り当て、コレクションを反復し、コレクション内の各要素のデータ要素を配列に追加する必要があります。あなたは、アプリケーション層に一般的であるように構造体のスライスのマップを、必要な場合は、移動中に簡潔にこれを表現することができます

https://play.golang.org/p/pk3Tl_BdlD

動的言語は、「汎用」タイプの「タイプ・ツリー」を構築します任意のタイプに対して1つのシンボルによって呼び出されるmapのような関数のような簡潔なプログラミングを可能にする。簡単な実験を可能にするためにコードをゆるやかに書くことができるため、開発者の生産性が大幅に向上します。

Goは、半永久的なソフトウェアを作成するために設計されています。これは、より多くの情報をコンパイラに供給する必要があるため、うまく機能します。マップは約3行のコードしかないので、開発者の生産性と効率のコスト/便益は、Goのパフォーマンス側にあります。 map、reduce、filterなどの関数は、必要に応じて明示的に記述する必要があります。

言語を評価するには、Goプログラムの問題を解決し、それがどこにあるかを確認することをお勧めします。

+0

ありがとう、私はGolangで24時間プログラミングしているだけなので、この例は非常に役に立ちます。 (私は実際にあなたの例を読むまで、どのように追加するのか分かりませんでした。) – kpie

関連する問題