From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16417 invoked by alias); 30 Sep 2015 08:08:01 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 20667 Received: (qmail 10678 invoked from network); 30 Sep 2015 08:07:58 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=ham autolearn_force=no version=3.4.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1443600081; bh=GjnG8Plh1zDw7waX2S6nWTVWrFjqdKUWPGo6YwRakbU=; h=From:To:In-Reply-To:References:Subject:Date; b=IOLdG4DulxW3zGW7aExHp6Dc2tuBx3y3FZGb+Nq4hUpdkA2YCwmT6ydsihPn0+1GN ycuYgDSEYD/rNoI4t/P1hYPi6AX37uKNdYPTV5amlDXnodxBrrBV5bUA8kVZBR6A1f nExKGs3EiySMOJmzmfaMIqPwrlFL4GZ7/zSWZduI= From: ZyX To: Ray Andrews , "zsh-users@zsh.org" In-Reply-To: <560B61C5.2080001@eastlink.ca> References: <55FAE223.2080502@eastlink.ca> <150917103419.ZM10067@torch.brasslantern.com> <150918171441.ZM27212@torch.brasslantern.com> <55FD7982.9030505@eastlink.ca> <150919092922.ZM28214@torch.brasslantern.com> <55FDA5D3.9020304@eastlink.ca> <150919142243.ZM23634@torch.brasslantern.com> <55FE04AD.1070304@eastlink.ca> <150919224120.ZM4736@torch.brasslantern.com> <55FF3F7E.4060906@eastlink.ca> <150920211840.ZM31871@torch.brasslantern.com> <5600386E.7060201@eastlink.ca> <150921111746.ZM388@torch.brasslantern.com> <56006401.5060902@eastlink.ca> <150921201943.ZM707@torch.brasslantern.com> <560B1BE7.8020507@eastlink.ca> <150929204047.ZM9646@torch.brasslantern.com> <560B61C5.2080001@eastlink.ca> Subject: Re: wheels within wheels MIME-Version: 1.0 Message-Id: <357101443600080@web28g.yandex.ru> X-Mailer: Yamail [ http://yandex.ru ] 5.0 Date: Wed, 30 Sep 2015 11:01:20 +0300 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=koi8-r 30.09.2015, 07:16, "Ray Andrews" : > On 09/29/2015 08:40 PM, Bart Schaefer wrote: >> š} >> š} I just learned that it's possible to declare a function within another >> š} function. A strange liberty. >> >> šInterpreted language. > > Yes. It's so easy to forget that. >> ššššššfunction foo { >> ššššššššecho defining bar >> ššššššššfunction bar { >> šššššššššecho hello from bar >> šššššššš} >> ššššššššecho redefining foo >> ššššššššfunction foo { >> šššššššššecho hello from new foo >> šššššššššbar >> šššššššš} >> šššššššš# this looks like infinite recursion, >> šššššššš# but it is not, because foo was redefined >> ššššššššfoo >> šššššš} > > Now that is mind expanding. If you tried that in C you'd collapse the > universe. > Interpreted .... sure, it can saw off the branch it's sitting on because > there is no > tree. Each command is past when it's past so that must mean that the > address of > first foo ... is there ... yes of course there is, the thing is in > memory ... just aborts > when second foo comes along. It will expect grammatical completion of > first foo > for the sake of etiquette. And when foo calls itself, it calls new foo > which is > not recursive. I am not yet able to snatch the pebble out of your hand, > but that's > a zsh koan. Nested *same* function definition is rather useful for initialization. Or when you need to alter the implementation based on some condition, and want to cache this to not check this condition again: # This will parse json array passed as argument to a shell array $reply. # Depending on whether zpython module is available it will either use built-in python interpreter support # which is faster or call python in a subshell. parse_json_array() { if zmodload libzpython 2>/dev/null ; then parse_json_array() { zpython 'import zsh, json; zsh.setvalue("reply", json.loads(zsh.getvalue("1")))' } else parse_json_array() { reply=( "${(@0)"$(python -c 'import sys, json; sys.stdout.write("\0".join(json.loads(sys.argv[1])))' "$1")"}" ) } fi parse_json_array "$@" } . Also this is a feature sometimes useful for metaprogramming: you can create a function which defines a function through eval. Will be needed if you for some reason want something like bash `export -f` feature. And this is *not* a zsh koan. I have been using the same technique for the same reasons in Python: e.g. in https://github.com/ZyX-I/powerline/blob/5ebf0875b85f85e7cd4c1e07aa8cdebbcc3bd17e/powerline/segments/common/bat.py#L163. Many interpreted languages allow this. Specifically *all* POSIX-like shells I know allow this: https://github.com/ZyX-I/powerline/blob/5ebf0875b85f85e7cd4c1e07aa8cdebbcc3bd17e/powerline/bindings/shell/powerline.sh#L74-L99 is known to work in dash, [m]ksh, busybox ash and bash. In C you may do something similar if you use function pointer as a public interface and store different address, but this makes call indirect. If you are OK with binding yourself to GCC you can even have nested definitions.