Re: $*CWD and chdir()
Martin D Kealey wrote: > I wonder if this is becoming the new Perl mantra "use lexically scoped > pragmata". Larry said it much more succinctly: all's fair if you predeclare. -- Jonathan "Dataweaver" Lang
Re: $*CWD and chdir()
On Wed, 19 Aug 2009, Timothy S. Nelson wrote: > ..but Perl is more magic than bash :). Seriously, I can see both > sides of the argument, and I'm leaning towards the $*CWD = chdir idea (as an > option if people want to use it), but I realise that a lot of people are > leaning the other way. So I'll argue for it, but don't care if I lose :). I want both. I can have both. Or in fact all three: $*CWD = "foo";# exception -- $*CWD isn't writable use Cwd :fake; $*CWD = "foo";# OK, faking it use Cwd :chdir; $*CWD = q; # OK, same as {chdir "/tmp"} I wonder if this is becoming the new Perl mantra "use lexically scoped pragmata". perl6 -MCwd=fake ... # legacy behaviour -Martin
Re: $*CWD and chdir()
Mark J. Reed wrote: On Wed, Aug 19, 2009 at 2:35 AM, Darren Duncan wrote: (If Perl really must have the ability to change the non-virtual "current working directory", such as because its going to spawn another non-Perl process, then this should use some separate mechanism to what all of Perl's own IO uses, and any such change would have no effect on any Perl $*CWD.) I would propose that whenever Perl spawns a non-Perl process, that process automatically executes a chdir() to the spawning thread's value of $*CWD. But this should be done without changing the parent process's external/OS working directory. In UNIX that's easy - fork(), then chdir(), then exec() - but in Windows it may be trickier. I agree with your proposal, which seems to better conform to expected behavior. -- Darren Duncan
Re: $*CWD and chdir()
On Wed, Aug 19, 2009 at 2:35 AM, Darren Duncan wrote: > Having read all of this thread to date, I'll state a solution which should > be elegant and which I'm not sure has been stated yet. I think that's basically what we were suggesting above, except: > (If Perl really must have the ability to change the non-virtual "current > working directory", such as because its going to spawn another non-Perl > process, then this should use some separate mechanism to what all of Perl's > own IO uses, and any such change would have no effect on any Perl $*CWD.) I would propose that whenever Perl spawns a non-Perl process, that process automatically executes a chdir() to the spawning thread's value of $*CWD. But this should be done without changing the parent process's external/OS working directory. In UNIX that's easy - fork(), then chdir(), then exec() - but in Windows it may be trickier. -- Mark J. Reed
Re: $*CWD and chdir()
Having read all of this thread to date, I'll state a solution which should be elegant and which I'm not sure has been stated yet. I propose that the concept of "current working directory" in Perl be a completely internal, virtual concept, and each Perl thread has its own "current working directory", and that Perl exclusively talks to the real file-system in terms of absolute paths. This means that the real file-system's chdir() is never invoked during the execution of a Perl program, and a Perl process' external concept of "current working directory" is static, not changing during its execution, as if the concept didn't actually exist. When a Perl process starts up, its internal $*CWD starts out identical to the external/system one, but any changes to $*CWD then move them out of sync. When a new Perl thread starts, its own separate $*CWD starts out identical to that of the thread that spawned it, but otherwise evolves separately. Perl can have a chdir(), but it only affects the virtual concept, same as updates to $*CWD do. All relative or not-fully-qualified paths used with IO operations in Perl are interpreted relative to the current thread's $*CWD, and then their action takes place external to Perl in terms of absolute/fully-qualified paths in the file system. If these suggestions are followed, we should have a solution that is all of: simple, thread-safe, portable, no surprises, etc. (If Perl really must have the ability to change the non-virtual "current working directory", such as because its going to spawn another non-Perl process, then this should use some separate mechanism to what all of Perl's own IO uses, and any such change would have no effect on any Perl $*CWD.) -- Darren Duncan
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 7:03 PM, Mark J. Reed wrote: > The OS-level chdir() and getcwd() are not thread-safe. The usual > advice is to ignore them completely in multithreaded programs, in > favor of absolute paths (or relative paths from a fixed location, > never calling chdir()). This is part of the a reason that Apache2 > recommends fastcgi for non-prefork MPMs (since the CGI spec requires > cgi scripts to start with getcwd() set to the directory containing > them). I like Timothy's suggestion: do not associate $*CWD with chdir at all, but tie $*CWD in with every standard routine that makes use of the "current working directory" concept. Keep chdir around, but add a note saying that its use should be avoided in favor of assigning to $*CWD. Ditto with getcwd and reading the value of $*CWD. The only thing that gets clobbered by this is the inability to use relative paths when changing the current working directory. Personally, I have no problem with the idea that $*CWD is a magical Path that resolves itself into an absolute Path when you assign a relative Path to it (that is, $*CWD = ($path.relative ?? $*CWD ~ $path :: $path).resolvepath, or something to that effect) - and thus is always an absolute Path; but I can understand that others have a problem with this. On a similar note, I wouldn't mind a bit of magic that has $*CWD test for the existence of the new value before actually making the change, and throwing an exception if the target is not a directory; that way, you're guaranteed that $*CWD is always a valid Path. With this magic in place, I would never be tempted to use chdir or getcwd. Alternatively, $*CWD should be readonly and have a chdir method that implements the above behavior, emulating the features of the OS's chdir in a thread-safe manner. Or just warn people _not_ to alter $*CWD directly, and change chdir and getcwd so that they alter and read $*CWD appropriately by default, and only perform their OS equivalents if you explicitly ask them to. -- Jonathan "Dataweaver" Lang
Re: $*CWD and chdir()
The OS-level chdir() and getcwd() are not thread-safe. The usual advice is to ignore them completely in multithreaded programs, in favor of absolute paths (or relative paths from a fixed location, never calling chdir()). This is part of the a reason that Apache2 recommends fastcgi for non-prefork MPMs (since the CGI spec requires cgi scripts to start with getcwd() set to the directory containing them). Since qqx has to fork a new process anyway, having it chdir(*CWD) is not a big deal - as long as it's the child, not the parent, that calls chdir(). But any process with multiple threads should generally avoid calling chdir() ever. All of this is assuming that P6's chdir() just calls the OS routine, of course. It could be made fancier and handle the thread-stuff itself... On 8/18/09, Timothy S. Nelson wrote: > Ok, here's a fairly significant point posted on IRC. > >wayland76: the point of using $*CWD would be (and would *have* > to > be, given how context vars work) to give each thread its own working > directory, independent of the process as a whole > > Now, given that chdir is an OS concept that applies to the process as > a whole, rather than individual threads, but $*CWD is designed for > individual > threads, that pretty much means that it is a really bad idea to have $*CWD > do > chdir() for us. > > Now, having said that, I think the idea of a per-thread CWD is a great > idea, and I'd be in favour of using $*CWD over whatever getcwd retrns in > Perl6 > as much as possible. So I think it would be cool if all relative paths > specified via p{} were relative to $*CWD, not getcwd(). So something like > this: > > chdir("/usr/bin"); > $*CWD = "/home/username"; > $path = p{Music}; > say $path.canonpath(); > # prints "/home/username/Music" > > My question is, what else uses chdir/getcwd style paths? I know > > qqx/$cmd @args[]/ > > ...will pass its current dir to the child. Maybe we could have Perl6 > do something like this pseudocode "under the hood" when someone does a qqx. > > > olddir = getcwd(); > chdir($*CWD); > exec(qqx string here); > chdir(olddir); > > That would mean that $*CWD would effectively act as a per-thread > working directory. > > No doubt someone will write in and tell me how bad an idea this is. I > look forward to having my ignorance exposed :). > > > - > | Name: Tim Nelson | Because the Creator is,| > | E-mail: wayl...@wayland.id.au| I am | > - > > BEGIN GEEK CODE BLOCK > Version 3.12 > GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- > PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- > -END GEEK CODE BLOCK- > > -- Sent from my mobile device Mark J. Reed
Re: $*CWD and chdir()
Ok, here's a fairly significant point posted on IRC. wayland76: the point of using $*CWD would be (and would *have* to be, given how context vars work) to give each thread its own working directory, independent of the process as a whole Now, given that chdir is an OS concept that applies to the process as a whole, rather than individual threads, but $*CWD is designed for individual threads, that pretty much means that it is a really bad idea to have $*CWD do chdir() for us. Now, having said that, I think the idea of a per-thread CWD is a great idea, and I'd be in favour of using $*CWD over whatever getcwd retrns in Perl6 as much as possible. So I think it would be cool if all relative paths specified via p{} were relative to $*CWD, not getcwd(). So something like this: chdir("/usr/bin"); $*CWD = "/home/username"; $path = p{Music}; say $path.canonpath(); # prints "/home/username/Music" My question is, what else uses chdir/getcwd style paths? I know qqx/$cmd @args[]/ ...will pass its current dir to the child. Maybe we could have Perl6 do something like this pseudocode "under the hood" when someone does a qqx. olddir = getcwd(); chdir($*CWD); exec(qqx string here); chdir(olddir); That would mean that $*CWD would effectively act as a per-thread working directory. No doubt someone will write in and tell me how bad an idea this is. I look forward to having my ignorance exposed :). - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 10:37 AM, Jan Ingvoldstad wrote: >> It's not that unreasonable. > > I disagree, and I think I've explained why, and perhaps we won't get much > further. I'm not claiming that it's a good idea for bash to adopt this behavior, only that it's a reasonable expectation tohave upon encountering the read behavior of $PWD. Its not unlike, say, applying an UPDATE to a view in an RDBMS: it seems like it should work. It might not, for various reasons, but it's not an unreasonable expectation. And in many versions of SQL it does work for the simpler view/table relationships. >> But USER isn't even a shell-maintained variable. > > I'm not sure what you mean by a "shell-maintained variable". I mean, it's not a parameter that is ever set by the shell. Unlike PWD, RANDOM, LINENO, PPID, etc. which are set by the shell. > As for $UID being read-only, that's a bashism. There's nothing inherent > about $UID that makes it read-only. Huh? I thought UID was a bashism. In my copies of ksh, it's not even set - AT&T ksh93 (version M 1993-12-28 s+ under UWIN, Version JM 93t+ 2009-05-01 on Linux) and pdksh 5.2.14. . If it's POSIX, it must be a a relatively recent addition. > In a POSIX shell, you get this: > > $ ksh --version > version sh (AT&T Research) 1993-12-28 s+ > $ echo $UID $USER > 501 jani Not here. > bash in POSIX mode agrees: What version of bash? bash-3.2: $ bash --posix bash-3.2$ echo $UID 1024 bash-3.2$ UID=500 bash: UID: readonly variable Did you maybe export UID, so it's being inherited by these subshells? > Even Perl 5 lets me change it: OK, you clearly exported UID. It's not exported by default, so $ENV{UID} in Perl should be unset. Try your experiments without exporting UID. In any case, %ENV isn't readonly in Perl. But neither are the contents of %ENV managed by Perl - just inherited from the parent process. -- Mark J. Reed
Re: $*CWD and chdir()
2009/8/19 Timothy S. Nelson : > > Ok, so suppose we only allowed direct assignment to absolute paths? > That would be currently how it works. -- Carlin
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 3:52 PM, Mark J. Reed wrote: > On Tue, Aug 18, 2009 at 9:26 AM, Jan Ingvoldstad > wrote: > > You think it's a bug that PWD="/etc" doesn't change your working > directory > > to /etc in bash? > > > > Please tell me you're joking. > > It's not that unreasonable. I disagree, and I think I've explained why, and perhaps we won't get much further. But see below. > But USER isn't even a shell-maintained variable. It's set by login(); > the shell just inherits it. A better example would be UID - which is > readonly. > I'm not sure what you mean by a "shell-maintained variable". As for $UID being read-only, that's a bashism. There's nothing inherent about $UID that makes it read-only. In a POSIX shell, you get this: $ ksh --version version sh (AT&T Research) 1993-12-28 s+ $ echo $UID $USER 501 jani $ USER=root $ UID=1000 $ echo $UID $USER 1000 root csh is no different: j...@krakas ~ >csh [krakas:~] root% echo $USER root [krakas:~] root% set USER=foo [krakas:~] root% echo $USER foo [krakas:~] root% echo $UID 501 [krakas:~] root% set UID=1000 [krakas:~] root% echo $UID 1000 bash in POSIX mode agrees: j...@krakas ~ >bash --posix j...@krakas ~ >echo $UID 501 j...@krakas ~ >UID=1000 j...@krakas ~ >echo $UID 1000 Even Perl 5 lets me change it: j...@krakas ~ >perl --version|grep v5 This is perl, v5.8.9 built for darwin-2level j...@krakas ~ >perl -e 'print "$ENV{UID}\n"; $ENV{UID}=1000; print "$ENV{UID}\n";' 501 1000 -- Jan
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 10:26 AM, Timothy S. Nelson wrote: > Ok, so suppose we only allowed direct assignment to absolute paths? Is there an echo in here? :) -- Mark J. Reed
Re: $*CWD and chdir()
On Wed, 19 Aug 2009, Carlin Bingham wrote: 2009/8/19 Timothy S. Nelson : So, if P5 does it for some global (note: global != environment) variables, then why not do it for some in P6? Because if (for some reason) I do: $> = 5; # Which calls setuid(5); print $>; # 5 Whereas: $*CWD = '..'; # which hypothetically calls chdir '..'; print $*CWD; # /home Ok, so suppose we only allowed direct assignment to absolute paths? - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: $*CWD and chdir()
2009/8/19 Timothy S. Nelson : > > So, if P5 does it for some global (note: global != environment) > variables, then why not do it for some in P6? > Because if (for some reason) I do: $> = 5; # Which calls setuid(5); print $>; # 5 Whereas: $*CWD = '..'; # which hypothetically calls chdir '..'; print $*CWD; # /home -- Carlin
Re: $*CWD and chdir()
On Tue, 18 Aug 2009, Jan Ingvoldstad wrote: On Tue, Aug 18, 2009 at 2:33 PM, David Green wrote: Huh. Thank you, I did not know that. It makes "sense" (in that I understand what's going on now that I see it, and indeed it seems almost obvious), but I certainly couldn't call it "expected" because I didn't. And I can guarantee I'm not the only one; in fact, I have no qualms about classifying that as a bug. You think it's a bug that PWD="/etc" doesn't change your working directory to /etc in bash? Please tell me you're joking. ..but Perl is more magic than bash :). Seriously, I can see both sides of the argument, and I'm leaning towards the $*CWD = chdir idea (as an option if people want to use it), but I realise that a lot of people are leaning the other way. So I'll argue for it, but don't care if I lose :). The environment variables are generally just descriptive variables. If you mess with them, they may no longer have bearing on reality. That is also expected behaviour; if you shoot yourself in the foot, you may get hurt. It can also be said to be expected behaviour because that's the way it has been behaving for maybe as long as environment variables have been in existence in Unix systems. Here's another example of something that, if I understand you correctly, you find as unexpected behaviour: j...@krakas ~ >USER=root j...@krakas ~ >echo $USER root # Am i root now? j...@krakas ~ >whoami jani # I'm not root. While there have been programs assuming that %ENV{USER} indicates who the current user is, and adjusting their behaviour based on that, such behaviour has generally been classified as a security vulnerability, and rightly so. I think David Green's argument would be that, in something as magic as Perl, doing USER=root should call setuid(), and chuck an error when it fails. And note that Perl 5 allows you to do exactly this, if I understand the documentation for "EFFECTIVE_USER_ID" in the perlvar manpage correctly. So, if P5 does it for some global (note: global != environment) variables, then why not do it for some in P6? Note that no-one's stopping you from doing this: chdir("/usr/bin"); say "%*ENV -- $*CWD\n" $*CWD = "/usr/lib"; %*ENV = "/foo/notadirectory"; say "%*ENV -- $*CWD\n" ...which would print: /usr/bin/ -- /usr/bin /foo/notadirectory -- /usr/lib So, you can still set %*ENV how you want, but $*CWD ties to getcwd and chdir the way some other people want. Yes? :) - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 9:26 AM, Jan Ingvoldstad wrote: > You think it's a bug that PWD="/etc" doesn't change your working directory > to /etc in bash? > > Please tell me you're joking. It's not that unreasonable. Given a variable that magically changes depending on your working directory, having your working directory change when you set that variable is eminently plausible. Especially since the cwd is completely under the shell's control. And changing dirs by setting PWD wouldn't get you any capability you don't have anyway via the cd builtin. Notably, while many of the special shell parameters have documented set behavior (setting RANDOM seeds the random number generator; many special parameters are readonly; others lose their magic entirely when unset), the behavior of setting PWD is not specified. So a shell could have PWD= do a cd() and even be within compliance. > Here's another example of something that, if I understand you correctly, you > find as unexpected behaviour: > > j...@krakas ~ >USER=root If that were going to work, it would presumably work like su(1): j...@krakas ~ > USER=root Password: j...@krakas ~ # _ But USER isn't even a shell-maintained variable. It's set by login(); the shell just inherits it. A better example would be UID - which is readonly. -- Mark J. Reed
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 2:33 PM, David Green wrote: > > Huh. Thank you, I did not know that. It makes "sense" (in that I > understand what's going on now that I see it, and indeed it seems almost > obvious), but I certainly couldn't call it "expected" because I didn't. And > I can guarantee I'm not the only one; in fact, I have no qualms about > classifying that as a bug. > You think it's a bug that PWD="/etc" doesn't change your working directory to /etc in bash? Please tell me you're joking. The environment variables are generally just descriptive variables. If you mess with them, they may no longer have bearing on reality. That is also expected behaviour; if you shoot yourself in the foot, you may get hurt. It can also be said to be expected behaviour because that's the way it has been behaving for maybe as long as environment variables have been in existence in Unix systems. Here's another example of something that, if I understand you correctly, you find as unexpected behaviour: j...@krakas ~ >USER=root j...@krakas ~ >echo $USER root # Am i root now? j...@krakas ~ >whoami jani # I'm not root. While there have been programs assuming that %ENV{USER} indicates who the current user is, and adjusting their behaviour based on that, such behaviour has generally been classified as a security vulnerability, and rightly so. -- Jan
Re: $*CWD and chdir()
On 2009-Aug-18, at 5:48 am, Jan Ingvoldstad wrote: On Tue, Aug 18, 2009 at 1:02 PM, David Green wrote: It doesn't seem that surprising to me, especially after seeing the docs the first time. Are there environments where you can set a variable like $*CWD and it doesn't do something like chdir? Yes, and that's normal and expected behaviour. Huh. Thank you, I did not know that. It makes "sense" (in that I understand what's going on now that I see it, and indeed it seems almost obvious), but I certainly couldn't call it "expected" because I didn't. And I can guarantee I'm not the only one; in fact, I have no qualms about classifying that as a bug. -David
Re: $*CWD and chdir()
Er, that "basename" down there should be a "dirname", for those playing along at home. Memo to self: do not type long screeds on Blackberry... On 8/18/09, Mark J. Reed wrote: > It would be nice if the bikeshed had aluminum siding. Er, I mean, if > chdir() changed *CWD and vice-versa, though I'm not sure offhand how > best to code that in idiomatic P6 to avoid the infinite recursion. > > Anyway, at the very least, a readonly *CWD holding a cached idea of > the current dir is good. Not having to call getcwd() is a definite > performance win. And if it functions like the POSIX shell PWD in > terms of tracking symlinks and translating relative pathnames to match > the apparent cwd instead of the physical one, so much the better. > > That is, in ksh/bash, if I do > > mkdir -p foo/bar/baz > cd foo > ln -s bar/baz . > cd baz > > Now getcwd() (via e.g. /bin/pwd) says I'm in .../foo/bar/baz. But > $PWD (and the shell builtin "pwd") says ".../foo/baz". And even > though the directory entry ".." is a link to ".../foo/bar", if I do > "cd .." I will be back in ".../foo", because the shell translates it > into the equivalent of 'cd "$(basename "$PWD")" '. > > Of course, other programs don't apply this logic to their arguments, > which can lead to confusion when e.g. "cd .. && cat myfile" yields a > different result from "cat ../myfile". But in general, this potential > confusion was deemed worth it for the added transparency and utility > of symbolic links. > > So perhaps a similar distinction between $*CWD and getcwd() would be > useful in P6. It would cut way down on the "not getting back what you > put in" problem with assigning to $*CWD. We could minimize that issue > even further by not allowing the assignment of relative pathnames, > only absolute ones (which of course can be constructed by simple ops > on the current value). > > On 8/18/09, Carlin Bingham wrote: >> 2009/8/18 David Green : >>> On 2009-Aug-18, at 3:27 am, Timothy S. Nelson wrote: On Tue, 18 Aug 2009, David Green wrote: > >>> or however that would work in P6. It may have problems, but by >>> definition >>> they're the same problems as chdir() has. What am I missing? >>> >>> >> >> chdir is a familar function with predictable behaviour. >> $*CWD, as a variable that "magically" changes to something other than >> what it was set to, is unfamiliar and unpredictable. >> >> Now there's nothing wrong with introducing new, unfamiliar >> functionality, if it provides a discernible benefit, but that doesn't >> seem to be the case here. >> >> -- >> Carlin >> > > -- > Sent from my mobile device > > Mark J. Reed > -- Sent from my mobile device Mark J. Reed
Re: $*CWD and chdir()
It would be nice if the bikeshed had aluminum siding. Er, I mean, if chdir() changed *CWD and vice-versa, though I'm not sure offhand how best to code that in idiomatic P6 to avoid the infinite recursion. Anyway, at the very least, a readonly *CWD holding a cached idea of the current dir is good. Not having to call getcwd() is a definite performance win. And if it functions like the POSIX shell PWD in terms of tracking symlinks and translating relative pathnames to match the apparent cwd instead of the physical one, so much the better. That is, in ksh/bash, if I do mkdir -p foo/bar/baz cd foo ln -s bar/baz . cd baz Now getcwd() (via e.g. /bin/pwd) says I'm in .../foo/bar/baz. But $PWD (and the shell builtin "pwd") says ".../foo/baz". And even though the directory entry ".." is a link to ".../foo/bar", if I do "cd .." I will be back in ".../foo", because the shell translates it into the equivalent of 'cd "$(basename "$PWD")" '. Of course, other programs don't apply this logic to their arguments, which can lead to confusion when e.g. "cd .. && cat myfile" yields a different result from "cat ../myfile". But in general, this potential confusion was deemed worth it for the added transparency and utility of symbolic links. So perhaps a similar distinction between $*CWD and getcwd() would be useful in P6. It would cut way down on the "not getting back what you put in" problem with assigning to $*CWD. We could minimize that issue even further by not allowing the assignment of relative pathnames, only absolute ones (which of course can be constructed by simple ops on the current value). On 8/18/09, Carlin Bingham wrote: > 2009/8/18 David Green : >> On 2009-Aug-18, at 3:27 am, Timothy S. Nelson wrote: >>> >>> On Tue, 18 Aug 2009, David Green wrote: >> or however that would work in P6. It may have problems, but by definition >> they're the same problems as chdir() has. What am I missing? >> >> > > chdir is a familar function with predictable behaviour. > $*CWD, as a variable that "magically" changes to something other than > what it was set to, is unfamiliar and unpredictable. > > Now there's nothing wrong with introducing new, unfamiliar > functionality, if it provides a discernible benefit, but that doesn't > seem to be the case here. > > -- > Carlin > -- Sent from my mobile device Mark J. Reed
Re: $*CWD and chdir()
On Tue, Aug 18, 2009 at 1:02 PM, David Green wrote: > On 2009-Aug-18, at 3:12 am, Jan Ingvoldstad wrote: >> >> It may seem cool, but I don't like secondary effects like that. They break >> the principle of least surprise. > > It doesn't seem that surprising to me, especially after seeing the docs the > first time. Are there environments where you can set a variable like $*CWD > and it doesn't do something like chdir? Yes, and that's normal and expected behaviour. viking...@shell:~$ uname -a Linux shell 2.4.37.5 #1 Sun Aug 16 12:47:03 CEST 2009 i686 unknown unknown GNU/Linux viking...@shell:~$ bash --version GNU bash, version 2.05b.0(1)-release (i486-slackware-linux-gnu) Copyright (C) 2002 Free Software Foundation, Inc. viking...@shell:~$ mkdir test viking...@shell:~$ touch test/testfile viking...@shell:~$ cd test viking...@shell:~/test$ ls testfile viking...@shell:~/test$ pwd /home/1/v/vikingmud/test viking...@shell:~/test$ echo $PWD /home/1/v/vikingmud/test viking...@shell:~/test$ PWD="foo/notreallyadirectory" viking...@shell:foo/notreallyadirectory$ ls testfile viking...@shell:foo/notreallyadirectory$ pwd /home/1/v/vikingmud/test viking...@shell:foo/notreallyadirectory$ echo $PWD foo/notreallyadirectory j...@krakas ~ >uname -a Darwin krakas.ELIDED 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386 j...@krakas ~ >bash --version GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0) Copyright (C) 2005 Free Software Foundation, Inc. j...@krakas ~ >mkdir test j...@krakas ~ >touch test/testfile j...@krakas ~ >cd test j...@krakas ~/test >ls testfile j...@krakas ~/test >pwd /Users/jani/test j...@krakas ~/test >echo $PWD /Users/jani/test j...@krakas ~/test >PWD="foo/notreallyadirectory" j...@krakas foo/notreallyadirectory >ls testfile j...@krakas foo/notreallyadirectory >pwd /Users/jani/test j...@krakas foo/notreallyadirectory >echo $PWD foo/notreallyadirectory -- Jan
Re: $*CWD and chdir()
On 2009-Aug-18, at 4:59 am, Carlin Bingham wrote: 2009/8/18 Timothy S. Nelson : It's not in the revised spec, but I think that, even though we've revived chdir, we should still have it so that changing $*CWD will do a chdir under the hood. While in the spirit of TIMTOWTDI, having a "magic" variable that behaves differently from other variables when it's being set would be rather odd. But really, it isn't different After all, a "current path" IS just a string; it's a string that shells helpfully insert for you at certain points to save you some typing. The automatic insertion may be "magical", but the string itself is quite ordinary. The metaphor of being "in" a directory is quite fascinating, really. Directories are not something you can be "in" -- they're lists that hang on the walls of office buildings, or get printed on the pages of a phone book. They're pointers, dir-ections to where you can find something -- an office, a telephone, or a file on a disk. Literally *on* the disk, not "in" it (disk platters are flat!). But this image of working "in" a directory seems to come quite easily and naturally. It wouldn't seem magical if we always wrote like this: ls $PWD/foo/bar PWD = $PWD/foo ls $PWD/bar That would still save a lot of typing, but not having to type the $PWD saves even more. But perhaps the apparent magic is that $*CWD = "/foo" sets the CWD to "/foo", but setting it to "foo" does not set the CWD to "foo", but rather to "$OLDCWD/foo". But that's not $*CWD's doing, that's our path-quoting. ~ p[/foo/bar] eq "/foo/bar"# path literal cast to Str ~ p[foo/bar] eq "$CWD/foo/bar" Not so strange to anyone familiar with the idea of relative paths, and no more magical than... say, the fact that a literal series of digits gets parsed as though it had an implicit "0d" in front of it. (Of course, I suspect that $*CWD should be able to be set to a plain Str, but the Str will be cast to an IO::Path because that's what $*CWD.STORE() will take in its signature.) -David
Re: $*CWD and chdir()
2009/8/18 David Green : > On 2009-Aug-18, at 3:27 am, Timothy S. Nelson wrote: >> >> On Tue, 18 Aug 2009, David Green wrote: >>> > or however that would work in P6. It may have problems, but by definition > they're the same problems as chdir() has. What am I missing? > > chdir is a familar function with predictable behaviour. $*CWD, as a variable that "magically" changes to something other than what it was set to, is unfamiliar and unpredictable. Now there's nothing wrong with introducing new, unfamiliar functionality, if it provides a discernible benefit, but that doesn't seem to be the case here. -- Carlin
$*CWD and chdir()
On 2009-Aug-18, at 3:27 am, Timothy S. Nelson wrote: On Tue, 18 Aug 2009, David Green wrote: Maybe setting $*CWD just calls chdir() under the hood? Same implementation, brand new shiny Perl-style interface! That was my intent, but we had some discussions on IRC about the whys and wherefores, and it will return as soon as I do my next commit (hopefully sometime within the next 4-5 hours). Unless you can think of a good way to do relative paths. In my naiveté, I would do: class IO::CurrentDir; # the type of $*CWD sub STORE($self: IO::Path $new) { chdir($new); $self = getcwd(); } or however that would work in P6. It may have problems, but by definition they're the same problems as chdir() has. What am I missing? On 2009-Aug-18, at 3:12 am, Jan Ingvoldstad wrote: It may seem cool, but I don't like secondary effects like that. They break the principle of least surprise. It doesn't seem that surprising to me, especially after seeing the docs the first time. Are there environments where you can set a variable like $*CWD and it doesn't do something like chdir? (And we can always keep chdir() as well, so old dogs aren't forced to learn new tricks.) On 2009-Aug-18, at 3:52 am, Mark J. Reed wrote: If $*CWD is really a Path object and not a Str, then it should be easy to use mutator methods to change to a relative directory and do other chdir()ish things. Say, concatenation works in terms of path components, for instance: $*CWD ~= $subdir; # chdir($subdir) Yes. Though $*CWD = "subdir" should also work; "subdir" is not the same path as "/subdir", so it knows whether you're assigning a relative path or not. Or rather, our path-type would know, and implicitly prepend the current dir when it parses/forms the actual pathname, so $CWD would effectively get a fully specified path every time. With a method for getting the parent: given $*CWD { $_ = $_.up ~ $sibling } # chdir("../$sibling") I like that. and so on. My favorite kshism is "cd old new" which does a search/replace on the current working directory; the bash equivalent "cd ${PWD/old/new}" which is not quite as handy. $*CWD could make that simple, too. Ditto. -David