On 5/14/06, Axel Liljencrantz <[EMAIL PROTECTED]> wrote:
On 5/12/06, Beni Cherniavsky <[EMAIL PROTECTED]> wrote:
>
> Now, later in this thread you explain that all expansion in fish works as
> outer products. For example::
>
> echo %.(echo a\nb).(echo 1\n2)
> echo {%,(echo a\nb),(echo 1\n2)},
>
> prints::
>
> %.a.1 %.a.2 %.b.1 %.b.2
> %, a, 1, %, a, 2, %, b, 1, %, b, 2,
>
> The first is obviously useful, for some of the examples you gave. The
> second is questionable.
But sometimes useful: ``fgrep {-f,(ls *.words)}`` expands to ``fgrep
-f some.words -f more.words``
> I agree brace/command/variable expansions written side-by-side
> (``%.$v.(seq 2)``)
> should form an outer product, but inside braces, I think they should be
joined,
> just like ``{%,{a,b},{1,2}}`` produces ``% a b 1 2``.
>
> What I'm driving at is that braces, not brackets, should be the
> joining operator
> that I talked about.
Thinking some more, I would like to consider the operators that are
frequently useful in a shell:
word_concat(a, 1) -> a1
list_concat([a b], [1 2]) -> [a b 1 2]
word_product([a b], [1 2]) -> [a1 a2 b1 b2]
list_product([a b], [1 2]) -> [a 1 a 2 b 1 b 2]
word_parallel([a b], [1 2]) -> [a1 b2]
list_parallel([a b], [1 2]) -> [a 1 b 2]
What we have now:
word_concat() doesn't really exist because words are built from items
like variable expansion that produce lists. In fish, it's a special
case of word_product(). [In bash, it's a special case of something
useless ;-). In rc, it's a special case of word_parallel().]
The top level of a command line is list_concat() but it's not
availiable otherwise.
list_product() is availiable through braces but in a surprising way.
word_parallel() and list_parallel() are not availiable.
You can implement word_parallel() as::
(paste -d "" (echo a\nb | psub) (echo 1\n2 | psub))
and list_parallel() as::
(paste -d \n (echo a\nb | psub) (echo 1\n2 | psub))
Both are rarely needed, so I think this is good enough.
In this thread we want list_concat() inside array indexing. Since
``$a[1 2]`` already expands into two words, it's not baseless. It can
be implemented as::
(printf '%s\n' 1 (seq 4 7))
but perhaps some direct syntax (not necessarily limited to indexing)
would be useful.
word_product() is extremely useful in simple cases like ``img(seq
5).png`` and it should remain availiable for such uses.
list_product() is sometimes useful (see fgrep example above). You
could implement it with::
(printf '%s' (echo a\nb)\n(echo 1\n2))\n
----
Note that all implementations using external commands suffer from
false splitting if any word contains newlines. It's not a critical
usability bug like space-splitting was in bash but it still might be a
security bug in some situations. Let's try reliable implementation
with arrays:
function vsub
# should check that it's unused and register deletion
# when calling job exits (see psub implementation)
set -l name _vsub_(random)
set -g $name $argv
echo $name
end
# Such functions that return variable names could
# be used like ``$(vsub ...)`` if fish didn't catch it.
# This is useful for testing
function deref
echo $$argv
end
function concat_arrays
# variable indirection is also a product!
vsub $$argv
end
function list_parallel
concat_arrays (
for i in (seq (count $$argv[1])) # should take max or min or what?
for v in $argv
echo $$v[1][$i]
end
end)
end
function word_parallel
concat_arrays (
for i in (seq (count $$argv[1]))
eval vsub (
for v in $argv
echo -n \${$v}\[$i\]
end)
end)
end
So I hacked perlish references int the flat data structures of fish.
May God forgive me ;-\.
No, I do NOT think this is the right way. But I do want robust
operations on word lists.
Ideas?
--
Beni Cherniavsky <[EMAIL PROTECTED]>, who can only read email on weekends.
Governments are like kernels - everything possible should be done in user space.