Re: Scripting with Variant from std.variant: parameter passing

2024-02-03 Thread Carl Sturtivant via Digitalmars-d-learn

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.


Re: Scripting with Variant from std.variant: parameter passing

2024-02-03 Thread Anonymouse via Digitalmars-d-learn

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?


Re: Scripting with Variant from std.variant: parameter passing

2024-02-03 Thread Danilo via Digitalmars-d-learn

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:
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));
}
```


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`.


Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Paul Backus via Digitalmars-d-learn

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:

```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.


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");
}
```


Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Carl Sturtivant via Digitalmars-d-learn
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





Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Anonymouse via Digitalmars-d-learn

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));
}
```


Re: Scripting with Variant from std.variant: parameter passing

2024-02-02 Thread Danilo via Digitalmars-d-learn

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!") );
}
```