Re: Making one struct work in place of another for function calls.

2024-04-16 Thread Paul Backus via Digitalmars-d-learn
On Wednesday, 17 April 2024 at 01:36:59 UTC, Liam McGillivray 
wrote:
To better understand what I mean, take the following example, 
where I have a function, and two structs.

```
struct typeA {
// Some member variables here
}

struct typeB {
// Some similar member variables here, but in a different 
format

}

float someFunction(typeB input) {
// Does some stuff
// Returns result
}
```

If I want to be able to call `someFunction` (or any function 
with `TypeB` as a parameter) using `TypeA` in place of `TypeB`, 
and I'm willing to modify the definition of `TypeA`, I know 
that I can add an `opCast` and `alias this = opCast!TypeB` to 
`TypeA`.


But what if `typeA` is in an external library? Is there any way 
I can get `someFunction` (and any function with a `typeB` 
parameter) to accept `typeA`, only modifying the definition of 
`TypeB` (and possibly adding a single global line in it's 
module)?


This is called [row polymorphism][1], and it does not exist in D.

You could approximate it by making `someFunction` a template, and 
accepting any type `T` that has the necessary members instead of 
only accepting `typeB`. But this is only possible if you are free 
to modify the definition of `someFunction`.


[1]: https://en.wikipedia.org/wiki/Row_polymorphism


Re: Why does disabling a struct's postblit increase its size in memory?

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

On Saturday, 2 March 2024 at 19:29:47 UTC, Per Nordlöw wrote:

On Saturday, 2 March 2024 at 19:28:08 UTC, Per Nordlöw wrote:

On Saturday, 2 March 2024 at 19:11:42 UTC, kinke wrote:
Not according to run.dlang.io, for all available DMD 
versions. Perhaps your tested `S` was nested in some 
function/aggregate and so had an implicit context pointer.


Ahh. Yes. Indeed. My mistake. Thanks.


Thanks. Neither my websearches nor ChatGPT plus couldn't figure 
that out.


FYI, you can dump the layout of a struct, including hidden 
fields, by iterating over its `.tupleof` property:


```d
void main()
{
struct S
{
@disable this(this);
int n;
}

static foreach (field; S.tupleof)
pragma(msg,
typeof(field).stringof, " ",
__traits(identifier, field), " ",
"at ", field.offsetof
);
}
```

This example prints out

```
int n at 0LU
void* this at 8LU
```


Re: Error when using `import`.

2024-02-24 Thread Paul Backus via Digitalmars-d-learn
On Saturday, 24 February 2024 at 10:31:06 UTC, Liam McGillivray 
wrote:


`Unit.d` & `Map.d` are longer files. `Map.d` begins with 
`import Tile;`, and `Unit.d` begins with `import Map;`.


Why are the errors happening? What's the problem? Why is it 
`currentclass.importedclass` instead of simply the imported 
class?


You can't give a class the same name as the file it's in. If you 
do, then when you try to use it from another file, the compiler 
will get confused and think you're referring to the file instead 
of the class (that's what "import is used as a type" means).


The easiest way around this is to change the name of the file to 
lower case. So, for example, you could change the name of the 
file with the `Unit` class in it to `unit.d`, and then write 
`import unit;` to access it from your other files.


Re: Circular enum member references in UDAs

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

On Thursday, 15 February 2024 at 18:12:42 UTC, realhet wrote:

Hello,

Today I tried to upgrade my sources to the latest LDC, but 
failed with this unfortunate error.


```
import std;

struct S{ E e; }

enum E
{
@S(e2) e1,
@S(e1) e2
}
```


Looks like someone reported a similar bug in 2018:

https://issues.dlang.org/show_bug.cgi?id=17656

There was an attempt to fix it, but it looks like the PR author 
wasn't able to get it working correctly in all cases.


Re: std.uni CodepointSet toString

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

On Friday, 9 February 2024 at 08:04:28 UTC, Danilo wrote:

Incredible! Seems like D is experiencing featuritis.
Priorities may be wrong.

Instead of bug fixing and stabilization, people concentrate on
getting new stuff like ˋ:blubˋ into the language.


If you look at the work actually being done in Github PRs, the 
vast majority of it is bug fixes and stabilization:


https://github.com/dlang/dmd/pulls?q=is%3Apr+is%3Amerged
https://github.com/dlang/phobos/pulls?q=is%3Apr+is%3Amerged

However, new features are more exciting to talk about, so they 
get more attention on the forums.


Re: real.sizeof

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

On Monday, 5 February 2024 at 16:45:03 UTC, Dom DiSc wrote:

Why is real.sizeof == 16 on x86-systems?!?
Its the IEEE 754 extended format: 64bit mantissa + 15bit 
exponent + sign.

It should be size 10!
I mean, alignment may be different, but why wasting so much 
memory even in arrays?


According to the language spec, `real` is the ["largest floating 
point size available"][1]. This means that on some systems, it's 
actually an IEEE 754 128-bit quadruple-precision float, not an 
x87 80-bit extended-precision float.


You can verify this by compiling the following test program:

pragma(msg, "real is ", cast(int) real.sizeof*8, " bits");
pragma(msg, "real has a ", real.mant_dig, "-bit mantissa");

On my laptop (Linux, x86_64), compiling this program with `dmd 
-c` prints


real is 128 bits
real has a 64-bit mantissa

[1]: https://dlang.org/spec/type.html#basic-data-types


Re: template/mixin magic for to! auto inferring type from variable

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

On Friday, 2 February 2024 at 23:25:37 UTC, Chris Katko wrote:
The auto solution won't work for a struct however which I'm 
using:


```D
struct procTable{ //contains all the fields inside a file I'm 
parsing

   uint time;
   int priority;
   string name;
   // etc
   }
```


Maybe you can use `typeof` in that case?

```d
procTable pt;
pt.time = to!(typeof(pt.time))(data[1]);
// etc
```

...although I guess then you're repeating the field name, which 
isn't great either.


You could avoid the repetition by wrapping the above pattern up 
in a helper function, though:


```d
void convertAssign(Dest, Value)(ref Dest dest, Value value)
{
import std.conv;
dest = to!Dest(value);
}

void main()
{
string[3] data = ["100", "-5", "foobar"];

uint time;
int priority;
string name;

time.convertAssign(data[0]);
priority.convertAssign(data[1]);
name.convertAssign(data[2]);

assert(time == 100);
assert(priority == -5);
assert(name == "foobar");
}
```


Re: template/mixin magic for to! auto inferring type from variable

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

On Friday, 2 February 2024 at 07:43:09 UTC, Chris Katko wrote:

Is there some way to do:
```D
string[3] data; //strings from some file input, some are ints, 
uints, etc.


auto into!(T)(T value){return to!???(value); } // ???

uint time = into!(data[1]); // We already know this is uint
int priority = into!(data[2]);
```

instead of:
```D
uint time = to!uint(data[1]); // specifying type twice
int priority = to!int(data[2])
```


No, D only does bottom-up type inference, not top down.

If you want to avoid repeating the type, use `auto` on the left 
side:


```d
auto time = to!uint(data[1]);
auto priority = to!int(data[2]);
```


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: Safety is not what you think

2024-01-30 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 30 January 2024 at 02:05:23 UTC, user1234 wrote:
I want to share a stupid program to show you that D safety is 
more complex than you might think:


```d
module test;

void test() @safe
{
int i;
int b = (*&(*&++i))++;
}

void main() @safe
{
test();
}
```

I'm not showing a deficiency of D, that program is undeniably 
safe ;)


I'm surprised `&++i` even compiles in the first place, but 
looking at [the spec][1], it seems to be intentional:


The following expressions, and no others, are called lvalue 
expressions or lvalues:


[...]
4. the result of the following expressions:
   * built-in unary operators + (when applied to an lvalue), *, 
++ (prefix only), -- (prefix only);


Testing it out, the address you get is the same as ``.

This definitely isn't allowed in C or C++. I wonder what the 
rationale is for having this behavior in D?


[1]: https://dlang.org/spec/expression.html


Re: Function Composition

2024-01-25 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 25 January 2024 at 08:25:02 UTC, atzensepp wrote:

```d
  int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f);
```

This leads to:
```
gdc lambda4.d
lambda4.d:28:25: error: template compose(E)(E a) has no value
   int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f);

```


Try using the address operator:

//  Here
//▼
int function(int) t = !(f,g,g,f,g,g,f,g,g,f);


Re: opApply + const

2024-01-23 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 16:11:25 UTC, ryuukk_ wrote:
It works fine.. but when the variable becomes ``const(Stuff)* 
stuff;``


It gives me:

```
onlineapp.d(13): Error: cannot uniquely infer `foreach` 
argument types

```

I have no idea what i should be doing, does anyone have a clue?


https://issues.dlang.org/show_bug.cgi?id=24353


Re: std.sumtype nested SumTypes

2024-01-22 Thread Paul Backus via Digitalmars-d-learn

On Monday, 22 January 2024 at 21:11:17 UTC, NonNull wrote:


I'd like SumType to combine the implicit tags so there's only 
one tag.


SumType does not do this automatically (because sometimes you 
might want to keep the inner SumTypes separate), but you can do 
it yourself like this:


alias A = SumType!(X, Y);
alias B = SumType!(Z, W);
alias C = SumType!(A.Types, B.Types);


Re: compute from a string the text of a string literal

2024-01-17 Thread Paul Backus via Digitalmars-d-learn
On Wednesday, 17 January 2024 at 18:44:14 UTC, Carl Sturtivant 
wrote:

Hello,
I'd like a function like this,
```
string image(string s)
```
that maps any string s into the doubly quoted backslash escaped 
text that would be a string literal for s were it pasted into a 
program. Perhaps with a second parameter with detailed options.


Is there something out there I could use?


There's a function that does this in Phobos, but it's `private`. 
Currently, the only way to access it is by calling `to!string` or 
`format` on a range that contains the string you want to convert 
as an element:


```d
void main()
{
import std.range, std.conv, std.stdio;

string s = `"foo"\bar`;
string escaped = only(s).to!string[1 .. $-1]; // slice off [ 
and ]

writeln(escaped); // "\"foo\"\\bar"
}
```


Re: Generating custom toString for structs

2024-01-07 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 7 January 2024 at 09:49:36 UTC, Renato wrote:

Is the above a "good" way to do this?


It looks ok to me. There are some minor changes I would make, 
like using `typeof(this)` instead of `S` to refer to the type of 
the struct you're mixing it into, but the overall approach is 
fine.


Are there libraries (or even something in Phobos?) that already 
provide some mixins or equivalent functionality?


For reference, I wanted something like Java [Lombok's ToString 
annotation](https://projectlombok.org/features/ToString), also 
present in 
[Groovy](https://docs.groovy-lang.org/latest/html/gapi/groovy/transform/ToString.html).


The [`boilerplate` package][1] has a [`GenerateToString` 
mixin][2] that looks pretty similar to the examples you linked.


[1]: https://code.dlang.org/packages/boilerplate
[2]: 
https://boilerplate.dpldocs.info/v1.9.1/boilerplate.autostring.GenerateToString.html


Re: Trying to understand map being a template

2024-01-06 Thread Paul Backus via Digitalmars-d-learn

On Friday, 5 January 2024 at 20:41:53 UTC, Noé Falzon wrote:
In fact, how can the template be instantiated at all in the 
following example, where no functions can possibly be known at 
compile time:


```
auto do_random_map(int delegate(int)[] funcs, int[] values)
{
auto func = funcs.choice;
return values.map!func;
}
```

Thank you for the insights!


It works for the same reason this example works:

```d
void printVar(alias var)()
{
import std.stdio;
writeln(__traits(identifier, var), " = ", var);
}

void main()
{
int x = 123;
int y = 456;

printVar!x; // x = 123
printVar!y; // y = 456
x = 789;
printVar!x; // x = 789
}
```


Re: Problems using rawWrite in an experiment with WAVs in D

2023-12-27 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 27 December 2023 at 20:20:23 UTC, tososdk wrote:

I was recreating some code from C++ to D:

[...]
But since I am somewhat new to these topics and even more so to 
Dlang, I don't understand very well. The problem occurs in the 
creation of the .wav, regarding rawWrite, I'm not really sure 
what to do in that specific part. Maybe I'm ignorant, but I'm 
not very good at these topics, plus it's for experimentation.


Here's the error message I got when I tried to compile your code:

```
Error: template `std.stdio.File.rawWrite` is not callable using 
argument types `!()(WavHeader)`
/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(1273):
Candidate is: `rawWrite(T)(in T[] buffer)`

```

What this message is saying is that you tried to pass a 
`WavHeader` to `rawWrite`, but `rawWrite` expects a slice (`T[]`, 
where `T` can be any type) as an argument.


The easiest way to fix this is to use [pointer slicing][1] to 
create a temporary slice that points to `wavh`:


```d
  file.rawWrite(()[0 .. 1]);
```

[1]: https://dlang.org/spec/expression.html#slice_expressions


Re: Something similar to "inline"

2023-12-27 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 27 December 2023 at 15:57:14 UTC, tososdk wrote:
Two things: Could you explain how "inline" works? Is there 
something similar in Dlang?


In C and C++, `inline` is a suggestion to the compiler that it 
should consider using [inline expansion][1] for calls to a 
particular function. However, the compiler is free to ignore this 
suggestion, and is also free to use inline expansion for 
functions that are not marked with `inline`.


In D, the closest equivalent is [`pragma(inline)`][2], which can 
be used to enable or disable inline expansion for a particular 
function. With `pragma(inline, true)`, the function will *always* 
be expanded inline; with `pragma(inline, false)`, it will *never* 
be expanded.


[1]: https://en.wikipedia.org/wiki/Inline_expansion
[2]: https://dlang.org/spec/pragma.html#inline


Re: Permutations of array (slice) ?

2023-12-12 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 12 December 2023 at 14:57:48 UTC, Kevin Bailey wrote:
perm.d:8:26: error: none of the overloads of template 
‘std.algorithm.iteration.permutations’ are callable using 
argument types ‘!()(char[])’

8 | foreach (perm; as.permutations)
  |  ^
/usr/lib/gcc/x86_64-linux-gnu/13/include/d/std/algorithm/iteration.d:7919:20: 
note: Candidate is: ‘permutations(Range)(Range r)’
 with `Range = char[]`
  must satisfy the following constraint:
`   isRandomAccessRange!Range`
 7919 | Permutations!Range permutations(Range)(Range r)
  |^


Because of autodecoding [1], slices of char and wchar are treated 
by Phobos as bidirectional ranges of dchar. (They are not 
random-access ranges because UTF-8 and UTF-16 are variable-length 
encodings.)


To work around this, use std.utf.byChar:

import std.utf: byChar;
foreach (perm; as.byChar.permutations)
writeln(perm);

[1] 
http://ddili.org/ders/d.en/ranges.html#ix_ranges.decoding,%20automatic


Re: opApply seems like it can infer delegate types AND parameters!?

2023-12-11 Thread Paul Backus via Digitalmars-d-learn

On Monday, 11 December 2023 at 23:21:45 UTC, Quirin Schroll wrote:
I always thought you had to provide aliases with all 16 
combinations of the attributes `@safe`, `@nogc`, `pure`, and 
`nothrow` for each actually desired instance. But you don’t and 
**I have no clue why**.


Why does it work?


Truly bizarre. I can't think of any explanation other than a 
compiler bug. Probably not a good idea to rely on this, even if 
the result is pretty handy.


Re: struct initializer

2023-12-01 Thread Paul Backus via Digitalmars-d-learn

On Friday, 1 December 2023 at 13:02:06 UTC, Dom DiSc wrote:

```d
S Fun(){ return { 5, 2 }; }
```

This IS an initialization and the type is known. Requiring the 
repetition of the type is also here annoying.


Technically you don't *have* to repeat the type. You can write 
the return type as `auto`:


```d
auto fun() { return S(5, 2); }
```

Or you can use `typeof(return)`:

```d
SomeReallyLongReturnType fun()
{
return typeof(return)(5, 2);
}
```


Re: struct initializer

2023-11-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 17:23:04 UTC, Antonio wrote:
On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus 
wrote:

... it even supports named arguments:


- Witch version of DMD supports named arguments?  Is it an 
experimental compiler option?


I don't know what the earliest version is that supports it, but I 
know the example I posted works in 2.105. It doesn't require any 
compiler options.


Named arguments are still a work in progress, and there are some 
situations where they aren't available (for example, I don't 
think they work for templates yet). With struct literals, though, 
you shouldn't have any problems using them.


Re: struct initializer

2023-11-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:38:36 UTC, Dom DiSc wrote:

```d
struct S2 { int a; int b; this(int c, int d) { a=c; b=d; } }

S2 fun3() { return S2( 5, 2 ); } // works but requires explicit 
constructor

```


You can use this syntax without an explicit constructor:

struct S3 { int a; int b; }

S3 fun() { return S3(5, 2); }

The language spec calls this a [struct literal][1]. If you're 
using a new enough compiler, it even supports named arguments:


S3 fun2() { return S3(b: 2, a: 5); }

[1]: https://dlang.org/spec/struct.html#struct-literal


Re: mixin issue

2023-11-29 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 13:31:14 UTC, DLearner wrote:

```
Error: found `End of File` when expecting `;` following 
statement

```

If an extra ; is added:
```
   }(` ~ strStartPtr ~ `,` ~ strPLPtr ~ `);`;
```

it works but doesn't seem correct.


This is an annoying limitation of the D compiler.

The root of the problem is that there is an ambiguity in D's 
grammar. When the compiler sees


mixin(whatever);

...it cannot tell whether it's supposed to be a [Mixin 
Statement][1], or an [Expression Statement][2] that contains a 
[Mixin Expression][3].


If it's a Mixin Statement, then there should be a semicolon 
inside the mixin. If it's an Expression Statement with a Mixin 
Expression, then there shouldn't be a semicolon inside the mixin.


To resolve this ambiguity, the compiler (currently) *assumes* 
that it's always a Mixin Statement, which means that it will 
always require a semicolon inside the mixin.


As a result, it is impossible to write a string mixin that can be 
used as both a statement and an expression.


If you have an expression mixin and you would like to use it as a 
statement, you can work around this limitation by adding 
`cast(void)` in front of the mixin:


cast(void) mixin(whatever);

This forces the compiler to parse the line as an Expression 
Statement containing a [Cast Expression][4], but does not 
otherwise change the meaning of the code.


[1]: https://dlang.org/spec/statement.html#mixin-statement
[2]: https://dlang.org/spec/statement.html#expression-statement
[3]: https://dlang.org/spec/expression.html#mixin_expressions
[4]: https://dlang.org/spec/expression.html#cast_expressions


Re: interface inference

2023-11-28 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 23 November 2023 at 19:17:20 UTC, Antonio wrote:
Basically, the ternary conditional ```?:``` result type is not 
inferred even if the type returned by the two possibilities are 
the same.


**Is it a bug or the expected behaviour?**


Known bug, first reported in 2009: 
https://issues.dlang.org/show_bug.cgi?id=3543


Re: mixin under -betterC

2023-11-23 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 23 November 2023 at 16:33:52 UTC, DLearner wrote:
Code below is intended to test simple mixin with lambda 
function under -betterC.
Works with full-D, but fails with 'needs GC' errors under 
-betterC.


Why is this so, bearing in mind the concatenations are executed 
at

compile, not run, time?


This is a known limitation: 
https://issues.dlang.org/show_bug.cgi?id=23637


The easiest way to work around it is to change `mxnTest` from a 
function to a templated manifest constant:


```d
enum mxnTest(string strVar1, string strVar2) =
`(int Var1, int Var2) {
if (Var1 > Var2) {
   return true;
} else {
   return false;
}
}(` ~ strVar1 ~ `,` ~ strVar2 ~ `)`;
```

Keep in mind that you will also have to change the call site to 
pass `"Var_A"` and `"Var_B"` as template arguments:


```d
// Note the ! in front of the argument list
FirstVarGreater = mixin(mxnTest!("Var_A", "Var_B"));
```


Re: Doubt about type Inference on templates

2023-11-22 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 22 November 2023 at 17:53:15 UTC, Antonio wrote:
Basically, it doesn't know witch version of ```filter``` to 
use, because it is inferring `i=>i%2==0` is `void` ?!?!?!


```
!()(IIterable!int, void)
```

If I explicitly write `(int i)=>i%2==0`, it compiles correctly 
again.


**Is it mandatory to explicitly tell that `S` is `int` when 
```IIterable!S source``` is  `IIterable!int` alredy?**


This is a bug/limitation in the compiler. I couldn't find an 
existing report on issues.dlang.org, so I've reported it myself 
as [issue 24255][1].


For now, I think the best way to work around it is to specify the 
type in the lambda, as in `(int i) => i%2 == 0`.


The reason you see `void` is that when the compiler cannot figure 
out the type of a function literal, it treats it as a template 
function:


```d
static assert(__traits(isTemplate, i => i % 2 == 0));
```

And for silly historical reasons, when the compiler tries to 
determine the type of a template, it returns `void` instead of 
giving an error:


```d
template example() {}
static assert(is(typeof(example) == void)); // what??
```

[1]: https://issues.dlang.org/show_bug.cgi?id=24255


Re: What is :-) ?

2023-11-20 Thread Paul Backus via Digitalmars-d-learn

On Monday, 20 November 2023 at 16:09:33 UTC, Antonio wrote:
What "breaks" my mind is that a compiler decision (treat a 
piece of code as function or delegate) is not completely 
transparent causing "side" effects on your code  (writeln 
doesn't work the same way:  it shows the delegate signature, 
but not the function signature).


It's certainly surprising that `writeln` treats function pointers 
and delegates differently. My guess is that it's because 
[`isPointer`][1] returns `true` for functions and `false` for 
delegates.


[1]: https://phobos.dpldocs.info/std.traits.isPointer.html

Is there any way to force D compiler to treat this 
"createCounter" declaration as **delegate** instead of 
**function**?


```d
  auto createCounter = (int nextValue) => () => nextValue++;
```


You can put the `delegate` keyword in front of the function 
literal:


```d
auto createCounter = delegate (int nextValue) => () => 
nextValue++;

```

This syntax is documented in the spec's section on [Function 
Literals][2] (look at the grammar box and the examples).


[2]: https://dlang.org/spec/expression.html#function_literals


Re: What is :-) ?

2023-11-20 Thread Paul Backus via Digitalmars-d-learn

On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote:
- What is the way to do ```writeln``` work with ```Counter``` 
function the same way it works with ```next``` function?


`writeln()` should do it.


Re: What is :-) ?

2023-11-20 Thread Paul Backus via Digitalmars-d-learn

On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote:
I understand the problem with UFCS (``next`` is not using UFCS 
because it is a delegate defined in the own main() function,  
and ``Counter``` without () is treated as a function call 
because it is UFCS eligible )


This is not UFCS, it's [optional parentheses][1], which is a 
separate language feature. (Reminder: UFCS only applies when the 
callee has the form `x.y`)


According to the spec, it's disabled for function pointers and 
delegates due to the potential for ambiguity.


[1]: https://dlang.org/spec/function.html#optional-parenthesis


Re: Struct copy constructor with inout

2023-11-14 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 14:36:57 UTC, dhs wrote:
Just to clarify some more: isn't "s1 = ss1" similar to 
something like:


```d
const(S1) s1;
S1 ss1; // ss1 is now S1.init
S1_copy_construct_const_in_const_out(ss1, s1);
```

If this is the case, the compile error is expected, but 
why/how/where do "implicit qualifer conversions" apply here?


The real answer is that constructors are special, and constructor 
calls follow different type-checking rules from normal function 
calls.


Here's an example:

```d
struct S
{
int n;
this(int n) const { this.n = n; }
void fun() const {}
}

void main()
{
S s;
s.__ctor(123); // error
s.fun(); // ok
}

```

Normally, it's fine to call a `const` method on a mutable object, 
because mutable implicitly converts to `const`. But when that 
method is a constructor, it's not allowed.


Why? Because constructors have a special "superpower" that no 
other functions in D have: they're allowed to write to `const` 
and `immutable` variables. This is documented in the spec under 
["Field initialization inside a constructor"][1].


If you could call a `const` constructor on a mutable object, it 
would be possible to use that constructor to violate the type 
system by storing a pointer to `immutable` data in a mutable 
field:


```d
struct S2
{
int* p;
this(const int* p) const
{
// Ok - counts as initialization
this.p = p;
}
}

immutable int answer = 42;

void main()
{
S2 s2;
// If this were allowed to compile...
s2.__ctor();
// ...then this could happen
*s2.p = 12345;
}
```

[1]: https://dlang.org/spec/struct.html#field-init


Re: Does exists some way to define a implementation for a symbol?

2023-11-14 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 13:43:03 UTC, Hipreme wrote:
Right now, I've been implementing classes separately, and I 
need a dummy symbol. The best world is not even having a symbol 
but having only its implementation, for example, I would like 
being able to do that:


```d
void pragma(mangle, "test")(int a){
writeln(a);
}
```

Is it possible somehow to do that?


You can use the following string mixin to generate an identifier:

```d
// Mixin to generate a new identifier that won't repeat within a 
scope

enum gensym(string prefix = "_gensym") =
	`"` ~ prefix ~ `" ~ __traits(identifier, {})["__lambda".length 
.. $]`;

```

But since D currently doesn't support mixing in only a function's 
name, you'd have to put the entire function definition inside a 
mixin:


```d
mixin(q{void pragma(mangle, "test") }, mixin(gensym), q{(int a) {
writeln(a);
}});
```


Re: Struct copy constructor with inout

2023-11-14 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 14 November 2023 at 13:41:32 UTC, Steven 
Schveighoffer wrote:

```
Error: copy constructor `testinoutctor.S1.this(ref const(S1) s) 
const` is not callable using argument types `(const(S1))`

```

I'm not sure what this means. There shouldn't be a copy being 
made here, as the thing is already const. I don't understand 
this error, and it looks like a bug to me.


The error is saying that the copy constructor expects a `const` 
`this` argument, but you're passing a mutable `this` argument.


It's confusing because (a) the `this` argument is hidden and 
doesn't appear in the parameter list, and (b) there's no explicit 
"mutable" qualifier. So when it prints out the list of argument 
types that were actually passed, the `this` argument (`S1 ss1`) 
gets printed as an empty string.


It's easier to see if you compare the actual and expected 
argument lists side-by-side


Expected: (ref const(S1) s) const
Actual:   (const(S1)  )
^
 Mismatched 'this' argument


Re: Struct copy constructor with inout

2023-11-14 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 November 2023 at 08:50:34 UTC, dhs wrote:

```d
struct S2
{
this(ref inout S2 s) inout { writeln("copy"); }
int i;
}

void test()
{
const(S1) s1;
S1 ss1 = s1; // error, ss1 not qualified as const

const(S2) s2;
S2 ss2 = s2; // fine, why?
}
```

Isn't "inout" supposed to copy the const-ness of its parameter 
to the constructor's attribute? In other words: why doesn't 
ss2=s2 fail here?


Because `S2` is a pure value type and contains no pointers or 
references, the compiler allows `const(S2)` to implicitly convert 
to `S2`. This is documented in the spec under ["Implicit 
Qualifier Conversions"][1], and you can verify it with a `static 
assert`:


```d
static assert(is(const(S2) : S2)); // ok
```

In order to prevent this conversion, you can replace `int i` with 
`int* p`:


```d
struct S3
{
this(ref inout S2 s) inout { writeln("copy"); }
int *p;
}

void test()
{
const(S3) s3;
S3 ss3 = s3;
// Error: cannot implicitly convert expression
// `s3` of type `const(S3)` to `S3`
}
```

[1]: 
https://dlang.org/spec/const3.html#implicit_qualifier_conversions


Re: How do I install a package globally?

2023-11-10 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 11 November 2023 at 01:50:54 UTC, Trevor wrote:
How does one install packages globally, and how can I write 
programs that use the third-party packages without being 
wrapped in a dub file?


Dub currently isn't able to do this. There's been some discussion 
about adding a `dub install` command, but it seems like no 
consensus was reached:


https://github.com/dlang/dub/issues/839


Re: "is not an lvalue" when passing template function to spawn function

2023-11-08 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 8 November 2023 at 16:30:49 UTC, Bienlein wrote:

Hello,

I get the error "`addToBiz(T)(Biz!T biz)` is not an lvalue and 
cannot be modified" when compiling the code below. Can't find a 
way how to do it right. Am a D newbie and would appreciate some 
help.


[...]

static void addToBiz(T)(Biz!T biz)
{
// ...
}


int main()
{
auto biz = new Biz!int(123);
spawn(, biz);
}


This is a really bad error message.

The actual problem here is that you can't take the address of a 
template without instantiating it first. To make your example 
work, replace `` with `!int`, like this:


spawn(!int, biz);


Re: How should class objects created in betterC be destroyed

2023-11-06 Thread Paul Backus via Digitalmars-d-learn

On Monday, 6 November 2023 at 05:30:02 UTC, zoe wrote:
I customized object.d in -betterc mode and created NEW 
templates, with modules I can seemingly create classes without 
extern(C++) mode, and type conversions in function calls seem 
to work fine. But when destroy doesn't find a way to call the 
__xtdor() method of the corresponding subclass, is there any 
way to execute __xtdor() correctly


Unfortunately, D classes cannot have virtual destructors, so 
TypeInfo is the only way to find the correct derived class 
destructor to call at runtime.


I think the best you can do is implement your own virtual 
destructors, and your own `destroy` function that knows how to 
call them; for example:


```d
interface BettercDestructible
{
void destruct() nothrow @nogc;
}

class MyClass : BettercDestructible
{
// ...
override void destruct()
{
// destructor implementation here
}

~this() { this.destruct(); }
}

void destroy(BettercDestructible obj)
{
obj.destruct();
}
```

Of course, for classes that don't implement 
`BettercDestructible`, you're still out of luck, but it's better 
than nothing.


Re: Is a shorter statement possible in this case?

2023-11-06 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 5 November 2023 at 18:36:40 UTC, Ctn-Dev wrote:

I wrote this earlier:

[...]

`if` runs when both "One" and "Two" are in the given array as 
intended, but its conditional statement looks verbose. Is there 
a more concise way of getting the same result?


If sorting the arrays is an option, you can use `setIntersection` 
from `std.algorithm.setops`, which returns the overlap between 
two sorted ranges:


```d
import std.stdio;
import std.algorithm.searching: count;
import std.algorithm.setops: setIntersection;
import std.algorithm.sorting: sort;

string[] numeric_traits_1 = [];
string[] numeric_traits_2 = ["Two"];
string[] numeric_traits_3 = ["One"];
string[] numeric_traits_4 = ["One", "Two"];

void main() {

void numeric_traits_contains(string[] numeric) {
sort(numeric); // required by setIntersection
size_t howMany = setIntersection(numeric, ["One", 
"Two"]).count;

if (howMany == 2) {
writeln("Array contains 'One' and 'Two'.");
} else if(howMany == 1) {
writeln("Array contains 'One' or 'Two'.");
} else {
writeln("Array contains neither 'One' nor 'Two'");
}
}

numeric_traits_contains(numeric_traits_1);
numeric_traits_contains(numeric_traits_2);
numeric_traits_contains(numeric_traits_3);
numeric_traits_contains(numeric_traits_4);
}
```


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 4 November 2023 at 03:00:49 UTC, Dadoum wrote:
I was wondering why C++ linkage forbids strings as arguments 
while we can with the C one.


With C linkage, it's translated to a template that's defined in 
the automatically generated header, but it just doesn't compile 
in C++.


`extern(C++)` functions use C++ name mangling, which includes the 
types of the parameters in the mangled name. However, since C++ 
does not have a built-in slice type like D's `T[]`, there is no 
valid C++ mangling for a D slice. Because of this, it is 
impossible to compile an `extern(C++)` function that has a D 
slice as a parameter.


As a workaround, you can convert the slice to a `struct`:

```d
struct DSlice(T)
{
T* ptr;
size_t length;

T[] opIndex() => ptr[0 .. length];
}

DSlice!T toDslice(T)(T[] slice)
{
return DSlice!T(slice.ptr, slice.length);
}

extern(C++) void hello(DSlice!(const(char)) arg)
{
import std.stdio;
writeln(arg[]);
}

void main()
{
const(char)[] greeting = "hello";
hello(greeting.toDslice);
}
```


Re: Keyword "package" prevents from importing a package module "package.d"

2023-11-02 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 2 November 2023 at 12:52:35 UTC, BoQsc wrote:
Therefore the need to import `package.d` is needed and I can't 
see a solution, which means
 that D Language might have to introduce a way to import 
`package.d` from inside the package, if there is a need to 
further improve experience of having a self-testing packages in 
both `dub` and `package modules`.


It's perfectly legal to write `import packagename;` in a file 
that's inside the `packagename/` directory. You just have to make 
sure that *the current directory in your terminal window* is 
outside the `packagename/` directory when you run the compiler.


The D compiler *always* looks up files *relative to your 
terminal's current directory*. It does not care at all where the 
files are relative to each other.


Re: Keyword "package" prevents from importing a package module "package.d"

2023-11-02 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 2 November 2023 at 11:12:58 UTC, BoQsc wrote:

Weirdly enough it does not work on Windows operating system.
[...]
```
program.d(1): Error: unable to read module `waffles`
program.d(1):Expected 'waffles.d' or 
'waffles\package.d' in one of the following import paths:

import path[0] = .
import path[1] = C:\D\dmd2\windows\bin\..\..\src\phobos
import path[2] = C:\D\dmd2\windows\bin\..\..\src\druntime\import
Failed: ["C:\\D\\dmd2\\windows\\bin\\dmd.exe", "-v", "-o-", 
"program.d", "-I."]


C:\waffles>dmd -i -run program.d
program.d(1): Error: unable to read module `waffles`
program.d(1):Expected 'waffles.d' or 
'waffles\package.d' in one of the following import paths:

import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
import path[1] = 
C:\D\dmd2\windows\bin64\..\..\src\druntime\import


```


The problem is the directory you're running the command from. You 
need to run `dmd` from the parent directory of `waffles`.


Re: Member field of type nested struct must be initialized in constructor: Why?

2023-10-22 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 22 October 2023 at 21:02:32 UTC, Inkrementator wrote:
Running the code with `rdmd -version=fix app.d` works, but 
running `rdmd -version=fix app.d` produces:
`Error: field `member` must be initialized in constructor, 
because it is nested struct`

Why?
I didn't find anything about this in [the 
spec.](https://dlang.org/spec/struct.html#nested)


Nested structs contain a context pointer that needs to be 
initialized at runtime. If you don't initialize them, the pointer 
gets set to `null`, and the struct will not be able to access its 
context.


Using `.init` doesn't fix this because `.init` is determined at 
compile time, and also has `null` in place of the context pointer.


Re: Forcing my module to be initialized first

2023-10-15 Thread Paul Backus via Digitalmars-d-learn

On Monday, 16 October 2023 at 03:31:13 UTC, dan wrote:
I have some code that i would like executed before anything 
else is.


The code is to set an environment variable which is used by a 
library.  I'm trying to find some way to avoid setting the 
environment variable on the command line, or in any shell 
script or initialization file.


I think the place to put such code would be in a 'static this' 
inside a module.


So i need some way to force my module to be initialized first, 
ahead of all others.


You may find this article enlightening:

https://devblogs.microsoft.com/oldnewthing/20050607-00/?p=35413


Re: The difference between T[] opIndex() and T[] opSlice()

2023-10-03 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 3 October 2023 at 18:29:49 UTC, Salih Dincer wrote:
More importantly, is there a priority order?  Because in our 
last example, when we leave a single overload, all features are 
executed through the ref opIndex except the bit:


The spec says:

If an index expression can be rewritten using `opIndexAssign` 
or `opIndexOpAssign`, those are preferred over `opIndex`.


Source: https://dlang.org/spec/operatoroverloading.html#array

So, the more specialized overloads are tried first, and the more 
general `opIndex` is tried last.


The only thing that's unclear here is the meaning of "can be 
rewritten"--as we've seen, the compiler only checks whether the 
specialized function *exists*, not whether it actually *works*, 
and will sometimes perform rewrites even when the resulting code 
does not compile.


Re: T[] opIndex() Error: .. signal 11

2023-10-03 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 3 October 2023 at 17:05:46 UTC, Steven Schveighoffer 
wrote:

```d
void main()
{
S s = 0;
{
scope int[] __r3 = s.opIndex()[];
ulong __key4 = 0LU;
for (; __key4 < __r3.length; __key4 += 1LU)
{
int x = __r3[__key4];
}
}
return 0;
}
```

Note the difference in how the foreach code is lowered. Inside 
`opIndex`, it's lowered to the range functions. Outside, it 
uses the slice operator to switch to iterating a `scope int[]`.


Naturally, this lowering is completely absent from [the language 
spec's section on `foreach`.][1] According to the spec, the only 
ways to iterate over a `struct` type are `opApply` and the input 
range interface.


I think it would probably be less confusing to have both 
`opApply` and `empty`/`front`/`popFront` take precedence over 
this lowering, but I have no idea how much existing code would be 
broken by such a change. At the very least, though, this needs to 
be documented.


[1]: https://dlang.org/spec/statement.html#foreach-statement


Re: The difference between T[] opIndex() and T[] opSlice()

2023-10-03 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 3 October 2023 at 16:45:39 UTC, Steven Schveighoffer 
wrote:


OK, so it's not as bad as I thought, but surely the compiler 
should recognize that `opIndexAssign(val, idx)` doesn't work, 
but `opIndex(idx) = val` does?


Maybe. On the other hand, if you make a typo in the body of your 
templated `opIndexAssign` overload, do you want the compiler to 
silently fall back to `opIndex`, or do you want an error? There 
are pros and cons to both approaches.


At the very least, the spec should do a better job of documenting 
when the compiler will try a fallback and when it won't.


Re: The difference between T[] opIndex() and T[] opSlice()

2023-10-03 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 3 October 2023 at 13:07:00 UTC, Steven Schveighoffer 
wrote:


Now, you can define a further `opIndexAssign(T val, size_t 
idx)`. However, now you lose capabilities like `a[0]++`, which 
I don't think has a possibility of implementing using an 
`opIndex` operator, and it would be pretty ugly if you had to.


Works for me, with both `++` and `+=`: 
https://run.dlang.io/is/JckTVG


AST output confirms that these are lowered to use `opIndex`.

Looking at the spec, it seems like `opIndex` would only be 
pre-empted here if you overloaded `opIndexUnary` (for `++`) 
and/or `opIndexOpAssign` (for `+=`).


Re: The difference between T[] opIndex() and T[] opSlice()

2023-10-02 Thread Paul Backus via Digitalmars-d-learn

On Monday, 2 October 2023 at 20:34:11 UTC, Salih Dincer wrote:
In an old version (for example, v2.0.83), the code you 
implemented in the places where Slice is written above works as 
desired.  In the most current versions, the parameterized 
opIndexAssign(T value) gives the error:


onlineapp.d(51): Error: function 
`onlineapp.Matrix!double.Matrix.opIndexAssign(double value)` 
is not callable using argument types `(double, ulong)`

onlineapp.d(51):expected 1 argument(s), not 2


**Source:** https://run.dlang.io/is/TPAg5m


I don't know what's wrong in your example but this works for me:

```d
struct S
{
void opIndexAssign(int value)
{
import std.stdio;
writeln("assigned ", value);
}
}

void main()
{
S s;
s[] = 7;
}
```


Re: The difference between T[] opIndex() and T[] opSlice()

2023-10-02 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 1 October 2023 at 17:41:08 UTC, Salih Dincer wrote:

Hi,

What is the difference between T[] opIndex() and T[] opSlice(), 
which haven't parameters?


`T[] opSlice()` is the D1 version and exists only for backwards 
compatibility. You should use `T[] opIndex()` in new code.


Re: How to print current type of a SumType?

2023-09-30 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 1 October 2023 at 01:17:50 UTC, Chris Piker wrote:

Hi D

I've a simple question but it's bedeviling me anyway.  How do I 
get a string representation of the current type of a SumType?  
I'm trying to avoid something like this:


```d
alias Vec3 = SumType!(void* /* invalid vector */, byte[3], 
short[3], char[][3]);


string prnType(Vec3 vec){

  return vec.match!(
 (void* _) => "void*",
 (byte[3] _) => "byte[3]",
 (short[3] _) => "short[3]",
 (char[][3] _) => "char[][3]"
  );
}
```

I'm sure there's a much easier way, especially once there's a 
largish number of vector types.


Thanks,


```d
return vec.match(value => typeof(value).stringof);
```


Re: Help on array pointers

2023-09-14 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote:

Questions:1
```
char[] invalid = (cast(char*)malloc(char.sizeof * 
length))[0..length];

```
The above statement allocate memory for char type and the size 
of the allocated memory is char.sizeof * length so what is the 
use of this "[0..length]";


The difference between a `char*` and a `char[]` is that the 
`char[]` includes both the pointer and the length in the same 
variable. The slicing operator `[0 .. length]` is used to combine 
the pointer and the length into a single `char[]` variable.


Strictly speaking, you don't *have* to do this--you could leave 
the pointer and the length in separate variables, and the program 
would still work. Most D programmers prefer to combine them 
because it's more convenient and less error-prone (for example, 
it makes it much harder to accidentally use the wrong length).



Question:2
```
char[]* invalidptr = 
```
Is this the right way to create a array pointer.


It depends on what you mean by "array pointer".

A `char[]` contains a pointer and a length. A `char[]*` is a 
pointer to a thing that contains a pointer and a length. In order 
to get from a `char[]*` to the actual `char` data, you have to 
follow *two* pointers. In that sense, you can think of `char[]*` 
in D as similar to `char**` in C.



Question: 3
```
ST1: char[] invalid = (cast(char*)malloc(char.sizeof * 
length))[0..length];
ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * 
length))[0..length];

```
What is the difference between the above to statement.


The first statement is valid code and the second one isn't.


Question: 4
Who do we free the memory allocated.
Code:
[...]


In order to ensure that the memory is freed correctly even when 
an exception is thrown, you can use a [`try`/`finally` block.][1]


char[] a = (cast(char*) malloc(char.sizeof * length))[0 .. 
length];


try {
doSomethingWith(a);
} finally {
  free(a.ptr);
}

However, this by itself will not fix the code in your example 
because it has another serious mistake: it does not initialize 
the memory allocated by `malloc`. Attempting to read from 
uninitialized memory results in [undefined behavior][2], which 
may cause your program to crash or behave unpredictably.


[1]: http://ddili.org/ders/d.en/exceptions.html#ix_exceptions.try
[2]: https://c-faq.com/ansi/undef.html


Re: Unicode validation for Posix

2023-09-03 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 3 September 2023 at 10:06:58 UTC, Vino wrote:

Hi All,

As per the documentation from std.process it states that an 
exception is thrown if the variable contains invalid UTF-16 
characters and it can also be validated using "validate" 
function from std.utf, so the question is do we have a similar 
one for Posix as this seem to be applicable only to Windows.


```
Exception if the environment variable does not exist, or 
std.utf.UTFException if the variable contains invalid UTF-16 
characters (Windows only).

```

From,
Vino


On POSIX, no validation is necessary, because the names of 
environment variables are allowed to contain any character except 
for `\0` (including invalid Unicode).


Re: Function Pointer

2023-08-30 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 30 August 2023 at 17:48:19 UTC, Vino wrote:

Hi All,

 Request your help on hot to create a pointer for a function 
whose function type is Result.


```
ReturnType!(typeof()).stringof; // Result

From
Vino
```


To get a function pointer type from a function type, you can add 
`*` on the end:


void func(int) {}

alias FuncType = typeof(func);
pragma(msg, FuncType); // void(int)

alias FuncPtrType = FuncType*;
pragma(msg, FuncPtrType); // void function(int)
static assert(is(FuncPtrType == typeof()));


Re: std.experimental.allocator

2023-08-13 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 13 August 2023 at 11:44:50 UTC, IchorDev wrote:
I feel like I can't possibly be the first to ask, but I 
couldn't find any prior discussion of this:
When is `std.experimental.allocator` going to be moved out of 
`experimental`? Is there any roadmap for it? Is it just in 
limbo?


The current design of `std.experimental.allocator` is 
incompatible with `@safe`. Most likely, it will eventually be 
replaced with a new "allocators v2" package, and moved to 
[`undead`][1].


[1]: https://code.dlang.org/packages/undead


Re: Syntax for Static Import of User Define Attributes

2023-07-27 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 27 July 2023 at 21:19:08 UTC, Vijay Nayar wrote:
Attempted Fix 2: Enclose the entire attribute name in 
parenthesis.

```
static import vibe.data.serialization;

class ChatCompletionFunctions {
  @(vibe.data.serialization.name)("name")
  ...
}
```


You almost had it. The correct syntax is to enclose the entire 
attribute (not just the name) in parentheses:


```
class ChatCompletionFunctions {
  @(vibe.data.serialization.name("name"))
  string name;
}
```


Re: `static` on module-level functions

2023-07-07 Thread Paul Backus via Digitalmars-d-learn
On Friday, 7 July 2023 at 13:31:59 UTC, Steven Schveighoffer 
wrote:
However, I can't think of a valid reason to allow `static` on a 
module-level scope. Applying static to a declaration at 
module-level should be a no-op. So maybe that's one "use" of 
static that can be eliminated.


Well, it can be used to work around this bug:

https://issues.dlang.org/show_bug.cgi?id=17435

So we might want to fix that issue before we make module-level 
`static` an error.


Re: std.sumtyp and option ?

2023-06-29 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 29 June 2023 at 14:18:05 UTC, kiriakov wrote:

How to create option type over std.sumtype ?


```
enum None;
struct Some(T) { T x; }
alias Option = SumType!(Some!T, None);
```
I get
Error: undefined identifier `T`


Looks like you meant to type

alias Option(T) = SumType!(Some!T, None);

Unfortunately, due to [issue 1807][1], this is not a good way to 
define an `Option` type. If you try to use it as a function 
parameter, you will get confusing error messages.


import std.sumtype;

struct None {}
struct Some(T) { T value; }
alias Option(T) = SumType!(None, Some!T);

bool isNone(T)(Option!T opt)
{
return opt.match!(
(Some!T _) => false,
(None _) => true
);
}

unittest
{
Option!int x = Some!int(123), y = None.init;
assert(!x.isNone);
assert(y.isNone);
// Error: none of the overloads of template `isNone` are 
callable using argument types `!()(SumType!(None, Some!int))`

}

To work around this issue, you should define your option type as 
a `struct` using `alias this`, as described in [this article on 
the D blog][2]. (This will also give you nicer-looking error 
messages.) For `Option`, that would look like this:


struct Option(T)
{
SumType!(None, Some!T) data;
alias data this;
this(Value)(Value value) { data = value; }
}

If I use this version of `Option` instead of the `alias` version, 
the example above compiles, and the unit test passes.


[1]: https://issues.dlang.org/show_bug.cgi?id=1807
[2]: 
https://dlang.org/blog/2018/05/21/complicated-types-prefer-alias-this-over-alias-for-easier-to-read-error-messages/


Re: Scope guards

2023-06-26 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 24 June 2023 at 17:00:36 UTC, Cecil Ward wrote:
I would like to use scope guards but in the guard I need to get 
access to some local variables at the end of the routine. This 
doesn’t really seem to make sense as to how it would work, 
because their values depend on the exact point where the scope 
guard is called at in the last, exiting line(s) of the routine. 
Am I misunderstanding?


Scope guards are syntax sugar for try/catch/finally. For example, 
when you write


auto f = open("foo");
scope(exit) close(f);
doSomethingWith(f);

...it gets transformed by the compiler into

auto f = open("foo");
try {
doSomethingWith(f);
} finally {
close(f);
}

I do not understand exactly what the problem is you are having, 
but hopefully this lets you figure out how to solve it.


Re: A couple of questions about arrays and slices

2023-06-21 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 22 June 2023 at 00:10:19 UTC, Cecil Ward wrote:
Is .reserve()’s argument scaled by the entry size after it is 
supplied, that is it is quoted in elements or is it in bytes? 
I’m not sure whether the runtime has a knowledge of the element 
type so maybe it doesn’t know anything about scale factors, not 
sure.


length, reserve, and capacity all use the same unit, which is 
elements.


reserve passes a TypeInfo instance to the runtime so that it 
knows the size of the elements. You can see the implementation 
here:


https://github.com/dlang/dmd/blob/v2.104.0/druntime/src/object.d#L3910


Re: How does D’s ‘import’ work?

2023-06-18 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 18 June 2023 at 20:24:10 UTC, Cecil Ward wrote:

On Thursday, 8 June 2023 at 05:11:04 UTC, Ali Çehreli wrote:


dmd's -makedeps command line switch should be helpful there. 
(I did not use it.)


Ali


I wasn’t intending to use DMD, rather ldc if possible or GDC 
because of their excellent optimisation, in which DMD seems 
lacking, is that fair? (Have only briefly looked at dmd+x86 and 
haven’t given DMD’s back end a fair trial.)


LDC has the same feature with its --makedeps flag.


Re: need `this` for `this` of type `ref @safe Test(string reg_arg)

2023-06-18 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 18 June 2023 at 19:05:19 UTC, rempas wrote:

On Sunday, 18 June 2023 at 18:17:16 UTC, Paul Backus wrote:


`__ctor` doesn't create a new object, it initializes an 
existing object. You need to create the object first, then 
call `__ctor` on it:


```d
void main() {
  Test test;
  test.__ctor!("non_def")("Hello");
}
```


Thank you! Do you know any other way to do it without using 
"__ctor".


No, there is no way to pass template arguments to a constructor 
without using `__ctor`.


My recommendation is to use a free function or a `static` method 
instead. For example:


```d
import std.stdio;

struct Test {}

Test makeTest(string type = "def")(string reg_arg)
{
writeln("reg_arg: ", reg_arg);
return Test();
}

void main()
{
auto test = makeTest!"non_def"("Hello");
}
```


Re: need `this` for `this` of type `ref @safe Test(string reg_arg)

2023-06-18 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 18 June 2023 at 17:43:01 UTC, rempas wrote:
Ok, so I'm having a struct that has a constructor that takes a 
template parameter. I suppose this question could also be named 
`how to initialize constructors with template parameters` but 
whatever! The funny thing is, I think that I may have already 
found how to do it in the past but I forgot... This time, I'm 
going to add the code in a big module in my project so I'm not 
going to have it as a reference and I won't forget it.


Here is a small sample code:

```d
import std.stdio;

struct Test {
  this(string type = "def")(string reg_arg) {
writeln("reg_arg: ", reg_arg);
  }
}

void main() {
  auto test = Test.__ctor!("non_def")("Hello");
}
```

And the error I get: `test.d(10): Error: need `this` for `this` 
of type `ref @safe Test(string reg_arg)`


`__ctor` doesn't create a new object, it initializes an existing 
object. You need to create the object first, then call `__ctor` 
on it:


```d
void main() {
  Test test;
  test.__ctor!("non_def")("Hello");
}
```


Re: How do I generate `setX` methods for all private mutable variables in a class?

2023-06-05 Thread Paul Backus via Digitalmars-d-learn

On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote:
How do I generate `setX` methods for all private mutable 
variables in my class? Do I need to use `__traits`?


I need this for my 
[tiny-svg](https://github.com/rillki/tiny-svg) project to 
generate `setX` methods for all Shapes.


Example:
```D
class Rectangle {
private immutable ...;
private Color fillColor;
private Color strokeColor;
private uint strokeWidth;

this(int x, int y) {...}

mixin(???);

// I need this:
Rectangle setFillColor(Color color) {...}
Rectangle setStrokeColor(Color color) {...}
Rectangle setStrokeWidth(uint color) {...}
}
```


Is there a reason you can't just make these fields `public`?

D supports property accessors, so you can always go back and make 
them `private` later on if it turns out you need to. For example:


```d
// Before
class MyClass1
{
public int data;
}

void example1(MyClass1 c)
{
c.data = 123; // set
int n = c.data; // get
}

// After
class MyClass2
{
private int data_;
int data() { return data; }
void data(int value) { data = value; }
}

void example2(MyClass2 c)
{
// Usage is exactly the same
c.data = 123; // set
int n = c.data; // get
}
```


Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-29 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 30 May 2023 at 02:57:52 UTC, Cecil Ward wrote:
I have often come into difficulties where I wish to have one 
routine that can be called with either immutable or (possibly) 
mutable argument values. The argument(s) in question are in, 
readonly, passed by value or passed by const reference. Anyway, 
no one is trying to write to the items passed in as args, no 
badness attempted.


When I call the routine from one place with an argument that is 
immutable and then from another that is not, or it could be 
const as well, or not, that’s when I get all kinds of type 
mismatch errors. And I certainly don’t want to pour cast-like 
type conversion operations over all the place at these problem 
occurrences. it’s surely asking for problems.


Normally you would use const for this, since a const parameter 
can accept either a mutable or an immutable argument. If const 
isn't working for you, then there's probably something else going 
on that you haven't mentioned. Can you post an example of the 
kind of code that gives you these errors?


Re: How to use @safe when a C library integration needed

2023-04-14 Thread Paul Backus via Digitalmars-d-learn

On Friday, 14 April 2023 at 14:10:41 UTC, Leonardo wrote:
Thanks. But this works only to one function per time. Is there 
any way to do this to an imported library at all? something 
like `@trusted import library`


No, there isn't. C is an unsafe language, so if you want to call 
C from `@safe` code, you have to do the work to make sure that 
each individual call is `@safe`.


If you are calling the same C function many times from `@safe` 
code, you can write a `@trusted` D wrapper function to avoid 
repeating the safety checks at every call site. For example, 
here's a `@trusted` wrapper for the standard C library function 
`puts`:


```d
import core.stdc.stdio: puts;
import std.exception: enforce;

@trusted
void safePuts(const(char)[] s)
{
// To safely call puts, we must pass it a valid C string
// To be a valid C string, s must be non-empty and 
NUL-terminated

enforce(s.length > 0, "An empty string is not a C string");
enforce(s[$-1] == '\0', "A C string must be NUL-terminated");

// If the checks above have passed, this call is safe
puts([0]);
}
```


Re: Memory leak issue between extern (c) and D function

2023-04-13 Thread Paul Backus via Digitalmars-d-learn

On Friday, 14 April 2023 at 03:50:37 UTC, backtrack wrote:
Dear All, I am new to D lang. I have been given a task to 
consume the .dll generated from a D lang project.


I added extern (c) function for call the .dll from CPP file. i 
have code like below



```
// myfile.d
extern(c)
{

mystruct* getmystruct()
{
mystruct* mystruct =  
cast(mystruct*)malloc(mystruct.sizeof);

return mystruct;

}
```

[...]

Now i have my cpp file which calls like below

```
mystruct* mystruct = lib.getmystruct();
char* output = lib.do_some_work(mystruct, "input", 5);

```

The problem i am facing is, the memory keep on increasing and i 
am not able to fix the memory issue. I am suspecting that since 
the D lang function is called from extern(c) function GC is not 
clearing the memeory.


The GC does not clean up memory allocated by `malloc`. Since 
you're using `malloc` to allocate your memory, the only way you 
can free it is by using `free`.


If you want the GC to clean up your memory, use `new` to allocate 
it instead of `malloc`. Like this:


```d
mystruct* getmystruct()
{
return new mystruct;
}
```


Re: Returning a reference to be manipulated

2023-04-13 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 13 April 2023 at 07:05:10 UTC, Chris Katko wrote:

Right now, I'm using pointers which resolves to:

```D
// float* opIndex(string key){...} using pointer
(*s["tacos"])++; // works with pointer, but is strange looking

s["tacos"]++; // preferred syntax or something similar
```


You can use a wrapper struct with `alias this` to make the 
pointer a little nicer to use:


```d
struct Ref(T)
{
T* ptr;
ref inout(T) deref() inout { return *ptr; }
alias deref this;
}

Ref!T byRef(T)(ref T obj)
{
return Ref!T();
}

struct stats
{
float[string] data;

Ref!float opIndex(string key)
{
return data.require(key, 0).byRef;
}
}

void main()
{
stats foo;
auto x = foo["tacos"];
x++;
assert(foo["tacos"] == 1);
}
```


Re: The Phobos Put

2023-03-31 Thread Paul Backus via Digitalmars-d-learn
On Friday, 31 March 2023 at 02:23:29 UTC, Steven Schveighoffer 
wrote:
There's a certain attempt in phobos in some places to try and 
ensure code that is going to confuse will not compile. I think 
this is one of those attempts.


Consider that if you pass a slice into `put`, then it returns 
nothing. There is no indication of what actually was written. 
It's essentially an inconclusive call, because the "result" is 
the output range itself. How many elements were written? You 
can't tell.


This is a general issue with the `put` interface—it has no 
standardized way to report failure or partial success to the 
caller. And the problem applies to both lvalue and rvalue output 
ranges. For example:


```d
void main()
{
import std.stdio, std.range;

auto sink = stdout.lockingTextWriter;
put(sink, "hello");
}
```

How many characters were written? Nobody knows! Maybe you can 
find out with `File.tell`, if the file is seekable, but there's 
no guarantee it is. And if you're working in a generic context, 
where you don't know the specific type of output range you're 
dealing with? Forget it.


I'd argue that the way input ranges are used as output ranges 
today is extremely confusing. It makes sort of a logical sense, 
but the fact that you need to store your "original" range, and 
then do some length math to figure out what was written makes 
such code very awkward all around. The output is decipherable, 
but not obvious.


I stand by my assertion that probably lvalue input ranges 
should never have been treated as output ranges implicitly. 
They should have had to go through some sort of wrapper.


IMO this is downstream of the issue with `put`. If `put` itself 
returned information about what was written, then there would be 
no need to try and recreate that information via side channels 
like this (or like `File.tell`).


I agree that there are ways we could change things to make the 
side channels easier to use, but ultimately that's treating the 
symptom, not the disease.


Re: The Phobos Put

2023-03-30 Thread Paul Backus via Digitalmars-d-learn
On Wednesday, 29 March 2023 at 20:50:04 UTC, Steven Schveighoffer 
wrote:

On 3/29/23 4:29 PM, ag0aep6g wrote:

But regardless of Salih's exact intent, the broader point is: 
a non-ref overload could be added to Phobos. And that would 
enable `a[1..$-1].phobos_put([2, 3])`. Which is what he asked 
about originally.


I think the idea of requiring ref output ranges is that you can 
then let the range keep track of its output state.


An input range with lvalue elements is therefore an output 
range, but only if it's accepted via ref, since it has to be 
iterated as it goes. If you iterate it only internally, then 
it's either in an undetermined state when you exit `put`, or it 
is a forward range that was copied without using `save`.


It's not the greatest situation. I feel like we probably 
shouldn't have made lvalue input ranges be output ranges 
automatically.


It should be fine to have both a `ref` and non-`ref` overload for 
`put`, though, right? If the non-`ref` overload is only called 
with rvalues, then it's fine to leave them in an undetermined 
state, because nothing can access them afterward anyway.


Re: #define-like behavior

2023-03-15 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 15 March 2023 at 16:40:52 UTC, bomat wrote:

Just out of curiosity:
Can you explain to me why this is called an `enum` although 
it's clearly not an enumeration?

Seems like a random abuse of a keyword...


It's shorthand for defining an unnamed `enum` with a single 
member:


```d
enum
{
myString = "hello"
}
```

D lets you leave out the `{}` in this case, for convenience.


Re: Better way to compromise on the lack of template alias resolution stuff?

2023-03-15 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 March 2023 at 10:19:24 UTC, Elfstone wrote:
I went back to some of my old code and couldn't stand what I 
had ended up with - If I already have a well-defined `Vector`, 
why do I have to write extra code to implement `isVector`, and 
use `isVector` instead of simply declaring the param to be 
`Vector`?


But that's simply the current state: it looks like DIP1023 
isn't going anywhere, and I'm not a compiler expert.


Note that I had to repeat `Matrix!(S, N, 1)` to for both 
`Vector` and `isVector`.


Is there a way around this?!


Currently the best workaround for this is to define `Vector` as a 
`struct` with `alias this` instead of as an `alias`:


```d
struct Matrix(S, size_t M, size_t N)
{
// ...
}

//alias Vector(S, size_t N) = Matrix!(S, N, 1);

struct Vector(S, size_t N)
{
Matrix!(S, N, 1) data;
alias data this;

// forward constructor calls to wrapped object
this(this This, Args...)(auto ref Args args)
{
import core.lifetime: forward;
data = forward!args;
}
}

void foo(U)(Vector!(U, 3) a)
{
import std.stdio;
writeln("Called with U = ", U.stringof);
}

void main()
{
Vector!(float, 3) v;
foo(v); // ok
}
```


Re: evenChunks on a string - hasLength constraint fails?

2023-03-14 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 March 2023 at 08:21:00 UTC, amarillion wrote:
I'm trying to understand why this doesn't work. I don't really 
understand the error. If I interpret this correctly, it's 
missing a length attribute on a string, but shouldn't length be 
there?


By default, D's standard library treats a `string` as a range of 
Unicode code points (i.e., a range of `dchar`s), encoded in 
UTF-8. Because UTF-8 is a variable-length encoding, it's 
impossible to know how many code points there are in a `string` 
without iterating it--which means that, as far as the standard 
library is concerned, `string` does not have a valid `.length` 
property.


This behavior is known as "auto decoding", and is described in 
more detail in this article by Jack Stouffer:


https://jackstouffer.com/blog/d_auto_decoding_and_you.html

If you do not want the standard library to treat your `string` as 
an array of code points, you must use a wrapper like 
[`std.utf.byCodeUnit`][1] (to get a range of `char`s) or 
[`std.string.representation`][2] (to get a range of `ubyte`s). 
For example:


```d
auto parts = evenChunks(line.byCodeUnit, 2);
```

Of course, if you do this, there is a risk that you will split a 
code point in half and end up with invalid Unicode. If your 
program needs to handle Unicode input, you would be better off 
finding a different solution—for example, you could use 
[`std.range.primitives.walkLength`][3] to compute the midpoint of 
the range by hand, and split it using [`std.range.chunks`][4]:


```d
size_t length = line.walkLength;
auto parts = chunks(line, length / 2);
```

[1]: https://phobos.dpldocs.info/std.utf.byCodeUnit.html
[2]: https://phobos.dpldocs.info/std.string.representation.html
[3]: 
https://phobos.dpldocs.info/std.range.primitives.walkLength.1.html

[4]: https://phobos.dpldocs.info/std.range.chunks.html


Re: #define-like behavior

2023-03-14 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 14 March 2023 at 05:47:35 UTC, Jeremy wrote:
Hi, in C and C++ you can use #define to substitute a value in 
place of an identifier while preprocessing. If you initialize a 
new string and don't change its value after that, will the 
compiler substitute the string identifier with its value, like 
#define in C, or will it make a string in memory and refer to 
that?


In D, you can get #define-like behavior by declaring the string 
as a [manifest constant][1], like this:


```d
enum myString = "hello";
```

For more tips on how to translate C preprocessor idioms to D, 
take a look at ["The C Preprocessor vs D"][2] in the ["Articles" 
section][3] of dlang.org.


[1]: https://dlang.org/spec/enum.html#manifest_constants
[2]: https://dlang.org/articles/pretod.html
[3]: https://dlang.org/articles/index.html


Re: 'auto' keyword

2023-03-12 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 12 March 2023 at 15:31:07 UTC, Salih Dincer wrote:

Moreover, `auto ref` or `ref auto` is needed in functions.


That's because `ref` isn't part of the argument or return value's 
type, so it isn't covered by **type** inference. Instead, D has a 
totally separate feature for "`ref` inference".


Re: foreach with assoc. array

2023-03-01 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 1 March 2023 at 19:05:10 UTC, DLearner wrote:

(1) & (2) compile and run with the expected results.
But (3) fails with:
```
Error: variable `wk_Idx` is shadowing variable 
`for3.main.wk_Idx`

```
Why is this usage wrong?


With `foreach`, you can't reuse an existing variable as the loop 
variable. It always declares a new one. If you want to reuse an 
existing variable for your loop, you have to use `for`.


Re: CompilerInvocationException

2023-02-26 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 26 February 2023 at 14:17:50 UTC, ryuukk_ wrote:

On Sunday, 26 February 2023 at 07:11:55 UTC, Paul Backus wrote:
Since `Expression` contains `Binary` and `Unary`, and `Binary` 
and `Unary` contain `Expression`, that means `Expression` 
contains itself--which is not allowed, because it would result 
in `Expression.sizeof` being infinite.


It should display the proper error message then


Normally when you do this you *will* get a proper error message. 
For example, attempting to compile the following program:


import std.sumtype;

alias Test = SumType!S;

struct S
{
Test st;
}

...will give you this error message:

/usr/include/dmd/phobos/std/sumtype.d(309): Error: union 
`std.sumtype.SumType!(S).SumType.Storage` no size because of 
forward reference
forum.d(3): Error: template instance 
`std.sumtype.SumType!(S)` error instantiating


I'm not sure why OP didn't get a proper error message. It's 
possible that there's some other issue with their code that stops 
the error message from being printed. I did not attempt to 
reproduce their error myself.


Re: CompilerInvocationException

2023-02-25 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 26 February 2023 at 02:33:21 UTC, guacs wrote:
NOTE: The error is happening when I'm using the SumType and I 
suspect that I'm using it incorrectly.


I am not sure whether this is the specific error that is causing 
your problem, but there is  a mistake in your use of `SumType` in 
`expr.d`. [1]


On line 10, you declare

alias Expression = SumType!(Number, Binary, Unary, Group);

Later, you declare `Binary` and `Unary` like this:

struct Binary {
Expression leftOperand;
Expression rightOperand;
Token operator;

// etc.
}

struct Unary {
Expression operand;
Token operator;

// etc.
}

Since `Expression` contains `Binary` and `Unary`, and `Binary` 
and `Unary` contain `Expression`, that means `Expression` 
contains itself--which is not allowed, because it would result in 
`Expression.sizeof` being infinite.


The fix is to change `Binary` and `Unary` so that they contain 
*pointers* to `Expression`, like this:


struct Binary {
Expression* leftOperand;  // pointer
Expression* rightOperand; // pointer
Token operator;

// etc.
}

struct Unary {
Expression* operand; // pointer
Token operator;

// etc.
}

[1] https://github.com/VisakhChekur/meval/blob/error/source/expr.d



Re: Template alias parameter: error: need 'this' for ...

2023-02-24 Thread Paul Backus via Digitalmars-d-learn

On Friday, 24 February 2023 at 14:22:17 UTC, user1234 wrote:
you can break using `goto`, restore `static` everywhere, and 
using local introspection determine whether the result exists.


```d
struct Bar
{
@("hello") int t;
}

static bool hasAttribute(alias F, T)()
{
static foreach (a; __traits(getAttributes, F))
{
static if (is(typeof(a) : T))
{
enum result = true;
goto L0;
}
}
L0:
static if (is(typeof(result)))
return result;
else
return false;
}

void main()
{
import std.stdio;

writeln(hasAttribute!(Bar.t, string));
}
```


Unfortunately there is a serious bug in this code. Take a look at 
what happens when you try it with this `struct Bar`:


```d
struct Bar
{
@("hello") @("goodbye") int t;
}
```


Re: Template + alias + basic type depends on another parameter = broken?

2023-02-22 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 22 February 2023 at 20:20:46 UTC, Dark Hole wrote:

```d
template Foo(T, alias T[] Array) {
// ...
}
// ...
Bar[] arr;
Foo!(Bar, arr);
```

This is valid D, but it doesn't work. It gives error "Error: 
template instance `Foo!(Bar, arr)` does not match template 
declaration `Foo(T, alias T[] Array)`".


Of course, there is some ways to avoid this error (e.g. check 
Array type in if), but I don't undestand why this code doesn't 
compiles.


Pretty sure this is just a bug. There are a lot of edge-case bugs 
like this where template instantiation doesn't work the way it's 
supposed to.


I've submitted a bug report for this on issues.dlang.org: 
https://issues.dlang.org/show_bug.cgi?id=23733


Re: Gneric linkedList range adaptor

2023-02-10 Thread Paul Backus via Digitalmars-d-learn

On Friday, 10 February 2023 at 22:10:20 UTC, Ben Jones wrote:
I'm trying to write a range adaptor for linked list types.  The 
range type seems to work OK, but my helper function to deduce 
the node type has a compiler error.  My hunch is that 
`nextField` loses its association with T when I'm trying to 
pass it as a template parameter inside the helper method, but I 
can't use __traits(child) there to fix it.


Any idea how to fix the helper method?


As a workaround, you can use a `string` instead of an `alias`:

```diff
--- before.d2023-02-11 01:48:08.922945736 -0500
+++ after.d 2023-02-11 01:47:42.062922019 -0500
@@ -1,7 +1,7 @@
 import std.stdio;
 import std.range;

-struct LinkedListAdaptor(alias nextField, T){
+struct LinkedListAdaptor(string nextField, T){
T current;
 @safe:
nothrow:
@@ -19,11 +19,11 @@
 }

 void popFront() {
-   current = __traits(child, current, nextField);
+   current = __traits(getMember, current, nextField);
 }
 }

-auto linkedListAdaptor(alias nextField, T)(T head) if(is(T == 
U*, U)){
+auto linkedListAdaptor(string nextField, T)(T head) if(is(T == 
U*, U)){

return LinkedListAdaptor!(nextField, T)(head);

 //fails with:
@@ -39,8 +39,8 @@
 void main(){
Node* head = new Node(10, new Node(20, null));

-auto rng1 = LinkedListAdaptor!(Node.next, Node*)(head);
-auto rng = linkedListAdaptor!(Node.next)(head);
+auto rng1 = LinkedListAdaptor!("next", Node*)(head);
+auto rng = linkedListAdaptor!("next")(head);
 foreach(const x; rng){
 writeln(x.data);
 }
```


Re: Assign to Array Column

2023-02-01 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 31 January 2023 at 01:04:41 UTC, Paul wrote:

Greetings,

for an array byte[3][3] myArr, I can code myArr[0] = 5 and have:
5,5,5
0,0,0
0,0,0

Can I perform a similar assignment to the column?  This, 
myArr[][0] = 5, doesn't work.


Thanks!


Here's a solution using standard-library functions:

import std.range: transversal;
import std.algorithm: map, fill;
import std.stdio: writefln;

void main()
{
byte[3][3] myArr;
myArr[]
.map!((ref row) => row[])
.transversal(0)
.fill(byte(5));
writefln("%(%s\n%)", myArr[]);
}

The only tricky part here is the call to `map`, which is 
necessary to change the type of the rows from `byte[3]` (which is 
not a range type) to `byte[]` (which is one).


Once we've done that, `transversal(0)` lets us iterate over the 
items at index 0 in each row (in other words, over the first 
column), and `fill` sets each of those items to the specified 
value.


By the way, if we use Godbolt to look at the generated code, we 
can see that LDC with optimizations enabled compiles this very 
efficiently--it is able to inline all the range functions and 
unroll the loop:


https://d.godbolt.org/z/orernGc9b


Re: How to access private variable of outer class from an inner struct

2023-01-15 Thread Paul Backus via Digitalmars-d-learn
On Sunday, 15 January 2023 at 12:26:15 UTC, thebluepandabear 
wrote:

If I have the following code:

```D
class X {
private int num;

struct Y {
// how to access num?
}
}
```

How would I access `num` from `Y`?

Whenever I try to I get a compilation error.

I believe that it's possible for nested/inner classes, but I 
don't know if it's possible for structs.


Help would be apprciated.


I don't think this works for structs. As a workaround, you give 
your struct an explicit reference to the outer class, like this:


```D
class X {
private int num;

struct Y {
X outer;
int fun() { return outer.num; }
}
}
```


Re: How should I return multiple const values from a function?

2023-01-02 Thread Paul Backus via Digitalmars-d-learn

On Monday, 2 January 2023 at 23:25:48 UTC, Charles Hixson wrote:


They syntax I wanted was something like:

bool func (const out Key k, const out Val v) { k = 
this.key.dup; v = this.val.dup; return true;    }


This works for me:

import std.typecons;

auto func(Key, Value)(Key k, Value v)
{
return Tuple!(const(Key), const(Value))(k, v);
}

void main()
{
string k;
uint v;
auto result = func(k, v);

static assert(is(typeof(result[0]) == const(string)));
static assert(is(typeof(result[1]) == const(uint)));
}


Re: How should I return multiple const values from a function?

2023-01-02 Thread Paul Backus via Digitalmars-d-learn

On Monday, 2 January 2023 at 22:53:13 UTC, Charles Hixson wrote:
I want to return values of the template parameter type, so 
there doesn't seem to be any way to dup or idup them.


It's hard to say where exactly you're going wrong if you only 
post the error message, without the code that produced it. If you 
post your code (or a simplified version with the same problem), 
I'm sure someone will be able to help you.


Re: Confusion about `Random`

2022-12-22 Thread Paul Backus via Digitalmars-d-learn
On Thursday, 22 December 2022 at 16:23:16 UTC, jwatson-CO-edu 
wrote:
I am confused about why Program 1 produces random output but 
Program 2 does not.


The code you have posted as "Program 2" is incomplete, and cannot 
be compiled as-is. I have made some changes in order to get it to 
compile and produce useful output, resulting in the following 
program:


 sparrow_core.d

```d
module sparrow_core;

import std.random;

Mt19937 rnd; // Randomness

void init_random(){
// Seed the RNG with the clock
rnd = Random( unpredictableSeed );
}

double rand01(){
// Uniform random sampling in [0,1)
return uniform( 0.0, 1.0, rnd);
}

void init_SPARROW(){
// Populate necessary global structures
init_random(); // --- RNG
}
```

 app.d

```d
module app;

import sparrow_core;
import std.stdio;

void main(){
init_SPARROW();
foreach (i; 0 .. 6)
writeln(rand01());
}
```

When I compile and run the above program, I get the following 
output:


```
0.289729
0.39377
0.693163
0.232496
0.388511
0.840994
```

So, as far as I can tell, there is nothing wrong with your code, 
and the random number generator is working as intended.


Most likely you have made a mistake somewhere in the part of the 
code that you did not post, and that mistake is what's causing 
the lack of randomness you observed in the output.


Re: /usr/bin/ld: [...] undefined reference to _D3std6format6internal6write...

2022-12-20 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 20 December 2022 at 20:01:04 UTC, Anonymouse wrote:

What does `-allinst` even do


`-allinst` tells the compiler to generate code for all 
instantiated templates, even if it thinks that code has already 
been generated in a different object file.


Why would the compiler think that? Sometimes, which templates get 
instantiated can depend on which flags the code is compiled with. 
If you compile your code with one set of flags, and link it 
against a library compiled with a different set of flags, then 
the different invocations of the compiler may disagree on which 
templates should end up in which object files.



and why does it seem to be insufficient here?


Hard to say without more information. Are you compiling with 
`-preview=dip1000`? If not, does adding that flag fix the error?


Re: Thinking about the difference between fixed and 'dynamic' arrays.

2022-12-03 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 3 December 2022 at 22:46:31 UTC, DLearner wrote:

I agree should not change existing meaning of
```
int[] A;
```

But why not allow a construct for value-type variable arrays 
like:

```
int[*] B;
```


There's no reason to add more complexity to the language for this 
when the same result can already be achieved using existing 
language features.


Re: Thinking about the difference between fixed and 'dynamic' arrays.

2022-11-29 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 29 November 2022 at 18:59:46 UTC, DLearner wrote:
To me, it appears that there are really two (_entirely 
separate_) concepts:


A. Supporting the useful concept of variable length (but 
otherwise entirely conventional) arrays;
B. Supporting a language feature that acts as a window to an 
array, through which that array can be manipulated.


And currently these two concepts are combined.


Yes, this is correct.

Suggestion: it would be clearer if the two concepts were 
separated:
1. Convert 'int[] VarArr;' so it produces a straightforward 
_value-type_ variable array, called 'VarArr';
2. Implement a new concept 'int slice Window;' to produce an 
object of type 'int slice', called 'Window'.
   'Window' is a 'slice' into an int array, not an array itself 
or even a variable.


Opinions?


IMO you have it the wrong way around. The built in `T[]` type 
should remain the way it is and be used if you want a slice 
(i.e., a "window"). If you want a dynamic array with value 
semantics, you should use a library-defined container type (e.g., 
`struct DynamicArray`).


Also, to avoid confusion, we should probably go through the 
language spec and documentation and change it to say "slice" 
instead of "dynamic array" whenever it refers to a `T[]`.


Re: __traits isCopyable vs isPOD

2022-11-28 Thread Paul Backus via Digitalmars-d-learn

On Monday, 28 November 2022 at 23:11:37 UTC, Per Nordlöw wrote:
the real question I had is whether one should use `isPOD` 
instead of `isCopyable` in cases


```d
static if (__traits(isCopyable, Element))
insertAt(element, index);
else
insertAt(move(element), index);
```

because that avoids any potential call to the copy-constructor 
and destructor of `Element`. Afaict, one should.


If your goal is to avoid calling the copy constructor (and, I 
assume, to avoid unnecessary instantiations of `move`), then 
yeah, `isPOD` is the one you want.


Re: __traits isCopyable vs isPOD

2022-11-28 Thread Paul Backus via Digitalmars-d-learn

On Monday, 28 November 2022 at 20:58:43 UTC, Per Nordlöw wrote:

For which types `T` does

```d
__traits(isCopyable, T)
```

differ from

```d
__traits(isPOD, T)
```

?


Lots of types. For example, types with copy constructors or 
destructors are not POD but may still be copyable.


This should be obvious if you read the definition of POD linked 
from the language spec: https://dlang.org/glossary.html#pod


Re: pointer escaping return scope bug?

2022-11-25 Thread Paul Backus via Digitalmars-d-learn

On Friday, 25 November 2022 at 14:07:28 UTC, ShadoLight wrote:
On Saturday, 19 November 2022 at 15:00:16 UTC, Paul Backus 
wrote:
Since, in your example, `lf` has global lifetime, the compiler 
deduces that `lf.fp` also has global lifetime, and therefore 
there is nothing wrong with assigning it to `p`.


I follow your rationale, but for the life of me I cannot see 
how `lf` _"has global lifetime"_.


You're right, my terminology here is sloppy. I'm really talking 
about the memory pointed to by `lf`, not `lf` itself, so I should 
really say that `lf` *points to memory* with global lifetime (or 
perhaps "`*lf` has global lifetime").


Re: "Little Scheme" and PL Design (Code Critique?)

2022-11-21 Thread Paul Backus via Digitalmars-d-learn
On Thursday, 17 November 2022 at 22:05:45 UTC, jwatson-CO-edu 
wrote:
* Compatibility with both Windows and Linux. What do I need to 
consider?

  - Can I create threads/processes under Windows?


[core.thread][1] and [std.process][2] provide 
platform-independent interfaces for this that should work on both 
Windows and Linux.


[1]: https://druntime.dpldocs.info/core.thread.html
[2]: https://phobos.dpldocs.info/std.process.html


Re: pointer escaping return scope bug?

2022-11-19 Thread Paul Backus via Digitalmars-d-learn
On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven 
wrote:

Hi,
The following seems like a bug to me (reduced code, FILE* 
changed to int*):

```d
@safe:

struct LockedFile
{
private int* fps;

auto fp() return scope => fps;
}

void main()
{
int* p;
{
auto lf = LockedFile(new int);
p = lf.fp;
}
assert(p != null); // address escaped
}
```
There's no error with -dip1000.
I'll file this unless I overlooked something.


I think this is intended behavior, because you *do* get an error 
if you replace `new int` with a pointer to a stack variable; e.g.,


int local;
auto lf = LockedFile();

The `return scope` qualifier on the method does *not* mean "the 
return value of this method is `scope`". It means "this method 
may return one of this object's pointers, but does not allow them 
to escape anywhere else." In other words, it lets the compiler 
determine that the return value of `lf.fp` has *the same* 
lifetime as `lf` itself.


Since, in your example, `lf` has global lifetime, the compiler 
deduces that `lf.fp` also has global lifetime, and therefore 
there is nothing wrong with assigning it to `p`.


Re: Actual lifetime of static array slices?

2022-11-16 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 15 November 2022 at 14:05:42 UTC, Siarhei Siamashka 
wrote:

On Tuesday, 15 November 2022 at 13:16:18 UTC, Paul Backus wrote:
D's safety model is the same. In `@safe` code, D will reject 
anything that the compiler cannot say for sure is memory safe. 
However, unlike in Rust, `@safe` is not the default in D, so 
you must mark your code as `@safe` manually if you want to 
benefit from these checks.


I specifically asked for Ali's opinion. Because the context is 
that the compiler couldn't catch a memory safety bug in the 
code that was annotated as @safe (but without -dip1000) and Ali 
commented that "the compiler cannot do anything about it in all 
cases and we wouldn't want it to spend infinite amount of time 
to try to determine everything". This sounds like he justifies 
the compiler's failure and accepts this as something normal.


The https://dlang.org/spec/memory-safe-d.html page also 
provides a rather vague statement: "@safe functions have a 
number of restrictions on what they may do and are intended to 
disallow operations that may cause memory corruption". Which 
kinda means that it makes some effort to catch some memory 
safety bugs. This weasel language isn't very reassuring, 
compared to a very clear Rust documentation.


The goal of `@safe` is to ensure that memory corruption cannot 
possibly occur in `@safe` code, period--only in `@system` or 
`@trusted` code. If the documentation isn't clear about this, 
that's failure of the documentation.


However, there are some known issues with `@safe` that require 
breaking changes to fix, and to make migration easier for 
existing code, those changes have been hidden behind the 
`-dip1000` flag. So in practice, if you are using `@safe` without 
`-dip1000`, you may run into compiler bugs that compromise memory 
safety.


That's what happened in your example. Slicing a stack-allocated 
static array *shouldn't* be allowed in `@safe` code without 
`-dip1000`, but the compiler allows it anyway, due to a bug, and 
the fix for that bug is enabled by the `-dip1000` switch.





Re: Actual lifetime of static array slices?

2022-11-15 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 15 November 2022 at 13:01:39 UTC, Siarhei Siamashka 
wrote:
Well, there's another way to look at it: 
https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html 
('Unsafe Rust exists because, by nature, static analysis is 
conservative. When the compiler tries to determine whether or 
not code upholds the guarantees, it’s better for it to reject 
some valid programs than to accept some invalid programs. 
Although the code might be okay, **if the Rust compiler doesn’t 
have enough information to be confident, it will reject the 
code**. In these cases, you can use unsafe code to tell the 
compiler, “Trust me, I know what I’m doing.”')


Are you saying that the D safety model is different? In the 
sense that if the D compiler doesn’t have enough information to 
be confident, it will accept the code?


D's safety model is the same. In `@safe` code, D will reject 
anything that the compiler cannot say for sure is memory safe. 
However, unlike in Rust, `@safe` is not the default in D, so you 
must mark your code as `@safe` manually if you want to benefit 
from these checks.


Re: difference between x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?

2022-11-10 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 10 November 2022 at 17:04:31 UTC, mw wrote:

Hi,

Anyone can help explain what is the difference between 
x.atomicOp!"+="(1) and atomicFetchAdd(x, 1)?


Looking at the source in druntime, `atomicOp!"+="` forwards to 
`atomicFetchAdd` internally, so they should have the same 
behavior.


Re: return scope vs. scope return

2022-11-05 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 5 November 2022 at 16:13:18 UTC, 0xEAB wrote:

Apparently there a difference between:

- ```d
  Message withBody(Body body_) return scope { /* … */ }
  ```
- ```d
  Message withBody(Body body_) scope return {  /* … */ }
  ```


```
Deprecation: returning `this._body` escapes a reference to 
parameter `this`

   perhaps change the `return scope` into `scope return`
```


What is it?
And why (…does the order of attributes matter)?


Basically, the `return` attribute is a modifier, and has no 
meaning on its own. Either it modifies `ref` to create `return 
ref`, or it modifies `scope` to create `return scope`. (In the 
case of a struct method, like in your example, the `ref` is 
implicit.)


In the past, if you used all 3 of `ref`, `scope`, and `return` on 
a single parameter, it was ambiguous whether the `return` was 
modifying `ref` or `scope`. This lead to a lot of confusion and 
frustration (see [this thread][1] for the gory details).


To resolve the ambiguity, Walter decided to make the *order* of 
the keywords significant: if you write `return scope`, in exactly 
that order, then `return` modifies `scope`; otherwise, it 
modifies `ref`.


I believe that the plan is to eventually require `return ref` to 
be written in exactly that order as well (see Walter's reply in 
[this thread][2]), but that's a breaking change, and will require 
a deprecation period. So in the meantime, we have kind of an 
awkward half-solution, where keyword order is significant for 
`return scope` but not for `return ref`.


[1]: 
https://forum.dlang.org/post/nbbtdbgifaurxokny...@forum.dlang.org

[2]: https://forum.dlang.org/post/snnd0r$132p$1...@digitalmars.com


Re: save() feature for iota

2022-11-03 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 3 November 2022 at 06:26:22 UTC, Salih Dincer wrote:

Hi All,

Isn't there a save feature for `iota()`?


Looking at the source, it seems that only the numeric overloads 
of `iota` implement `save`. I think this is probably just an 
oversight, though, since I can't see any reason why `save` 
wouldn't work just as well for the generic version.


I've submitted an enhancement request for this to the D bug 
tracker: https://issues.dlang.org/show_bug.cgi?id=23453


Re: Unit testing a function returning void

2022-11-03 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 3 November 2022 at 10:00:27 UTC, Bruno Pagis wrote:

Good morning,
I have the following class:

```
class A {
  int[] array;

  ...

  void print() {
writeln("array = ", this.array);
  }
}
```

I would like to unit test the print function (yes, I know, not 
very useful on the above example since print is merely a 
duplicate of writeln...). Is there a way to use assert to test 
the output of the print function to stdout?


The easiest way to do this is to modify the function so it can 
output somewhere other than stdout. Then you can have it output 
to a file in the unittest, and check the contents of the file to 
verify the result.


For example:

```d
import std.stdio;

class A
{
int[] a;

this(int[] a) { this.a = a; }

void print(File output = stdout) {
output.writeln("array = ", this.a);
}
}

unittest {
import std.file;

A a = new A([1, 2]);
a.print(File("test.txt", "wb"));
assert(readText("test.txt") == "array = [1, 2]\n");
}
```


Re: public vs private alias this

2022-11-01 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 1 November 2022 at 23:01:57 UTC, Per Nordlöw wrote:

When is it preferrable to use

```d
struct S { private T t; alias t this; }
```

instead of

```d
struct S { public T t; alias t this; }
```

for any given type `T`?


If the `alias this` needs to work outside the module where `S` is 
defined, you must make the member variable `public`. So in almost 
all cases, the second form is the correct one.


  1   2   3   4   5   6   7   8   9   >