Forum Discussion
Accumulation, result error / not error
- 5 days ago
Ignore my previous reply, i was having a dumb moment.
Step by Step this is what your top code is doing and its issues:- Splitter.SplitTextByWhitespace() splits the sentence into a list of words.
- List.Transform processes each word x with List.Accumulate({0,1}, x, ...).
- For each word, it accumulates over indices {0,1} :
- c=0: Text.Remove(s, removves) strips . , , , ; , ' , s from the word, then compares the result to old{0} ("cat"), producing a boolean (true/false). This boolean becomes the new accumulator value s .
- c=1: it then tries Text.Remove(s, removves) again — but s is now a boolean, not text. Text.Remove requires a text value, so this step throws a type-conversion error ("We cannot convert the value True/False to type Text").
Other issues:
- new = {"TIGER", "WOLF"} is defined but never used. There's no actual replacement happening, despite the variable name replace implying substitution.
- removves strips the letter "s" from anywhere in the word, not just trailing plural "s". This would mangle words like "was" → "wa".
- Because old{1} ("dog") is never checked in a way that survives (the accumulator overwrites itself with a boolean after the first pass), even if the type error didn't occur, the "dog" comparison logic is broken.
Net result:
This query will fail at evaluation time with a type error on the second accumulation step for every word, it does not successfully identify or replace "cat"/"dog" occurrences with "TIGER"/"WOLF".
Comparing that to your second code, this version fixes the type bug and actually does the replacement. Key differences:- Accumulator now stays text-typed throughout
- test = Text.Remove(s, removves) = old{c} still computes the boolean, but it's only used inside an if, not stored as the accumulator.
- if test then Text.Replace(s, old{c}, new{c}) else s the accumulator s always remains a string: either the replaced text or the unchanged original. This avoids the previous "boolean fed into Text.Remove" type error.
- new is now actually used
- When the stripped word matches old{c}, Text.Replace swaps the original word text (s , punctuation/apostrophes intact) for new{c} e.g., "cat's" → since Text.Remove("cat's", removves) = "cat" matches old{0}, it does Text.Replace("cat's", "cat", "TIGER") → "TIGERs'" ... actually let's check: Text.Replace replaces the substring "cat" inside "cat's", giving "TIGER's". Punctuation around it is preserved, not stripped.
- Both indices now meaningfully checked
- c=0 checks against "cat"/"TIGER", c=1 checks against "dog"/"WOLF", each independently applied to whatever s currently is, so a word can be tested/replaced for cat, then (unchanged, since it won't match "dog") passed through for the dog check.
- Added Text.Combine(replace, " ")
- Rejoins the transformed word list into a single string, so the result is readable text, whereas the original returned a list of words with no recombination.
Problems I still see:
- Stripping "s" anywhere (not just trailing) still risks false matches (e.g., "dogs" → "dog" correctly, but any word containing an internal "s" gets mangled before comparison, though the replacement itself uses the original s , so display text is safer than before).
- Words like "cats'" → stripped to "cat" → matches → Text.Replace("cats'", "cat", "TIGER") → "TIGERs'" (plural/apostrophe artifacts remain, since only the substring "cat" is replaced, not the whole cleaned token).
- Whitespace based splitting means original punctuation attached to words is retained in s, so replacements produce oddly suffixed results like "TIGER's", "WOLFs", "TIGERs'".
Ignore my previous reply, i was having a dumb moment.
Step by Step this is what your top code is doing and its issues:
- Splitter.SplitTextByWhitespace() splits the sentence into a list of words.
- List.Transform processes each word x with List.Accumulate({0,1}, x, ...).
- For each word, it accumulates over indices {0,1} :
- c=0: Text.Remove(s, removves) strips . , , , ; , ' , s from the word, then compares the result to old{0} ("cat"), producing a boolean (true/false). This boolean becomes the new accumulator value s .
- c=1: it then tries Text.Remove(s, removves) again — but s is now a boolean, not text. Text.Remove requires a text value, so this step throws a type-conversion error ("We cannot convert the value True/False to type Text").
Other issues:
- new = {"TIGER", "WOLF"} is defined but never used. There's no actual replacement happening, despite the variable name replace implying substitution.
- removves strips the letter "s" from anywhere in the word, not just trailing plural "s". This would mangle words like "was" → "wa".
- Because old{1} ("dog") is never checked in a way that survives (the accumulator overwrites itself with a boolean after the first pass), even if the type error didn't occur, the "dog" comparison logic is broken.
Net result:
This query will fail at evaluation time with a type error on the second accumulation step for every word, it does not successfully identify or replace "cat"/"dog" occurrences with "TIGER"/"WOLF".
Comparing that to your second code, this version fixes the type bug and actually does the replacement. Key differences:
- Accumulator now stays text-typed throughout
- test = Text.Remove(s, removves) = old{c} still computes the boolean, but it's only used inside an if, not stored as the accumulator.
- if test then Text.Replace(s, old{c}, new{c}) else s the accumulator s always remains a string: either the replaced text or the unchanged original. This avoids the previous "boolean fed into Text.Remove" type error.
- new is now actually used
- When the stripped word matches old{c}, Text.Replace swaps the original word text (s , punctuation/apostrophes intact) for new{c} e.g., "cat's" → since Text.Remove("cat's", removves) = "cat" matches old{0}, it does Text.Replace("cat's", "cat", "TIGER") → "TIGERs'" ... actually let's check: Text.Replace replaces the substring "cat" inside "cat's", giving "TIGER's". Punctuation around it is preserved, not stripped.
- Both indices now meaningfully checked
- c=0 checks against "cat"/"TIGER", c=1 checks against "dog"/"WOLF", each independently applied to whatever s currently is, so a word can be tested/replaced for cat, then (unchanged, since it won't match "dog") passed through for the dog check.
- Added Text.Combine(replace, " ")
- Rejoins the transformed word list into a single string, so the result is readable text, whereas the original returned a list of words with no recombination.
Problems I still see:
- Stripping "s" anywhere (not just trailing) still risks false matches (e.g., "dogs" → "dog" correctly, but any word containing an internal "s" gets mangled before comparison, though the replacement itself uses the original s , so display text is safer than before).
- Words like "cats'" → stripped to "cat" → matches → Text.Replace("cats'", "cat", "TIGER") → "TIGERs'" (plural/apostrophe artifacts remain, since only the substring "cat" is replaced, not the whole cleaned token).
- Whitespace based splitting means original punctuation attached to words is retained in s, so replacements produce oddly suffixed results like "TIGER's", "WOLFs", "TIGERs'".