zsh-workers
 help / color / mirror / code / Atom feed
* Set operations
@ 2008-09-27  9:02 Phil Pennock
  2008-09-27 20:48 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Phil Pennock @ 2008-09-27  9:02 UTC (permalink / raw)
  To: Zsh hackers list

Somehow, until a recent post from Bart, I'd missed ${array:#element} to
remove an element from an array.  That was the clean removal method I'd
been missing for using -U unique arrays as sets.

So the below is a first pass implementation of set arithmetic; however,
the safesub stuff shows that my big problem is, when joining existing
elements together with |, escaping pattern-characters in the original
array elements.  It does try to be fairly resistant to non-normal
setups without going full emulate, since it only uses a few features.

So given 'b' naming the set variable with the elements to remove, I do a
first pass approximation like this:

safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")

instead of just, for set subtraction of b from a:

  "${(P@)a:#${(Pj,|,)~b}}"

However, this obviously doesn't deal with the full set of
pattern-matching characters, so is incomplete.

So, before I head off and implement a parameter expansion flag to escape
pattern-matching characters (honouring current pattern-affecting
options), the question is whether I'm missing something obvious to do
this set arithmetic cleanly already, or if there's already a clean way
to escape pattern characters?

Any feedback on the complete set (so to speak) of functionality or
naming or implementation appreciated, with an eye to adding this to the
standard zsh install (autoloaded function set_operations to define
these?)

Or is the thing to do to overload the arithmetic operations in
arithmetic expansion, for let, to be able to handle -U arrays as sets
natively?  :-)  (let diff=a-b ...)

(The number of times I work with large lists of machines interactively
in shell and want to deal with them as sets and manipulate appropriately
is somewhat high and I'm fed up of switching to Python.)

Regards,
-Phil

#----------------------------8< cut here >8------------------------------
function newset {
	setopt local_options no_ksh_arrays
	local name="$1"; shift
	typeset -gUa $name
	set -A $name "$@"
}

function copyset_tofrom {
	setopt local_options no_ksh_arrays
	local new="$1" old="$2"
	typeset -gUa $new
	set -A $new "${(P@)old}"
}
function copyset_fromto { copyset_tofrom "$2" "$1" }

function set_add_new {
	setopt local_options no_ksh_arrays
	local new="$1" a="$2" b="$3"
	typeset -gUa $new
	set -A $new "${(P@)a}" "${(P@)b}"
}

function set_add_in {
	setopt local_options no_ksh_arrays
	local name="$1" b="$2"
	set -A $name "${(P@)name}" "${(P@)b}"
}

function set_add_print {
	setopt local_options no_ksh_arrays
	local a="$1" b="$2"
	typeset -Ua tmp
	tmp=("${(P@)a}" "${(P@)b}")
	print -r -- ${(q)tmp}
}

function set_subtract_new {
	setopt local_options no_ksh_arrays
	local new="$1" a="$2" b="$3"
	typeset -gUa $new
	typeset -Ua safesub
	safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $new "${(P@)a:#${(j,|,)~safesub}}"
}

function set_subtract_in {
	setopt local_options no_ksh_arrays
	local name="$1" b="$2"
	typeset -Ua safesub
	safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $name "${(P@)name:#${(j,|,)~safesub}}"
}

function set_subtract_print {
	setopt local_options no_ksh_arrays
	local a="$1" b="$2"
	typeset -Ua tmp
	typeset -Ua safesub
	safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	tmp=("${(P@)a:#${(j,|,)~safesub}}")
	print -r -- ${(q)tmp}
}

function set_intersection_new {
	setopt local_options no_ksh_arrays
	local new="$1" a="$2" b="$3"
	typeset -gUa $new
	typeset -Ua safesub
	safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $new "${(@PM)a:#${(j,|,)~safesub}}"
}

function set_union_new { set_add_new "$@" }
function set_union_in { set_add_in "$@" }
function set_union_print { set_add_print "$@" }

function set_difference_new { set_subtract_new "$@" }
function set_difference_in { set_subtract_in "$@" }
function set_difference_print { set_subtract_print "$@" }

function set_symmetric_difference_new {
	setopt local_options no_ksh_arrays
	local new="$1" a="$2" b="$3"
	typeset -gUa $new
	typeset -Ua safe_a safe_b
	safe_b=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $new "${(P@)a:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_a}}"
}

function set_symmetric_difference_in {
	setopt local_options no_ksh_arrays
	local name="$1" b="$2"
	typeset -Ua safe_name safe_b
	safe_a=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $name "${(P@)name:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_name}}"
}

function set_symmetric_difference_print {
	setopt local_options no_ksh_arrays
	local a="$1" b="$2"
	typeset -Ua tmp
	typeset -Ua safe_a safe_b
	safe_b=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	tmp=("${(P@)a:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_a}}")
	print -r -- ${(q)tmp}
}

function set_insert_list {
	setopt local_options no_ksh_arrays
	local name="$1"; shift
	set -A $name "${(P@)name}" "$@"
}

function set_remove_list {
	setopt local_options no_ksh_arrays
	local name="$1"; shift
	typeset -Ua safesub
	safesub=("${(@)${(@)${(@)${(P)@//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
	set -A $name "${(P@)name:#${(j,|,)~safesub}}"
}
#----------------------------8< cut here >8------------------------------


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

end of thread, other threads:[~2008-09-28  1:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-27  9:02 Set operations Phil Pennock
2008-09-27 20:48 ` Peter Stephenson
2008-09-28  1:50   ` Phil Pennock

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).