Open debilosaurus opened 7 months ago
I have found a fix, but I am still thinking that some "autocast" feature dont work properly:
Change:
println(v.generic_new(math.abs)) // error
To:
math_abs := fn (s f64) f64 { return math.abs(s) }
println(v.generic_new(math_abs)) // fix with new function
Again: This is no priority bug, maybe it isn't an issue at all. But here is another hint why I think that there must be casting issues; this time with an interface type.
Backround: For testing purposes with signed distance functions I wrote my own vector implementation. Then I tried to reduce the code to the absolute minimum - with interfaces . my goal is to generalize it in a simple way to more dimensions or other implementations (eg. array). But vlang sometimes is a beast ...
// vlang test, reduced for git:
// - vector operations (example) build with an interface
// - derive functions for a group of basic types
// questions:
// - how to use interface methods withou an additional cast
// - where are casts or generic types missing
module main
// scalar, basic type
type Scalar = f64
// basic function, not build as method, needed as arg
fn add_scalar(s1 Scalar, s2 Scalar) Scalar {
return s1 + s2
}
// vector, interface an derived functions
interface Vector {
libs (fn (Scalar, Scalar) Scalar) Scalar
// lib2 (Vector, fn (Scalar, Scalar) Scalar) Vector
}
// derived method 1
fn (v Vector) sum() Scalar {
return v.libs(add_scalar)
}
/* // derived method 2
fn (v1 Vector) add(v2 Vector) Vector {
return v1.lib2(v2, add_scalar)
}
*/
// vec3, representation of the interface
type Vec3 = struct {
x Scalar
y Scalar
z Scalar
}
// basic method a, safisfies the interface type
fn (v Vec3) libs(f fn (Scalar, Scalar) Scalar) Scalar {
return f(v.x, f(v.y, v.z))
}
/* // interface method b, safisfies the interface type
fn (v1 Vec3) lib2(v2 Vec3, f fn (Scalar, Scalar) Scalar) Vec3 {
//fn (v1 Vec3) lib2(v2 Vector, f fn (Scalar, Scalar) Scalar) Vector {
return Vec3{f(v1.x, v2.x), f(v1.y, v2.y), f(v1.z, v2.z)}
}
*/
fn main() {
println('### start')
// define a vector
v := Vec3{1, 2, 3}
// check if "Vec3" satifies the interface "Vector" -> ok
println(Vector(v))
// try method of type with fn as arg -> ok
println(v.libs(add_scalar))
// try methods of interface -> explicit cast needed, why?
// println(v.sum()) // should work
println(Vector(v).sum()) // but only works with a cast
// try methods of interface -> error
// - "Vec3" as args produce "unknown method Vec3.sum/add"
// - "Vector" as args produce "no field name x/y/z"
// println(v.add(v))
// the goal, concat
// println(v.add(v).add(v))
println('### end')
}
After some time spending to other things, I tried to find the cause of this behavior. I hope this helps to improve your language.
// vlang test, reduced for git:
// - vector operations (example) build with an interface
// - derive functions for a group of basic types
// questions/problems:
// - the compiler assumes initially that a type dont satisfies an interface,
// and so he cant solve references to the type itself
// - interface methods should work without an additional cast
module main
// scalar, basic type
type Scalar = f64
// basic function, not build as method, needed as arg
fn add_scalar(s1 Scalar, s2 Scalar) Scalar {
return s1 + s2
}
// vector, interface and derived functions
interface Vector {
elem (int) Scalar // dependency of an additional method
libs (fn (Scalar, Scalar) Scalar) Scalar
lib2 (Vector, fn (Scalar, Scalar) Scalar) Vector
}
// derived method 1
fn (v Vector) sum() Scalar {
return v.libs(add_scalar)
}
// derived method 2
fn (v1 Vector) add(v2 Vector) Vector {
return v1.lib2(v2, add_scalar)
}
// vec3, representation of the interface
//type Vec3 = struct { // syntax change?
struct Vec3 {
x Scalar
y Scalar
z Scalar
}
// problem 1: additional method needed, because v assumes a "not-satisfying"
fn (v Vec3) elem(i int) Scalar {
if i == 1 { return v.x }
if i == 2 { return v.y }
if i == 3 { return v.z }
return Scalar(0.0)
}
// basic method a, safisfies the interface type
fn (v Vec3) libs(f fn (Scalar, Scalar) Scalar) Scalar {
return f(v.x, f(v.y, v.z))
}
// interface method b, safisfies the interface type
//fn (v1 Vec3) lib2(v2 Vec3, f fn (Scalar, Scalar) Scalar) Vec3 {
//fn (v1 Vec3) lib2(v2 Vec3, f fn (Scalar, Scalar) Scalar) Vector {
fn (v1 Vec3) lib2(v2 Vector, f fn (Scalar, Scalar) Scalar) Vector {
// this failes, because it is assumed that it does NOT satisfies the interface
//return Vec3{f(v1.x, v2.x), f(v1.y, v2.y), f(v1.z, v2.z)}
// so a function is needed, even if we know how to address the elements for this type
return Vec3{f(v1.elem(1), v2.elem(1)), f(v1.elem(2), v2.elem(2)), f(v1.elem(3), v2.elem(3))}
}
fn main() {
println('### start')
// define a vector
v := Vec3{1, 2, 3}
// check if "Vec3" satifies the interface "Vector" -> ok
println(Vector(v))
// try method of type with fn as arg -> ok
println(v.libs(add_scalar))
// try methods of interface -> explicit cast needed, why?
// println(v.sum()) // should work
println(Vector(v).sum()) // problem 2: only works with a cast
// try methods of interface -> error
// - "Vec3" as args produce "unknown method Vec3.sum/add"
// - "Vector" as args produce "no field name x/y/z"
// println(v.add(v)) // should work
println(Vector(v).add(v)) // problem 2: only works with a cast
// the goal, concat/mix own/derived methods
// println(v.add(v).add(v)) // should work
println(Vector(v).add(v).add(v)) // problem 2: only works with a cast
println('### end')
}
Describe the bug
I am not 100% shure if this is bug, but I am not able to create a function with another function (from a std library) as argument. In my opinion this should work, but everything I tried didnt. Ths snipped is the most basic one. I tried with setting the generic to "f64" (the error message than refers surprisingly to the module like "math.f64"), or try to cast the function type (more errors of course).
I hope that I have made a mistake, but this type of functions would be very helpfull to avoid unnecessary (escecially for lazy people like me).
Reproduction Steps
Code: https://play.vlang.io/p/0a82f72d9f
Expected Behavior
No error and the same result for "abs_oldstyle()" and "generic_new(math.abs)".
Current Behavior
Output:
Possible Solution
No response
Additional Information/Context
No response
V version
V 0.4.5 872bcbc
Environment details (OS name and version, etc.)