Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nameref fails with nested associative arrays #594

Open
elmehdou opened this issue Dec 29, 2022 · 5 comments
Open

nameref fails with nested associative arrays #594

elmehdou opened this issue Dec 29, 2022 · 5 comments
Labels
bug Something is not working

Comments

@elmehdou
Copy link

Setting a nested associative arrays in one go fails on references:

function func_a1 {
	typeset -n ref=$1
	ref=(
		[key1]=(
			[key2]=val2
		)
	)
}

function func_a2 {
	typeset -n ref=$1
	typeset -A ref
	typeset -A ref[key1]=(
		[key2]=val2
	)
}

function func_b {
	typeset map1
	func_a1 map1
	echo "Function a1: $(typeset -p map1)"

	typeset map2
	func_a2 map2
	echo "Function a2: $(typeset -p map2)" 
}

func_b
@hyenias
Copy link

hyenias commented Dec 29, 2022

Your local scoped map1 variable via func_b function using func_a1 function ends up in the default global namespace as follows.

$ typeset -p map1 map1[0]
typeset -a map1=(([key2]=val2) )
typeset -A map1[0]=([key2]=val2)

It is difficult at this time for ksh to arrive at your desired nested or multidimensional array structure by simply parsing your one liner nested compound assignment. ksh's default assignment for =() is a compound variable [-C] not an indexed array [-a] nor associative array [-A]. ksh's current ambiguity in syntax as well as its current parsing methods has ended up in your map1 variable being an indexed array of 1 element containing an associative array of one element.

In this case as you have done in func_a2 function the multidimensional array structure needs to be defined before use so that ksh does not implicitly determine things. See below for a small adjustment to func_a1 defining the top level of your desired multidimensional array to be an associate array and not the default of a compound variable.

function func_a1 {
	typeset -n ref=$1
        typeset -A ref
	ref[key1]=([key2]=val2)
}

$ func_b
Function a1: typeset -A map1=([key1]=([key2]=val2) )
Function a2: typeset -A map2=([key1]=([key2]=val2) )
$ typeset -p map1 map2
$

Or perhaps, we might set variable map1 to be an associate array from the start.

function func_a1 {
	typeset -n ref=$1
	ref[key1]=([key2]=val2)
}

function func_b {
	typeset -A map1
	func_a1 map1
	echo "Function a1: $(typeset -p map1)"

	typeset map2
	func_a2 map2
	echo "Function a2: $(typeset -p map2)" 
}
$ func_b
Function a1: typeset -A map1=([key1]=([key2]=val2) )
Function a2: typeset -A map2=([key1]=([key2]=val2) )
$ typeset -p map1 map2
$

See issue #148 for more insights.

@elmehdou
Copy link
Author

elmehdou commented Dec 29, 2022

I have to say, it's quite frustrating when such important features are still unstable.
The company I work at relies heavily on ksh for complex operations, so having to find workarounds for each feature that's supposed to make my life easier and scripts cleaner is very scary.
Thanks for you feedback.

@hyenias
Copy link

hyenias commented Dec 29, 2022

I can understand your frustrations but I do not share your sentiment that ksh has important unstable features.

Hopefully, as your proficiency with ksh continues to grow; your life will become easier and far less scary. From my viewpoint, most other command line scripting languages lack multidimensional array support so I consider ksh's array support as absolutely beneficial allowing me to program in a more concise and flexible manner than having to create workarounds with one-dimensional arrays only.

@McDutchie McDutchie added the bug Something is not working label May 31, 2023
@McDutchie
Copy link

This does look like a bug. The following version of the reproducer makes it slightly more obvious that the two functions should be equivalent:

function func_a1 {
	typeset -n ref=$1
	typeset -A ref=(
		[key1]=(
			[key2]=val2
		)
	)
}

function func_a2 {
	typeset -n ref=$1
	typeset -A ref
	ref[key1]=(
		[key2]=val2
	)
}

function func_b {
	typeset map1
	func_a1 map1
	echo "Function a1: $(typeset -p map1)"

	typeset map2
	func_a2 map2
	echo "Function a2: $(typeset -p map2)" 
}

func_b

Output:

Function a1: typeset -A map1=()
Function a2: typeset -A map2=([key1]=([key2]=val2) )

Expected output:

Function a1: typeset -A map1=([key1]=([key2]=val2) )
Function a2: typeset -A map2=([key1]=([key2]=val2) )

@hyenias
Copy link

hyenias commented Jun 3, 2023

Additional testing results based on new reproducer:

Container type func_a1 Test Result Success
nested associative arrays typeset -A ref=([key1]=([key2]=val2) ) typeset -A map1=() No
nested indexed arrays typeset -a ref=( (a b) (c d) ) typeset -a map1 No
compound variables with indexed arrays typeset -C ref=( a=(c d); b=(e f) ) typeset -C map1=(typeset -a a=(c d);typeset -a b=(e f);) Yes
nested compound variables typeset -C ref=( a=(c=e; ); b=(d=f;) ) ksh: func_b[3]: func_a1: line 3: map1.a.c=e: no parent No
2d fixed indexed array typeset -a ref[2][2]; ref=( (a b) (c d) ) Memory fault or Segmentation fault No

An example of pasted code change above:

function func_a1 {
	typeset -n ref=$1
	typeset -a ref[2][2]; ref=( (a b) (c d) )

}
func_b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is not working
Projects
None yet
Development

No branches or pull requests

3 participants