scrap commands?

Discuss the future of the AutoHotkey language

Should command-like syntax for functions (functions without parentheses) be removed?

Remove the command-like syntax for functions.
33
79%
Keep the command-like syntax for functions.
9
21%
 
Total votes: 42
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

scrap commands?

18 Nov 2017, 16:18

Note: this poll says nothing about control flow statements:
Break, Continue, Else, Gosub, Goto, If, Loop, Return, While.
Catch, Finally, For, Throw, Try, Until.

Note: this poll says nothing about directives e.g. #If and #IfWinActive.

At present you can do this:

Code: Select all

Func(Arg1, Arg2)
Func Arg1, Arg2 ;command-like syntax
If one were to 'scrap commands', then you would only be able to do this:

Code: Select all

Func(Arg1, Arg2)
I will not vote until a few votes are in.

Comments are welcome.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: scrap commands?

19 Nov 2017, 18:27

The easy way out would be to scrap it, no one will ever question why they cannot call their functions without (). With the current behaviour, there will be confusion, but the syntax can be convenient and people, including me, will always be confused about something. So I'm glad it is not up to me :).

☕
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: scrap commands?

20 Nov 2017, 08:37

I cannot see any advantage in using the "command-like function call syntax". So I'll don't use it and voted for 'remove'.

It would be interesting to hear why those who voted for 'keep' did it.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: scrap commands?

20 Nov 2017, 10:12

just me wrote:It would be interesting to hear why those who voted for 'keep' did it.
i initially was going to vote remove, but i hesitated, and chose not to vote. my reason was, there is definite value in keeping the historical "identity" of AHK. but, how much that value brings, in comparison to the headaches and confusion that the syntax causes, i cannot say.

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: scrap commands?

20 Nov 2017, 11:10

The advantage is convenience, due to less typing, I cannot imagine any other reason (edit: I can respect the nostalgic arguments by guest3456, although, I do not suffer from nostaliga ;) ). Maybe there are implementation benefits, performance? I will probably not use it for other things than debug-msgboxes and such. Eg,

Code: Select all

msgbox var
; vs
msgbox(var)
There will be confusion of course, and ugly code,

Code: Select all

obj.method.g 37,,,,,,37 ; :((
g 37,,,,,,37			; :(
g(37,,,,,,37)			; :|
Spoiler
And even those who doesn't want to use it, might eventually experince new bugs in their code,

Code: Select all

g (37,38)	; accidental space, passes 38 as the first parameter, nothing else
g(37,38)	; does what you think
We cannot use ternary or x && y at the beginning of a line without omitting spaces or enclosing in (), eg

Code: Select all

x ? y : z ; No!
(x ? y : z) ; Yes!
x? y : z ; Yes!

x && y ; No!
(x && y) ; Yes!
Cheers.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: scrap commands?

20 Nov 2017, 18:10

Helgef wrote:The advantage is convenience, due to less typing, I cannot imagine any other reason (edit: I can respect the nostalgic arguments by guest3456, although, I do not suffer from nostaliga ;) ).
upon further thought, since the "Command syntax" has changed so much, with all params now expressions (text is no longer literal and variables are no longer derefd with %%), it already looks nothing like in the past, so any and all nostalgic reasoning is pretty much gone. i voted remove.
Helgef wrote: And even those who doesn't want to use it, might eventually experince new bugs in their code,

Code: Select all

g (37,38)	; accidental space, passes 38 as the first parameter, nothing else
g(37,38)	; does what you think
thats absolutely awful

User avatar
hoppfrosch
Posts: 443
Joined: 07 Oct 2013, 04:05
Location: Rhine-Maine-Area, Hesse, Germany
Contact:

Re: scrap commands?

21 Nov 2017, 00:34

Voted remove

Ambiguities should be avoided as far as possible, to avoid confusion of new users.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: scrap commands?

21 Nov 2017, 01:21

Some of my concerns about keeping both notations are as follows:
- Everything is doubled up in the documentation. What's the default notation, do we use the with/without parentheses version for this particular function.
- Horrible scripts that interchange randomly between the 2 styles.
- You write it without the parentheses, but then you need its return value so you have to add in the parentheses.
- Everything looks better and cleaner with the parentheses.
- I'd rather be going over people's scripts that used the parentheses style.
- More consistency, less ambiguity.
- With functions without parentheses being almost identical to functions with parentheses, it seems pointless to keep them both.
- In a beginner tutorial, I can't see how I can rightly explain or justify why the no-parentheses style exists.
- One subtle advantage of removing the no-parentheses style for functions is that it makes clear the distinction between functions and control flow statements, which is an important distinction. It was a revelation after many years to finally realise the exact distinction when trying to recreate the AHK commands as functions.
- I don't know how severe this is, but I believe it hampers the maintenance and improvement of the AHK source code. I believe there were/are issues trying to create custom functions (with/without the same name as default functions) on-the-fly that had a command-style syntax equivalent that behaved in the same way. The problems associated with keeping the 2 notations may even be a key obstacle to AHK v2 being released, I'm not sure.
- When AHK v3 comes around, we'll be thinking, finally time to get rid of the no-parentheses notation.

- My one and only argument in favour of keeping it might be for use with MsgBox, to save a bit of effort in typing. However it looks uglier without the parentheses, and all you need is a hotstring to save the effort in typing, and I would be using a hotstring anyway:

Code: Select all

:*:mx1-::MsgBox, % "
:*:mx2-::MsgBox("){Left}

MsgBox, % Clipboard := vOutput
MsgBox % Clipboard := vOutput
MsgBox Clipboard := vOutput
MsgBox(Clipboard := vOutput)

MsgBox, % Clipboard := Func()
MsgBox % Clipboard := Func()
MsgBox Clipboard := Func()
MsgBox(Clipboard := Func())

MsgBox, % Func()
MsgBox % Func()
MsgBox Func()
MsgBox(Func())

MsgBox, % Func(var1, var2)
MsgBox % Func(var1, var2)
MsgBox Func(var1, var2)
MsgBox(Func(var1, var2))
- The other point would be nostalgia for commands. But my nostalgia for commands requires the presence of initial commas. Anyhow, I have the memories, plus we can put a few old scripts that use commas into a picture frame. And besides, control flow statements and directives would remain command-like in appearance.
- I think maybe some are reluctant to undo Chris's work, but I think that removing commands entirely will make things easier for newbies, in line with Chris's ethos. I found it odd that there were two styles when I first started using AutoHotkey, and I was already more used to the function style from Excel sheet functions, the commands concept was new to me.

- Amazing example Helgef. Cheers.
- Further arguments for removing commands, were made here:
commands and commas - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=39469
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
SirRFI
Posts: 404
Joined: 25 Nov 2015, 16:52

Re: scrap commands?

03 Dec 2017, 04:12

As I mentioned in the other thread - having 2 syntaxes for same thing creates inconsistency, which may also lead to confusion (especially to newcomers).

Voted remove.

I also use ()s for control flow statements and things like #If, unless nothing comes afterwards (in example: non-conditional else or "cleaning-out" #If (removing conditions that were set by another one)), because there is simply nothing to put inside.
Last edited by SirRFI on 09 Dec 2017, 08:38, edited 1 time in total.
Use

Code: Select all

[/c] forum tag to share your code.
Click on [b]✔[/b] ([b][i]Accept this answer[/i][/b]) on top-right part of the post if it has answered your question / solved your problem.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: scrap commands?

09 Dec 2017, 00:11

Helgef wrote:And even those who doesn't want to use it, might eventually experince new bugs in their code,

Code: Select all

g (37,38)	; accidental space, passes 38 as the first parameter, nothing else
g(37,38)	; does what you think
g (37,38) throws an error if the function requires more than one parameter.
x := g (37,38) concatenates g and 38 regardless and will never throw an error, regardless of the outcome of this thread.
My conclusion: This argument does not support your position very well.
We cannot use ternary or x && y at the beginning of a line without omitting spaces or enclosing in (),
This is a separate issue and may be solved without changing the syntax. Initially (in v1), commands had priority because they had known, fixed names; i.e. x ? y : z worked but MsgBox ? y : z gave you a MsgBox. In v2-alpha, user-defined commands were given priority over ternary for consistency with built-in commands. This is no longer necessary, because a valid expression cannot start with ? or &&; i.e. x && y and x ? y : z only have one valid interpretation each.

I too would like to hear the reasons for voting "keep".
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: scrap commands?

09 Dec 2017, 01:15

The only thing I could imagine is if someone's keyboard is broken and they cannot type ( or ).

And they installed a virus where any program that remaps other keys to ( and ), or any attempts to copy and paste parentheses, fails or BSODs.

Gonna vote remove. The more consistency, the better.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: scrap commands?

09 Dec 2017, 15:32

Hello :wave:
lexikos wrote:This argument does not support your position very well.
That was not an argument for my position, which I have neither decided nor stated, it was highligting a fact. The problem would obviously arise when the function is actually called, not when you get notified of a load time error pointing an arrow at the mistake.
a valid expression cannot start with ? or &&; i.e. x && y and x ? y : z only have one valid interpretation each.
No, only one interpretation implies a valid expression. The current interpretation is still valid. You can make the choise to interpret it as not being an invalid expression for the first parameter in a function call. Whatever you choose, the transformation of a function call with parentheses to one without, isn't invertible.

Cheers.
Juan

Re: scrap commands?

09 Dec 2017, 19:56

Actually, the controversy function-command exist mainly because of Autohotkey Classic. In fact, having two such different syntaxes gave rise to tremendous problems for beginners and to generate documentation.

In contrast, the specific case of the function calls without parentheses is trivial and easily understandable, even for beginners, provided they do not have the trauma of Authotkey Classic:
No user commands. There are only functions. And if a line begins with a function call, the parentheses can be omitted:

MsgBox sin(x)
MsgBox(sin(x))

That's all. I prefer the first call. I save writing and the code is clearer and nicer, at least as long as the text editors do not put the nested parentheses smaller.
And, in any case, those extra parentheses only cause unnecessary noise. If you don't like the first notation use the second. Nobody prevents you. Do not force others to use your notation.
In addition, the absence of parentheses shows that we want to make a procedure-call emphasizing the intention not to use the return value if it exists.

VBA also allows that and there is not so much controversy. Why? Because they do not start from the previous bad experience of Authotkey classic.

In Autohotkey, as in all languages, there are many cases in which things can be done in two ways and many people agree that this versatility compensates the inconvenience of making the language more complex. For example, the substitution of variables and expressions within a literal string is not strictly necessary (you can achieve the same by concatenating literals and expressions). The concept of substitution within a literal is much more complex than the case at hand and may confuse a novice who intends to write a literal message and encounters an unexpected substitution:

"You can write %(percent)"

But people still like this feature, and many languages have ended up including it because it makes life more comfortable and enjoyable for the writer-programmer and for the reader-programmer:

"Write a value between %(start) and %(end), please"
"Write a value between " . start . " and " . end . ", please"

If we suppress all (presumably) unnecessary characteristics we will remain with a rigid and boring language.

Many times people talk about syntactic sugar pejoratively without realizing that sugar sweetens the life of the programmer making their task more pleasant and enjoyable. This also increases productivity!
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: scrap commands?

10 Dec 2017, 02:04

Thank you for your input.
Helgef wrote:That was not an argument for my position, which I have neither decided nor stated, it was highligting a fact.
I misinterpreted your position, but the point I was trying to make had absolutely nothing to do with your position. Allow me to rephrase: The fact you have highlighted is of very little relevance. Anyone might eventually experience bugs in their code due to putting a space before the parentheses, regardless of whether function calls require them in all instances or not.
The problem would obviously arise when the function is actually called, not when you get notified of a load time error pointing an arrow at the mistake.
The problem "arises" when the program does not behave as expected, whether that is at load time, when the function is called, or at any other time when the effects of the mistake are actually felt. The solution is very easily found when load-time checking points out the error. In that case, the problem is less severe. There are effectively two problems:
  1. g (37,38) written at the beginning of a line, currently interpreted as a call to g with one parameter. If g requires two parameters, the problem will be immediately pointed out.
  2. g (37,38) written elsewhere, interpreted as concatenation. The problem will never be detected at load time; it may not be detected at all, and when its effects are felt, the cause may be hard to find.
Only #1 is relevant to this topic, but #2 is a larger problem and will remain a problem regardless of the outcome of this thread.
No, only one interpretation implies a valid expression. The current interpretation is still valid.
It is "valid" to interpret the code according to the rules even if the rules say the code can't run, and the rules can be whatever we like, so "valid" can mean anything. This makes discussion of validity (in this sense) pointless. If I say the rule is "parentheses may be omitted except where the first parameter begins with a binary operator", it is invalid to interpret x && y as a function call.

I was not talking of the act of interpreting, but the meaning being assigned. The current interpretation of x && y is x( && y), and x( && y) is invalid, therefore the current interpretation is invalid.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: scrap commands?

17 Dec 2017, 04:39

I have tried to put some more thoughts into the topic, specifically I wanted to come up with reasons to scrap it, so I don't regret saying I want to keep it. I'm still undecided but have questions, comments, opinions and things to note. In no particular order,

Code examples
I took a function from the gdip lib by tic, and converted it to the new syntax, so we can look at a real example, as opposed to just msgbox or x y,z examples. This function does many calls without retrieving the return values, I put all versions in one code box, I suggest you put them in your editor in different tabs and alternate between them.

Code: Select all

; 1. Original
Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_DeleteRegion(Region)
	return E
}
; 2. Original but extra spaces after opening ( and before closing )
Gdip_FillRoundedRectangle( pGraphics, pBrush, x, y, w, h, r )
{
	Region := Gdip_GetClipRegion( pGraphics )
	Gdip_SetClipRect( pGraphics, x-r, y-r, 2*r, 2*r, 4 )
	Gdip_SetClipRect( pGraphics, x+w-r, y-r, 2*r, 2*r, 4 )
	Gdip_SetClipRect( pGraphics, x-r, y+h-r, 2*r, 2*r, 4 )
	Gdip_SetClipRect( pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4 )
	E := Gdip_FillRectangle( pGraphics, pBrush, x, y, w, h )
	Gdip_SetClipRegion( pGraphics, Region, 0 )
	Gdip_SetClipRect( pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4 )
	Gdip_SetClipRect( pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4 )
	Gdip_FillEllipse( pGraphics, pBrush, x, y, 2*r, 2*r )
	Gdip_FillEllipse( pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r )
	Gdip_FillEllipse( pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r )
	Gdip_FillEllipse( pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r )
	Gdip_SetClipRegion( pGraphics, Region, 0 )
	Gdip_DeleteRegion( Region )
	return E
}
; 3. No (), added one space only
Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect pGraphics, x-r, y-r, 2*r, 2*r, 4
	Gdip_SetClipRect pGraphics, x+w-r, y-r, 2*r, 2*r, 4
	Gdip_SetClipRect pGraphics, x-r, y+h-r, 2*r, 2*r, 4
	Gdip_SetClipRect pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion pGraphics, Region, 0
	Gdip_SetClipRect pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4
	Gdip_SetClipRect pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4
	Gdip_FillEllipse pGraphics, pBrush, x, y, 2*r, 2*r
	Gdip_FillEllipse pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r
	Gdip_FillEllipse pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r
	Gdip_FillEllipse pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r
	Gdip_SetClipRegion pGraphics, Region, 0
	Gdip_DeleteRegion Region
	return E
}
; 4. No (), added one tab
Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect	pGraphics, x-r, y-r, 2*r, 2*r, 4
	Gdip_SetClipRect	pGraphics, x+w-r, y-r, 2*r, 2*r, 4
	Gdip_SetClipRect	pGraphics, x-r, y+h-r, 2*r, 2*r, 4
	Gdip_SetClipRect	pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion	pGraphics, Region, 0
	Gdip_SetClipRect	pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4
	Gdip_SetClipRect	pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4
	Gdip_FillEllipse	pGraphics, pBrush, x, y, 2*r, 2*r
	Gdip_FillEllipse	pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r
	Gdip_FillEllipse	pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r
	Gdip_FillEllipse	pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r
	Gdip_SetClipRegion 	pGraphics, Region, 0
	Gdip_DeleteRegion 	Region
	return E
}
Number 3 is not very nice in my opinion, number 4 is much better, I prefer number 2. What do you (all) think? I wonder if those who voted to keep, would use it like this? I wouldn't. In the next example, the functions are well known, which helps I think, and uses zero to one parameter,

Code: Select all

; "Original"
run("notepad")
winWaitActive("ahk_class Notepad")
send("hello")
sleep(1000)
winClose()
exitapp()

; No (), one space added
run "notepad"
winWaitActive "ahk_class Notepad" 
send "hello"
sleep 1000
winClose
exitapp
Omitting the parentheses works well here I think.

One-line hotkeys
Currently,

Code: Select all

a::func
makes the hotkey call func, even though func isn't at the beginning of a line, at least not in the scripter's text editor, I guess it is internally interpreted as

Code: Select all

a::
	func
return
I consider this mostly nice, eg, a::send "text", but a::b is a remapping, and a::b c is a function call. So there are some special cases, depending on the function name, and if passing parameters or not, to consider and document.

Omitting the first parameter
I really do not like the call without parantheses when the first parameter is omitted,

Code: Select all

f x,y
; omitting x
f ,y
f	,y
f(,y)

msgbox msg,title
; omitting msg
msgbox ,title
msgbox(,title)
I wonder if anyone likes this? In this context, f(,y) looks beautiful :lol:.

Variadic* calls
Note, currently, variadic calls doesn't work, they should I guess, so either it is not yet implemented or maybe I missed a note about it in one of the pages. There are two errors, too few parameters, and missing operand,

Code: Select all

f p*	 ; missing operand
g [x,y]* ; too few parameters
f(a){
}
g(a,b){
}
Just as we could allow x ? y : z, I wonder, given that variadic calls are suposed to work, should we allow

Code: Select all

f p*, (expr)
; equivalent to
f(p*), (expr)
it could look a bit odd.

Object notation
I really do not like the notation for method calls, there is already some awkwardness in that parentheses can be used with properties, eg,

Code: Select all

obj.xyz			; Property get or method call?
obj.xyz w 		; same question.
No conclusions
☕

User communication
lexikos wrote:The fact you have highlighted is of very little relevance.
I do not think a fact about the discussed topic is of very little relevance, even if it doesn't qualify as a stong argument, either for or against. Your addition about throwing an error highlights that the mistake sometimes is easy to spot, sometimes not.
The problem "arises" when the program does not behave as expected
Anyone might eventually experience bugs in their code due to putting a space before the parentheses
The novelty I tried to highlight is the case when the outcome of the old mistake is a function call, consequently, when you get unexpected results, the problem is more likely to appear to be related to the inners of the function, rather than at the place where it was called, making it more difficult to find. I consider it worth noting.
I was not talking of the act of interpreting, but the meaning being assigned.
That make sense, I should have figured, I apologise.

@ juan, hello.
the specific case of the function calls without parentheses is trivial and easily understandable, even for beginners [...] if a line begins with a function call, the parentheses can be omitted [...] That's all.

Code: Select all

MsgBox sin(x)
Your specific example with the msgbox is easy to understand and readable, I agree. But from the perspective of a novice, something like this,

Code: Select all

g x
, f(y)
which isn't equivalent to

Code: Select all

g(x)
, f(y)
might not be trivial and easily understandable, I would probably have a hard time getting used to that too. I do not think the sweet taste of AHK is greatly affected by the presence or absence of this syntax.

Cheers.
User avatar
derz00
Posts: 497
Joined: 02 Feb 2016, 17:54
Location: Middle of the round cube
Contact:

Re: scrap commands?

18 Dec 2017, 09:20

Are you saying that you can/could also omit parentheses for custom functions? I thought it was just for built-in... Or are you just using the custom functions as an example?

Edit: Sure enough, this calls x() in v2:

Code: Select all

x "test"
x(v){
	MsgBox v
}
I didn't know that :think:
try it and see
...
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: scrap commands?

18 Dec 2017, 12:17

derz00 wrote: I didn't know that :think:
:)

https://autohotkey.com/v2/v2-changes.htm
Known issues:

Some commands have not been fully converted. Defining a function with the same name as one of these commands currently overrides the command only for the function() style of calling; i.e. if parentheses are omitted, the original command is called.

_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Re: scrap commands?

02 Jan 2018, 05:26

Strongly remove command style syntax.
Strongly made parentheses mandatory.
AHKv2.0 alpha forever.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: scrap commands?

17 Jan 2018, 03:50

- Interesting, 80% in favour of scrapping the command-style notation for functions.
- I'm partially sympathetic to the idea of MsgBox having 2 styles. However, I have an alternative idea.
- I would make MsgBox function-only, like all of the other functions. But I would have a special 'Print' function, that would allow you to omit parentheses. The Print function would be an alternate name for MsgBox, but could be set to do something else, like run ToolTip, or a custom function that prints to a console window. E.g. see:
AHK Console - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 89#p170789
- I like the idea of separating MsgBox and Print, so that you know that when you see MsgBox, that that's a part of the script proper, whereas Print implies debugging. It also makes it easier to find lines related to debugging in big scripts.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: scrap commands?

14 Apr 2018, 01:58

PHP has a print statement, which is not a function but can be called with or without parentheses (functions in PHP require parentheses).

Perl has a print function and allows parentheses to be omitted from function calls.

I think there's something wrong about the idea of making print a statement (presupposing that functions require parentheses and statements do not), but then allowing it to be redefined. Either we have one statement that can be redefined, unlike every other statement (or one function that doesn't require parentheses, unlike every other function), or we use a less obvious method to define what happens (like a built-in variable).

Helgef wrote:Currently, a::func makes the hotkey call func, even though func isn't at the beginning of a line,
Any statement can be recognized to the right of a:: (but won't necessarily form a valid program). "At the beginning of the line" is easier to grasp without any previous knowledge/reading, but function call statements are really allowed anywhere that allows a statement, as mentioned in the current documentation.
but a::b is a remapping, and a::b c is a function call. So there are some special cases, depending on the function name, and if passing parameters or not, to consider and document.
This is due to the similarity between the remapping syntax and hotkeys. It causes ambiguity in v1 and is likely to continue to cause ambiguity regardless of the outcome of this thread. For instance, a::return is interpreted as a return statement, since that's the most useful interpretation and most likely what the user wants, but a::^return and a::enter are remappings.

However, return is probably the most benign example, being a control flow statement commonly used as such, rarely used as a key name, and also redundant (we could remove it in favour of Enter). There are other key names that seem more likely to be used as user-defined functions, like Launch_Mail.

Currently (and in v1.0), Pause is specifically excluded from remapping to allow the command to be called. If parentheses are required for calling Pause(), this exclusion can be removed.

Side note: calls with zero parameters are where I most want to omit parentheses: ListVars, Pause, MsgBox, etc. By default, Pause() requires 40% more key-presses than Pause. ;)
Note, currently, variadic calls doesn't work,
That was fixed in v2.0-a084.

However, it touches on another point of potential ambiguity. The current implementation of line continuation requires the next line to start with an operator, but it could be possible to "continue" by ending a line with a binary operator. Since * is also a binary operator, Fn array* would be ambiguous. If parentheses are required, there's no question of which way to interpret the asterisk.

On the other hand, implementing this type of continuation would prevent any future use of current operator symbols as postfix operators (like the variadic call operator, written after its input). There's also the option of changing the variadic operator (e.g. ...).

This would also affect commas. Multi-statement comma is technically a binary operator.
should we allow

Code: Select all

f p*, (expr)
; equivalent to
f(p*), (expr)
I see no reason to think the asterisk would terminate the parameter list. f p*, (expr) is equivalent to f(p*, (expr)), which is not supported right now but logically should be.

More generally, a user might think that f p, (expr) would be evaluated as (f p), (expr), or even that x := f p will call function f. Many things can be misunderstood if the user lacks requisite experience and knowledge. In this case, it shouldn't be hard to pick up on how function call statements work vs. auto-concat, even if the user doesn't read the documentation. The current documentation (written after your post), uses the phrase "the remainder of the line is taken as the function's parameter list". There's also "Line breaks generally act as a statement seperator, terminating the previous function call or other statement."
I really do not like the notation for method calls, there is already some awkwardness in that parentheses can be used with properties, eg,

Code: Select all

obj.xyz			; Property get or method call?
obj.xyz w 		; same question.
Both of the above are method calls, just as they would be function calls if you removed obj.. x := obj.xyz is not a method call, just as x := xyz is not a function call.

Re "parentheses can be used with properties": obj.xyz() is always a method call, even if it might be implemented by calling a property function. That will always be possible via meta-functions. It's currently possible by default for class-defined properties and some built-in properties, but that will change (as I've indicated in v2-thoughts).

But I agree that method call statements can be awkward.
[Example] might not be trivial and easily understandable,
I think the main argument for parentheses being optional is that omitting them can make the code more readable. It won't force the user to write less readable code against their will. I suppose that your example was written for the express purpose of demonstrating code you consider unreadable, so did it help you to achieve your goal, and if so, how can that be a bad thing? ;)

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: DaveT1 and 29 guests