Docker Bake: Add `transposelist()`
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 4.5k
- Forks
- 682
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 29
Description
Description
I would like the ability to convert a list from rows into columns, AFAIK the typical term for this functionality is transpose.
It can currently be implemented via a user-defined function but may be worthwhile functionality for Docker Bake to include in it's stdlib functions:
function transposelist {
params = [nested_list]
result = [
for i in range(0, length(nested_list[0])):
nested_list[*][i]
]
}
FWIW, Terraform has similar functionality for maps of lists as a transpose collection function.
Reference
For context, I'm aware of some related functionality in HCL and Docker Bake.
Related functionality:
- This functionality is similar to the
matrixfield intargetblocks, but could be leveraged elsewhere such as via user-defined functions or global scope attributes. - HCL also has the splat syntax such that you can get a new list by a sublist index across all elements, or from a common key of each object element:
# Splat with indices: example = [["a", "1"], ["a", "2"], ["a", "3"]] formatlist("Left: %s, Right: %s", example[*][0], example[*][1]) # This is equivalent to `example...`, it does not spread a splat of all indices: formatlist("Left: %s, Right: %s", example[*]...) map_example = [{a: "1"}, {"a": "2"}, {"a": "3"}] formatlist("Value of key `a`: %s", map_example[*].a)
AFAIK the splat syntax lacks a way to do full transposition of the list, so you would need to repeat it for each element unless it could take a range.
There is also the ... spread operator that can only be used as the last parameter to a function, expanding a list of values into additional args.
Without a key or index applied after a splat, the list will remain unchanged, making the use of ... unhelpful towards transposition as example[*]... / example[*][...] / example[*...] are not valid forms to express transpose all element indices of a list.
Instead you either splat each index explicitly (as shown above), or via a for expression:
# Produces: [["a", "1"], ["a", "2"], ["a", "3"], ["b", "1"], ["b", "2"], ["b", "3"]]
matrix = setproduct(["a", "b"], ["1", "2", "3"])
# Currently to transpose a list you would need to know the fixed range
# to iterate and splat each column into a new collection:
# Transpose to: [["a", "a", "a", "b", "b", "b"], ["1", "2", "3", "1", "2", "3"]]
transposed = [for i,v in matrix[0]: matrix[*][i]]
# Proposed:
# This enables a list produce like `setproduct()` as the input without
# reliance on a reference like the the `for` expression needs.
transposed = transposelist(
setproduct(["a", "b"], ["1", "2", "3"])
)
This approach is compatible with ... to expand list elements into args:
# Current workaround (assuming a reference is available for the input):
formatlist("Left: %s, Right: %s", [for i,v in matrix[0]: matrix[*][i]]...)
# Proposed is capable of inlining the value instead of depending upon a reference:
formatlist("Left: %s, Right: %s", transposelist(matrix)...)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Docker Bake's stdlib functions documentation and the user-defined transposelist example in the issue, then trace how Bake exposes its built-in functions. Done means Docker Bake provides transposelist as a stdlib function that converts nested-list rows into columns and supports the usage shown in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100