我想为任何坐标类型的东西定义一个接口,它实现一个Distance()方法,可以用来计算相同类型的另一个坐标类型的距离(可能是笛卡儿,也许是按时间顺序,等等)
这是一般的想法:
type Distancer interface {
Distance(other interface{}) int
}
但这并不为Distance()的参数提供类型安全性,它必须是相同的类型。例如,我可能有一个实现Distance()的ParticularTime结构;传递另一个ParticularTime对象作为参数是有道理的,但传递一个ParticularLocation根本没有意义。
我怀疑至少在某些情况下,这可以在编译时捕获,例如这显然是错误的:
x := ParticularLocation{}
y := ParticularTime{}
distance := x.Distance(y)
有没有办法表达这个限制?或者我必须在Distance()的每个实现中进行运行时类型检查?
我是否以错误的方式思考这个问题?
答案 0 :(得分:3)
这是的同态。如果我们假设 distance 表示expression problem,这也是相对容易概括的,这对于广泛的应用是合理的假设。但是,由于Go不支持euclidean distance或任何想要的东西,我们将不得不在我们想要支持的维度数量上做出合理的妥协,转而支持类型安全。
让我们为前三个维度实现这一点。
func OneDimensionalDistance(a OneVectorer, b OneVectorer) float64 {
return euclideanDistance(a.Vector()[:], b.Vector()[:])
}
func TwoDimensionalDistance(a TwoVectorer, b TwoVectorer) float64 {
return euclideanDistance(a.Vector()[:], b.Vector()[:])
}
func ThreeDimensionalDistance(a ThreeVectorer, b ThreeVectorer) float64 {
return euclideanDistance(a.Vector()[:], b.Vector()[:])
}
func euclideanDistance(a, b []float64) float64 {
// invariant: a and b have same length
c := 0.0
for i, _ := range a {
c += math.Pow(b[i]-a[i], 2)
}
return math.Sqrt(c)
}
然后是三种类型安全的方法:
'use strict';
// SystemJS configuration file, see links for more information
// https://github.com/systemjs/systemjs
// https://github.com/systemjs/systemjs/blob/master/docs/config-api.md
/***********************************************************************************************
* User Configuration.
**********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
'moment': 'vendor/moment/moment.js',
'ng2-bootstrap': 'vendor/ng2-bootstrap'
};
/** User packages configuration. */
const packages: any = {
'moment': {
format: 'cjs'
},
'ng2-bootstrap': {
format: 'cjs',
defaultExtension: 'js',
main: 'ng2-bootstrap.js'
}
};
////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
* Everything underneath this line is managed by the CLI.
**********************************************************************************************/
const barrels: string[] = [
// Angular specific barrels.
'@angular/core',
'@angular/common',
'@angular/compiler',
'@angular/forms',
'@angular/http',
'@angular/router',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
// Thirdparty barrels.
'rxjs',
// App specific barrels.
'app',
'app/shared',
'app/photos'
/** @cli-barrel */
];
const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
cliSystemConfigPackages[barrelName] = { main: 'index' };
});
/** Type declaration for ambient System. */
declare var System: any;
// Apply the CLI SystemJS configuration.
System.config({
map: {
'@angular': 'vendor/@angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js'
},
packages: cliSystemConfigPackages
});
// Apply the user's configuration.
System.config({ map, packages });
所以,一个时间点可以是OneVectorer,笛卡尔点是TwoVectorer,依此类推......
您可以根据自己的需要定义更多类型,以使程序更具表现力,并在其方法中映射到此向量算法。