Page 1 of 2

Can a function return two values?

Posted: Wed Jan 30, 2019 11:49 pm
by kaveh1000
I have a (long) piece of text that I want to split using certain criteria. I want a function to do the splitting, but I then want the two pieces of text returned, so simplistically I want to say:

Code: Select all

function split_it pText
[...do some magic to get tText1 and tText2...]
return tText1
return tText2
which is of course not possible. I could say:

Code: Select all

function split_it pText
[...do some magic to get tText1 and tText2...]
return tText1, tText2
using comma as a delimiter. But of course there are commas in the text. I could then use a unique string as the delimiter, but it gets increasingly messy.

I am sure I am missing something simple, so look forward to slamming my forehead at the solution. ;-)

Thanks.

Kaveh

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 12:27 am
by Klaus
The magic word is ARRAY! 8)

Code: Select all

...
put tText1 into tArray[1]
put tText2 into tArray[2]
return tArray
...

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 12:54 am
by kaveh1000
Thank you sir! I must get into using arrays. :-) Great.

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:16 am
by dunbarx
Klaus' array is compact and modern.

But in more basic LC-ese you might think of inserting an unprintable character at the break point. Then you can use the itemDelimiter to separate the text. So if you had a large body of text in a variable "longText", you could:

Code: Select all

on mouseUp
  set the itemDel to numToChar(202) --my favorite
  put trunc(the length of longText / 2) into tMiddle -- about the middle of any string
  put numToChar(202) after char tMiddle of longText
  put item 1 of longText into firstPortion --about half the string
  put item 2 of longText into secondPortion --the other half
  --do whatever here with your two halves
end mouseUp
Reassembling is straightForward. And when you separate longText using an item, the item itself is not included in either portion of the resulting two strings. Note that you do not NEED to use an unprintable character, anything above 127 might do, but strange extended ASCII chars to oftentimes work themselves into text.

I mention all this because I think it is important to play with LC string functionality at a low level; it helps with the fancier stuff later on.

Craig Newman

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:26 am
by dunbarx
It just occurred to me that you wanted a function. Again, given a string,

Code: Select all

on mouseUp
      put "1234567890" into longText
   answer splitText(longText)
end mouseUp

function splitText tText
   set the itemDel to numToChar(202)
   put trunc(the length of tText / 2) into tMiddle -- about the middle of any string
   put numToChar(202) after char tMiddle of tText
   return item 1 of tText  & return & item 2 of tText
end splitText
Craig

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:28 am
by FourthWorld
I don't know how well this will fit your situation, but you can pass in variables by reference and they'll change the values in the calling handler automatically for you.

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 5:07 am
by mwieder
I also have some functions that just return a comma-separated pair of numbers. As in

Code: Select all

function someFunction
local tWidth, tHeight

  -- do something here
  return tWidth,tHeight
end someFunction

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 8:53 am
by kaveh1000
Thank you all.

@Mark, your solution is what I tried first and useful for values, but here I am dealing with long text that includes commas, so need an unusual character for delimiter.

@Craig, what is char 202? I am dealing with 3rd party text. is there a chance that char would be in the text I am passing to the function?

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 11:07 am
by bogs
dunbarx wrote:
Thu Jan 31, 2019 3:16 am
Klaus' array is compact and modern.
But in more basic LC-ese you might think of inserting an unprintable character at the break point. Then you can use the itemDelimiter to separate the text. So if you had a large body of text in a variable "longText", you could:

Code: Select all

on mouseUp
  set the itemDel to numToChar(202) --my favorite
  put trunc(the length of longText / 2) into tMiddle -- about the middle of any string
  put numToChar(202) after char tMiddle of longText
  put item 1 of longText into firstPortion --about half the string
  put item 2 of longText into secondPortion --the other half
  --do whatever here with your two halves
end mouseUp
Reassembling is straightForward. And when you separate longText using an item, the item itself is not included in either portion of the resulting two strings. Note that you do not NEED to use an unprintable character, anything above 127 might do, but strange extended ASCII chars to oftentimes work themselves into text.
I mention all this because I think it is important to play with LC string functionality at a low level; it helps with the fancier stuff later on.
Craig Newman
You might want a non type-able non displaying character in something like that, like null.
Lc Dictionary wrote: null
Type: constant
See Also: space Constant, constant Command
Introduced: 2.0
Platforms: Desktop, Server, Web and Mobile
Summary:
Equivalent to the null character (ASCII zero).
Examples:
read from file modem: until null
Use the null constant as an easier-to-read substitute for numToChar(0).
Comments:
The null constant is needed because you can't type the character it represents in a script.
I love null from the days where I wrote batch scripts in dos, because I often used your favorite ctn(202) as part of the *display design. I also think it is what csv files should have used (cnv?) :D

@Kaveh,
You can find a chart of all ascii text in any search, like this result.
In this case, ASCII code 202 = ╩ ( Box drawing character double line horizontal and up )

*Display design - before real gui desktops, it was all crafted at the CLI
Image

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 11:21 am
by Thierry
Hi kaveh,

Never forget that LiveCode is sooooo flexible...

So, here is one way by setting your own delimiter:

Code: Select all

local kaveh_delimiter = "__KAVEH__"

function split_it pText
   // ...do some magic to get tText1 and tText2
   put char 1 to 10 of pText into tText1
   put char 11 to -1 of pText into tText2
   
   return tText1 & kaveh_delimiter & tText2
end split_it
and use it this way:

Code: Select all

on test
   local R
   put split_it( "1234567890abcdef") into R
   set the itemdel to kaveh_delimiter
   // check results:
   answer item 1 of R
   answer item 2 of R
end test
or another one which I prefer:

Code: Select all

command split_it2 pText, @tText1, @tText2
   // ...do some magic to get tText1 and tText2
   put char 1 to 10 of pText into tText1
   put char 11 to -1 of pText into tText2
end split_it2

Code: Select all

on test
   local R1, R2
   split_it2 "1234567890abcdef", R1, R2
   // check results:
   answer R1
   answer R2
end test
HTH,
Thierry

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 2:37 pm
by kaveh1000
Thank you all for these gems. And Thierry, yes, I love LiveCode because of its flexibility and the fact that we can be so creative in it. One of my favorite discoveries is using a multi-character LineDelimiter. Wonderful concept...

I am going to study the replies very carefully and see which method works best.

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:42 pm
by richmond62
To answer the initial question just go and work out the square root of 4. 8)

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:46 pm
by dunbarx
The ability to set the itemDel to multiple chars is cool indeed.

When I suggested ASCII 202, it was just because that char is VERY unlikely to appear in any conceivable text. But since multiple chars can now be an item, you could also use "ZZZZZZZZ", and that, too, is unlikely to appear in any conceivable text.

so.

Code: Select all

on mouseUp
      put "1234567890" into longText
   answer splitText(longText)
end mouseUp

function splitText tText
   set the itemDel to "ZZZZZZZZ"
   put trunc(the length of tText / 2) into tMiddle -- about the middle of any string
   put "ZZZZZZZZ"  after char tMiddle of tText
   return item 1 of tText  & return & item 2 of tText
end splitText
Craig

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 3:50 pm
by kaveh1000
Well I am not going to take a risk with ZZZZZ. I tell you what, I have actually been using the millisecs as the itemdelimiter. So it is generated on the fly and pretty foolproof. ;-)

Re: Can a function return two values?

Posted: Thu Jan 31, 2019 5:05 pm
by mwieder
I regularly use numtochar(3) as a delimiter when I need something that is guaranteed to be unprintable.