Re: Why is opIndexAssign replaced by opSlice here?

2021-10-18 Thread Elmar via Digitalmars-d-learn

On Monday, 18 October 2021 at 03:42:35 UTC, Paul Backus wrote:
What happens here is, the compiler first tries the D2-style 
rewrite:


```d
s.opIndexAssign(arr[1..4], s.opSlice!0(0, 3))
```

However, that rewrite fails to compile, because your `opSlice` 
does not take a template argument specifying the dimension 
along which to slice, as specified in the language spec's 
section on ["Slice Operator Overloading".][1]


Since the above rewrite fails to compile, it falls back to 
rewriting the expression using D1-style operator overloads:


For backward compatibility, `a[]` and `a[i..j]` can also be 
overloaded by implementing `opSlice()` with no arguments and 
`opSlice(i, j)` with two arguments, respectively. This only 
applies for one-dimensional slicing, and dates from when D did 
not have full support for multidimensional arrays. This usage 
of opSlice is discouraged.


...which results in the following rewritten statement:

```d
s.opSlice(0, 3) = arr[1..4];
```

My guess is that you got into this situation by trying to 
follow the example in the spec's section on ["Slice Assignment 
Operator Overloading"][2]. Unfortunately, that example is 
incorrect.


Here is a fixed version of your example on run.dlang.io: 
https://run.dlang.io/is/dtfT5y


[1]: https://dlang.org/spec/operatoroverloading.html#slice
[2]: 
https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator


Woow! You fixed the problem, it now works for me.

I wish the compiler would have been able to make me understand 
the problem. It was no help because it only tells the final 
erroneous consequence, that the return value of `opSlice` cannot 
be assigned ("is no lvalue", beginner-unfriendly language). It 
doesn't even mention `opSlice` or the fallback (reason) with no 
warning.


Re: How to do a function pointer to "malloc" and "free"?

2021-10-17 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 17:14:30 UTC, Adam Ruppe wrote:

On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote:
The language subset "BetterC" is required for calling D 
functions from C though.


This is false.

You can use any D features when calling it from C, you just 
need to provide an init and term function that is called from C 
that runtime initialize and terminate for the full experience.



BetterC helper librarys like Tanya or Tango do exist.


I don't know tanya, but Tango has absolutely nothing to do with 
betterC. It is a set of classes that use the full runtime.


That's nice!

Do you have a link for more information how to initialize the D 
runtime? I just wondered about that because I thought it actually 
shouldn't be much more difficult than just linking the runtime 
into the foreign-language compiled program. I didn't find 
information on that. Maybe I didn't search long enough.


Re: Why is opIndexAssign replaced by opSlice here?

2021-10-17 Thread Elmar via Digitalmars-d-learn

Btw, I should have written:

`s.opIndexAssign(arr[1..4], s.opSlice(0,3));`

But it compiles the same way.


Why is opIndexAssign replaced by opSlice here?

2021-10-17 Thread Elmar via Digitalmars-d-learn

Hello Dear community.

I'd like to overload `opIndexAssign` for a struct which wraps 
around a generic array (so that it can't support `opIndex` due to 
unknown return type).


Broken down as much as possible this is the code:

```
import std.stdio : writeln;
import std.range : ElementType;

struct S {
void opIndexAssign(X, RANGE)(X x, RANGE range)
if (is(ElementType!RANGE : size_t))
{
writeln(__FUNCTION__);
}

auto opSlice(size_t start, size_t end) {
import std.range : iota;
return iota(start, end);
}
}

void main()
{
auto arr = new int[7];

S s;
s.opIndexAssign(arr, s.opSlice(1,4));  // works
	s[0..3] = arr[1..4];  // does not work, compiles to 
`s.opSlice(0,3) = arr[1..4]`

}
```

I'm clueless about why it wouldn't compile the last statement to 
`s.opIndexAssign(arr[1..4], s.opSlice(0,3))`.


Help appreciated :-)


Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote:
It would be nice if one could use pattern-matching for it in 
D. Is this possible?




As I know it's impossible, but you can use a regular template:
...


If anyone is interested in pattern matching, someone provides a 
package "dpmatch" which uses PEG (some parsing grammer which is 
implemented in D) to achieve Haskel-style pattern matching, yet 
for sum-type definitions only. And they use GC + interfaces. 
Hence it cannot be used with BetterC.


Sumtypes can also be created with the `sumtype` package which 
uses D's delegate literals for pattern matching.


Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote:


As I know it's impossible, but you can use a regular template:
```d
template isPointedStaticArray(T)
{
static if (isPointer!T)
enum isPointedStaticArray = 
isStaticArray!(PointerTarget!T);

else
enum isPointedStaticArray = false;
}
```
https://run.dlang.io/is/lR7feP
this compiles from 2.086.1 and above


That's indeed close to pattern matching and is probably the best 
answer :-) .


Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 15:01:17 UTC, Elmar wrote:


```d
enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, 
size_t N);

```

```d
	enum isPointedStaticArray(X : P*, P) = 
.isStaticArray!(PointerTarget!X);

```



`isStaticArray` is a good example that makes me ask how to 
outline an `is()` expression without losing the error catching 
semantics of the inlined `is()` expression.




Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 14:36:50 UTC, Elmar wrote:

On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote:

You just need to check if T is a pointer:
```D
import std;

alias DA = int[];
alias SA = int[3];

alias PSA = SA*;
alias PDA = DA*;

version(all)
	enum isPointedStaticArray(T) = isPointer!T && 
isStaticArray!(PointerTarget!T);

else
	enum isPointedStaticArray(T) = isPointer!T && 
is(PointerTarget!T : P[N], P, size_t N);  // this way you can 
get array length


static assert(!isPointedStaticArray!DA);
static assert(!isPointedStaticArray!SA);
static assert(!isPointedStaticArray!PDA);
static assert( isPointedStaticArray!PSA);

void main()
{
}
```
https://run.dlang.io/is/qKdx1D

Also you can use another way to detect static array - it can 
be useful if you need to get its length


Wow, this is a fine solution. I gonna use it, thank you :-) .


Well, I just wondered why your code would compile and mine 
wouldn't. The `version(all)` variant will not compile on my 
computer with `rdmd` because `PointerTarget` only allows pointers.


But the 2nd one will compile. The `is()` expression catches the 
compilation error which is nice. This is sufficient:


```d
enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, 
size_t N);

```

It would be nice if one could use pattern-matching for it in D. 
Is this possible?


```d
	enum isPointedStaticArray(X : P*, P) = 
.isStaticArray!(PointerTarget!X);

enum isPointedStaticArray(X : else) = false;
```



Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote:

You just need to check if T is a pointer:
```D
import std;

alias DA = int[];
alias SA = int[3];

alias PSA = SA*;
alias PDA = DA*;

version(all)
	enum isPointedStaticArray(T) = isPointer!T && 
isStaticArray!(PointerTarget!T);

else
	enum isPointedStaticArray(T) = isPointer!T && 
is(PointerTarget!T : P[N], P, size_t N);  // this way you can 
get array length


static assert(!isPointedStaticArray!DA);
static assert(!isPointedStaticArray!SA);
static assert(!isPointedStaticArray!PDA);
static assert( isPointedStaticArray!PSA);

void main()
{
}
```
https://run.dlang.io/is/qKdx1D

Also you can use another way to detect static array - it can be 
useful if you need to get its length


Wow, this is a fine solution. I gonna use it, thank you :-) .


Re: How to do a function pointer to "malloc" and "free"?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote:


Actually I know about BetterC and how to call C functions from 
D and visa versa. I would also disagree that "BetterC" is 
almost no improvement over C as about 90% of the language is 
there!! C++ classes are also supported


Nice :-) , you're right. I need to be more optimistic here. Happy 
coding.


Re: How to do a function pointer to "malloc" and "free"?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote:


The language subset "BetterC" is required for calling D 
functions from C though. Unfortunately, the runtime features of 
BetterC are limited and some of C's language features aren't 
availabe like C99 variable-length-arrays. "BetterC" is like 
programming in C with little more comfort but phobos is 
unusable which makes BetterC almost no improvement over C. 
BetterC helper librarys like Tanya or Tango do exist.




Oh well, I could also be wrong with BetterC support of Tanya and 
Tango but both are alterantives to Phobos.


Re: How to do a function pointer to "malloc" and "free"?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 13:10:27 UTC, rempas wrote:


Thanks, I'm converting a library from C to D so I have to fix 
all the other bugs first to see If it's working but probably it 
will. Have an amazing day my friend!


Hopefully it will :-) .

D has some good C support. You can call any C function from `D` 
by declaring it `extern(C) `.


The language subset "BetterC" is required for calling D functions 
from C though. Unfortunately, the runtime features of BetterC are 
limited and some of C's language features aren't availabe like 
C99 variable-length-arrays. "BetterC" is like programming in C 
with little more comfort but phobos is unusable which makes 
BetterC almost no improvement over C. BetterC helper librarys 
like Tanya or Tango do exist.


In that case it can indeed be better for you to convert the 
program's entry point into D code. This is unfortunate because it 
prevents C code bases from using D.


There is a tool [C++ Conversion 
Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic.


Re: What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn
PS: the title is a misnomer. `is(T : P*, P) && isStaticArray!P` 
doesn't either compile when inlined because `P` is not defined 
when not matched.


What is the proper way to outline static-if-conditions ?

2021-10-10 Thread Elmar via Digitalmars-d-learn

Hey D people.

Currently in my project I have worked on a unified type interface 
for all arrays which requires fixed-size arrays to be stored as 
pointer (in correspondence to dynamic and associative arrays) and 
allow them being allocated with any selected allocator.


There can be code like this:

```d
enum isPointedStaticArray(T) = (is(T : P*, P) && 
.isStaticArray!P);


//...
static if (.isPointedStaticArray!T)
{
// ...
}
```

It won't compile when the argument of `isPointedStaticArray()` is 
NO pointer.


The compiler complains, about **`P` being undefined**.

What is the best workaround for this?
It's crazy. I can reverse the problem that it only fails if the 
argument IS a pointer:


```d
enum isPointedStaticArray(T) =
(){
		enum condition = `is(`~T.stringof~` : P*, P) && 
.isStaticArray!P`;

static if (__traits(compiles, mixin(condition)) )
return mixin(condition);  // "P already defined" error
else
return false;
}();
```

Types defined in `__traits(compiles, ...)` are emitted to the 
outside?!


Okay, this is my current workaround:

```d
enum isPointedStaticArray(T) =
(){
static if (is(T : P*, P))
return .isStaticArray!(P);
else
return false;
}();

// ...
static if (isPointedStaticArray!T)
{

}
```

for outlining an expression `is(...) && ...`


Is there a simpler way in D to do this? If there only would be a 
`&&&` short circuit operator which doesn't compile the right side 
if the left side wouldn't compile to true.


Did someone already had the idea of a `static-try-catch` which 
catches compilation errors?


Re: What is a "comma expression"?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote:
This is the first time I'm finding something like that. I'm 
having the following code in C:


```
  if (0 == (i >> 7)) {
if (len < 1) return -1;
v = i;
return *ret = v, 1;
  }
```

This is part of a function that returns an `int`. When I'm 
running this in C, it works. However in D, I'm getting the 
following error message:


```
Error: Using the result of a comma expression is not allowed
```

Can someone explain what comma expressions are and why they 
don't work in D (or if the only doesn't work as returned values 
from a function)?


Hello rempas.

The comma-operator `,` is like `;` but results in an expression 
value, not a statement like `;` would. The left side of `,` is 
executed like a statement and the value of the right side of `,` 
is returned. Comma-expressions are merely used to pack additional 
instructions into places where only expressions are allowed.


```d
if (x = y, myNiceFunction(), yay(x), x > 5)
{
   // ...
}
```

or

```d
if (hasFancyFunkyStuff)
x = z, fancy(x), funkyUpdate(z);   // too lazy for braces
```

Many consider the `,` operator to be a design-flaw because it 
makes expressions difficult to read and can be easily abused 
because the above should actually be:


```d
x = y;
myNiceFunction();
yay(x);
if (x > 5)
{
// ...
}
```

In `D` you can still write the second example of code but not the 
first example of code. The designers of D thought they could make 
it less painful by just forbidding comma-expressions to be used 
as expression value and only as statement. This is because then 
comma-expressions can still be used in `for`-loops:


```d
for (x = y, z = a; x < z; x++, z--)
{
;
}
```

In conclusion, your C snippet should actually look like:

```c
  if (0 == (i >> 7))
  {
if (len < 1)
  return -1;
*ret = v = i;
return 1;
  }
```

The previous snippet even could mislead readers to think that it 
would return a tuple of two elements which it doesn't.


Re: How to do a function pointer to "malloc" and "free"?

2021-10-10 Thread Elmar via Digitalmars-d-learn

On Sunday, 10 October 2021 at 10:44:15 UTC, rempas wrote:

I'm having the following C code:

```
static void* (*ppmalloc)(size_t) = malloc;
static void (*ppfree)(void*) = free;
```

I want to covert this code in D so I try to do the following:

```
static void* function(size_t)*ppmalloc = malloc;
static void  function(void*)*ppfree = free;
```

If I do that, I'm getting the following error message:

```
Error: function `core.stdc.stdlib.malloc(ulong size)` is not 
callable using argument types `()`

```

I'm also trying to do the same using "pureMalloc" and 
"pureFree" instead but this time I'm getting the following 
error:


```
cannot implicitly convert expression `pureMalloc()(size_t 
size)` of type `void` to `extern (C) void* function(ulong)*`

```

Any ideas?


Hello rempas.

This is the way:

```d
import core.stdc.stdlib : malloc, free;
extern(C) void* function(ulong) mallocPointer = 
extern(C) void function(void*) freePointer = 
```

`function` in the type is already a function pointer. Not 
immediately obvious though: You also must annotate the type with 
`extern(C)` otherwise it will not work.


What is the meaning of @future ?

2021-09-16 Thread Elmar via Digitalmars-d-learn

Hello D community.

I was browsing the `__traits` keywords and I found `isFuture` 
whose descriptions says something about `@future`-annotated 
variables.


[link](https://dlang.org/spec/traits.html#isFuture)

I didn't find anything about `@future` for the D programming 
language. I only found that this annotation is used in Apex to 
denote futures (a.k.a. promises) as programming concept.


Is this something which exists, existed, was abandoned early as 
an idea? I remember I had read that D uses a "fiber" library to 
provide coroutines and such.


Maybe somebody knows an answer for this.


Re: Array permutations

2021-09-16 Thread Elmar via Digitalmars-d-learn
I also should discourage its current form with large 
`tupleSize`s. The computation is in O(exp(values.length)). 
Instead of `~=` I would suggest an `std.array.appender` of arrays 
instead of an 2D-array for the `choices`, if the `choices` become 
large. Most efficient is a preallocated array capacity. In that 
case `~=` has very low overhead.


Re: Array permutations

2021-09-16 Thread Elmar via Digitalmars-d-learn

On Saturday, 11 September 2021 at 19:37:42 UTC, Vino wrote:

Hi All,

   Request your help on the below to print the below array as 
"Required output", Was able to get these values 
"[1,2],[2,3],[3,4],[4,5]" by using list.slide(2), need your 
help to get values "1,3],[1,4],[1,5],[2,4],[2,5],[3,5]"


auto list[] = [1,2,3,4,5]

Required output
[1,2],[2,3],[3,4],[4,5],[1,3],[1,4],[1,5],[2,4],[2,5],[3,5]

From,
Vino


Would this be a valid solution to your problem?

```D
pure @safe nothrow
T[][] computeChoices(T)(T[] values, size_t tupleSize = 2)
{
if (tupleSize == 0) {
return [[]];
}

T[][] choices = [];
tupleSize--;
foreach(i, element; values[0 .. $ - tupleSize])
{
import std.algorithm.iteration : map;
import std.array : array;
choices ~= computeChoices(values[i+1 .. $], tupleSize)
.map!(choice => element ~ choice)
.array;
}

return choices;
}

unittest
{
assert(computeChoices([1, 2, 3, 4, 5], 2)
   	== [[1,2], [1,3], [1,4], [1,5], [2,3], [2,4], [2,5], 
[3,4], [3,5], [4,5]] );

}
```

You can choose in the 2nd parameter how large the inner arrays 
should be. It uses GC to allocate the result via the function 
`array`. If that is a problem, you could choose an allocator from 
`std.experimental.allocator` and use the `makeArray` function 
with the allocator instead of the `array` function. (Manual 
deallocation could be required then as well.)


Re: Forward references

2021-06-10 Thread Elmar via Digitalmars-d-learn

Hello there,

I got a weird compilation error which was hard to debug (even for 
just a little program) and I thought, this is quite related to 
this thread. This is my error message:


```
***search.d(42,1): Error: class ***.XXX has forward references
***box.d(21,32): Error: template instance *** error instantiating
***.d(16,2):instantiated from here: ...
...

```

It was odd, the fix was not obvious and the compiler didn't show 
me the place of the erroneous forward reference. The problem was 
a scoped `import` statement!! I had put the import statement for 
the Box class into the abstract base class Search, the only place 
where it is used, but this seems to cause a mess with many 
errors. The imported Box uses a sub class of Search as parameter 
type and since Search is extended by its subclasses it creates a 
circular reference in the subclass. The only way to fix was 
putting the import outside of the abstract base class (I assume 
because the import statement literally imports the Box together 
with the used subclass into Search itself).


The lesson is, you cannot put your import just everywhere.



Re: Working with ranges

2021-05-29 Thread Elmar via Digitalmars-d-learn

On Saturday, 29 May 2021 at 19:55:30 UTC, Elmar wrote:
In many or most of the cases the use case doesn't actually 
require GC-allocation.


Btw, I'm talking about core-level and systems software which 
concentrates on data transformations.


When I only want to access a data structure but not mofify it 
then GC-allocation would not fit the lifetime logic of a 
variable.


With "modification" I mean the data's size or it's order in 
memory but not the stored data itself.


Re: Working with ranges

2021-05-29 Thread Elmar via Digitalmars-d-learn

On Wednesday, 26 May 2021 at 15:07:12 UTC, Jack wrote:

On Wednesday, 26 May 2021 at 13:58:56 UTC, Elmar wrote:
On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe 
wrote:

[...]


That's amazing, this should be one thing that should appear in 
every tutorial just right at the start! I was looking hours 
for a way to generate an "iterator" (a range) from a 
fixed-size array which doesn't copy the elements (unless 
elements are deleted/added).


[...]


maybe array from std.array to make that range in array of its 
own?


The main incentive here is, that I would like to obtain an 
iterator (some kind of access view) over a background storage 
which can be anywhere in memory which I don't care about. It 
might be on stack frame. In many or most of the cases the use 
case doesn't actually require GC-allocation. `array()` does 
GC-allocation and personally, I think `array()` should be avoided 
whereever the use case doesn't justify GC-allocation, at least if 
you care for *logically correct* memory management of your 
program.
GC-allocation might just work the same way (most of the time even 
better than with stack-allocated storage due to design of D) and 
it adds convenience for you to omit explicit destruction calls 
which can spare you some conditional checks if the need for 
destruction depends on runtime cases. But with logical 
correctness I mean appropriateness here, an allocation scheme 
which reflects the nature of a variable's lifetime correctly. For 
example, if the lifetime, maximum storage requirements or the 
de-/allocation points in code are already known at compile-time 
then GC-allocation isn't appropriate. It has many drawbacks in 
performance critical sections, such as non-deterministic 
destruction time (which probably is the worst), the overhead of 
scanning GC-allocated regions and the memory fragmentation caused 
by dynamic allocation (i.e. non-deterministic available storage 
space) and in the worst case provides additional attack vectors, 
e.g. with heap overflows or use-after-free. In many cases, it is 
just better to GC-allocate an entire growable pool or slaps of 
objects for fast use-case specific allocation.



So whatfor I would like to use an iterator? An iterator basically 
is a meta-data structure which stores meta data (like indices and 
pointers) for accessing another data structure's contents. And if 
I just want to change the access of or iteration over a data 
structure then I don't need to touch how the actual data or 
memory is stored and I don't even require expensive memory 
allocation when I could rearrange the iterator contents inplace 
and if the meta data is much smaller than the actual data. All 
that is not achieved by `array()`. `array()` is not an iterator 
but a dynamically allocated copy. Using an iterator like 
`array[]` saves me expensive GC-allocations. When I only want to 
access a data structure but not mofify it then GC-allocation 
would not fit the lifetime logic of a variable.


When I understand correctly then the iterator concept in D is 
called "range". Ranges neither designate a data structure nor a 
specific data arrangement but it defines a generic access 
interface of aggregate data whose purpose is to work independent 
of whatever data structure is accessed via this interface.


Now, I'm only missing methods to allocate range iterators on the 
stack or modifying iterators inplace.


Re: Working with ranges

2021-05-26 Thread Elmar via Digitalmars-d-learn

On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe wrote:

On Saturday, 8 December 2018 at 03:48:10 UTC, Murilo wrote:
Try passing `ps[]` to the function instead of plain `ps` and 
see what happens.


How do I transform an array into a range?


With the slicing operator, [].


That's amazing, this should be one thing that should appear in 
every tutorial just right at the start! I was looking hours for a 
way to generate an "iterator" (a range) from a fixed-size array 
which doesn't copy the elements (unless elements are 
deleted/added).


But my issue now is, I have strided arrays (or just any Result 
range) and I want to use the slicing operator `[]` with that 
range to copy it into a fixed-size array or apply element-wise 
operations on it. How can I do that?


This example will not compile:

```
auto starts = arr[0..$].stride(2);
auto ends = arr[1..$].stride(2);
randomNumbers[] = ends[] - starts[];
```

Because `[]` is not defined for the Result range. Is there a 
standard wrapper function which wraps an elementwise `[]` 
operator implementation around a range?