Jump to page: 1 2
Thread overview
Introducing alid
Sep 12, 2022
Ali Çehreli
Sep 12, 2022
rikki cattermole
Sep 12, 2022
Ali Çehreli
Sep 12, 2022
rikki cattermole
Sep 14, 2022
Ali Çehreli
Sep 14, 2022
Adam D Ruppe
Sep 14, 2022
rikki cattermole
Sep 13, 2022
Salih Dincer
Sep 13, 2022
Salih Dincer
Sep 13, 2022
Ali Çehreli
Sep 14, 2022
Salih Dincer
Sep 14, 2022
rikki cattermole
Sep 14, 2022
Salih Dincer
Sep 14, 2022
Ali Çehreli
Sep 15, 2022
Ali Çehreli
Sep 15, 2022
Salih Dincer
Sep 15, 2022
Ali Çehreli
September 12, 2022
I am happy to publish on code.dlang.org for the first time:

  https://code.dlang.org/packages/alid

Thanks to everyone who made registering a dub package so easy! :)


1) Currently, the main module in `alid` is `cached`, which

- caches range elements to ensure each is executed once (most
  useful with generator ranges that use e.g. `map`),

- as a result, elevates InputRanges to ForwardRanges (plus
  opIndex).

2) But I like `errornogc` as well, which helps throw Error
   objects from @nogc code.


Copying from the README:

* `cached` is for executing elements only once while not holding
  on to already popFront'ed elements for too long. `cached` was
  the main topic of Ali's DConf 2022 lightning talk.

* `circularblocks` was written for storing range elements by
  cached. It can be used independently.

* `blockreusable` was written as storage blocks for
  circularblocks. It can be used independently.

* `errornogc` was needed for throwing Errors from @nogc code. It
  can be used independently.

* `test` contains some helper utilities for unit testing.

Ali
September 13, 2022
Looks pretty well tested, nice!

But in other less nice things, I take it you did not test with GDC? GDC does not support cli args with the same names as dmd. One of these is -mv.

The file structure of subPackage/alid/subPackage will not require it and you will not have the cross import issues, where if you depend on errornogc you can also import (and then get linker errors) for circularblocks.
September 12, 2022
On 9/12/22 07:43, rikki cattermole wrote:
> Looks pretty well tested, nice!

Thanks! Proud with 100% coverage. :)

> But in other less nice things, I take it you did not test with GDC? GDC does not support cli args with the same names as dmd. One of these is -mv.

So far, I started learning by copying arsd's dub.json. (Thank you, Adam! The misunderstandings are mine. :) )

> The file structure of subPackage/alid/subPackage will not require it and you will not have the cross import issues, where if you depend on errornogc you can also import (and then get linker errors) for circularblocks.

If I understand you correctly, the directory structure need to be the following (also introducing src, which is clearly missing :)):

alid/src/errornogc/alid/errornogc.d
     .../circularblocks/alid/circularblocks.d
[...]

Can I add a CI step to catch all such issues? It would be awesome if dub provided that.

Ali

P.S. Another issue is function attributes seemingly used inaccurately but I asked that question on the 'learn' newsgroup already. Ping! ;)
September 13, 2022
On 13/09/2022 4:25 AM, Ali Çehreli wrote:
> On 9/12/22 07:43, rikki cattermole wrote:
>> Looks pretty well tested, nice!
> 
> Thanks! Proud with 100% coverage. :)

I was going to ask about coverage, that is awesome!

>> But in other less nice things, I take it you did not test with GDC? GDC does not support cli args with the same names as dmd. One of these is -mv.
> 
> So far, I started learning by copying arsd's dub.json. (Thank you, Adam! The misunderstandings are mine. :) )

It has the same issues, which is why I recommended against copying it.

>> The file structure of subPackage/alid/subPackage will not require it and you will not have the cross import issues, where if you depend on errornogc you can also import (and then get linker errors) for circularblocks.
> 
> If I understand you correctly, the directory structure need to be the following (also introducing src, which is clearly missing :)):
> 
> alid/src/errornogc/alid/errornogc.d
>       .../circularblocks/alid/circularblocks.d
> [...]

No, you don't need the src directory, the subPackage directory functions as this.

So:

dub.json
errornogc/alid/errornogc.d
circularblocks/alid/circularblocks.d

That'll work.

> Can I add a CI step to catch all such issues? It would be awesome if dub provided that.

There is:

https://github.com/dlang-community/setup-dlang

But it doesn't look to support gdc or have been updated in a little while. Guess I need to start pinging people about it.


> Ali
> 
> P.S. Another issue is function attributes seemingly used inaccurately but I asked that question on the 'learn' newsgroup already. Ping! ;)

I have no solution to that unfortunately beyond template all the things.
September 13, 2022

On Monday, 12 September 2022 at 09:15:34 UTC, Ali Çehreli wrote:

>

I am happy to publish on code.dlang.org for the first time:

https://code.dlang.org/packages/alid

Thanks to everyone who made registering a dub package so easy! :)

Hoş geldin AliD :)

Thank you very much for bringing these codes over a thousand lines to the D World. I was looking forward to trying it right away, and when I tried it with the classic iota() and its sister inclusiveRange(), I found that it didn't get along well with cycle().

For example:

immutable size_t pageSize = 4096;

void main()
{
  "D Compiler v".writeln(__VERSION__*.001); // D Compiler v2.087
  {
    auto r = iota(3).cached(0);/*
    auto r = iota(3);//*/

    r.cycle.take(30).writeln;
  }

  {
    auto r = inclusiveRange(3).cached(0);/*
    auto r = inclusiveRange(3);//*/

    r.cycle.take(30).writeln;
  }
}/* Prints:

/usr/src/dmd/linux/bin64/../../src/phobos/std/range/package.d(3928): Error: mutable method `source.CachedRange!(ElementCache!(Result)).CachedRange.front` is not callable using a `const` object
/usr/src/dmd/linux/bin64/../../src/phobos/std/range/package.d(3928):        Consider adding `const` or `inout` to source.CachedRange!(ElementCache!(Result)).CachedRange.front
/usr/src/dmd/linux/bin64/../../src/phobos/std/range/package.d(4060): Error: template instance `std.range.Cycle!(RefCounted!(CachedRange!(ElementCache!(Result)), cast(RefCountedAutoInitialize)0))` error instantiating
instantiated from here: `cycle!(RefCounted!(CachedRange!(ElementCache!(Result)), cast(RefCountedAutoInitialize)0))`

*/

Is it the same with the new D versions?

SDB@79

September 13, 2022

On Tuesday, 13 September 2022 at 07:25:18 UTC, SDB@79 wrote:

>

Is it the same with the new D versions?

Now I replaced the cycle() to the leftward and tried it with the current version. It works great!

0.iota!double(1,.1).cycle.cached.take(30).writeln;

// [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

Surely it's a useless implementation for cycle() I guess?

SDB@79

September 13, 2022
On 9/12/22 22:24, Salih Dincer wrote:

> `source.CachedRange!(ElementCache!(Result)).CachedRange.front` is not
> callable using a `const` object

This exposes at least two issues:

1) The error was because I did not define cached's front as const because it has to expand the underlying buffer (a member) as needed. (I would have marked the buffer 'mutable' but we don't have that in D.)

This can be solved in some ways, crudest of which is the following:

        (cast()this).expandAsNeeded(id, 1);

Which is technically undefined behavior because the 'cached' range object could really be on read-only memory but since we are talking about a range, and such objects are supposed to be mutated, it becomes an interesting discussion at that point.

(There must be other ways like casting just the buffer but it is related to the discussion below.)

After fixing it that way (not pushed to github), I hit another compilation error.

2) This point is about a topic that I brought up recently: Types gain a 'const' eagerly (and they have to, understandably).

For example, in your example you are caching an 'int', but my code sees const(int) just because std.range.Cycle.front chose to put a 'const' on itself. (With all good intentions: Cycle.front really does not mutate a Cycle object.)

However, as my range picks the element type with ElementType!T, I see const(int) as well. Again, all good so far... And here is my opApply funtion:

    int opApply(int delegate(ref EC.ET) func) scope
    {
        while(!empty)
        {
            auto f = front;

            int result = func(f);    // ERROR
            if (result)
            {
                return result;
            }
            popFront();
        }

        return 0;
    }

ERROR: delegate `func(ref int)` is not callable using argument types `(const(int))`

Oh! See: I am passing an int... oh! by ref...  I guess I shouldn't expect my users to use 'const' in their foreach parameters. (I am not trying to see whether it is possible.)

So instead, I should have decided on my storage type as int (not const(int)) in this case. It can be done like this:

            static if (hasIndirections!(EC.ET))
            {
                // Use the exact type
                alias StorageT = T;
            }
            else
            {
                alias StorageT = Unqual!T;
            }

But... Do I have the right to choose my storage type as 'int' even though I am caching const(int)? Perhaps I shouldn't because as discussed earlier in the general forum, my choice changes function overloading for my users. So, perhaps I should really store const(int)... (?)

I have to digest these issues more before jumping to a solution. :/

Ali

P.S. Related, I had to provide an opApply function because of this reason:

/**
    Support for `foreach` loops
 */
// This is needed to support foreach iteration because although
// RefCounted!CachedRange implicitly converts to CachedRange, which would be
// a range, the result gets copied to the foreach loop. Unfortunately, this
// type does not allow copying so we have to support foreach iteration
// explicitly here.
int opApply(int delegate(ref EC.ET) func) scope
{
    // ...
}

See that 'ref' there? Maybe I should have provided different opApply() functions to cover all cases. I am thinking... :)

Or maybe I should use something else other than RefCounted... Still thinking...
September 14, 2022

On Tuesday, 13 September 2022 at 15:24:20 UTC, Ali Çehreli wrote:

>

On 9/12/22 22:24, Salih Dincer wrote:
2) This point is about a topic that I brought up recently: Types gain a 'const' eagerly (and they have to, understandably).

For example, in your example you are caching an 'int', but my code sees const(int) just because std.range.Cycle.front chose to put a 'const' on itself. (With all good intentions: Cycle.front really does not mutate a Cycle object.)

However, as my range picks the element type with ElementType!T, I see const(int) as well. Again, all good so far... And here is my opApply funtion:

    int opApply(int delegate(ref EC.ET) func) scope
    {
        while(!empty)
        {
            auto f = front;

            int result = func(f);    // ERROR
            if (result)
            {
                return result;
            }
            popFront();
        }

        return 0;
    }

ERROR: delegate func(ref int) is not callable using argument types (const(int))

I'm far from making a solid recommendation. Immutable with const still doesn't make sense to me. I claim we can live without them. Immutable confuses me a lot.

I think we should take control by creating our own types. D Language should be unornamented.

SDB@79

September 14, 2022
On 14/09/2022 2:48 PM, Salih Dincer wrote:
> I'm far from making a solid recommendation.  Immutable with const still doesn't make sense to me.  I claim we can live without them. Immutable confuses me a lot.
> 
> I think we should take control by creating our own types.  D Language should be unornamented.

We have to have immutable.

You need a way in a systems language to say that a given chunk of memory is read only to prevent accidental writes.

Of course you are free to lie and say its mutable, but you can't lie to the cpu. It'll error if you try to write to it, resulting in the end of a process.
September 14, 2022

On Wednesday, 14 September 2022 at 02:58:07 UTC, rikki cattermole wrote:

>

Of course you are free to lie and say its mutable, but you can't lie to the cpu. It'll error if you try to write to it, resulting in the end of a process.

I agree with what you said. Moreover, I sign it as an electronics engineer. However, we have to perform write protection with our own types. Anyway, I don't want to get into the discussions that are full of pages.

SDB@79

« First   ‹ Prev
1 2