Introduce string.elem() method.
RELNOTES[NEW]:
Strings have a new .elems() method, that provides an iterator on the characters of the string.
PiperOrigin-RevId: 189980269
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 5913537..9856c7a 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -894,6 +894,27 @@
}
};
+ @SkylarkSignature(
+ name = "elems",
+ objectType = StringModule.class,
+ returnType = SkylarkList.class,
+ doc =
+ "Returns an iterable value containing successive 1-element substrings of the string. "
+ + "Equivalent to <code>[s[i] for i in range(len(s))]</code>, except that the "
+ + "returned value might not be a list.",
+ parameters = {@Param(name = "self", type = String.class, doc = "This string.")}
+ )
+ private static final BuiltinFunction elems =
+ new BuiltinFunction("elems") {
+ public SkylarkList<String> invoke(String self) throws ConversionException {
+ ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
+ for (char c : self.toCharArray()) {
+ builder.add(String.valueOf(c));
+ }
+ return SkylarkList.createImmutable(builder.build());
+ }
+ };
+
@SkylarkSignature(name = "endswith", objectType = StringModule.class, returnType = Boolean.class,
doc = "Returns True if the string ends with <code>sub</code>, "
+ "otherwise False, optionally restricting to [<code>start</code>:<code>end</code>], "
diff --git a/src/test/skylark/testdata/string_elems.sky b/src/test/skylark/testdata/string_elems.sky
new file mode 100644
index 0000000..3dbe724
--- /dev/null
+++ b/src/test/skylark/testdata/string_elems.sky
@@ -0,0 +1,13 @@
+# string.elems
+assert_eq(list("abcd".elems()), ["a", "b", "c", "d"])
+
+assert_eq(len("aaa".elems()), 3)
+
+def test_iter():
+ i = 0
+ for c in "abcd".elems():
+ assert_eq(c, "abcd"[i])
+ i += 1
+ assert_eq(i, 4)
+
+test_iter()