{
"title": "compose",
"category": "strings/core",
"keywords": [
"compose",
"format",
"string array",
"sprintf",
"gpu"
],
"summary": "Format numeric, logical, and text data into MATLAB string arrays using printf-style placeholders.",
"references": [
"https://www.mathworks.com/help/matlab/ref/compose.html"
],
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [],
"broadcasting": "none",
"notes": "Formatting runs on the CPU. GPU inputs are gathered to host memory before substitution."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 1,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::strings::core::compose::tests",
"integration": "builtins::strings::core::compose::tests::compose_gpu_argument"
},
"description": "`compose(formatSpec, A1, ..., An)` substitutes data into MATLAB-compatible `%` placeholders and returns the result as a string array. It combines `sprintf`-style formatting with string-array broadcasting so you can generate multiple strings in one call.",
"behaviors": [
"`formatSpec` must be text: a string scalar, string array, character vector, character array, or cell array of character vectors.",
"If `formatSpec` is scalar and any argument array has more than one element, RunMat broadcasts the scalar specification over the array dimensions.",
"When `formatSpec` is a string or character array with multiple elements, the output has the same shape as the specification. Each element uses the corresponding row or cell during formatting.",
"Arguments can be numeric, logical, string, or text-like cell arrays. Non-text arguments are converted using MATLAB-compatible rules (logical values become `1` or `0`, complex numbers use the `a + bi` form).",
"When you omit additional arguments, `compose(formatSpec)` simply converts the specification into a string array, preserving the original structure.",
"Errors are raised if argument shapes are incompatible with the specification or if format specifiers are incomplete."
],
"examples": [
{
"description": "Formatting A Scalar Value Into A Sentence",
"input": "msg = compose(\"The answer is %d.\", 42)",
"output": "msg = \"The answer is 42.\""
},
{
"description": "Broadcasting A Scalar Format Spec Over A Vector",
"input": "result = compose(\"Trial %d\", 1:4)",
"output": "result = 1×4 string\n \"Trial 1\" \"Trial 2\" \"Trial 3\" \"Trial 4\""
},
{
"description": "Using A String Array Of Formats",
"input": "spec = [\"max: %0.2f\", \"min: %0.2f\"];\nvalues = compose(spec, [3.14159, 0.125])",
"output": "values = 1×2 string\n \"max: 3.14\" \"min: 0.12\""
},
{
"description": "Formatting Each Row Of A Character Array",
"input": "C = ['Row %02d'; 'Row %02d'; 'Row %02d'];\nidx = compose(C, (1:3).')",
"output": "idx = 3×1 string\n \"Row 01\"\n \"Row 02\"\n \"Row 03\""
},
{
"description": "Combining Real And Imaginary Parts",
"input": "Z = [1+2i, 3-4i];\ntxt = compose(\"z = %s\", Z)",
"output": "txt = 1×2 string\n \"z = 1+2i\" \"z = 3-4i\""
},
{
"description": "Using A Cell Array Of Format Specs",
"input": "specs = {'%0.1f volts', '%0.1f amps'};\nreadings = compose(specs, {12.6, 3.4})",
"output": "readings = 2×1 string\n \"12.6 volts\"\n \"3.4 amps\""
},
{
"description": "Formatting GPU-Resident Data",
"input": "G = gpuArray([10 20 30]);\nlabels = compose(\"Value %d\", G)",
"output": "labels = 1×3 string\n \"Value 10\" \"Value 20\" \"Value 30\""
}
],
"faqs": [
{
"question": "What happens if the number of format arguments does not match the placeholders?",
"answer": "RunMat raises `compose: format data arguments must be scalars or match formatSpec size`. Ensure that each placeholder has a corresponding value or broadcast the specification appropriately."
},
{
"question": "Can `compose` handle complex numbers?",
"answer": "Yes. Complex numbers use MATLAB's canonical `a + bi` formatting, so `%s` specifiers receive the string form of the complex scalar."
},
{
"question": "How does `compose` treat logical inputs?",
"answer": "Logical values are converted to numeric `1` or `0` before formatting so they work with `%d`, `%i`, or `%f` placeholders."
},
{
"question": "Does `compose` modify the shape of the output?",
"answer": "No. The output matches the broadcasted size between `formatSpec` and the input arguments. Scalar specifications broadcast across non-scalar arguments."
},
{
"question": "What if I pass GPU arrays?",
"answer": "Inputs that reside on the GPU are automatically gathered to host memory before formatting. The resulting string array always lives on the CPU."
},
{
"question": "How do I emit literal percent signs?",
"answer": "Use `%%` inside `formatSpec` just like `sprintf`. The formatter converts `%%` into a single `%`."
},
{
"question": "Can I mix scalars and arrays in the arguments list?",
"answer": "Yes, as long as non-scalar arguments all share the same number of elements or match the size of `formatSpec`. Scalars broadcast across the target shape."
},
{
"question": "What happens when `formatSpec` is empty?",
"answer": "`compose(formatSpec)` returns an empty string array with the same shape as `formatSpec`. When `formatSpec` and arguments have zero elements, the output is `0×0`."
}
],
"links": [
{
"label": "string",
"url": "./string"
},
{
"label": "sprintf",
"url": "./sprintf"
},
{
"label": "strcat",
"url": "./strcat"
},
{
"label": "join",
"url": "./join"
},
{
"label": "char",
"url": "./char"
},
{
"label": "num2str",
"url": "./num2str"
},
{
"label": "str2double",
"url": "./str2double"
},
{
"label": "strcmp",
"url": "./strcmp"
},
{
"label": "strcmpi",
"url": "./strcmpi"
},
{
"label": "string.empty",
"url": "./string.empty"
},
{
"label": "strings",
"url": "./strings"
},
{
"label": "strlength",
"url": "./strlength"
},
{
"label": "strncmp",
"url": "./strncmp"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/strings/core/compose.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/strings/core/compose.rs"
},
"gpu_behavior": [
"`compose` is a residency sink. When inputs include GPU-resident tensors, RunMat gathers the data back to host memory using the active acceleration provider before performing the formatting logic. All formatted strings live in host memory, so acceleration providers do not need compose-specific kernels."
]
}