PxPlus User Forum

Main Board => Discussions => Wish List => Topic started by: Thomas Bock on November 15, 2023, 08:45:15 AM

Title: string interpolation
Post by: Thomas Bock on November 15, 2023, 08:45:15 AM
In C# there is the possibility to build strings by referencing/including variables.

Code: [Select]
string name = "Tom";
var date = DateTime.Now;
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");

These strings are much more readable than coding a concatenation of several small strings. E.g. building a SQL-statement becomes more straight forward.
If PxPlus would provide such functionality, we could gain speed, because the interpreter would not need to translate several lines of code.
Title: Re: string interpolation
Post by: Devon Austen on November 15, 2023, 10:16:13 AM
Here is an example of your code in PxPlus:

Code: [Select]
name$ = "Tom"
print "Hello, "+name$+"! Today is "+dte(0:"%Wl")+", it's "+dte(0:"%Hz:%mz")+" now."

Concatenation can happen on the same line of code.

As for speed I don't think the $"xxxx {var} xxxx" style string building would be any faster from a performance standpoint. Internally the same thing will be happening building the string plus now you have to scan the string for the variables as well.

Does that syntax work for you?
Title: Re: string interpolation
Post by: Allen Miglore on November 15, 2023, 10:20:17 AM
I agree, this is a handy feature of many languages.  I wrote a function to do something similar a while back and use it internally in UnForm.

def fn%resolveexpr$(local s$)
   local x,expr$,before$,after$,val$,between$
   s$=sub(s$,"\{",$01$),s$=sub(s$,"\}",$02$)
   x=msk(s$,"{[^{}]*}")
   while x>0
      before$=s$(1,x-1),between$=s$(x+1,msl-2),expr$="str("+s$(x+1,msl-2)+")",after$=s$(x+msl)
      val$=$01$+between$+$02$,val$=evs(expr$,err=*next)
      s$=before$+val$+after$
      x=msk(s$,"{[^{}]*}")
   wend
   s$=sub(s$,$01$,"{"),s$=sub(s$,$02$,"}")
   return s$
end def

It works with anything that can be resolved with evs().

a=123, b$="456"

?fn%resolveexpr$("This is a: {str(a:""###0.00"")}, this is b$: {b$}")
This is a:  123.00, this is b$: 456

Internal braces can be escaped:

?fn%resolveexpr$("This is a: {str(a:""###0.00"")}, this is b$: \{b$\}")
This is a:  123.00, this is b$: {b$}

Title: Re: string interpolation
Post by: Stéphane Devouard on November 16, 2023, 06:55:57 AM
Thomas

String interpolation exists (kinda) in PxPlus :

Code: [Select]
print MSG(="Hello, %1 ! Today is %2, it's %3 now.",name$,dte(0:"%Wl"),dte(0:"%Hz:%mz"))
Title: Re: string interpolation
Post by: Mike King on December 14, 2023, 11:46:40 AM
Actually here is a simple object that you can use to accomplish what you are looking for:

Code: [Select]
  def class "string"
  function perform Eval$(string$)
  local _.x$,_.o
  enter (_.x$)
  _.o=pos("\"=_.x$)
  if _.o \
   then _.x$=sub(_.x$,"\{",$01$);
        _.x$=sub(_.x$,"\}",$02$);
        _.x$=sub(_.x$,"\"+quo,$03$)
 !
  translate _.x$,"{"+chr(6)+"""+STR("+"}"+chr(3)+")+"""
  _.x$=evs(quo+_.x$+quo)
  if _.o \
   then translate _.x$,$01$+chr(1)+"{"+$02$+chr(1)+"}"+$03$+chr(1)+quo
  return _.x$
  end def

Basically you can pass it a string with values/expressions to expand surrounded by curly braces.  If you want to input actual curly braces or a quote in the output string, prefix them with a backslash.  For example:

->name$="Tom"
->o=new("string")
->print o'Eval$("Hello, {name$}! Today is {day}")
Hello, Tom! Today is 12/14/23


If the string has an error such as unmatched curly braces or a invalid value/expression the error will be returned to the caller.