Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix Issue 12368 - std.file.write conflicts with std.stdio.write #2011

Merged
merged 4 commits into from
Mar 27, 2016

Conversation

CyberShadow
Copy link
Member

@yebblies
Copy link
Member

@monarchdodra
Copy link
Collaborator

Good luck.

Yeah, I think that's by design...

@andralex
Copy link
Member

Yah, it doesn't seem this is needed. At some point or another, libraries (including stdlib) and applications will expose the same name from different modules. It doesn't seem that adding aliases like this would scale well.

@yebblies
Copy link
Member

@andralex Shouldn't we try and prevent these conflicts at least within phobos? The std.file.write vs std.stdio.write comes up again and again, because all of my modules import std.stdio.

I love that the module system lets us disambiguate manually, but it would be better not to have to...

@andralex
Copy link
Member

But this changes "call std.file.write" with "call fileWrite". Hardly progress. Also instead of using well-known qualification people need to learn a new symbol. How is this any better?

@yebblies
Copy link
Member

I guess, although the old name is retained, so it's an alternative and not a replacement.

I'm more concerned about future phobos additions introducing more conflicts. encode and compress are two which seem likely.

@andralex
Copy link
Member

I guess, although the old name is retained, so it's an alternative and not a replacement.

It's more churn for no progress.

I'm more concerned about future phobos additions introducing more conflicts. encode and compress are two which seem likely.

I understand. Let's cross that bridge when we get to it.

OK to close?

@JakobOvrum
Copy link
Member

There have been lengthy discussions about unambiguous contextual names versus pushing the burden of disambiguating on the user. Although it's a bit of a hand-wavy argument, I think the consensus generally gravitates towards the latter approach, and that is certainly the approach exercised in Phobos today. If someone wants to change this - as I said in the bug report too - it should be taken up in dm.D, not in a small Github PR.

@CyberShadow
Copy link
Member Author

After posting this, I realized that this was not, in fact, the change that I wanted.

The problem with disambiguating conflicts using the fully-qualified module name is that it doesn't work with UFCS chaining. However, the write signature isn't very UFCS-friendly to begin with, because you're most likely to be chaining the data to write to the file, and not the filename. So I what I really wanted was a writeTo function with the arguments swapped. I don't know if that passes the trivia test, though, but it does solve two tiny annoyances in one go.

Anyway, I'd like to reply to two arguments posted here:

If someone wants to change this - as I said in the bug report too - it should be taken up in dm.D, not in a small Github PR.

I sort of disagree here, because discussions on the NG come and go, lots of things and proposals and arguments are presented and ultimately no one comes up with something concrete and the discussion stalls and nothing gets done. A GitHub PR presents a concrete change that can be reviewed on its own merits.

Second, Jakob brought up the renamed import argument. I'm not sure I like the idea of renamed imports in general, because these are only a little better than pasting a bunch of custom helper functions at the top of each module. In effect, you are creating your very own tiny adapter library, with new symbols that map to symbols in the standard library, which everyone reading your code needs to know. They won't be encapsulated properly and they will likley be different from one programmer to another. These module-local "customizations" bother me more than the other proposed solutions, personally.

OK to close?

Do we want a writeTo? If not, OK to close.

@andralex
Copy link
Member

I think there's merit in toFile that takes buffer first and file second.

@andralex
Copy link
Member

How about we make that change, document it nicely and with examples, all in this pull request.

@JakobOvrum
Copy link
Member

How about we make that change, document it nicely and with examples, all in this pull request.

Agreed, toFile can justify itself with a nice UFCS example. It should then be obvious to the reader which of them is used for what (write and toFile should probably reference each other with See_Also as well).

@CyberShadow
Copy link
Member Author

Hmm. I've been thinking.

A toFile function would be more useful if it would accept a range, rather than only an array. This way, one wouldn't need to buffer all the data of a range into memory just to send it to disk immediately after.

std.stdio.File already has a range interface (LockingTextWriter), but it would not be suitable here because it does some complicated things with string types, which go against the principle of std.file.write (you wouldn't be able to use it to e.g. convert a file to UTF-32 without casting the dstring to an uint[] first).

So, there would be two overloads of toFile with different template constraints (one for arrays of POD types, such as void[] or string, and one for ranges). Question: what should the constraints for those be? Is there precedent for this in Phobos? Or am I massively overthinking this and should just leave it at arrays like std.file.write?

@andralex
Copy link
Member

YES. I was thinking the exact same thing. toFile is the perfect sink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

@CyberShadow
Copy link
Member Author

All right, pushed first toFile implementation. I like how the example turned out, a nice showcase of std.algorithm and std.range, although it might be a bit too much for this particular function.

@CyberShadow
Copy link
Member Author

Here is its output, BTW:

out

@andralex
Copy link
Member

Oh, I was expecting toFile to take the file name, but taking a File is even better it seems.

@CyberShadow
Copy link
Member Author

I added a convenience shorthand which takes a filename too, if that's OK :)

recurrence!((a, n) => x + y*1i + a[n-1]^^2)(0+0i)
.take(ubyte.max)
.countUntil!(z => z.re^^2 + z.im^^2 > 4))
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is on its own line the previous one should be as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this?

iota(-1, 3, 2.0/size).map!
(
    y => iota(-1.5, 0.5, 2.0/size).map!
    (
        x => cast(ubyte)(1+
            recurrence!((a, n) => x + y*1i + a[n-1]^^2)(0+0i)
            .take(ubyte.max)
            .countUntil!(z => z.re^^2 + z.im^^2 > 4))
    )
).toFile(stdout);

It looks a bit weird...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, the previous closing paren

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you mean the next one (since this comment is attached to the first one's line). Okay.

@andralex
Copy link
Member

lgtm modulo nits

@andralex
Copy link
Member

I'd say no shorthand; for consistency we'd need to put it in std.file, which is odd.

@andralex
Copy link
Member

r.toFile(File("name")) is good enough

@CyberShadow
Copy link
Member Author

r.toFile(File("name"))

That'll open it for reading, not writing... and you'll almost surely want "b" so your binary data doesn't get corrupted.

@CyberShadow
Copy link
Member Author

So, what of the shorthand? Aye or nay? It appears to be hanging by the "rb" mode string.

r.front.toFile(f);
r.popFront();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why is this function better than:

r.copy(f);

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. File does not have a range interface, LockingTextWriter does
  2. LockingTextWriter does some things with strings to put them in the FILE*'s orientation
  3. Since we know it doesn't make sense to write pointers to files, we can have toFile write arrays and ranges of any number of dimensions (see the example).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File is not an output range. You have to use File.lockingTextWriter for that, which apparently deals with text.

edit:

Oops, didn't refresh.

@braddr
Copy link
Member

braddr commented Mar 16, 2014

This pull request hung on all the non-windows testers

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
12379 Add toFile function which writes its first argument to a file

@CyberShadow
Copy link
Member Author

OK, fixed up and updated.

@JackStouffer
Copy link
Member

Proper/safe file writing is beyond me, so I can't really comment on the quality, but I am glad this isn't dead as it has some cool changes :)

@quickfur
Copy link
Member

lockingBinaryWriter is something we ought to have had since a long time ago! (IMO :-P) So the sooner this merges, the better.

.countUntil!(z => z.re^^2 + z.im^^2 > 4))
)
)
.copy(stdout.lockingBinaryWriter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Love this code example.

FILE* fps_;

// the unshared version of fps
@property _iobuf* handle_() @trusted { return cast(_iobuf*)fps_; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after )

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andralex
Copy link
Member

Auto-merge toggled on

@andralex
Copy link
Member

Auto-merge toggled off

@andralex
Copy link
Member

I approve the addition with the nits mentioned. Go for it!

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
12379 Add toFile function which writes its first argument to a file

@CyberShadow
Copy link
Member Author

Fixed style nits.

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
12379 Add toFile function which writes its first argument to a file

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
12379 Add toFile function which writes its first argument to a file

@JakobOvrum
Copy link
Member

Auto-merge toggled on

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.