Replacing percent signs

Discuss the future of the AutoHotkey language
lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Replacing percent signs

29 Apr 2017, 21:48

I wrote: I have also been reconsidering percent-sign derefs in quoted strings, as they were primarily an attempt at integrating the "legacy" syntax with expressions and bringing more consistency to the language. Though I'm reluctant to deviate from the v1 expression syntax, I think there are more readable alternatives for variable/expression substitution within strings.
Source: Removal of command syntax
Chris and others wrote:

Code: Select all

var = "The value in x is ""$x""."  ; Alternative: Resolve $var inside double-quoted strings ($ seems easier than %%).
[...]
The $var approach is attractive because not only is it easier to type than the dual-percent-sign method, the $ character might need to be escaped less often (due to being more rarely used than %). However, if $ seems too confusing or ambiguous (especially for PHP users, who are used to a $ being the mandatory first character in all variable names), the double-percent-sign method could be used instead.

Another thing about the $var method is that it could also be applied to all commands. For example: MsgBox The value in var is $var. However, there would be some ambiguous situations such as $varstring, in which string is intended to be literal text (not part of the variable name). Something like ${var}string could be used in these cases. It's important to verify the rarity these cases because if the braces are needed too frequently, staying with the percent-sign method is probably the better choice.

(Titan: What about an explicit end char like $var;string instead of braces? This goes for RegEx too.)
-> Interesting idea, but it doesn't seem as readable. In fact, it might seem cryptic to anyone unfamiliar with the syntax, not to mention breaking from tradition and thus having more of a learning curve for people going to (or coming from) other languages. On the other hand, it's clearly easier to type. But if the semicolon-or-braces are rarely needed in practice, perhaps the choice between semicolon and braces doesn't matter too much.

Source: AutoHotkey v2
Early v2 alpha builds allowed #DerefChar to specify a starting and ending character, and allowed the ending character to be omitted. The directive was removed because I prefer to not encourage different incompatible syntax variations within the main program, and the ending character requirement was restored to allow expressions within %..%.

More recently, I implemented Format() based on a mix of .NET (String.Format/Console.Write) syntax and C++ format specifiers. I think that using something balanced like braces makes it easier to discern which parts are the placeholders/variables and which parts are literal.

Even more recently, C# and VB got string interpolation. Instead of String.Format("Name = {0}, hours = {1:hh}", name, hours), you can write $"Name = {name}, hours = {hours:hh}", putting the expression directly into the string, along with the optional format specifier. (I think they were initially planning "Name = \{name}, hours = \{hours:hh}", but later changed it.)

Also recently, JavaScript got template literals: `Name = ${name}, hours = ${hours}`.

For AutoHotkey, plain {} isn't ideal because it's used frequently with Send, and `backquote` isn't ideal because we want to allow escape sequences inside the string (and I don't want to change the escape character). "Name = `{name}" is one idea, but I think it looks especially strange because of the amount of whitespace under the backquote.

I think it's reasonable to use () in place of {}, since expressions are often enclosed in (). But it would probably need to be immediately preceded by another symbol to avoid confusion (as opposed to starting the string literal with a special symbol and then using only () around expressions).

So I'm not set on any particular idea, but considering combinations of methods:
  • Using a special character immediately before the quote mark, as with $" ... ", to denote that it contains sub-expressions.
  • Enclosing the expression in balanced symbols, like {}, () or [].
  • Preceding the enclosing symbols and/or a variable name with a special symbol, such as $, %, or something else.
The main point is that "including" a value in a quoted string in v1 requires using the same symbol that starts/ends the string, which I think makes it harder to read. I'm not sure whether the requirement for whitespace makes it easier or harder to read (maybe both, depending on the case). The space requirement could be removed, so "Name = "name", hours = "hours would be officially valid (and to some people that is more readable), but I think it has the same sort of problem as the percent signs, where it's sometimes hard to tell which side is literal (without accurate syntax highlighting). And it might be more confusing than percent signs. Another reason I'd prefer not to do that is to allow for the possibility of other syntax extensions, like Python's R"Raw strings", Lua's ability to omit the parentheses when calling a Function"with one string", or something no one has thought of yet.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Replacing percent signs

30 Apr 2017, 04:43

As far as I understand, the topic is "percent-sign derefs within quoted strings". So I assume that "percent-sign derefs outside of quoted strings" will stay unchanged. If so, I see neither any problems with the current implementation nor any advantage when replacing %-signs by other signs. IMO, it's consistent to use them in both cases.
lexikos wrote:The space requirement could be removed, so "Name = "name", hours = "hours would be officially valid (and to some people that is more readable)
God forbid!
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Replacing percent signs

30 Apr 2017, 05:13

I can already see the amount of confusion this would bring along.
Recommends AHK Studio
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Replacing percent signs

30 Apr 2017, 08:33

just me wrote:As far as I understand, the topic is "percent-sign derefs within quoted strings". So I assume that "percent-sign derefs outside of quoted strings" will stay unchanged. If so, I see neither any problems with the current implementation nor any advantage when replacing %-signs by other signs. IMO, it's consistent to use them in both cases.
Great point that I had originally missed. If a double-deref in an expression is still going to be within %var%, then it doesn't make sense to have different syntax..

I'm not really a fan of this change. Seems the only reason against the current way is that "it's sometimes hard to tell which side is literal". I think that that readability downside is fairly small to justify such a bigger syntax change. That could be worked around by docs that suggest parens along with the %s when used inside strings. "Name = %(name)%, hours = %(hours)%" if extra readability is needed. Thats really only one extra char (seems like you want to remove the trailing % here) and it already works

HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: Replacing percent signs

30 Apr 2017, 14:49

I would keep %%, it is familiar and I don't see why it needs to be changed.
If change for expressions in strings is required I would vote for "Name = %(name), hours = %(hours)" which was already implemented in early stage afaik.
User avatar
fincs
Posts: 527
Joined: 30 Sep 2013, 14:17
Location: Seville, Spain
Contact:

Re: Replacing percent signs

30 Apr 2017, 15:19

HotKeyIt wrote:I would keep %%, it is familiar and I don't see why it needs to be changed.
If change for expressions in strings is required I would vote for "Name = %(name), hours = %(hours)" which was already implemented in early stage afaik.
I am in favour of this, as I fail to see any compelling reason to shy away from the well established convention of % in the context of AutoHotkey. If all, %(expr) could be considered instead of %expr%. This way % would need to be followed by ( to be treated as string interpolation, in any other case it would be treated as a literal percent sign (and obviously, `%( could be used to introduce literal percent+opening-parenthesis).
fincs
Windows 11 Pro (Version 22H2) | AMD Ryzen 7 3700X with 32 GB of RAM | AutoHotkey v2.0.0 + v1.1.36.02
Get SciTE4AutoHotkey v3.1.0 - [My project list]
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replacing percent signs

30 Apr 2017, 15:52

Chris and others wrote: The $var approach is attractive because not only is it easier to type than the dual-percent-sign method, the $ character might need to be escaped less often (due to being more rarely used than %).
I would like to point out that it is easier because it is just one symbol on one side of the variable name, the actual typing of the $ is slightly awkward in some non-english layouts. I need to do a ctrl+alt+4 to produce a $. The % sign is probably more common than $ in most languages, hence it might be an easier character to type, simple shift+5 is all I'm required to do for that. Most strings doesn't contain any % or $, hence, in most strings, there is no need to escape either of them.
lexikos wrote: So I'm not set on any particular idea, but considering combinations of methods:
  • Using a special character immediately before the quote mark, as with $" ... ", to denote that it contains sub-expressions.
  • Enclosing the expression in balanced symbols, like {}, () or [].
  • Preceding the enclosing symbols and/or a variable name with a special symbol, such as $, %, or something else.
I think "%var" when not ambigious, and "%(var)" when wanted or ambigious is excellent. Finally, I'm not at all against ditching the %, personally, I'd even prefer a double prefix of something easier to type, for example, "::var" or ";;var", double because it is more visible and less likely to be needed to be escaped. Double-typing is almost as fast and easy as single-typing. But I guess that would be too much for some people with old habits :lol:
I don't like enclosing in []{} due to them being used for objects. For example, does the following put "name1" in a the outer array %[...] or is the outer array not an array :crazy:

Code: Select all

var:=1
MsgBox("My name is %[["name1","name2"][var]]") ; {} would be ok I guess...
with "%var" and "%(var)" it would be

Code: Select all

var:=1
MsgBox("My name is %["name1","name2"][var]") ; My name is [var]
MsgBox("My name is %(["name1","name2"][var])") ; My name is name1
Cheers.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Replacing percent signs

30 Apr 2017, 18:00

so normal double derefs remain as:

Code: Select all

var1 := "world"
var2 := "var1"
var3 := "hello " %var2%
but string derefs would be:

Code: Select all

var1 := "world"
var2 := "var1"
var3 := "hello %(%(var2))"
; or?
var3 := "hello %(%var2%)"
; or
var3 := "hello %(var1)"
:crazy:

there has yet to be a substantial reason to make any change at all

if you insist on this, why not just change Format()?

lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: Replacing percent signs

30 Apr 2017, 23:21

guest3456 wrote:so normal double derefs remain as:
What makes you think they will?
there has yet to be a substantial reason to make any change at all
Quite right, but maybe not in the way you meant. There arguably isn't a substantial reason to allow variable references inside quoted strings at all. Given that I'm unlikely to remove auto-concat, I may just remove the percent sign derefs and leave it at that for v2.0.0. It's been good enough for user-defined functions (and other expressions) for this long, after all.
if you insist on this, why not just change Format()?
Why should Format() be changed and how?
Helgef wrote:I'd even prefer a double prefix of something easier to type, for example, "::var" or ";;var", double because it is more visible and less likely to be needed to be escaped.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Replacing percent signs

30 Apr 2017, 23:57

lexikos wrote:There arguably isn't a substantial reason to allow variable references inside quoted strings at all. Given that I'm unlikely to remove auto-concat, I may just remove the percent sign derefs and leave it at that for v2.0.0. It's been good enough for user-defined functions (and other expressions) for this long, after all.
I don't think there is any good reason to remove them altogether either. But, while I like the convenience of derefs inside quoted strings, I'd rather them be removed completely than have any of the suggestions so far. I used to dislike auto concat but I've gotten used to it because all of those periods everywhere were getting to be too much.

User avatar
Ragnar
Posts: 611
Joined: 30 Sep 2013, 15:25

Re: Replacing percent signs

01 May 2017, 05:03

I like the idea of using "%var" and "%(var)". However, regardless of nostalgia the prefix char doesn't necessarily have to be a %, at least for QWERTZ keyboard layouts. It doesn't matter whether I press Shift-5 for % or Shift-4 for $.
User avatar
tank
Posts: 3122
Joined: 28 Sep 2013, 22:15
Location: CarrolltonTX
Contact:

Re: Replacing percent signs

01 May 2017, 05:14

If the conversation is to use some other character for deref and use % everywhere else then it will only lead to confusion and lots of support topics. that said i am in favor of any single symbol preceding ALL variables instead
We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Telegram is the best way to reach me
https://t.me/ttnnkkrr
If you have forum suggestions please submit a
Check Out WebWriter
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replacing percent signs

01 May 2017, 08:55

guest3456 wrote:so normal double derefs remain as:

Code: Select all

var1 := "world"
var2 := "var1"
var3 := "hello " %var2%
but string derefs would be:

Code: Select all

var1 := "world"
var2 := "var1"
var3 := "hello %(%(var2))"
; or?
var3 := "hello %(%var2%)"
; or
var3 := "hello %(var1)"
With "%var" and"%(var)" I would think (hope) that you could do var3:="hello %%var2" to make var3:="hello world".
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Replacing percent signs

01 May 2017, 15:07

var3:="hello %%var2"Why not var3 := "hello " . var2

@Topic: I think this discussion brings up the topic of where AHKs long time development is going.
Some people want to get closer to C.
Some people want some functionality from other scripting languages like php.
I personally want to move closer to OOP like Java or similar.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replacing percent signs

02 May 2017, 09:04

nnnik wrote:I can already see the amount of confusion this would bring along.
nnnik wrote:var3:="hello %%var2"Why not var3 := "hello " . var2
Point made ;)
lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: Replacing percent signs

20 May 2017, 20:46

I have long felt that all of the changes I made to command syntax (up to the current build) were inadequate; despite the cost (to compatibility), they would not eliminate the confusion users have with percent signs or make the syntax easier to learn, and the language and documentation are still (or would be) unnecessarily complicated.

My current feeling is that removing percent sign derefs is along the same lines as removing command syntax. Percent-derefs are (debatably) more readable and/or convenient, like command syntax. They are entirely redundant, like command syntax. There are still different meanings of %, so it doesn't eliminate the risk of users mistakenly using percent signs where they aren't needed. Basically, %variable% derefs must go.

Double-derefs and dynamic function calls

If percent signs are only used for double-derefs and dynamic function calls (never normal derefs), there probably wouldn't be much risk of confusion. However, the syntax for dynamic function calls has been redundant since Func objects were added. None of the built-in functions create pseudo-arrays anymore, and I generally discourage their use. There are probably still situations where double-derefs provide a good solution or convenient shortcut, but that may not be enough to justify having special syntax for it.

One mistake some users make is to try to use double-deref syntax with actual arrays: array := Array(), array%i% := x. Users also occasionally ask how to "dynamically declare" a variable, but it isn't possible. Perhaps a good solution is to combine double-derefs with object syntax: local["array" i] := x or global.myFoo. It would also improve clarity - it will always be clear whether the code intends to deref/create a local, static or global variable.

Comparing to v1, that would solve the problem of double-derefs accidentally returning global variables when they're intended to be local. (That doesn't happen much in v2 since dynamic references respect/require declarations the same as non-dynamic references.) For v2, performing a global double-deref would no longer require making the function assume-global or declaring each global variable.

%(expression)

I have been playing with syntax highlighting (not the interpreter) and I think that %(expression) is the most readable alternative (excluding $(expression) because of the reasons Helgef gave, and others). I don't think it's a good idea to allow %variable due to ambiguity, and false similarity to languages which have a mandatory prefix on variable names. Requiring parentheses reminds the user that this is an expression - I can't see it being likely to cause confusion of the kind that results in if (%x% > 1).

This is what it looks like in my editor:
formatstring.png
formatstring.png (3.58 KiB) Viewed 11099 times
The bright green 08x is a format specifier, coloured the same as escape sequences as a reminder that it controls the formatting of the string, but is not literal. The first idea was to specify it after a comma, like in Visual Studio's debugger. %(hwnd,08x) seemed a bit clearer than %(hwnd:08x) (which would be based on Format using {1:08x}, but might be confusing with key:value, ternary or (future) named parameters). It would virtually never be necessary to escape a literal percent sign if the parentheses were mandatory.

The second idea was to specify it before the parentheses, like how RegExReplace supports $U{1} (U is also a valid format specifier). But it seemed less clear or more ambiguous, especially once I considered that format specifier can contain space. It would seem necessary to require literal percent signs to always be escaped, at least for clarity.

The F prefix was an early idea to replace $" ... ", where F reminds the reader of Format. I probably won't keep it. (I just set it up that way in the highlighter, to keep normal strings functional while I experiment. If the placeholders were {} rather than %(), it would seem better to enable them with a special prefix than have them enabled by default.)
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Replacing percent signs

20 May 2017, 21:14

lexikos wrote: One mistake some users make is to try to use double-deref syntax with actual arrays: array := Array(), array%i% := x. Users also occasionally ask how to "dynamically declare" a variable, but it isn't possible. Perhaps a good solution is to combine double-derefs with object syntax: local["array" i] := x or global.myFoo. It would also improve clarity - it will always be clear whether the code intends to deref/create a local, static or global variable.
"improve clarity"? At first look, that wasn't clear to me AT ALL. After some thought, I now understand what is going on with that, but if something requires extra time to process, that's the opposite of being 'clear'. I think its an example of being overly clever. Or its an example that I'm just slow

I really have no idea what's going on in this thread. I stick with my opinion from previous posts. Maybe I'm in the minority, I don't know

lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: Replacing percent signs

20 May 2017, 21:53

"Clarity" was in reference to an informed user reading the intent of the code, as I explained.

But I did also consider it obvious from the context of the example that local would be a collection of the function's local variables and global would be a collection of the script's global variables, so I neglected to explain. Lua has a similar mechanism with the table _G/_ENV (the global environment), and JavaScript in the browser has window.

Your point of view is biased by your experience with AutoHotkey v1. I think it would be accurate to say that most new or inexperienced users have little chance of guessing the meaning of %name% without first reading or being told about it. I think that local[name] has a better chance of being intuitively understood. You may be used to thinking of variables and associative array elements as separate things, but they're fundamentally the same; array elements are variables within the context of the array, and local variables are array elements of the function's local environment. If an uninformed reader doesn't make that mental connection, at least "local" is easier to search for than "%".
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Replacing percent signs

22 May 2017, 06:13

lexikos wrote: I think that %(expression) is the most readable alternative.
I don't think it's a good idea to allow %variable due to ambiguity, and false similarity to languages which have a mandatory prefix on variable names. Requiring parentheses reminds the user that this is an expression
It would virtually never be necessary to escape a literal percent sign if the parentheses were mandatory.
[quote cut and pasted to taste, by helgef]
It is very readable. Regarding %variable, I agree with your arguments about ambiguity and escaping. (In general) I'm not very fond of arguments about how other languages work though, knowing multiple languages should have teached one to read documentation more carefully, often it seems like the more experienced programmers assume global knowledge. (Not directed at you specifically (at all))
Comparing readabillity and convenience of typing, a typical ahk string,

Code: Select all

"x%x y%y w%w h%h"				; Most convenient, still readable
"x%(x) y%(y) w%(w) h%(h)"		; Most readable, slightly less convenient
"x" x " y" y " w" w " h" h		; Inconvenient, awkward to read imo. Especially easy to miss spaces.
About the second line in the code box above, I'd use a hotstring in my editor, almost nullifying the slight inconvenience

Code: Select all

:*?:%%::
	SendInput("`%(){left}")	; Note, probably need to esacape % here
return
Also, interesting ideas regarding object syntax for local/global.
Sort of thinking aloud here I guess. Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Replacing percent signs

22 May 2017, 07:26

Helgef wrote: Comparing readabillity and convenience of typing, a typical ahk string,

Code: Select all

"x%x y%y w%w h%h"				; Most convenient, still readable
"x%(x) y%(y) w%(w) h%(h)"		; Most readable, slightly less convenient
"x" x " y" y " w" w " h" h		; Inconvenient, awkward to read imo. Especially easy to miss spaces.
I think it would be very convenient to remove that sort of syntax in general.
{x:x,y:y,w:w,h:h} seems like the best candidate for that.
Recommends AHK Studio

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 39 guests