QB64 Community

Development => Unimplemented QBASIC Commands => Topic started by: Galleon on February 26, 2010, 03:23:32 PM

Title: DEF FNname (GWBASIC-style functions)
Post by: Galleon on February 26, 2010, 03:23:32 PM
No work has been done on this command yet.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: angros47 on February 28, 2010, 03:15:06 AM
In QBasic and GWBasic DEF FN works in different ways:

In GwBasic, you can define and redefine functions at runtime:
Code: [Select]
DEF FNA(x)=2*x
PRINT fna(10)
DEF FNA(x)=x/2
PRINT fna(10)
Works in GwBasic, don't work in QB (duplicate definition)

In GWBasic, you can also do things like:
Code: [Select]
10 IF X = 1 THEN DEF FNA(x)=2*x

It doesn't work in QBasic
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on February 28, 2010, 06:50:56 PM
In Qbasic you only need to define a function once. Why redefine it again? Just use a different Fn name for each definition.

Your second example is not necessary in either GW or QB.

DEF FnA(x) = x * 2
IF x = 1 THEN x = FnA(x)

If the value was not one, then why call the function?

I don't think Galleon is gonna adapt to GW Basic any time soon.

Ted

Title: Re: DEF FNname (GWBASIC-style functions)
Post by: angros47 on March 03, 2010, 07:52:41 AM
Quote
In Qbasic you only need to define a function once. Why redefine it again? Just use a different Fn name for each definition.

Redefining a function may be useful, to "simulate" function pointers (that were not available in GwBasic and QBasic).

Example:

Code: [Select]
0 DEF FNY(X) = X
10 INPUT "SELECT FUNCTION";A
20 IF A = 1 THEN DEF FNY(X) = X ^ 2
30 IF A = 2 THEN DEF FNY(X) = 2 ^ X

....
100 FOR X = O TO 640
110 PLOT X,FNY(X)
120 NEXT

Quote
Your second example is not necessary in either GW or QB.

DEF FnA(x) = x * 2
IF x = 1 THEN x = FnA(x)

If the value was not one, then why call the function?

My second example was only to show syntax, I know that it's useless

Quote
I don't think Galleon is gonna adapt to GW Basic any time soon.

Neither I do. ;)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: qbguy on March 03, 2010, 05:47:01 PM
Why not just use LISP?

Code: [Select]
(define dx 1/10000)
(define (integrate f a b)
   (let do-my-fscking-integral ((x a) (sum 0))
      (if (> x b)
         sum
        (do-my-fscking-integral (+ x dx) (+ sum (* (f x) dx))))))

Examples:
Code: [Select]
(integrate (lambda (x) x) 0 1)
.50005

(integrate sin 0 3.14159)
1.99999

(integrate exp 0 1)
1.71828

(integrate (lambda (x) (/ x)) 1 2.71828)
1.00004

versus

Code: [Select]
integrate:
sum = 0
FOR x = a TO b STEP dx
sum = sum + FNintegratethisshit(x) * dx
NEXT

but then to call it:

Code: [Select]
dx = 1e-5
a = 0
b = 2.718281828
DEF FNintegratethisshit(x) = EXP(x)
GOSUB integrate
PRINT sum
By requiring multiple lines of code to call a function you give up any gains in clarity you got from the infix notation.

With QB64, you could make use of QBASIC's improved structure, but it would be easier to implement real function pointers in a compiled language rather than the DEF FN hack.


Hmm... not enough swearing. Maybe code differentiation.

Code: [Select]
(define (differentiate f)
  (lambda (x) (/ (- (f (+ x dx)) (f x)) dx)))

Oh well.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: angros47 on March 04, 2010, 10:19:55 AM
Well, if I need pointers, I can use FreeBasic (it has pointers)

Anyway, I think that many people here misunderstood my post: I am not asking for a feature! I only wanted to show a quirk of QBasic and GWBasic: since QB64 is aimed to be a perfect retrocompatible language (Galleon talked about some deprecated features, like KEY ON/ KEY OFF, or like the old OPEN syntax used in GWBasic), I tried to show another, less known one (that makes in some cases QBasic incompatible with GWBasic).

DEF FN has many other problems: in FreeBasic, for example, it hasn't been inplemented because it would have broken compatibility with all names starting with FN ("FName", for example).
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: stylin on March 04, 2010, 10:50:15 AM
A little off-topic, but as you may know, QuickBASIC/QBasic has support for calling procedures via their address using CALL ABSOLUTE. This has always been a painful substitute for "real" procedure pointers, as the procedures must be written in assembly or machine-code, but it can be an effective workaround nonetheless.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: angros47 on March 06, 2010, 06:15:57 PM
I know it, but the procedure is not written in QBasic: worse, it usually is in 16-bit assembly, so it cannot be ported to QB64 (that works in 32-bit mode), unless you add a whole 16-bit emulator (like the one used for DosBox)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: stylin on March 07, 2010, 03:05:57 PM
Quote
unless you add a whole 16-bit emulator (like the one used for DosBox)

Unless I'm very mistaken, this is exactly what Galleon wants to work towards. There is already the beginnings of x86 real-mode/DOS conventional memory emulation (for string character data storage, PEEK/POKE, a few common memory-mapped I/O locations, etc.) which is 16-bit segmented addressing. There is also some (placeholder ?) code for x86 emulation as well.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Galleon on March 07, 2010, 11:55:13 PM
Code: [Select]
There is also some (placeholder ?) code for x86 emulation as well.It's more than a placeholder! Checkout '.\samples\qb64\original\cabsmous.bas'. Admittedly, there are still many more opcodes to add support for. It's just not the priority atm. It should also be noted that BYVAL is not supported in CALL ABSOLUTE yet.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on March 16, 2010, 12:38:28 PM
CALL ABSOLUTE also does not support mouse functions above 3 (reading the mouse status) in QB64 either.

As for BYVAL, I think QB64 should allow it to be used more than QB did. Additional parenthesis were never intuitive.

That might also include ANY, which also was not used much.

Ted
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: codeguy on June 10, 2010, 04:44:32 PM
I think functions that act predictably (namely using the FUNCTION statement) are what qb64 needs to focus on, otherwise constructs like
IF x=1 THEN FNA(x)=x^2 ELSE FNA(x)=sqr(x/2) will make for somewhat unpredictable or inexplicable code. in programming, neatness counts. Not that some people intend their code to be used in other programs, but that happens far more frequently than you might expect. So I say ditch the GW-Basic style FN's and stick to FUNCTION, perhaps using SELECT CASE to determine which function to use if there are many.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on June 10, 2010, 05:39:10 PM
Not to mention that Fn also does not allow variable names such as Fname$ for a first name.

Qbasic Help even recommends Functions over DEF Fn.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Cyperium on June 11, 2010, 05:09:28 PM
We can't just ditch it, we need it for old source. It should strive for 100% QB 4.5 compatibility and it was compatible with DEF FN so...

...we've also had questions about it, it shouldn't be up to us to decide what the user wants.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on June 11, 2010, 07:35:08 PM
I'd rather see the GW Basic OPEN statement done first. Amazing how "supposed programmers" get lost converting it to a normal QB4.5 OPEN statement. It's NOT hard even!

But if he starts adding GW stuff then PDS will be next yearning. Amazing how many of those PDS functions you can create with a little thought.

Ted
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Pete on June 12, 2010, 11:52:20 AM
What I see is a gap between people who have already "moved on" and people who have quit programming or who are end users who discover this project in the hopes their old software will rise from the grave. So either there is insufficient interest to convert old programs, or there is a lack of ability to try and convert them with faith in an eventual outcome.

What I think this project needs is a expanded core of users who still wish to program in BASIC or want to learn BASIC. Where to find those people should be the main focus of the project. This is why I agree with the addition of the new keywords, to get new users, instead of just old ones. The addition of new features will make QB64 a coding choice, rather than just a way to run old programs on new machines.

I try to meet Galleon half way, when I can. I converted all my multi-modular programs and DEF Fn statements. That probably took 100 hours of work to do, not so bad, especially when considering DEF FN is not yet implemented, and multi-modular support is not even a topic anymore. I'm fine with that, as DEF FN was fairly easy to convert, and I made and posted a method to convert multi-modular programs, while I was converting mine. I also know there would be very few QB programmers that use multi-modular programming, anyway and statements like ON KEY and LPRINT would be more pressing. I an thankful for the LOCK, UNLOCK work. I do think that and TCP/IP support are needed for the future, as all devices are being geared to accessing each other, that, and "cloud" computing. And what I really appreciate about Rob is that he does try to accommodate our requests for features we need to keep converting our programs.

I'm still in the FTC mindset though and  I wish once per quarter a new release would contain the next prioritized statement from this sub-forum menu, until all the compiler compatibility work is done, but those are just my feelings, which are void of responsibility. I worry about Galleon, that one day he might end up in an asylum with his nails bit down to the quick and muttering things like, "The compiler, no, the IDE, no, the new keywords, the WIKI, the forum, ahhhhhh!"

DEF FNitely something to consider,

Pete

Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on June 17, 2010, 02:09:41 PM
What we need are more complainers. I think I hounded Galleon about CHAIN until it was done. That worked. You got RUN going!

Unfortunately, many people keep quiet and just observe. I wish they would get more involved. We could use some more suggestions from users.

I'm hoping to get PRINT USING expanded for new formatting options like VB has.

Ted
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: toml_12953 on August 13, 2010, 07:51:41 AM
Quote from: Pete on June 12, 2010, 11:52:20 AM
What I see is a gap between people who have already "moved on" and people who have quit programming or who are end users who discover this project in the hopes their old software will rise from the grave. So either there is insufficient interest to convert old programs, or there is a lack of ability to try and convert them with faith in an eventual outcome.
Pete

One "feature" of DEF FN:  Any variable not in the parameter list is GLOBAL! 

DEF FNA(X) = B * X
B=3
PRINT FNA(5)

will print 15 in QBasic.  Just something to keep in mind when implementing it.

Tom L
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: codeguy on August 13, 2010, 08:38:20 AM
but then that means making ALL variables global or handing them in a special way when it comes to FN, which i think is a disastrous thing indeed (i smell code bloat again for a questionably (imho, of course) marginal benefit). some variables i intend to be global (by dim shared or const) and others i strictly prefer them to be and remain local. maybe if FN comes up against a variable it doesn't recognize, it can just use the ones not declared by DIM SHARED (that is in MAIN program data segment).
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on August 13, 2010, 12:49:52 PM
DEF Fn is made for lazy one line functions. It has few redeeming qualities as it can not be used recursively. Might as well make a real function.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Pete on August 13, 2010, 06:44:46 PM

Serious QB coders use DEF FN to save precious code space. Lazy QB programmers use CHAIN.  ;D

Pete
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DarthWho on December 05, 2010, 01:35:41 PM
thanks for getting rid of the bot galleon ;D
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on September 14, 2011, 03:28:48 PM
Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

I CAN'T MAKE a new topic! AFLAC!  ;D

Quote from: Pete on August 13, 2010, 06:44:46 PM

Serious QB coders use DEF FN to save precious code space. Lazy QB programmers use CHAIN.  ;D

Pete

PRECIOUS CODE SPACE! And LOSE HUNDREDS of FN variable names! I hope Galleon takes that into consideration! You only need a FEW extra keywords

FUNCTION   instead of DEF FN

END FUNCTION

That IS NOT worth losing hundreds of variable names FOREVER! Hundreds of QB64 programs will start SPEWING ERRORS! What I would do is make it so that FN variable names can be used that are NOT defined in a DEF FN statement. That would solve the problem!        

Besides, QB64 should NEVER CRY about space... :'(      
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Barrykgerdes on September 20, 2011, 02:29:35 PM
DEF Fn is a handy way of reducing code size when programming in Basic/Qbasic, particularly  complex mathmatical routines. However it is not an insurmountable problem in making Qbasic code compatible with Qb64 code and is only needed in Qb64 for compatability problems.

With complex Functions you can quite easily replace the call with the complete routine or a sub routine.
With simple functions eg DEF FNM(w) = w* .01745329252  the conversion of degrees to radians.
Delete the DEF and do a change all "FNM* to "FNM * " and make the Variable FNM=.01745329252  The problem here is that FNM is OK as a variable in QB64 but is a reserved word in Qbasic so you do another change all and make FNM into something else. Of course this could have been done at the first "change all"

Barry
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on September 20, 2011, 02:38:34 PM
QB64 "could" RESERVE function names defined in DEF FN statements and allow those FN names when they are not defined. Qbasic reserved ALL variable names beginning with FN. QB64 shouldn't have to!
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: kidfrommars on September 20, 2011, 03:51:41 PM
Quote from: Clippy on September 20, 2011, 02:38:34 PM
QB64 "could" RESERVE function names defined in DEF FN statements and allow those FN names when they are not defined. Qbasic reserved ALL variable names beginning with FN. QB64 shouldn't have to!

I agree.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: desA on January 15, 2012, 05:23:09 AM
Not overly sure what all the fuss is about. (New fogie on the block)

DEF FNW(A)=blah*A ...

Becomes

Code placed at end of program - using insert Function command. Also declare global variables required upfront.

FUNCTION W(A) : W = blah*A ... : END FUNCTION

After this, use W(A) as required... A tad longer to declare the function, but less hassle within the code calling the function.

Just converted a 23-year old QBASIC 4.0 program last evening. Seems to work a treat, thus far. I'm most grateful for QB64, I must say.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on January 15, 2012, 08:32:17 AM
The "fuss" is that old programs use DEF FN often. Fortunately most were GW Basic programs.

LOSING FN variable names would be a KILLER at this point in QB64's progress.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DSMan195276 on January 15, 2012, 09:51:39 AM
Quote from: Clippy on January 15, 2012, 08:32:17 AM
The "fuss" is that old programs use DEF FN often. Fortunately most were GW Basic programs.

LOSING FN variable names would be a KILLER at this point in QB64's progress.

I don't see why we'd have to lose FN variable names. I mean, we can have FN functions and FN variables, I don't see why DEF FN would mess that up (Especially if it just gets converted to a proper function).

Now what would make DEF FN worth wild for using is if a one-line DEF FN could be added directly into the code for some optimization. Not sure how much overhead is caused by calling a FUNCTION, but if you could do something like this:

Code: [Select]
DEF FNnum(x) = sin(x * 2) + 4 'random function

print FNnum(21);
end
A normal function would be converted into something like this(Very crude example, but it gets the point across):
Code: [Select]
#include <stdio.h>
#include <math.h>
using namespace std;
int main(){
  cout << FNnum(21);
  cout << "\n Press any key to continue...";
  cin.get();
  return 0;
}
double FNnum(int x){
  return sin(x * 2) + 4;
}
But the DEF FN could be converted something like this:
Code: [Select]
#include <stdio.h>
#include <math.h>
using namespace std;
int main(){
  cout << sin(21 * 2) + 4;
  cout << "\n Press any key to continue...";
  cin.get();
  return 0;
}

Having DEF FN do some optimization like that could help speed things up since DEF FN functions were pretty almost always related to math. If I remember right there were multiple line DEF FN statements, but that's no big deal since if it goes into multiple lines then you can just treat it like a normal FUNCTION.

Matt
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on January 15, 2012, 10:38:04 AM
Quote
Now what would make DEF FN worth wild for using is if a one-line DEF FN could be added directly into the code for some optimization.

worth while...?

Anyhow, Qbasic made a big deal out of FN variable names. We shouldn't have that problem if QB64 can work around that. I would NEVER use FN to "optimize" anything! Calculate the stuff if you only use it once. Otherwise use a FUNCTION. Then it is optimized for multiple uses.

Apparently FN has been put on hold...

Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DSMan195276 on January 15, 2012, 11:12:44 AM
Quote from: Clippy on January 15, 2012, 10:38:04 AM
Quote
Now what would make DEF FN worth wild for using is if a one-line DEF FN could be added directly into the code for some optimization.

worth while...?

Anyhow, Qbasic made a big deal out of FN variable names. We shouldn't have that problem if QB64 can work around that. I would NEVER use FN to "optimize" anything! Calculate the stuff if you only use it once. Otherwise use a FUNCTION. Then it is optimized for multiple uses.

Apparently FN has been put on hold...



Sorry, bad grammar on my part, it should have said:
Quote
Now what would make DEF FN worth wild to use is if a one-line DEF FN could be added directly into the code for some optimization.

QBasic made a big deal out of them but it really didn't need to. I imagine it did that just to keep people from being confused from what is a DEF FN and what is a variable starting with FN.

And I don't think you understand what I meant by optimize, take this example:

Code: [Select]
DEF FNcalc(x) = x ^ 2 + 2

m = 4
PRINT FNcalc(m);
end

Basically the idea is that 'm' is some variable that is going to change, or IE can't be hard-coded in. And FNcalc does some calculation that you might want to change at some point. The code would then be converted into:

Code: [Select]

m = 4
PRINT m ^ 2 + 2;
end

And by doing that it takes away the overhead of calling the function, but you still have the flexibility of being able to change it if you need.

Matt
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on January 15, 2012, 11:28:18 AM
Well the whole point of supporting DEF FN is for old Qbasic programs. I would not encourage people to use it in new code, but they could. I'm not crazy about GOSUB either but I've used it at times when I was lazy...

There is an innate problem when you use sub-procedures that don't require parameters. ANY variable value can be used in any procedure and name duplication must be avoided. The same thing can happen when you use SHARED for everything. You can make more errors that are harder to find.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DeeBee on January 15, 2012, 06:25:53 PM
Unless I'm missing something, you do not need DEF FN.

The ONLY reason there is a DEF FN is because it was implemented before
there were SUB and FUNCTION statements.
(and it is an old (almost 'original', but not quite) BASIC legacy implementation)

ANYTHING that can be done using DEF FN can be used with FUNCTION now.

And it's not even a difficult mod to make. (it's what I've always done, even when
DEF FN was implemented, because, imo, DEF FN is deprecated (or should be), along with GO/TO/SUB)

I guess if Galleon wanted to get 'fancy', he could just wrap any DEF FN statements
into their FUNCTION equivalent, and I don't think anyone would notice any difference.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SkyCharger001 on January 16, 2012, 08:32:05 AM
from what I've seen DEF FN can be seen as a macro-statement. (a macro-call tells the pre-compiler to replace the call with the code defined by the macro)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on January 16, 2012, 08:42:48 AM
Either way I am hoping that Galleon can just exclude the use of the DEF function FN name as a variable only after it is defined.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Cyperium on February 08, 2012, 05:38:49 AM
I agree, there's no point in loosing all the FN variables, QB probably didn't loose them either without putting up a fight so if QB64 can keep them then that would be more BASIC than QB could achieve.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on February 08, 2012, 09:54:13 AM
A fight?  ???

As I recall you couldn't start ANY variable names with FN. Fname$...for firstname$ or filename$

Then it gave you an OBTUSE "Duplicate definition" error that made it EVEN HARDER to figure what was wrong when you used it more than once and tried to run it!
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: codeguy on February 08, 2012, 10:00:20 AM
i think def fn should be eliminated as there are FAR better function constructs (namely, FUNCTION: http://qb64.net/wiki/index.php?title=FUNCTION (http://qb64.net/wiki/index.php?title=FUNCTION)) which is the way i'd prefer to see other programmers do this. that way, we get to keep all the FN variable names and avoid conflicts. those too uninspired, lazy or otherwise to change should maybe consider getting a job programming big iron in cobol. ;D edited to include link to FUNCTION
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on February 08, 2012, 10:15:43 AM
Yeah, but QB64 is SUPPOSED to be compatible with QB4.5. That shouldn't be hard to do!
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: codeguy on February 08, 2012, 10:21:54 AM
yes, all it would involve is expanding the FN macro (which is what it really is) into a c++ function and maybe a bit of smart analysis to see if it really is a function or just simply an FN variable. not too difficult but then i say that from a point of inexperience. or perhaps just removing fn and changing it to a c macro. (modified to include last statement)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on February 08, 2012, 10:32:04 AM
ONE THING FOR SURE! OLD code won't have ANY variable names with FN  at the beginning!
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Aramis on September 26, 2012, 11:53:33 AM
Y'know, it could be set with a start of code flag...

_$DEFFN enabling the classic DEF FN mode... but only when needed.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on September 26, 2012, 04:07:11 PM
No, then it wouldn't be compatible with old code! That's the ONLY reason to use it anyhow unless you're really lazy... ;)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Aramis on September 26, 2012, 05:52:44 PM
Quote from: Clippy on September 26, 2012, 04:07:11 PM
No, then it wouldn't be compatible with old code! That's the ONLY reason to use it anyhow unless you're really lazy... ;)
You can't go a day without insulting people?

One of the best reasons for backward compatibility is the surfeit of old source that can be torn apart by newbs. A top-of code flag is far easier than newbs having to learn to revise the code first.

And easier on grogs who can easily set the top-of-code flag, and get it to compile without revision of the rest of the code.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Johny B. on September 26, 2012, 07:11:01 PM
Unless I'm missing something here, there isn't any reason to prevent the program using variables that start with fn. After it is defined, why can't the name just be treated as another user-created identifier?
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on September 26, 2012, 10:47:14 PM
Quote
_$DEFFN enabling the classic DEF FN mode... but only when needed.

WTF was I insulting?  If you want insulting then WTF would your new keyword do but break compatibility even worse.

The only thing I would like to see, IF Galleon EVER decides to add it, is that QB64 allow FN names that are NOT found after the DEF keywords. Then even if you NEVER use DEF FN, it won't bother the Hell out of everybody else!

The SIMPLEST solution right now is to just change it to a REAL FUNCTION and toss it at the end of your code. If you can't do that much work then you are lazy. No doubt about that.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Aramis on October 03, 2012, 01:22:19 PM
Clippy, I have seen very few of your posts where you are NOT insulting someone.

It gets old.

adding a _$GWBasic keyword instead, and including support for the needed compatibility modes in one fell swoop would be an extension of the same idea. It's not laziness, but accessibility.

Likewise, a _$MBasic keyword  and support would make all the old "mumblesoft basic" programs available to a new generation to learn to code.

See, the problem is, you're approach is "We don't need to cater to newbs" and then to call everyone who thinks of compatibility/accessibility lazy... but you ignore that the vast array of basic programs on the net won't compile in QB, let alone QB64.

Books on QB are not common; books using mbasic are. Many used bookstores have a dozen+.



Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on October 03, 2012, 01:56:29 PM
Just because you have a "Newbie" tag in this forum means nothing to me! You could be very experienced.

Your proposal doesn't make an sense when DEF Fn could be added seamlessly using mine.

The only reason some GW Basic keywords are supported at all is because QB 4.5 supported them.

WHO would have to ADD all of those keywords to QB64? NOT YOU! It ain't gonna fly kiddo.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Johny B. on October 03, 2012, 06:44:19 PM
FN functions can be supported without having a keyword to witch to some compatibility mode. Believe it or not, Clippy actually  had the right idea in his rants. We treat FN functions as they were in Qbasic, except we don't reserve the whole fn namespace for them. Problem Solved.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SMcNeill on October 03, 2012, 07:12:46 PM
The problem with DEF FN and FUNCTION FN is that DEF FN generally used all the variables our main routine uses.  Functions don't.

The way to implement Fn would be to design it like a label and goto statement, with auto return.

Code: [Select]
CLS
I = 10
PRINT FNdemo(10)
END

DEF FNdemo(x)
   FNdemo = I + x
END DEF

For the above to work, DEF FNdemo(x) would have to be counted as a goto from the main program.  Then it'd have access to any other variables in the main process.  END DEF would have to return the program back to where it was called from, and return the value of FNdemo to itself to print.

So basically, behind the scene it'd need to:
See the FN call.
Find a name of FN for a match.
If no match, then FN is a variable, not a function.  (FName could be First Name, not FN ame). Do variable stuff.
Check for a return code
If code is 0, then set a return label.  Send the parameters to DEF FNname via goto.
Do the calculations.
Get to END DEF, set return code to 1.  Goto back to sending label.
At label, check return code.
If code is 1, then put value in FNname, ignore parameters.
Set code back to 0 to reset for next call.
Continue code on from that point.....
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on October 03, 2012, 08:25:56 PM
My solution is really simple. The only FN names reserved would be the ones used after DEF FN

So FName can be used unless it is used after DEF. QB did not allow ANY FNnames.

That is the main reason it has not been implemented in QB64 yet.

It may never be, if Galleon doesn't see a need for it.

Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SMcNeill on October 03, 2012, 10:00:26 PM
I don't think it'd be too hard to implement.  Basically the compiler would need to do like this:

Code: [Select]
SCREEN _NEWIMAGE(1280, 720, 32)
CLS

PRINT "This is how we'd break down an DEF FN statement for use in QB64"
PRINT
PRINT "We write our code as:"
PRINT
PRINT "DEF FNAddOne(x) = x +1"
PRINT "PRINT FNAddOne(10)"
PRINT "PRINT FNAddOne(100)"
PRINT "PRINT FNAddOne(1000)"
PRINT
PRINT
PRINT "Analyzing your statement."
PRINT "From the first line I get:"
PRINT
PRINT "_FN1: 'this is our label"
PRINT "'Initilize variables'"
PRINT "FNAddOne = 0"
PRINT "x = x"
PRINT "'Done with variables, initilize formula"
PRINT "FnAddOne = x + 1"
PRINT "'Done with formula, return."
PRINT "RETURN"
PRINT "_Last_Command = 'PRINT'"
PRINT "x = 10"
PRINT "Gosub FN1"
PRINT "Command$ = _Last_Command + FNAddOne' In this case, it makes for a Command$ of PRINT 11 which the compiler then executes."
PRINT "_Last_Command = 'PRINT'"
PRINT "x = 100"
PRINT "Gosub FN1"
PRINT "Command$ = _Last_Command + FNAddOne' In this case, it makes for a Command$ of PRINT 101 which the compiler then executes."
PRINT "_Last_Command = 'PRINT'"
PRINT "x = 1000"
PRINT "Gosub FN1"
PRINT "Command$ = _Last_Command + FNAddOne' In this case, it makes for a Command$ of PRINT 1001 which the compiler then executes."

First, it looks at the DEF FN statement and breaks it apart. 
It becomes basically a GOSUB with a default label the compiler gives it.
Then it looks to see what variables are needed and initializes them.
Then it writes the formula using those variables.
Then it returns.

When you write the FN portion of the statement, it:
matches any constants to the variables above.
Checks to see what the last command is
GOSUBs to the auto-label QB64 gave it
Returns with any and all values changed that it processed.
Executes the previous statement, but substitutes the value of the FN for the FN.

It's a little work for the behind the scene compiler, but that'd be the process to do it.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on October 03, 2012, 10:59:52 PM
ERGO more work for Galleon. That's why it isn't done. There are higher priorities.

If any C coders want to take a stab at it, let us know...
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DSMan195276 on October 04, 2012, 07:43:02 PM
Quote from: Clippy on October 03, 2012, 10:59:52 PM
ERGO more work for Galleon. That's why it isn't done. There are higher priorities.

If any C coders want to take a stab at it, let us know...

Personally, I don't see why this couldn't be a higher proiority, because this is just one more thing inbetween reaching as close to 100% QBasic compatibility as possible. But of course, that's up to Galleon.

No C code should have to be changed if what SMcNeill posted works. The compiler is written in QB64 code, SMcNeill's code can be used as a sort of preprocessor to fix DEF FN functions before the code is actually compiled. It could probably be implmemented almost as is into the QB64 code right now without to many changes.

Matt
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on October 04, 2012, 09:29:03 PM
Some people did not want the FN name limitations just to implement a bygone keyword. Personally I'd probably never use it but I don't use GOTO or GOSUB much either.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: DSMan195276 on October 04, 2012, 09:34:08 PM
Quote from: Clippy on October 04, 2012, 09:29:03 PM
Some people did not want the FN name limitations just to implement a bygone keyword. Personally I'd probably never use it but I don't use GOTO or GOSUB much either.

I don't see why something like what SMcNeill posted couldn't be implemented without preventing people from using FN variable names. It's not to hard to cross check a 'FN' variable name against a list of FN functions in the code and check that something is a variable and not a function. If a preprocessor type thing for FN is implemented, then it won't even be an issue. All DEF FN statements will be converted and gone before the Compiler even touches the code, and something like having a regular function that starts with FN or having a GOSUB that starts with FN has never been a problem.

Matt
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SMcNeill on October 04, 2012, 10:25:20 PM
Quote from: Clippy on October 04, 2012, 09:29:03 PM
Some people did not want the FN name limitations just to implement a bygone keyword.

The way I posted wouldn't give you any limitations for names.   A FN has to follow a DEF FN statement.   If DEF FN is used first, you set a label automatically and make a FN(name) variable.

If  a FN(name) is issued without a DEF defining it, it'd become a variable automatically.  No name restrictions imposed, except the FN you name yourself.

My DBASE project is (sorta) wrapped up at the moment.  I might try and get an actual QB64 DEF FN set of code up and going over the next few days.

Then all someone would need to do is figure out where to plug it into the QB64 source to make it work as intended.   :)
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SMcNeill on October 05, 2012, 12:00:37 AM
Here's a sample of how the code would actually work, but with several limitations.

Code: [Select]
DIM var$(1000)


SCREEN _NEWIMAGE(1280, 720, 256)
COLOR 15, 127
CLS



PRINT "Give me a single line DEF FN statement, and I'll analyze it."
PRINT
INPUT UserDef$
UserDef$ = LTRIM$(RTRIM$(UCASE$(UserDef$))) + " "
PRINT: PRINT
IF LEFT$(UserDef$, 6) <> "DEF FN" THEN
    PRINT "You did not enter a correct DEF FN statment."
    PRINT
    PRINT "Now I have to laught at you, becuase I can't test what isn't a DEF FN statement, since I'm just a DEF FN simulator!"
    PRINT
    PRINT "BUWHA HA HA HA HA HA HA!"
    END
END IF
thisfar = 5
sb = INSTR(UserDef$, "(") 'startbracket
se = INSTR(UserDef$, "=") 'startequal
IF sb < se THEN
    ' FNname(variable) = something
    FNname$ = MID$(UserDef$, 5, sb - thisfar)
    thisfar = sb + 1
    vc = 1
    eb = INSTR(thisfar, UserDef$, ")") 'startbracket
    var$(vc) = MID$(UserDef$, thisfar, eb - thisfar)
    thisfar = se + 2
ELSE
    'FNname = something
    FNname$ = MID$(UserDef$, 5, se - thisfar)
    thisfar = se + 2
END IF
IF FNname$ = "FN" THEN
    PRINT "You did not give your FN a name."
    PRINT: PRINT "Now I have to laught at you, becuase you're silly!"
    PRINT: PRINT "BUWHA HA HA HA HA HA HA!"
    END
END IF
e = thisfar - 3
label$ = "Qb64_Internal_Label_" + FNname$

'We have now analyzed past the = sign.  Let's see if there's any more variables to deal with.
'I'm going to assume that each statement would have been caught by the IDE and spaced properly
'For example, DEF FNaddone(x)=x+1 should be spaced DEF FNaddone(x) = x + 1
DO
    sp = INSTR(thisfar, UserDef$, " ")
    temp$ = MID$(UserDef$, thisfar, sp - thisfar)
    vcadd = 1
    FOR i = 1 TO vc
        'check to see if we already have a variable like this one
        IF var$(i) = temp$ THEN vcadd = 0
    NEXT
    check$ = "+-/*^"
    FOR i = 1 TO LEN(check$)
        IF temp$ = MID$(check$, i, 1) THEN vcadd = 0: EXIT FOR
    NEXT
    temp1$ = LTRIM$(STR$(VAL(temp$)))
    IF VAL(temp$) = VAL(temp1$) AND temp$ = temp1$ THEN
        'it's a constant!
        vcadd = 0
    ELSE
        'it's a variable
    END IF
    IF vcadd = 1 THEN vc = vc + 1: var$(vc) = temp$
    thisfar = sp + 1
LOOP UNTIL thisfar >= LEN(UserDef$)

'Anaylze formula now
PRINT: PRINT: PRINT
formula$ = FNname$ + RIGHT$(UserDef$, LEN(UserDef$) - e + 1)


PRINT
PRINT
PRINT "GOSUB ";label$;":"
PRINT "'                                              Initilizing variables. (This part is optional since we're just defining a variable as itself."
PRINT "'                                              I just put it in here to help me watch it find the variables as needed."
PRINT
PRINT FNname$; " = "; FNname$
FOR i = 1 TO vc
    temp$ = var$(i) + " = " + var$(i)
    PRINT temp$
NEXT
PRINT
PRINT "'                                              Analyzing formula"
PRINT formula$
PRINT
PRINT "'                                                  Returning"
PRINT "RETURN"
END

At the moment, this asks you to give it a single line DEF FN statement.   (DEF FNAddOne(x) = x + 1 or something similar)
It assumes that this has already been through the IDE and has proper spacing and such.   DEF FNAddOne(x)=x+1 wouldn't work.  SPACE your code properly yourself.
It doesn't actually try to let you use the FN, though that wouldn't really be hard to add - this just shows how it'd break down the process to work, like a proof of concept illustration.
The only operations we support here is the simple math.   (+-/*^)  It'd need a full list of operators to work properly, but QB64 should have those already.  After all it already processes formula's nicely.

So, remembering the rules, give this a quick run and try it with a few single line DEF FN statements to see how it'd analyze them and break them down into code that WOULD run in QB64 even now.

It wouldn't tie up any fn names, so you could still use FName for a first name variable if you wanted to.   Only the FN(name) shown in the analyzing section would get used and added to QB64's list of variables the user has used in their program.

Since the DEF FN is analyzed, the FN would be real simple.   It'd check itself against the list of DEF FN names.  If found, it'd turn itself into a GOSUB like I illustrated would be needed above.  If it's not found in the list, then it must be a user-variable and should be treated like one.

Try it out.  See if this doesn't look like it'd translate DEF FN into a set of code that would be usable in QB64.   It makes it a GOSUB, tracks the variables, and doesn't have the limit of FUNCTION needing shared variables to pass to it.   If there's a variable in the main module, this would work with it.


Personally, I'd never use a DEF FN command I don't think, but the exercise in logic to figure out HOW to make one work is nice.  ;)

I guess the drawback to this method is that you wouldn't be able to use (Qb64_Internal_Label_" + FNname$) as a label or variable in your code anymore.  Dang it!  That breaks its usability for me....   :P
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: SMcNeill on October 05, 2012, 01:10:39 AM
Actually, since I couldn't sleep, here's a sort of very puny pre-compiler that would show how it'd work

Give it a DEF FN command, using the rules above.
Then give it a very simple use for that FN.

Watch it work.

(and yes, this has almost no real power or error-checking abilities)

Try it with something like:

DEF FNaddone(x) = x + 1
PRINT FNaddone(10)

or

DEF FNx3(x) = x * 3
k = k + FNx3(10)

Note:  it assumes your FN comes last, so any command after it is going to get ignored.  I'm lazy and ready to go back to bed, so I didn't worry with the rest of it.   :P
Note2:  It also assumes that you made your FN with a variable in it.  I know you don't have to, as the first half breaks it down without it, but as I said, I'm getting tired and lazy.
Use this for DEF FNname(variable) =  .......        It won't work with DEF FNname = ......

As I said before, this is just a very simple little pre-compiler type breakdown.  If anyone wants, feel free to expand upon it.  I'm certain this way would end up making a DEF FN and FN set of code that would run under QB64.  ;)


EDIT:  LOL - Toldja I was tired.  I forgot to attach the code!   

Here it is.  Give it a shot:
Code: [Select]
DIM var$(1000)


SCREEN _NEWIMAGE(1280, 720, 256)
COLOR 15, 127
CLS

PRINT "Give me a single line DEF FN statement, and I'll analyze it."
PRINT
INPUT UserDef$
UserDef$ = LTRIM$(RTRIM$(UCASE$(UserDef$))) + " "
PRINT: PRINT
IF LEFT$(UserDef$, 6) <> "DEF FN" THEN
    PRINT "You did not enter a correct DEF FN statment."
    PRINT
    PRINT "Now I have to laught at you, becuase I can't test what isn't a DEF FN statement, since I'm just a DEF FN simulator!"
    PRINT
    PRINT "BUWHA HA HA HA HA HA HA!"
    END
END IF
thisfar = 5
sb = INSTR(UserDef$, "(") 'startbracket
se = INSTR(UserDef$, "=") 'startequal
IF sb < se THEN
    ' FNname(variable) = something
    FNname$ = MID$(UserDef$, 5, sb - thisfar)
    thisfar = sb + 1
    vc = 1
    eb = INSTR(thisfar, UserDef$, ")") 'startbracket
    var$(vc) = MID$(UserDef$, thisfar, eb - thisfar)
    thisfar = se + 2
ELSE
    'FNname = something
    FNname$ = MID$(UserDef$, 5, se - thisfar)
    thisfar = se + 2
END IF
IF FNname$ = "FN" THEN
    PRINT "You did not give your FN a name."
    PRINT: PRINT "Now I have to laught at you, becuase you're silly!"
    PRINT: PRINT "BUWHA HA HA HA HA HA HA!"
    END
END IF
e = thisfar - 3
label$ = "Qb64_Internal_Label_" + FNname$ + ":"

'We have now analyzed past the = sign.  Let's see if there's any more variables to deal with.
'I'm going to assume that each statement would have been caught by the IDE and spaced properly
'For example, DEF FNaddone(x)=x+1 should be spaced DEF FNaddone(x) = x + 1
DO
    sp = INSTR(thisfar, UserDef$, " ")
    temp$ = MID$(UserDef$, thisfar, sp - thisfar)
    vcadd = 1
    FOR i = 1 TO vc
        'check to see if we already have a variable like this one
        IF var$(i) = temp$ THEN vcadd = 0
    NEXT
    check$ = "+-/*^"
    FOR i = 1 TO LEN(check$)
        IF temp$ = MID$(check$, i, 1) THEN vcadd = 0: EXIT FOR
    NEXT
    temp1$ = LTRIM$(STR$(VAL(temp$)))
    IF VAL(temp$) = VAL(temp1$) AND temp$ = temp1$ THEN
        'it's a constant!
        vcadd = 0
    ELSE
        'it's a variable
    END IF
    IF vcadd = 1 THEN vc = vc + 1: var$(vc) = temp$
    thisfar = sp + 1
LOOP UNTIL thisfar >= LEN(UserDef$)

'Anaylze formula now
PRINT
formula$ = FNname$ + RIGHT$(UserDef$, LEN(UserDef$) - e + 1)

'good so far
'Now let's get a useage

PRINT "Now give me an FN to use with it."
INPUT fnc$
PRINT: PRINT: PRINT
fnc$ = LTRIM$(RTRIM$(UCASE$(fnc$)))

sb = INSTR(fnc$, "(") + 1 'start bracket
eb = INSTR(fnc$, ")") 'end bracket

constant$ = MID$(fnc$, sb, eb - sb)

PRINT
PRINT
PRINT label$
PRINT "'                                                  Initilizing variables. (This part is optional since we're just defining a variable as itself."
PRINT "'                                                  I just put it in here to help me watch it find the variables as needed."
PRINT
PRINT FNname$; " = "; FNname$
FOR i = 1 TO vc
    temp$ = var$(i) + " = " + var$(i)
    PRINT temp$
NEXT
PRINT
PRINT "'                                                  Analyzing formula"
PRINT formula$
PRINT
PRINT "'                                                  Returning"
PRINT "RETURN"
PRINT
PRINT
PRINT "'                                                   Here's where we break down the command you gave."
PRINT var$(1); " = "; constant$
PRINT "GOSUB "; label$
PRINT LEFT$(fnc$, INSTR(fnc$, "(") - 1)

NOTE:  Since I'm too tired to even copy and paste code into a topic properly, I won't swear to this thing doing anything at the moment.  It it doesn't work using the basic examples I showed above, then someone drop me a memo and I'll see what I didn't copy/paste properly.  This SHOULD convert a DEF FN and FN statement over to a set of code that would run through QB64 even now (within the limitations of my laziness and lack of sleep at the moment).
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Clippy on October 05, 2012, 07:53:11 AM
QB64 already reserves SUB names as procedures. It could do the same thing with FNnames after DEF.

I gather you are trying to roll your own workaround. Have fun.  ;)

Title: Re: DEF FNname (GWBASIC-style functions)
Post by: codeguy on October 10, 2012, 12:07:52 PM
Quote
_$DEFFN enabling the classic DEF FN mode... but only when needed.

WTF was I insulting?  If you want insulting then WTF would your new keyword do but break compatibility even worse.

The only thing I would like to see, IF Galleon EVER decides to add it, is that QB64 allow FN names that are NOT found after the DEF keywords. Then even if you NEVER use DEF FN, it won't bother the Hell out of everybody else!

The SIMPLEST solution right now is to just change it to a REAL FUNCTION and toss it at the end of your code. If you can't do that much work then you are lazy. No doubt about that.
i really agree with clippy. functions are easy to code and give your program a more modular look. i  say that from the point of experience. i have RARELY ever used def fn except when i first learned basic. it was never implemented in the dec corporation's flavor of basic and i believe only added as a shortcut when disk space and memory were at a premium. so generally, my vote is no for def fn. development time is better used for other things than def fn in my opinion.
Title: Re: DEF FNname (GWBASIC-style functions)
Post by: Barrykgerdes on April 10, 2013, 01:55:03 AM
I have a few dozen ond GW basic programs that used DEF FNx as a means of condensing space and memory when these items were at a premium. When I first needed to use Qb64  to run my programs on a 64 bit system I came up with this "deficiency". Of course none of these programs would run with Qb64 but an examination of the functions showed that most of them could be fixed with a simple variable and an operator and the rest with a sub routine

This was easily done with a batch replace command in most cases. I modified all my source code and everything now works in Qb64 but also still works in GWBasic and Qbasic as well. I don't see any urgency to provide this command in Qb64. In fact there are quite a few commands that don't work universally but there are work arounds for everything I have found and these work arounds are all compatable with all systems.

Barry