MV Your Way: Extending mvBASIC

Most flavors of mvBASIC have a little used, often misunderstood structure called FUNCTION . It isn't exactly like FUNCTION in other languages. In PHP, JavaScript, nearly every language that has it, you can stack dozens of FUNCTION s into a single script or source record. The one in mvBASIC requires its own document. One function per source record. On a quick glance, this makes it look like a poor cousin of SUBROUTINE . You couldn't be blamed for thinking it has no real purpose.

That's what I thought for most of my career. Now, I'm beginning to develop a deep respect for it instead. In this article, and the next, I hope to sell you on the value of the humble FUNCTION .

The line of code in Figure 1 will not compile in mvBASIC.

019 doz = xconv(quantity,'unitsToDozens')
Figure 1

It sure would be nice to have a built-in library of any-to-any math conversions. If XCONV existed, it could convert radius to circumference. It could change liters to ounces. There are plenty of standard conversions that I don't need to recode over and over again.

If we write a subroutine to solve this, it would look something like Figure 2.

019 call xconv(doz,quantity,'unitsToDozens')
Figure 2

We'd support that with a routine like Figure 3.

001 subroutine xconv(result,value,rule)
002 begin case
003 case rule = 'unitsToDozens'
004 result = int(value/12)
005 result<2> = rem(value/12)
Figure 3

It'll work. It just isn't as elegant. However, we can recast the SUBROUTINE as a FUNCTION and keep our original syntax [Figure 4].

001 function xconv(value,rule)
002 begin case
003 case rule = 'unitsToDozens'
004 result = int(value/12)
005 result<2> = rem(value/12)
xxx return result

Figure 4

Now our original line 19, the one that looks like mvBASIC has always had an XCONV, will compile and work. We just need to add a DEFFUN to connect the FUNCTION to the calling program [Figure 5].

005 deffun xconv()
Figure 5

I haven't scanned the documentation on every MultiValue flavor, so you may need to check your version and make minor tweaks. I believe this should work for most or all of them.

So, what really is the difference between a FUNCTION and a SUBROUTINE ? While they can be pressed into equivalent service, the FUNCTION is more organic. It extends the language. See a quick example in Figure 6.

001 function search(needle,haystack)
002 result = ''
003 locate(needle,haystack;pos) then
004 result = 'ATTR'
005 result<2> = pos
006 end else
007 pos = index(haystack,needle)
008 if (pos > 0) then
009 result = 'CHAR'
010 result<2> = 'pos'
011 end
012 end
013 return result

Figure 6

Now we have a combined command that can easily be extended to search for multivalues or subvalues or any case insensitivity… many, many options. Once again, yes, we can do this more awkwardly with SUBROUTINEs but why? The same way that we use multiplication when repeated addition can achieve the same result. Multiplication is clearer and cleaner.

Next issue, we'll show you how to use FUNCTION to do a massive MultiValue makeover.


Charles Barouch is the CTO of HDWP, Inc. He is also a regular contributor to International Spectrum Magazine, a former Associate Editor for both Database Trends and for Gateways Magazine, a former distance learning Instructor for CALC. He is presently the Past President of the U2UG. Mr. Barouch has presented technology and business topics in front of hundreds of companies, in a wide range of product and service categories. He is available for on-site speaking and consulting engagements in and out of the United States.

View more articles


May/Jun 2018