From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 21257 invoked from network); 9 Feb 2023 20:50:31 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 9 Feb 2023 20:50:31 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Message-ID:Date:Content-ID: Content-Type:MIME-Version:Subject:To:References:From:In-reply-to:cc:Reply-To: Content-Transfer-Encoding:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID; bh=yuAdu3YfzbNX9nVVgQtOqtokzttiqkmG0LXaJ+igJjg=; b=WnHbpJDYBNbmv1auZDWGI1Lwzb qt9vMySvyPF2wqffrZmIL2zQ5Nw4IrsVbw1JcORFH9NuOy4wqnM9/M9gFM7l3kAddT6EQ12Tla6Es FUZop/H/RQC46m43/vunwLtz26sQS7deok/VAsSF555hBGgDM4C8mjtGq2vEt6fjgM4l6w/QMiHrX Qw/HrPnPXwuvNm6tcVvbUxPEbsfoz1wuWci5UTU3pUjpKuvA0Ao6Xym0wewe6p80arrRBgl1wyzMf BiqWMnMOxTmCsbfGknAPWj02sbk/zNCP48MF3hlXNgGNNe2D7YbMkyZ+KOyYp63Kx4VhRQIX6ehAq Q2PSKyvA==; Received: by zero.zsh.org with local id 1pQDsD-000B8o-Vr; Thu, 09 Feb 2023 20:50:30 +0000 Received: by zero.zsh.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) id 1pQDrh-000Aol-7y; Thu, 09 Feb 2023 20:49:57 +0000 Received: from [192.168.178.21] (helo=hydra) by mail.kiddle.eu with esmtp(Exim 4.95) (envelope-from ) id 1pQDrg-000HBG-4N; Thu, 09 Feb 2023 21:49:56 +0100 cc: Zsh hackers list In-reply-to: From: Oliver Kiddle References: <67689-1675827940.088548@BxvG.D9_b.7RzI> <12608-1675903622.800470@Xj82.e3y1.svhG> To: Bart Schaefer Subject: Re: [PATCH 1/3]: Add named references MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <66044.1675975796.1@hydra> Date: Thu, 09 Feb 2023 21:49:56 +0100 Message-ID: <66045-1675975796.128039@FBF_.0yMO.Y8fk> X-Seq: 51389 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: , List-Subscribe: , List-Unsubscribe: , List-Post: List-Owner: List-Archive: Bart Schaefer wrote: > My general feeling is to be ksh compatible where I don't think ksh is stupid. Sounds reasonable. > > It solves the problem of name clashes between a function and the calling > > function. > > OK, so if > typeset ref > () { typeset -n ref=ref } > works / is not a loop, then we don't need any other magic? The following is similar: var=hello typeset -n ref () { typeset var=x ref=var echo $ref } typeset -p ref echo $ref This creates a reference to a variable at a deeper local level. Ksh prints "global reference cannot refer to local variable". With zsh's dynamic scoping you could do the same thing with a reference that isn't "global" but which has a scope that will outlast the variable. Making var outlive the function is a feature you'd get with a reference counting approach to namerefs. The best might be if ref returns to being unset when the function returns but an error like ksh is fine too. > I'm still not seeing that. The writer of the caller of _call_function > should know that it's a general rule that another function can't > access a private variable. Why would the writer pass a private name > as an argument to any function, even a blackbox, if not expecting it > to be referenced? The rule for a private should be that you always > pass its value. I hadn't really thought about it that way, perhaps because ksh only has private scoping and I'm used to writing in languages that only have lexical scoping. Certainly if it is hard to implement, I have no objection to this approach. It does have the big advantage of making the whole uplevel question a non-issue. We do lose some orthogonality in that you can use a private with builtins that take variable names like read, compadd and printf (-v). Wrappers of those would have an added limitation. (_approximate relies on a function wrapper of compadd so privates can't be used with that) When relying only on dynamic scoping, it would be good practice to define all the namerefs to passed parameters as early as possible in a function to reduce the risk of a name clash. > Correct me if I still misunderstand, but I interpret the example above > as implying that > > f2() { > typeset -n ref=$1 > # ... do stuff to $ref ... > } > f1() { > private var > f2 var > } > > should work just because the name is passed in a positional? I would > disagree with that on the grounds that you're making positionals into > a special case, just a different kind of special case from ksh, that > violates the intent of "private". It isn't about the positionals being special but that it is useful to be able to write a function that exposes an interface similar to read where a variable can be named as a parameter. Ksh's making $1, $2.. special on the rhs of typeset -n really is very ugly. > The case I was asking about (and the only one I so far consider > possibly viable) is > > f1() { > private var > typeset -n ref=var > f2 ref > } This puts the complexity into the caller so f2's interface is less nice. And by needing ref as a local, f1 hasn't really benefitted from var being able to be private. But if this is easy to implement then it could be useful. If not, printing an error is fine too. > Or perhaps you mean to be tagging on to your other suggestion and it would be > f2 \&var My intention with that suggestion is that you'd only do that to refer to $var from the scope of f1's caller. So in practice that'd sooner be something like \&$3. For this, it'd be just `f2 var` and f2() would declare `private -n mine=\&1` > which feels like syntactic sugar for my example above, with the > benefit of not needing to declare an extra parameter. That's an > interesting idea but I would not want this to work: Again, the key difference is that the caller needed the extra parameter where as using some sort of uplevel goes in the callee. You can't wrap e.g. compadd transparently if the caller needs to change. > With a hash that's just: > > typeset -n ref > for ref in 'hash[(e)'${(k)^hash[(R)?*]}']'; do ... "just"!? > > And it could be wise to limit what can be done as part of the > > subscript evaluation to avoid a CVE similar to the last one. > > validate_refname() is calling parse_subscript() ... would further > examination of the accepted string be sufficient, or something more > needed? I think the greatest danger is of creating an infinite > recursion, which can't really be caught in advance. So if a function gets the target of a nameref from untrusted input the function writer needs to know to validate it with something like [[ $var = [[:IDENT:]]## ]] It might deprive us of many clever tricks but parse_subscript() could gain a flag to disable anything questionable like command substitution and math evaluation side-effects. This should be an error perhaps: typeset -n ref=arr[1][2] Currently it isn't possible to create a reference fo $!, $?, $@, $+, $# and $$. If easy to add, there would be no harm in them. And in 51388, Bart wrote: > How about > can't change type via subscript reference > ?? That sounds fine. Oliver