String Reversal -- the Fun Way!

So I was tooling around with KM, as you do, and wondered about reversing the characters in a string. Most languages have a built-in to do that, KM might too (I never looked!), but if a language has a particular feature you can always go back to basics and DIY...

Here's an example in AppleScript:

reverseString("Hello World!")

on reverseString(aString)
	--display dialog "Chopping -- string is \"" & aString & "\""
	if length of aString > 1 then
		set firstChar to first character of aString
		set aString to reverseString(characters 2 thru -1 of aString as text)
	else
		return aString
	end if
	set aString to aString & firstChar
	--display dialog "Joining -- string is \"" & aString & "\""
	return aString
end reverseString

If you aren't sure what's happening, remove the comment marks ("--") from the two "display dialog" lines so you can "step through" and see how "aString" changes.

But can this be replicated in KM? Turns out, it can!

String Reverse.kmmacros (6.7 KB)
String Reverse Sub.kmmacros (4.6 KB)

Summary


Run "String Reverse" and it'll use "String Reverse Sub" as a subroutine to do the actual processing. Which is either brilliant, or has just earnt me the Forum's "Complete Idiot" badge and a lifetime ban :wink:

Biggest gotcha, as stated in the opening dialog, is the limit on the length of string you can process. Entering 25 or more characters fails without notification, crashing the KME. Coincidentally, I think it's related to this current topic, except every subroutine instances counts as two "normal" macros (tested by running increasing numbers of "stay open" macros -- every 2 decreased the number of characters that could be process by 1).

So (if you've got this far) -- KM does recursion! I'm not sure how useful that actually is in practice -- perhaps tree-walking to process folders of folders of files? -- but some might find a use for it.

Note: I did have a quick search through the Forum, but the hits I found for "recurs" were mainly JavaScripts etc rather than KM-native. Apologies if this feature is well-known and has been done to death already...

on reversedString(s)
    reverse of characters of s as string
end reversedString


on run
    reversedString("some string or other")
end run

--> "rehto ro gnirts emos"
1 Like

Yes, I know. As I said:

The point isn't that this example is a good way to reverse a string but that it is a way to use recursion to reverse a string. Perhaps the fact that you can write a recursive function in KM is old hat and not worthy of comment, perhaps it both useless and pointless. I just found it interesting, especially that each recursion counted as 2 normal macros since I stumbled across it at the same time as this.

But like I said -- perhaps this has been covered before?

I don't think I've seen recursion used in KM macros :- )


In passing, one possible variant of your AppleScript recursion might, FWIW, use:

  • rest for the tail of a list
  • and a recursion with an accumulator
-- reverse :: [a] -> [a]
on |reverse|(xs)
    script
        on rev(ys, a)
            if {} ≠ ys then
                rev(rest of ys, item 1 of ys & a)
            else
                a
            end if
        end rev
    end script
    
    rev(xs, {}) of result
end |reverse|


on reversedString(s)
    |reverse|(characters of s) as string
end reversedString


on run
    reversedString("Not palindromic")
end run

That's possibly better, but I don't think it's as understandable for most people as my example, which keeps the string as a string most of the time (and also makes it easier to display the "progression dialogs"). The main "What?!?" is the characters 2 thru -1 of aString construct -- it would be much clearer if AppleScript allowed last rather than -1, even better would be rest of aString to avoid the whole "make a list and coerce it to text" thing (and I missed out the whole TIDs capture/set/reset routine, for brevity). But you work with what you've got...

More importantly -- the simple, understandable, AS function is replicated almost action-for-line in the KM subroutine, so people can see I'm not pulling a fast one! It really is "here's an example of recursion in AppleScript, and here's the same in KM" that anyone can follow along with -- albeit with the caveat that depth is severely limited in KM.

And that, given some of the amazingly inventive things I've seen from you guys in my short time here, probably says all I need to know about its (lack of) usefulness!