Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type-casting issue when providing a generic function as argument. #21132

Open
debilosaurus opened this issue Mar 28, 2024 · 2 comments
Open

Type-casting issue when providing a generic function as argument. #21132

debilosaurus opened this issue Mar 28, 2024 · 2 comments
Labels
Bug This tag is applied to issues which reports bugs. Generics[T] Bugs/feature requests, that are related to the V generics. Status: Confirmed This bug has been confirmed to be valid by a contributor. Unit: Checker Bugs/feature requests, that are related to the type checker. Unit: Compiler Bugs/feature requests, that are related to the V compiler in general.

Comments

@debilosaurus
Copy link

debilosaurus commented Mar 28, 2024

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

// function-as-argument to reduce code

import math

type Vec5 = struct {
	x f64
	y f64
	z f64
	a f64
	b f64
}

fn from(s f64) Vec5 {
	return Vec5{s, s, s, s, s}
}

fn (v Vec5) abs_oldstyle() Vec5 {
	return Vec5{math.abs(v.x), math.abs(v.y), math.abs(v.z), math.abs(v.a), math.abs(v.b)}
}

fn (v Vec5) generic_new(f fn (f64) f64) Vec5 {
	return Vec5{f(v.x), f(v.y), f(v.z), f(v.a), f(v.b)}
}

fn main() {
	println('### start')

	mut v := from(-1)
	println(v)
	println(v.abs_oldstyle()) // ok
	// error: cannot use `fn (T) T` as `fn (f64) f64` in argument 1 to `Vec5.generic`
	println(v.generic_new(math.abs)) // error

	println('### end')
}

Expected Behavior

No error and the same result for "abs_oldstyle()" and "generic_new(math.abs)".

Current Behavior

Output:

code.v:32:23: error: cannot use `fn (T) T` as `fn (f64) f64` in argument 1 to `Vec5.generic_new`
   30 |     println(v.abs_oldstyle()) // ok
   31 |     // error: cannot use `fn (T) T` as `fn (f64) f64` in argument 1 to `Vec5.generic`
   32 |     println(v.generic_new(math.abs)) // error
      |                          ~~~~~~~~
   33 | 
   34 |     println('### end')
Exited with error status 1

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.4.5 872bcbc

Environment details (OS name and version, etc.)

V full version: V 0.4.5 872bcbc
OS: linux, Debian GNU/Linux 11 (bullseye) (VM)
Processor: 1 cpus, 64bit, little endian, Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

getwd: /home/admin/playground
vexe: /home/admin/v/v
vexe mtime: 2024-03-28 12:23:26

vroot: OK, value: /home/admin/v
VMODULES: OK, value: .vmodules
VTMP: OK, value: /tmp/v_0

Git version: git version 2.30.2
Git vroot status: Error: fatal: detected dubious ownership in repository at '/home/admin/v'
To add an exception for this directory, call:

	git config --global --add safe.directory /home/admin/v
.git/config present: true

CC version: cc (Debian 10.2.1-6) 10.2.1 20210110
thirdparty/tcc status: Error: fatal: detected dubious ownership in repository at '/home/admin/v/thirdparty/tcc'
To add an exception for this directory, call:

	git config --global --add safe.directory /home/admin/v/thirdparty/tcc
 Error: fatal: detected dubious ownership in repository at '/home/admin/v/thirdparty/tcc'
To add an exception for this directory, call:

	git config --global --add safe.directory /home/admin/v/thirdparty/tcc

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

@debilosaurus debilosaurus added the Bug This tag is applied to issues which reports bugs. label Mar 28, 2024
@debilosaurus
Copy link
Author

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

@debilosaurus
Copy link
Author

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')
}

@spytheman spytheman changed the title Type-casting issue when providing a function as argument. Type-casting issue when providing a generic function as argument. Mar 31, 2024
@spytheman spytheman added Generics[T] Bugs/feature requests, that are related to the V generics. Unit: Checker Bugs/feature requests, that are related to the type checker. Unit: Compiler Bugs/feature requests, that are related to the V compiler in general. Status: Confirmed This bug has been confirmed to be valid by a contributor. labels Mar 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug This tag is applied to issues which reports bugs. Generics[T] Bugs/feature requests, that are related to the V generics. Status: Confirmed This bug has been confirmed to be valid by a contributor. Unit: Checker Bugs/feature requests, that are related to the type checker. Unit: Compiler Bugs/feature requests, that are related to the V compiler in general.
Projects
None yet
Development

No branches or pull requests

2 participants