Help with function name

I will be adding a function to my M_String module that will try to emulate the kind of functionality that some other languages provide, to wit, the ability to put a variable into a string so it is evaluated.

In Swift, for example, you can do this:

var personName="Kem"
println("Hi \\(personName)!")
// prints "Hi Kem!"

Naturally I can’t do quite that in a Xojo function, but I can do something similar to the way a prepared statement works, so you can do something like:

MsgBox MyFunction( "Hi \\?!", "Kem" )

That’s a simple example. With Variants, you should be able to do:

MsgBox MyFunction( "The \\? \\? the \\? by a score of \\? to \\?", "Yankees", "beat", "Red Sox", 15, 1 )
// "The Yankees beat the Red Sox by a score of 15 to 1"

But what to call “MyFunction”? Some thoughts:

Inject
Prepare

Since the function will end with “_MTC” it should be fairly short for convenience but still descriptive. Suggestions?

Kem.

In other languages, this is called String Expansion. How about Expand()?

BTW, one thing with PostgreSQL expansion is it uses $1, $2, $3… So, in cases like that you can:

MsgBox Expand("Hello $1, I hope you are having a great time. $1, be sure to visit $2 while in town!", "Kem", "McDonalds")

It is extra work though if you go back and refactor your parameter list. i.e. changing $1’s to $2’s if inserting something at the start. Just a thought.

I like Brad’s suggestion, Kem.
That or Prep (short for prepare since you’re adding 4 characters with _MTC)

Oh… One more thing about $1 and $2… If you are using your source string as a constant and your app is multi-lingual… Some languages may have various orders. Using $1, $2 would enable the programmer to rearrange order in the output string.

Jeremy, Expand is good, I’ll think on that. And I like the other suggestion too. I hadn’t considered the cases where you might want the same variable injected in two different spots or in different order. I just have to think about cases where the number of variables gets into the double-digits so $1 and $10 don’t get confused.

Oh, of course, I’ll work backwards.

Tim, I appreciate the suggestions (well, the second one anyway). Prep is too short for my liking, so I’ll never remember what it means. I’m leaning towards Inject but Expand is good too.

infuse

Just allow a maximum of 9 variables, $1 - $9. I can’t think of any sane use case for needing more than 9 variables in a one-line substitution function. Btw, it’s sometimes called substitution/substitute.

I’ve also seen it done with {1} instead of $1. (E.g., Python.)

[quote=101995:@Kem Tekinay]I just have to think about cases where the number of variables gets into the double-digits so $1 and $10 don’t get confused.

Tim, I appreciate the suggestions (well, the second one anyway). Prep is too short for my liking, so I’ll never remember what it means. I’m leaning towards Inject but Expand is good too.[/quote]
Could just take the easy way out and limit it to 9 replacements.

Beaten to the punch.

I’m against the python look.

No need to limit it, working backwards works fine. Now I just have to solve the problem of one variable containing a token, e.g.,

s = Expand_MTC( "This is $2", "wrong", "$1" )
// Should get "This is $1"

BTW, I’ve decided to allow both types. If “\?” is present, it will be used in order. Otherwise, it will look for the “$#” form.

Jeremy has talked me into Expand, btw. Thanks for the suggestions.

This is the code I came up with, complete with comments. I haven’t yet tested for speed. Suggestions welcome.

Function Expand_MTC(src As String, ParamArray vars() As Variant) As String
  // Takes a string and replaces the occurrences of a token with the values of the
  // Variants. Those Variants must be able to get a string value.
  // Values that exceed the number of tokens will be ignored.
  //
  // Two forms of tokens are accepted. If "\\?" is present in the string, it will
  // replace those in order. Otherwise, it will look for the form "${#}"
  // where # represents a specific value in the array.
  //
  // Examples:
  //  s = Expand_MTC( "The ${1} beat the ${2} by a score of ${3} to ${4}", "Yankees", "Red Sox", 15, 1 )
  //  s will be "The Yankees beat the Red Sox by a score of 15 to 1"
  //  s = Expand_MTC( "\\? is a great \\?", "Derek Jeter", "shortstop" )
  //  s will be "Derek Jeter is a great shortstop"
  
  if vars.Ubound = -1 then return src
  if src = EmptyString then return src
  
  const kToken = "\\?"
  
  if src.InStr( kToken ) = 0 then
    
    // Using the "${#}" form
    for i as Integer = 0 to vars.Ubound
      dim token as string = "${" + str( i + 1 ) + "}"
      src = src.ReplaceAll( token, vars( i ).StringValue )
    next i
    
  else // Using the "\\?" form
    
    dim srcArr() as string = src.Split( kToken )
    dim resultArr() as string
    if srcArr.Ubound <> -1 then
      resultArr.Append srcArr( 0 )
      dim srcIndex as Integer = 1
      dim varIndex as Integer = 0
      do until srcIndex > srcArr.Ubound or varIndex > vars.Ubound
        dim thisVar as String = vars( varIndex ).StringValue
        varIndex = varIndex + 1
        
        resultArr.Append thisVar
        resultArr.Append srcArr( srcIndex )
        srcIndex = srcIndex + 1
      loop 
      
      // Add any missing source
      for i as Integer = srcIndex to srcArr.Ubound
        resultArr.Append kToken
        resultArr.Append srcArr( i )
      next i
      src = join( resultArr, "" )
    end if
    
  end if
  
  return src
  
End Function

You could probably do away with the braces by working downward through the array.

For I as integer = Ubound(vars) downto 0

[quote=101976:@Kem Tekinay]MsgBox MyFunction( “The \? \? the \? by a score of \? to \?”, “Yankees”, “beat”, “Red Sox”, 15, 1 )
// “The Yankees beat the Red Sox by a score of 15 to 1”[/quote]

What is it with you and Sox bashing? :stuck_out_tongue:

I’m against nonsensical naming. Xojo is English based, and Kem in English have no meaning, but in Vietnamese means Cream. :stuck_out_tongue:

“Expand” is good enough.[quote=102004:@Kem Tekinay]

If “\?” is present, it will be used in order. Otherwise, it will look for the “$#” form.[/quote]

I would suggest you trying to keep the sequential and positional syntax similar, like:
“my name is \? and my dog is \?”, name, dog
“my name is \2? and my dog is \1?”, dog, name
“my name is \2? and my dog is \1? and the name 37 is \37?”, arrayOfNames

One regex like this gets all of them “\\\d*\?”

Have you seen the LR recently? :slight_smile:

Rick, thanks for the suggestions, but I wanted to avoid ambiguity, and I wanted to keep the syntax different in case one type can’t be used.

I thought about that, but if the second value contains, for example, “$100”, then the next pass will incorrectly replace that with the contents of the first value. I also want to avoid ambiguity if a token is pressed up against a number like “$132”.

However, after sleeping on it, I think I might split the string and replace the parts rather than using ReplaceAll. That way, if value 1 contains “${2}”, it won’t be replaced on the next pass. Highly unlikely, but I like being thorough.