digitalmars.D.learn - Scripting with Variant from std.variant: parameter passing
- Carl Sturtivant (3/3) Feb 02 It seems I cannot pass e.g. an int argument to a Variant function
- Danilo (13/16) Feb 02 Just tell the compiler clearly what you want.
- Anonymouse (24/27) Feb 02 The easiest thing would be to actually pass it a `Variant` with
- Danilo (7/35) Feb 03 To be honest, this doesn't make sense.
- Anonymouse (58/65) Feb 03 I read it several times but I don't think I understand what you
- Steven Schveighoffer (26/29) Feb 02 You'd have to implement the function that accepts the parameters
- Carl Sturtivant (3/24) Feb 02 Thanks for this idea. I'll work on it.
- Paul Backus (38/48) Feb 02 Another variation on the same theme:
- Carl Sturtivant (2/28) Feb 03 Thanks, will study the library machinery you used here.
It seems I cannot pass e.g. an int argument to a Variant function parameter. What's the simplest way to work around this restriction?
Feb 02
On Friday, 2 February 2024 at 08:22:42 UTC, Carl Sturtivant wrote:It seems I cannot pass e.g. an int argument to a Variant function parameter. What's the simplest way to work around this restriction?Just tell the compiler clearly what you want. ```d import std; void f(Variant x) { writeln(x); } void main() { f( Variant(42) ); f( Variant(2.5) ); f( Variant("Hi!") ); } ```
Feb 02
On Friday, 2 February 2024 at 08:22:42 UTC, Carl Sturtivant wrote:It seems I cannot pass e.g. an int argument to a Variant function parameter. What's the simplest way to work around this restriction?The easiest thing would be to actually pass it a `Variant` with `someFunction(Variant(myInt))`. The more-involved thing would be to write a template constrained to non-`Variants` that does the above for you. ```d auto someFunction(T)(T t) if (!is(T : Variant)) { return someFunction(Variant(t)); } auto someFunction(Variant v) { // ... } void main() { someFunction(42); someFunction("hello"); someFunction(3.14f); someFunction(true); someFunction(Variant(9001)); } ```
Feb 02
On Friday, 2 February 2024 at 11:31:09 UTC, Anonymouse wrote:On Friday, 2 February 2024 at 08:22:42 UTC, Carl Sturtivant wrote:To be honest, this doesn't make sense. `if (!is(T : Variant))` returns true for inputs like 42, "hello", 3.14f, but the input is not a Variant but a random type. Yes, it's nice that it works in this case. It's just not logical, it doesn't make sense because 42 just simply isn't a Variant, it's an `int`.It seems I cannot pass e.g. an int argument to a Variant function parameter. What's the simplest way to work around this restriction?The easiest thing would be to actually pass it a `Variant` with `someFunction(Variant(myInt))`. The more-involved thing would be to write a template constrained to non-`Variants` that does the above for you. ```d auto someFunction(T)(T t) if (!is(T : Variant)) { return someFunction(Variant(t)); } auto someFunction(Variant v) { // ... } void main() { someFunction(42); someFunction("hello"); someFunction(3.14f); someFunction(true); someFunction(Variant(9001)); } ```
Feb 03
On Saturday, 3 February 2024 at 08:04:40 UTC, Danilo wrote:To be honest, this doesn't make sense. `if (!is(T : Variant))` returns true for inputs like 42, "hello", 3.14f, but the input is not a Variant but a random type. Yes, it's nice that it works in this case. It's just not logical, it doesn't make sense because 42 just simply isn't a Variant, it's an `int`.I read it several times but I don't think I understand what you mean. The constraint `if (!is(T : Variant))` is true for every input that is not a `Variant`, yes. The point of it is to let calls to `someFunction(myVariant)` resolve to the non-templated `auto someFunction(Variant)`. Is your argument that it's wrong to assume an `int` *can be* wrapped in a `Variant`, because it isn't one? That in turn doesn't make sense -- your example does the same, just explicitly. ```d void main() { f( Variant(42) ); f( Variant(2.5) ); f( Variant("Hi!") ); } ``` How is this different from the following? ```d void main() { (v){ f(Variant(v)); }(42); (v){ f(Variant(v)); }(2.5); (v){ f(Variant(v)); }("Hi!"); } ``` And how is that different from the following? ```d void main() { auto g(T)(T t) { f(Variant(t)); } g(42); g(2.5); g("Hi!"); } ``` Which is in what way different from the following? ```d auto g(T)(T t) if (!is(T : Variant)) { return f(Variant(t)); } auto f(Variant v) { // ... } void main() { g(42); g("hello"); g(3.14f); g(true); } ``` And how is that not the same as my original example?
Feb 03
On Friday, 2 February 2024 at 08:22:42 UTC, Carl Sturtivant wrote:It seems I cannot pass e.g. an int argument to a Variant function parameter. What's the simplest way to work around this restriction?You'd have to implement the function that accepts the parameters and wraps in a Variant. This is the best I can come up with, which should be copy/pasteable to other shims: ```d void foo(Variant x, Variant y) { ... } import std.meta : allSatisfy; enum isVariant(T) = is(T == Variant); // this is going to suck at CTFE but... string argsAsVariants(size_t count) { import std.format; import std.range; import std.alglorithm; import std.array; return iota(count).map!(i => format("Variant(args[%s])", i).join(","); } // shim auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args)) { mixin("return foo(", argsAsVariants(args.length), ");"); } ``` -Steve
Feb 02
On Friday, 2 February 2024 at 19:22:22 UTC, Steven Schveighoffer wrote:```d void foo(Variant x, Variant y) { ... } import std.meta : allSatisfy; enum isVariant(T) = is(T == Variant); // this is going to suck at CTFE but... string argsAsVariants(size_t count) { import std.format; import std.range; import std.alglorithm; import std.array; return iota(count).map!(i => format("Variant(args[%s])", i).join(","); } // shim auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args)) { mixin("return foo(", argsAsVariants(args.length), ");"); } ```Thanks for this idea. I'll work on it.-Steve
Feb 02
On Friday, 2 February 2024 at 20:28:50 UTC, Carl Sturtivant wrote:On Friday, 2 February 2024 at 19:22:22 UTC, Steven Schveighoffer wrote:Another variation on the same theme: ```d void foo(Variant x, Variant y) { import std.stdio: writeln; writeln("x = ", x); writeln("y = ", y); } /// map over a variadic argument list template mapArgs(alias fun) { auto mapArgs(Args...)(auto ref Args args) { import std.typecons: tuple; import core.lifetime: forward; import std.meta: Map = staticMap; auto ref mapArg(alias arg)() { return fun(forward!arg); } return tuple(Map!(mapArg, args)); } } import std.variant: Variant; import std.meta: allSatisfy; enum isVariant(T) = is(T == Variant); auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args)) { return .foo(mapArgs!Variant(args).expand); } void main() { foo(123, 456); foo("hello", "world"); } ``````d // shim auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args)) { mixin("return foo(", argsAsVariants(args.length), ");"); } ```Thanks for this idea. I'll work on it.
Feb 02
On Friday, 2 February 2024 at 20:58:12 UTC, Paul Backus wrote:Another variation on the same theme: ```d /// map over a variadic argument list template mapArgs(alias fun) { auto mapArgs(Args...)(auto ref Args args) { import std.typecons: tuple; import core.lifetime: forward; import std.meta: Map = staticMap; auto ref mapArg(alias arg)() { return fun(forward!arg); } return tuple(Map!(mapArg, args)); } } import std.variant: Variant; import std.meta: allSatisfy; enum isVariant(T) = is(T == Variant); auto foo(Args...)(Args args) if (!allSatisfy!(isVariant, Args)) { return .foo(mapArgs!Variant(args).expand); } ```Thanks, will study the library machinery you used here.
Feb 03