zsh-workers
 help / color / mirror / code / Atom feed
* Re: Example function
@ 1999-02-01 10:48 Sven Wischnowsky
  1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Sven Wischnowsky @ 1999-02-01 10:48 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> (One of the things on the associative-array wishlist is "reverse pattern"
> lookup, that is, treat the array keys as patterns and match them against
> the subscript.  Then you could do silly stuff like
> 
> 	typeset -A map
> 	map=('*.(gz|Z)'	zcat
> 	     '*.bz2' 'bzip2 -dc'
> 	     '*.bz' 'bzip -dc'
> 	     '*' '<')
> 	eval ${(q)map[$argv[i]]} '$argv[i]'
> 
> where I'm using (q) as the fictional reverse-pattern query flag; probably
> there's a better letter.)
> 
> Incidentally, the reason this isn't there already is that associative arrays
> are unordered hashes, so you can't predict _which_ pattern will match the
> subscript when you do the query -- '*' might match before '*.bz' is tried.

I was thinking about this... we could make the code keep a counter in
assoc arrays, increment it whenever a new key is added and store the
current value in the structure for this new element. Then we can treat 
the whole thing as being sorted by `time of addition'.

Hm, does this sound like the right thing?

Bye
 Sven

P.S.: Is `foo=( ${(kv)foo[(I)^key]} )' the easiest way to remove a
      key/value-pair from an associative array?

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Associative array ordering and selective unset (Re: Example function)
  1999-02-01 10:48 Example function Sven Wischnowsky
@ 1999-02-01 17:02 ` Bart Schaefer
  1999-02-01 17:39   ` Bruce Stephens
  1999-02-02 20:07   ` Phil Pennock
  0 siblings, 2 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-02-01 17:02 UTC (permalink / raw)
  To: zsh-workers

On Feb 1, 11:48am, Sven Wischnowsky wrote:
} Subject: Re: Example function
}
} I was thinking about this... we could make the code keep a counter in
} assoc arrays, increment it whenever a new key is added and store the
} current value in the structure for this new element. Then we can treat 
} the whole thing as being sorted by `time of addition'.
} 
} Hm, does this sound like the right thing?

Almost.  Something about it doesn't seem quite right to me, but I can't
put my finger on what different behavior I'd expect.

I don't like the idea that every parameter table hash would end up with
another integer of overhead in every entry, but maybe that's not so bad.

} P.S.: Is `foo=( ${(kv)foo[(I)^key]} )' the easiest way to remove a
}       key/value-pair from an associative array?

Probably, if you have extendedglob set.  If you don't have extendedglob,
that's a moderately hard way to remove -all- the key/value pairs.

We could go the ksh route and make `noglob unset foo[key]` work.  Like:

	function unset() {
	    emulate -R zsh
	    setopt localoptions extendedglob
	    local arg i
	    for i
	    do
		arg=( "${(@s:[:)i}" )
		if [[ $#arg > 1 &&
		    $(eval print '${(t)'${arg[1]}'}') == association ]]
		then
		    eval "$arg[1]=( \${(kv)$arg[1][(I)^${(j:[:)arg[2,-1]} )"
		else
		    builtin unset $i
		fi
	    done
	}

Can you think of a better idiom than $(eval print '${(t)'${arg[1]}'}') to
get the type of the variable whose name is the value of $arg[1] ?  I keep
thinking there ought to be a way with ${(e)...} but couldn't make it work.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Associative array ordering and selective unset  (Re: Example function)
  1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
@ 1999-02-01 17:39   ` Bruce Stephens
  1999-02-01 19:09     ` Bart Schaefer
  1999-02-02 20:07   ` Phil Pennock
  1 sibling, 1 reply; 8+ messages in thread
From: Bruce Stephens @ 1999-02-01 17:39 UTC (permalink / raw)
  To: zsh-workers

"Bart Schaefer" <schaefer@brasslantern.com> writes:

> On Feb 1, 11:48am, Sven Wischnowsky wrote:
> } Subject: Re: Example function
> }
> } I was thinking about this... we could make the code keep a counter in
> } assoc arrays, increment it whenever a new key is added and store the
> } current value in the structure for this new element. Then we can treat 
> } the whole thing as being sorted by `time of addition'.
> } 
> } Hm, does this sound like the right thing?
> 
> Almost.  Something about it doesn't seem quite right to me, but I
> can't put my finger on what different behavior I'd expect.

It would be a bit tricky to reorder the associative array, wouldn't
it?  i.e., if I set up some configuration, and then want to insert
some pattern before some others, then I'd need to recreate the
associative array.  Maybe that's OK, but it feels a bit awkward.

Emacs (and other Lisps) has assoc-lists, which is maybe a better model
for this: they're explicitly lists (so they have ordering), but you
can access them by key.  I've no idea how this would map onto a shell,
but perhaps this is saying that associative arrays don't quite fit
what's wanted.

> I don't like the idea that every parameter table hash would end up
> with another integer of overhead in every entry, but maybe that's
> not so bad.

I agree, the extra integer is probably trivial.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Associative array ordering and selective unset (Re: Example function)
  1999-02-01 17:39   ` Bruce Stephens
@ 1999-02-01 19:09     ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-02-01 19:09 UTC (permalink / raw)
  To: zsh-workers

On Feb 1,  5:39pm, Bruce Stephens wrote:
} Subject: Re: Associative array ordering and selective unset (Re: Example f
}
} It would be a bit tricky to reorder the associative array, wouldn't
} it?  i.e., if I set up some configuration, and then want to insert
} some pattern before some others, then I'd need to recreate the
} associative array.  Maybe that's OK, but it feels a bit awkward.

I just thought of a really clever way to do the specific example that I
gave.  Assume for a moment that the (q) modifier were implemented, i.e.
that (almost repeating the original example) given

        typeset -A map
        map=('*.(gz|Z)' zcat
             '*.bz2' 'bzip2 -dc'
             '*.bz' 'bzip -dc'
             '*' '<')

then ${map[(q)$argv[i]]} returns the value for the first subscript match
found, and ${map[(Q)$argv[i]]} returns the array of values for every key
that matches the subscript.

(Note that I moved the (qQ) into the subscript flags, which is probably
where it really has to be.  And I still hope for a better letter.)

Now change the assignment a little:

        map=('*.(gz|Z)' ': 1; zcat
             '*.bz2' ': 2; bzip2 -dc'
             '*.bz' ': 3; bzip -dc'
             '*' ': 4; <')

Now we can use the (o) substitution flag like so:

	eval ${${(o)map[(Q)$argv[i]]}[1]} '$argv[i]'

That says "find all the values for which the key is a pattern that matches
$argv[i], sort them in ascending order, take the first one, and evaluate
it as a command with argument $argv[i]."  By embedding the "preferred"
ordering in the value as a leading ":" command, we're assured of always
getting the most-specific match.

Now, if only this actually worked ... I'm about to be tied up in a several-
week consulting job, so I probably won't get a chance to do anything with
this anytime soon.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Associative array ordering and selective unset (Re: Example function)
  1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
  1999-02-01 17:39   ` Bruce Stephens
@ 1999-02-02 20:07   ` Phil Pennock
  1 sibling, 0 replies; 8+ messages in thread
From: Phil Pennock @ 1999-02-02 20:07 UTC (permalink / raw)
  To: zsh-workers

Typing away merrily, Bart Schaefer produced the immortal words:
> On Feb 1, 11:48am, Sven Wischnowsky wrote:
> } I was thinking about this... we could make the code keep a counter in
> } assoc arrays, increment it whenever a new key is added and store the
> } current value in the structure for this new element. Then we can treat 
> } the whole thing as being sorted by `time of addition'.
> } 
> } Hm, does this sound like the right thing?
> 
> Almost.  Something about it doesn't seem quite right to me, but I can't
> put my finger on what different behavior I'd expect.
> 
> I don't like the idea that every parameter table hash would end up with
> another integer of overhead in every entry, but maybe that's not so bad.

A pointer in each to embed a linked list?
-- 
--> Phil Pennock ; GAT d- s+:+ a23 C++(++++) UL++++/I+++/S+++/B++/H+$ P++@$
L+++ E-@ W(+) N>++ o !K w--- O>+ M V !PS PE Y+ PGP+ t-- 5++ X+ R !tv b++>+++
DI+ D+ G+ e+ h* r y?


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Example function
  1999-01-27  0:25 ` Bart Schaefer
@ 1999-01-27  0:37   ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 1999-01-27  0:37 UTC (permalink / raw)
  To: Bart Schaefer, Phil Pennock, Zsh Development Workers

On Jan 26,  4:25pm, Bart Schaefer wrote:
> Subject: Re: Example function
> (One of the things on the associative-array wishlist is "reverse pattern"
> lookup, that is, treat the array keys as patterns and match them against
> the subscript.  Then you could do silly stuff like
> 
> 	typeset -A map
> 	map=('*.(gz|Z)'	zcat
> 	     '*.bz2' 'bzip2 -dc'
> 	     '*.bz' 'bzip -dc'
> 	     '*' '<')
> 	eval ${(q)map[$argv[i]]} '$argv[i]'
> 
> where I'm using (q) as the fictional reverse-pattern query flag; probably
> there's a better letter.)

Incidentally, the reason this isn't there already is that associative arrays
are unordered hashes, so you can't predict _which_ pattern will match the
subscript when you do the query -- '*' might match before '*.bz' is tried.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Example function
  1999-01-26 18:42 Example function Phil Pennock
@ 1999-01-27  0:25 ` Bart Schaefer
  1999-01-27  0:37   ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 1999-01-27  0:25 UTC (permalink / raw)
  To: Phil Pennock, Zsh Development Workers

On Jan 26,  6:42pm, Phil Pennock wrote:
> Subject: Example function
>       
> It's a zless which automatically determines from the file extension
> which decompressor to use.  The comments explain it.  This has evolved
> over about a year and a half, hence my needing help sorting out the
> array bit.

This is certainly interesting, but I'm really puzzled why you wanted to
do it the way you did it.  For example, why build a parallel dispfunc
array and then merge it with argv at the end, rather than just rewrite
argv in place (which you already do in some instances)?

Also the (@) flags in the variable expansions in the last line are
extraneous.

Anyway, here's how I'd write that same function (runs in 3.0.5, too, which
Phil's doesn't because of the for (( )) syntax):

function zl() {
  emulate -R zsh
  [[ $# -ge 1 ]] || return
  local lessopts
  set -A lessopts
  integer i=1 loi=1
  while ((i <= $#))
  do
    case $argv[i] in
    -zforce) argv[i,i+2]=("=($argv[i+1] \"$argv[i+2]\")"); ((++i));;
    -*) lessopts[loi++]=\"$argv[i]\"; argv[i]=(); continue;;
    *.(gz|Z)) argv[i]="=(zcat \"$argv[i]\")";;
    *.bz2) argv[i]="=(bzip2 -dc \"$argv[i]\")";;
    *.bz) argv[i]="=(bzip -dc \"$argv[i]\")";;
    esac
    ((++i))
  done
  eval command less $lessopts $*
}

Of course, this still assumes you don't have any less options or file names
that contain double-quote characters ...

(One of the things on the associative-array wishlist is "reverse pattern"
lookup, that is, treat the array keys as patterns and match them against
the subscript.  Then you could do silly stuff like

	typeset -A map
	map=('*.(gz|Z)'	zcat
	     '*.bz2' 'bzip2 -dc'
	     '*.bz' 'bzip -dc'
	     '*' '<')
	eval ${(q)map[$argv[i]]} '$argv[i]'

where I'm using (q) as the fictional reverse-pattern query flag; probably
there's a better letter.)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Example function
@ 1999-01-26 18:42 Phil Pennock
  1999-01-27  0:25 ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Phil Pennock @ 1999-01-26 18:42 UTC (permalink / raw)
  To: Zsh Development Workers

Hi,

      
A couple of months back zefram decided that he wanted one of my sicker
zsh shell functions for the examples.  I gave it to him then.  Here it  
is again for inclusion.

      
It's a zless which automatically determines from the file extension
which decompressor to use.  The comments explain it.  This has evolved
over about a year and a half, hence my needing help sorting out the
array bit.

Uhm, have fun or whatever.  Peter, any chance of this going in your next
sub-distrib?

Thanks

PS: Note that the last line is 108 chars long; your mailer may
interfere?

-----------------------------< cut here >-------------------------------
#!/usr/bin/zsh -f
#
# zsh function script to run less on various inputs, decompressing as required.
# Author: Phil Pennock.  zsh-hacks@athenaeum.demon.co.uk
# Thanks to zefram@fysh.org for a great deal of help in sorting this out,
# ie wrt syntax for unsetting members of arrays and eval "$(...)" when I
# asked for something better than . =(...)
# Other than that the whole sick beauty is mine.
#
# Use -zforce to pass through a display-formatting command
#  zless -zforce 'bzip2 -dc' foo-no-dotbz2
#  zless -zforce 'od -hc' foo-binfile
#
# If you can understand all of this without reference to zshexpn(1)
# and zshparam(1) then you either have a photographic memory or you
# need to get out more.
#

[[ $# -ge 1 ]] || return
local -i i loi max
local dispfunc lessopts
set -A dispfunc
set -A lessopts
loi=1 
max=$[$#+1]
for ((i=1; i != $max ; ++i))
do
	dispfunc[i]='<' 
	[[ $argv[i] = \-zforce ]] && {
		dispfunc[i+2]="$argv[i+1]"
		argv[i,i+1]=()
		dispfunc[i,i+1]=()
		let max-=2
		continue
	}
	[[ $argv[i] = \-* ]] && {
		lessopts[loi++]="$argv[i]" 
		argv[i,i]=()
		dispfunc[i,i]=()
		let max-=1
		let i-=1
		continue
	}
	[[ $argv[i] = *.gz ]] && dispfunc[i]=zcat 
	[[ $argv[i] = *.bz2 ]] && dispfunc[i]='bzip2 -dc' 
	[[ $argv[i] = *.Z ]] && dispfunc[i]=zcat 
	[[ $argv[i] = *.bz ]] && dispfunc[i]='bzip -dc' 
done
eval "$(print command less "${(@)lessopts}" "=($dispfunc[i=1] \"${(@Nej:\") =($dispfunc[++i] \":)argv}\")")"
-----------------------------< cut here >-------------------------------
-- 
--> Phil Pennock ; GAT d- s+:+ a23 C++(++++) UL++++/I+++/S+++/B++/H+$ P++@$
L+++ E-@ W(+) N>++ o !K w--- O>+ M V !PS PE Y+ PGP+ t-- 5++ X+ R !tv b++>+++
DI+ D+ G+ e+ h* r y?


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~1999-02-02 20:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-01 10:48 Example function Sven Wischnowsky
1999-02-01 17:02 ` Associative array ordering and selective unset (Re: Example function) Bart Schaefer
1999-02-01 17:39   ` Bruce Stephens
1999-02-01 19:09     ` Bart Schaefer
1999-02-02 20:07   ` Phil Pennock
  -- strict thread matches above, loose matches on Subject: below --
1999-01-26 18:42 Example function Phil Pennock
1999-01-27  0:25 ` Bart Schaefer
1999-01-27  0:37   ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).