From fc7a031261c8ddb92990320167fc0e4b274a4a63 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Mon, 23 Sep 2024 16:52:51 -0400 Subject: [PATCH 1/4] Create 20240923-simple-string-interpolation.md --- .../20240923-simple-string-interpolation.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 cadence/20240923-simple-string-interpolation.md diff --git a/cadence/20240923-simple-string-interpolation.md b/cadence/20240923-simple-string-interpolation.md new file mode 100644 index 00000000..afaf3723 --- /dev/null +++ b/cadence/20240923-simple-string-interpolation.md @@ -0,0 +1,93 @@ +--- +status: draft +flip: 288 +authors: Raymond Zhang (raymond.zhang@flowfoundation.org) +sponsor: Supun Setunga (supun.setunga@flowfoundation.org) +updated: 2024-09-23 +--- + +# FLIP 288: Simple String Interpolation + +## Objective + +This FLIP proposes adding support for simple string interpolation limited to identifiers only (no support for full expressions). + +## Motivation + +Currently Cadence has no support for string interpolation. It is convenient for developers to be able to inline variables in strings as opposed to the current solution of applying `concat` repeatedly. + +In general many languages support string interpolation for readability and ease-of-use. + +## User Benefit + +Developers can avoid repeatedly using `concat` to generate strings which will simplify code and readability. + +## Design Proposal + +There are many possible implementations two of which are highlighted below. The main constraint is backward compatibility, existing Cadence 1.0 code cannot be affected. + +### Python f-string syntax +Support the following: +```python +f"value is {value}" +``` +This change is backwards compatible as it introduces a new class of strings. + +### Swift \\() +Support the following: +```swift +"value is \(value)" +``` +This change is backwards compatible because `\(` is not currently a valid escape character. + +### Drawbacks + +None. + +### Alternatives Considered + +String interpolation is preferred over a formatting function (such as `printf`) for the following reasons: + +- Formatting is error prone (e.g. passing a `String` to `%d`) +- There are many languages which moved from traditional formatting to string interpolation (e.g. Python) + +### Performance Implications + +None, non-interpolated strings should not be affected. + +### Dependencies + +None. + +### Engineering Impact + +This change should be simple to implement. + +### Best Practices + +It may be preferred to use string interpolation over concat once implemented. + +### Compatibility + +Proposed changes are backwards compatible. + +### User Impact + +This is a feature addition, no impact. + +## Related Issues + +Extension to support expressions as opposed to just identifiers. Support custom `toString()` functions as well. + +## Prior Art + +- https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#String-Interpolation +- https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals + +## Questions and Discussion + +Feel free to discuss on the PR. + +Questions: +- Preferences or concerns on proposed syntax +- It may be less work to allow expressions versus enforcing identifier only, how much extra testing would be involved? From ff6e071d6920d4e2f8a8287d952d8c56d7e7e268 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 24 Sep 2024 12:20:40 -0400 Subject: [PATCH 2/4] Update 20240923-simple-string-interpolation.md --- .../20240923-simple-string-interpolation.md | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/cadence/20240923-simple-string-interpolation.md b/cadence/20240923-simple-string-interpolation.md index afaf3723..f5576f03 100644 --- a/cadence/20240923-simple-string-interpolation.md +++ b/cadence/20240923-simple-string-interpolation.md @@ -24,22 +24,20 @@ Developers can avoid repeatedly using `concat` to generate strings which will si ## Design Proposal -There are many possible implementations two of which are highlighted below. The main constraint is backward compatibility, existing Cadence 1.0 code cannot be affected. +The main constraint is backward compatibility, existing Cadence 1.0 code cannot be affected. The proposed solution follows the syntax of swift as below: -### Python f-string syntax -Support the following: -```python -f"value is {value}" -``` -This change is backwards compatible as it introduces a new class of strings. - -### Swift \\() -Support the following: ```swift -"value is \(value)" +"Variable = \(someVar)" ``` + This change is backwards compatible because `\(` is not currently a valid escape character. +For this initial proposal there will be several limitations on `someVar`: +- `someVar` will only be variable references with ability to be extended to expressions in the future +- `someVar` must support the built-in function `toString()` meaning it must be either a String, Number, Address or Character. + +This is still useful for the first iteration since there are easy workarounds for these limitations such as extracting expressions into local variables. + ### Drawbacks None. @@ -77,7 +75,7 @@ This is a feature addition, no impact. ## Related Issues -Extension to support expressions as opposed to just identifiers. Support custom `toString()` functions as well. +https://github.com/onflow/cadence/issues/3579 ## Prior Art @@ -88,6 +86,6 @@ Extension to support expressions as opposed to just identifiers. Support custom Feel free to discuss on the PR. -Questions: -- Preferences or concerns on proposed syntax -- It may be less work to allow expressions versus enforcing identifier only, how much extra testing would be involved? +## Implementation + +A POC is available at https://github.com/onflow/cadence/pull/3585. From 7e464e7470581d5729a584c34abb8c214dc61eae Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Tue, 24 Sep 2024 16:50:39 -0400 Subject: [PATCH 3/4] Update 20240923-simple-string-interpolation.md --- .../20240923-simple-string-interpolation.md | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/cadence/20240923-simple-string-interpolation.md b/cadence/20240923-simple-string-interpolation.md index f5576f03..a038c249 100644 --- a/cadence/20240923-simple-string-interpolation.md +++ b/cadence/20240923-simple-string-interpolation.md @@ -20,21 +20,23 @@ In general many languages support string interpolation for readability and ease- ## User Benefit -Developers can avoid repeatedly using `concat` to generate strings which will simplify code and readability. +Developers can avoid repeatedly using `concat` to generate strings which will simplify code and readability. Repeated concatenation is inefficient, as each concatenation results in an intermediate/temporary result, leading to an allocation and associated metering (computation and memory usage). + +In comparison, string interpolation can be implemented efficiently, and will thus also will lead to the user benefit of being less costly in terms of computation and memory usage. ## Design Proposal -The main constraint is backward compatibility, existing Cadence 1.0 code cannot be affected. The proposed solution follows the syntax of swift as below: +The proposed syntax for the string-literal with interpolation looks like follows: ```swift "Variable = \(someVar)" ``` -This change is backwards compatible because `\(` is not currently a valid escape character. +The main constraint is backward compatibility, existing Cadence 1.0 code cannot be affected. This change is backwards compatible because `\(` is not currently a valid escape character. For this initial proposal there will be several limitations on `someVar`: - `someVar` will only be variable references with ability to be extended to expressions in the future -- `someVar` must support the built-in function `toString()` meaning it must be either a String, Number, Address or Character. +- `someVar` must support the built-in function `toString()` meaning it must be either a `String`, `Number`, `Address`, `Character`, `Bool` or `Path`. This is still useful for the first iteration since there are easy workarounds for these limitations such as extracting expressions into local variables. @@ -44,14 +46,27 @@ None. ### Alternatives Considered -String interpolation is preferred over a formatting function (such as `printf`) for the following reasons: +String interpolation is preferred over a formatting function (such as `printf`) for two main reasons (1) string formatting is error prone and (2) there are many languages which moved from traditional formatting to string interpolation (e.g. Python). + +To talk more about (1): +- The type of the argument passed to the formatting facility may not match the format specifier (e.g. value of type `String` is passed to format specifier for type Integer like `%d`) +- Number of arguments passed to the formatter might not match the number of placeholders in the format specifier (e.g. too many or too few arguments) +- When there are many placeholders in the format string, the order of arguments can get mixed up easily +In most implementations of string formatting facilities, like when it is implemented as a normal function, these errors can not be detected statically, but only at run-time. + +However, some languages have formatting facilities that avoid some of the problems noted above, by statically checking the format specifier and the argument list. For example, Rust's `format!` macro does that. + +There are also many other implementations for string interpolation itself. For example: +- Python has "f-strings" where an `f` prefix of a string-literal indicates interpolation with curly brace placeholders (e.g. `f"{someVar}"`) +- JavaScript has backticks to indiciate string interpolation with curly brace placeholders (e.g. `` `{someVar}` ``) +- Kotlin has string interpolation in normal string literals with optional curly brace placeholders with a leading `$` (e.g. `"$someVar and ${someVar2}"`) + +There exists no clear "standard". The proposed design leverages the fact that escaping is already supported `\` and parentheses naturally surround values in expressions. Therefore, no new syntax is introduced (e.g. no literal prefix, no placeholder indicator, no new expression surround characters). -- Formatting is error prone (e.g. passing a `String` to `%d`) -- There are many languages which moved from traditional formatting to string interpolation (e.g. Python) ### Performance Implications -None, non-interpolated strings should not be affected. +None, non-interpolated strings should not be affected. The proposed design of string interpolation has much better performance compared to repeated string concatenation. ### Dependencies @@ -78,9 +93,11 @@ This is a feature addition, no impact. https://github.com/onflow/cadence/issues/3579 ## Prior Art - +Existing instances in other languages - https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#String-Interpolation - https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals +Some rationale and useful comparisons of string interpolation versus string formatting +- https://peps.python.org/pep-0498/ ## Questions and Discussion From 14c74cdee87e9cf646dcde2f9dd77191e9ec9986 Mon Sep 17 00:00:00 2001 From: Raymond Zhang Date: Wed, 30 Oct 2024 12:49:37 -0400 Subject: [PATCH 4/4] Accept FLIP --- cadence/20240923-simple-string-interpolation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cadence/20240923-simple-string-interpolation.md b/cadence/20240923-simple-string-interpolation.md index a038c249..f06c7769 100644 --- a/cadence/20240923-simple-string-interpolation.md +++ b/cadence/20240923-simple-string-interpolation.md @@ -1,9 +1,9 @@ --- -status: draft +status: accepted flip: 288 authors: Raymond Zhang (raymond.zhang@flowfoundation.org) sponsor: Supun Setunga (supun.setunga@flowfoundation.org) -updated: 2024-09-23 +updated: 2024-10-30 --- # FLIP 288: Simple String Interpolation