Page 1 of 3

Macros for literal strings

Posted: Sun Oct 04, 2009 8:31 am
by PB
Macros are great, but they don't work for literal strings. In my apps, I have the same text over and over in places (eg. my app's name), which means I have to type it over and over. It would be great if another type of Macro existed, one where only the literal text in a string gets replaced. Something like this:

Code: Select all

; Pseudo-code.

StringMacro PB
  PureBasic
EndStringMacro

MessageRequester("","This PB example was coded in PB")
When run, the above code would output this:

Image

I know we can do the following, but it's extra code and extra typing. A macro is much easier and nicer.

Code: Select all

; This is even far more bothersome to type, IMO. :)
; Typing  "+pb$+"  is a pain compared to typing PB.

pb$="PureBasic"
MessageRequester("","This "+pb$+" example was coded in "+pb$)

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 5:25 am
by Blue

Code: Select all

Macro MsgBox(message = "Just waiting..", titre = "information")
    MessageRequester(titre, message, 0)
EndMacro

Macro mPB
+" PureBasic "+
EndMacro

MsgBox("This strange" mPB "example was coded in" mPB "")
You're right. Macros specifically for strings would be real nice. However, in the meantime, here's a compromise. It looks unnatural, but it works well.
Notice the required empty Double Quotes at the very end of the message string.
And i believe it would be perfect for inserting your app's name all over the place.

The big shortcoming, of course, is 1 abbreviation = 1 macro ! And if you use a lot of abbreviations...

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 6:58 am
by PB
@Blue: But it's not just for MessageRequesters. I want (for example) the string "MyApp" to be replaced everywhere in my code with my app's real name, without doing a search/replace in every source template. A single string macro at the head would solve this, and it's not too different to the current Macro system, so it should be easy to implement. It's even compatible with a single-pass compiler. ;)

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 10:30 am
by Kaeru Gaman
I agree, would be a nice addition.
but it should be some extra functionallity like in your first example, to make sure it will not interfere with the usage of standard macros.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 11:18 am
by Thorium
I think this would be a major bug producer.

I mean using macros in strings makes only sence if you use small macro names. But if you use small macro names the chance is high that text will be replaced that should not been replaced. A possible solution would be to mask the macro name.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 11:56 am
by Little John
PB wrote:It would be great if another type of Macro existed, one where only the literal text in a string gets replaced.
Interesting idea. It also shouldn't be too hard, to build this functionality into an existing pre-processor. When I have time, I'll probably do so with my pre-processor LPP. :-)
Thorium wrote:But if you use small macro names the chance is high that text will be replaced that should not been replaced. A possible solution would be to mask the macro name.
I understand your concerns. My first idea for a solution is, to use a prefix similar to the way PB uses '#' for constants. For a text that is going to be replaced by a "string macro", e.g. '$' could be used as prefix. Then the original suggestion by PB would look like this:

Code: Select all

; Pseudo-code.

StringMacro $PB
  PureBasic
EndStringMacro

MessageRequester("","This $PB example was coded in $PB")
Is something like this what you mean with "to mask"?

Regards, Little John

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 12:01 pm
by Thorium
Little John wrote: Is something like this what you mean with "to mask"?
Yes, mask was just the wrong word.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 12:13 pm
by PB
> I think this would be a major bug producer

What? Let the coder be the judge of that. Any type of macro can lead to bugs if used incorrectly. A mask can certainly be used by the coder if he wants.

BTW, in case someone's thinking: "why not just do a search/replace?", or "why not just use a variable?", the answer is to save typing and to save resources (yes, variables use resources!) when using the same string over and over in your app. In fact, if anyone's against this idea, then they are against the use of standard macros too, since they both are fundamentally the exact same concept. :P

Here's a practical example of how it saves typing, in conjunction with regular macros too:

Code: Select all

Macro HKCU
  #HKEY_CURRENT_USER
EndMacro

StringMacro $SF
  Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
EndStringMacro

appdata$=ReadRegString(HKCU,"$SF","AppData")
history$=ReadRegString(HKCU,"$SF","History")
mymusic$=ReadRegString(HKCU,"$SF","My Music")
mypictures$=ReadRegString(HKCU,"$SF","My Pictures")
myvideo$=ReadRegString(HKCU,"$SF","My Video")
nethood$=ReadRegString(HKCU,"$SF","NetHood")
recent$=ReadRegString(HKCU,"$SF","Recent")
sendto$=ReadRegString(HKCU,"$SF","SendTo")
See how much typing that saves? One could argue that actually leads to fewer bugs due to removing the risk of typos -- EnableExplicit doesn't catch typos in strings! ;) And there are no variables created except for the paths that we actually want to store. That's the point too -- no more wasting variables just to specify a string over and over.

For comparison, here's the same code as above, but without any macros at all:

Code: Select all

appdata$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","AppData")
history$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","History")
mymusic$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","My Music")
mypictures$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","My Pictures")
myvideo$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","My Video")
nethood$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","NetHood")
recent$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrantVersion\Explorer\Shell Folders","Recent")
sendto$=ReadRegString(#HKEY_CURRENT_USER,"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders","SendTo")
I know which one I'd rather type. ;) BTW, with the code block above, did you see how the app would fail to get the recent$ folder? The variable recent$ would be null. String macros would prevent that sort of hard-to-spot bug.
Little John wrote:When I have time, I'll probably do so with my pre-processor LPP. :-)
Just mention in your docs that I came up with the idea, then. Thanks.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 1:04 pm
by Little John
PB wrote:Just mention in your docs that I came up with the idea, then. Thanks.
Of course. Credit where credit is due.

Regards, Little John

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 1:08 pm
by freak
Features added purely to support people's laziness are a bad thing. Any shortcut you take out of laziness today has the tendency to come back to bite you in six months time.

Writing good software is all about _not_ being lazy.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 1:14 pm
by PB
> Features added purely to support people's laziness are a bad thing

It's not just for laziness, as I showed with the bug-avoidance aspect of it. It gives an equivalent of EnableExplicit to literal strings in the source, which EnableExplict cannot detect. Oh well, at least I asked. Nothing ventured, nothing gained.

> [...] has the tendency to come back to bite you in six months time

Depends on the coder.

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 2:02 pm
by Kaeru Gaman
couldn't this be something for IDE-Macros?

I mean, pressing F12-A-B-C or so and the Macro is inserted directly into the source...

anyhaw, what is so hard about typing " + + ", is it hidden behind strange functionalities on the french keyboard layout?

Re: Macros for literal strings

Posted: Mon Oct 05, 2009 2:19 pm
by freak
PB wrote:> Features added purely to support people's laziness are a bad thing

It's not just for laziness, as I showed with the bug-avoidance aspect of it. It gives an equivalent of EnableExplicit to literal strings in the source, which EnableExplict cannot detect. Oh well, at least I asked. Nothing ventured, nothing gained.
You get the same effect by using a constant.
PB wrote:> [...] has the tendency to come back to bite you in six months time

Depends on the coder.
That may be your opinion.

Re: Macros for literal strings

Posted: Tue Oct 06, 2009 12:27 am
by Thorium
For saving memory with much used fixed strings i use constants. But i agree that this string macros are easier to use because you don't need to constuct things like: "text1" + #AppTitle + "Text2".

And don't get me wrong, i don't said i don't want this feature in PB. I just wanted to point out a possible problem.
I would not use the feature but since it's not a "must use feature" i don't care if it's there or not.
freak wrote: Writing good software is all about _not_ being lazy.
Show me just one programer thats not lazy. :mrgreen:

Re: Macros for literal strings

Posted: Tue Oct 06, 2009 7:34 am
by Blue
PB wrote:@Blue: But it's not just for MessageRequesters. I want (for example) the string "MyApp" to be replaced everywhere in my code with my app's real name, without doing a search/replace in every source template. [...]
:roll: ? ? ? That's pretty obvious for anyone who can read. But just as obviously, not everyone can.

Have you even tried the sample macro provided in my first reply ? If so, how did you come to the conclusion that it's limited to MessageRequesters() ?

This string macro works with ANY string, anywhere in your code.

Here's the same, working with debug statements and a string assignment
(i removed the requester() macro so it wouldn't blind you to the string macro )
:

Code: Select all

Macro mPB
+" PureBasic "+
EndMacro

#mPB = "PureBasic" 

Define.S a_String_var
a_String_var = "This" mPB "string variable was put together using a macro in" mPB ""

Debug a_String_var
Debug "This" mPB "debug instruction makes use of" mPB "'s macro features."
Debug "In" +#mPB + ", you can use string constants as well. Go" mPB ""