docker / docker/buildx

Docker Bake: Add `transposelist()`

Open
#3,559 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kind/enhancement status/triage
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 matrix field in target blocks, 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.