www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - scoped chdir and similar patterns

reply Timothee Cour <thelastmammoth gmail.com> writes:
A1.

Is there a (clever?) way to achieve the following using a single function
call?

//does chdir

void fun(){
...
  string dir0=getcwd;  scope(exit) chdir(dir0);  chdir(dir);
...
}

//desired:
void fun(){
...
  chdir_scoped(dir);
...
}

AST macros should make that easy, but that's not for tomorrow apparently...

A2.
Likewise with temp file creation and similar patterns.

A3.
can we support an optional dir argument in the std.process functions to
execute inside a given directory dir (I believe the exec family should
support this)
Dec 04 2013
next sibling parent reply "qznc" <qznc web.de> writes:
On Thursday, 5 December 2013 at 01:07:19 UTC, Timothee Cour wrote:
 A1.

 Is there a (clever?) way to achieve the following using a 
 single function
 call?
You could (mis)use destructors. ============= struct chdir_scoped { string olddir; this(string newdir) { olddir = "bar"; writeln("chdir to "~newdir); } ~this() { writeln("chdir back to "~olddir); } } int main() { auto x = chdir_scoped("foo"); writeln("doing work in foo"); return 0; } ============= Output: chdir to foo doing work in foo chdir back to bar ============= Feels hacky to me, since "x" is not used anywhere.
Dec 04 2013
next sibling parent "anonymous" <anonymous example.com> writes:
On Thursday, 5 December 2013 at 06:24:52 UTC, qznc wrote:
 =============
 struct chdir_scoped {
   string olddir;
   this(string newdir) {
     olddir = "bar";
     writeln("chdir to "~newdir);
   }
   ~this() {
     writeln("chdir back to "~olddir);
   }
 }

 int main() {
   auto x = chdir_scoped("foo");
   writeln("doing work in foo");
   return 0;
 }
 =============
 Output:
 chdir to foo
 doing work in foo
 chdir back to bar
 =============

 Feels hacky to me, since "x" is not used anywhere.
with(chdir_scoped("foo")) writeln("doing work in foo"); Alas: https://d.puremagic.com/issues/show_bug.cgi?id=8269
Dec 05 2013
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 05, 2013 07:24:50 qznc wrote:
 On Thursday, 5 December 2013 at 01:07:19 UTC, Timothee Cour wrote:
 A1.
 
 Is there a (clever?) way to achieve the following using a
 single function
 call?
You could (mis)use destructors. ============= struct chdir_scoped { string olddir; this(string newdir) { olddir = "bar"; writeln("chdir to "~newdir); } ~this() { writeln("chdir back to "~olddir); } } int main() { auto x = chdir_scoped("foo"); writeln("doing work in foo"); return 0; } ============= Output: chdir to foo doing work in foo chdir back to bar ============= Feels hacky to me, since "x" is not used anywhere.
That technique is called RAII - Resource Acquisition Is Initialization - and it's a standard technique in C++ which D's structs also purposefully support. In C++, without it, having exception-safe C++ is very, very difficult, if not impossible. Prime examples of it are smart pointers and mutex autolocks/guards. Unlike C++, D has finally and scope statements (as well as the GC), which help, but still, RAII is vital for a number of paradigms. I can understand that it seems a bit weird to have a variable that you declare and don't do anything else with, but there's nothing hacky about it. It's an extremely useful and heavily-used paradigm. https://en.wikipedia.org/wiki/RAII - Jonathan M Davis
Dec 05 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-12-05 02:07, Timothee Cour wrote:
 A1.

 Is there a (clever?) way to achieve the following using a single
 function call?

 //does chdir

 void fun(){
 ...
    string dir0=getcwd;  scope(exit) chdir(dir0);  chdir(dir);
 ...
 }

 //desired:
 void fun(){
 ...
    chdir_scoped(dir);
 ...
 }
Delegates can be used as well: chdir_scoped!({ chdir(dir); }); void chdir_scoped (alias block) () { string dir0=getcwd; scope(exit) chdir(dir0); block(); ) -- /Jacob Carlborg
Dec 04 2013