Thread overview
Am I misusing with?
Jan 19, 2019
faissaloo
Jan 19, 2019
Rubn
Jan 19, 2019
faissaloo
Jan 19, 2019
Q. Schroll
January 19, 2019
This seems to work fine

    file = File("test.txt", "r");
    with (file)
    {
      scope(exit) close();

      foreach (string line; file.lines())
      {
        line_array ~= line;
      }
    }

however:

    file = File("test.txt", "r");
    with (file)
    {
      scope(exit) close();

      foreach (string line; lines())
      {
        line_array ~= line;
      }
    }

Tells me I'm attempting to read from an unopened file, what's going on here? It seems like I'm able to use lines() like this within with statements unless they're in my foreach iterator. Is this a bug or intended behaviour?
January 19, 2019
On Saturday, 19 January 2019 at 17:49:31 UTC, faissaloo wrote:
> This seems to work fine
>
>     file = File("test.txt", "r");
>     with (file)
>     {
>       scope(exit) close();
>
>       foreach (string line; file.lines())
>       {
>         line_array ~= line;
>       }
>     }
>
> however:
>
>     file = File("test.txt", "r");
>     with (file)
>     {
>       scope(exit) close();
>
>       foreach (string line; lines())
>       {
>         line_array ~= line;
>       }
>     }
>
> Tells me I'm attempting to read from an unopened file, what's going on here? It seems like I'm able to use lines() like this within with statements unless they're in my foreach iterator. Is this a bug or intended behaviour?

If you look at the implementation, "lines" is a struct.

https://github.com/dlang/phobos/blob/v2.084.0/std/stdio.d#L4330

I didn't know you could use structs with UFCS, which is why you are probably confused as well. It's a function defined in "file". If you use lines() by itself, you are constructing a new "lines" struct where the default File is an unopened file.

I tend to avoid "with" altogether because of things like this. It becomes hard to tell what is actually part of the struct and what is just UFCS. If you do want to use the object with UFCS you have to explicitly use the object anyways so the point is kind of mute.

UFCS if you don't know just means you can use global functions (and apparently structs) with the same syntax as if it were a member function:


struct testStruct {
    this( int value ) {
    	import std.stdio : writeln;
        writeln("testStruct - ", value);
    }
}

void test(int value) {
    import std.stdio : writeln;
    writeln( value );
}

void main() {
    10.test(); // prints 10
    20.testStruct();
}

https://run.dlang.io/is/0Xpnmt
January 19, 2019
On Saturday, 19 January 2019 at 20:07:34 UTC, Rubn wrote:
> On Saturday, 19 January 2019 at 17:49:31 UTC, faissaloo wrote:
>> [...]
>
> If you look at the implementation, "lines" is a struct.
>
> https://github.com/dlang/phobos/blob/v2.084.0/std/stdio.d#L4330
>
> [...]

Ah that makes some sense, thanks for the explanation.
January 19, 2019
On Saturday, 19 January 2019 at 20:38:00 UTC, faissaloo wrote:
> On Saturday, 19 January 2019 at 20:07:34 UTC, Rubn wrote:
>> On Saturday, 19 January 2019 at 17:49:31 UTC, faissaloo wrote:
>>> [...]
>>
>> If you look at the implementation, "lines" is a struct.
>>
>> https://github.com/dlang/phobos/blob/v2.084.0/std/stdio.d#L4330
>>
>> [...]
>
> Ah that makes some sense, thanks for the explanation.

If you import symbols explicitly, you'd have known.

Probably in your code:

    import std.file;

What should be there:

    import std.file : File, lines;

If lines is a member of the File struct, the import fails. If lines is not a member of File, not importing it fails. You get more detailed information.
Using import bind lists [1] usually is a good idea.

[1] https://dlang.org/spec/module.html#import-declaration