Page 1 of 2

Object declaration syntax

Posted: 21 Jan 2018, 21:48
by formicant
Currently, both in AHK 1.1 and 2.0-a, one can declare objects like this:

Code: Select all

singleLineArray := [ "item1", "item2", "item3" ]
singleLineObject := { key1: "value1", key2: "value2", key3: "value3" }

multiLineArray
  := [ "item1"
     , "item2"
     , "item3" ]
multiLineObject
  := { key1: "value1"
     , key2: "value2"
     , key3: "value3" }
The downside of this syntax for multi-line objects is that it is relatively hard to edit. For instance, one cannot just move or delete whole lines to reorder or delete items since the first and the last items differ from the other ones in formatting. Simple tasks need too much editing.

Is it possible to make the syntax a bit less strict?
Namely:
  • Allow line breaks around the brackets
  • Allow trailing comma after the last item

Code: Select all

multiLineArray :=
[
  "item1",
  "item2",
  "item3",
]

multiLineObject :=
{
  key1: "value1",
  key2: "value2",
  key3: "value3",
}
This would allow all the item lines being formatted identically making editing considerably simpler.

Re: Object declaration syntax

Posted: 21 Jan 2018, 22:17
by geek
I haven't done much with v2, but in v1 you can put your object into a continuation section and format it however you want (as shown in my tips thread). For v2 you may have to specify the Quotes option after LTrim Join.

Code: Select all

; http://www.json.org/example.html
MyObject :=
( LTrim Join
{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}
)

Re: Object declaration syntax

Posted: 21 Jan 2018, 23:09
by formicant
GeekDude wrote: For v2 you may have to specify the Quotes option after LTrim Join.
Oh thanks!
I tried continuation sections but haven’t come to the idea of LTrim Join Quotes combination.

Anyway, wouldn’t it be more convenient to make all { } behave like a continuation section?

Re: Object declaration syntax

Posted: 22 Jan 2018, 01:09
by geek
I've never studied the AutoHotkey source directly, so I may be a little off the mark, but this is what I understand the situation to be:

It'd be more convenient to use, but the current way it works is very simple to implement and maintain. Essentially, any line that begins with an operator character (such as comma, dot, plus, minus, etc) is appended to the line before it before further processing can proceed. This allows an expression, or the parameters of a command, to be spread across multiple lines. However, it isn't complex enough to recognize the difference between a plain text parameter and an object in an expression.

If quotes and braces were to be added to the list of symbols which cause implicit line concatenation, it would effectively break the behavior of closing braces, and for opening braces where the previous line does not support OTB. To implement the change you're suggesting would require a deep level change in how AutoHotkey treats individual lines and parses expressions.

Because of these reasons, it's much more effective to give AHK the hint that you want to combine those lines. This can be done, as previously demonstrated, by using a continuation section with the Join option (LTrim is not technically required). Though I suppose if there ever was a time to make this unnecessary it would be now during the active development of v2 :).

Re: Object declaration syntax

Posted: 22 Jan 2018, 03:24
by lexikos
Allowing this is one of my long-term goals for when the parser is redesigned. If I think of a good way to hack it into the current parser, I may do it.

v2 treats naked newline characters in expressions the same as spaces, so you do not need the Join option. However, you can do this with Join:

Code: Select all

x := {
  (Q Join,
    key1: "value1"
    key2: "value2"
  )}

y := ["
  (Join","
    item1
    item2
  )"]
  
; This is probably more conventional:
y := StrSplit("
  (
    item1
    item2
  )", "`n")
Be aware that there is currently a limit of 512 tokens per expression, where [, ], {, }, "item1", key1, : and , each count as one token. When you create large data structures with a single object literal, it is more likely you will encounter this limit.

Re: Object declaration syntax

Posted: 22 Jan 2018, 03:32
by jeeswg
I came across these issues for the first time recently, when working on the example here.
objects: hierarchies: listing/comparing objects - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 02#p195302

• Allow line breaks around the brackets [workaround: use continuation sections]
• Allow trailing comma after the last item [workaround: add and remove dummy keys (not great)]

Code: Select all

q:: ;create arrays via continuation sections (AHK v1 code)
multiLineArray :=
(LTrim Join
[
  "item1",
  "item2",
  "item3",
  "dummy"
]
)
multiLineArray.Pop()

multiLineObject :=
(LTrim Join
{
  key1: "value1",
  key2: "value2",
  key3: "value3",
  dummy: "dummy"
}
)
multiLineObject.Delete("dummy")

vOutput := ""
for vKey, vValue in multiLineArray
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

vOutput := ""
for vKey, vValue in multiLineObject
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput
return
- If arrays/objects could accept something like 'ignore this parameter', then that could be a solution.
- Although the add/remove dummy keys solution isn't great, I might consider using it, for a list of keys that I'm modifying a lot.
- Another idea, if possible, would be to redefine the blueprint for the default AHK array temporarily, to change the __Set() meta-function, so that when you try to add a dummy key with a particular value, it is blocked.

Re: Object declaration syntax

Posted: 22 Jan 2018, 05:53
by lexikos
jeeswg wrote:Allow trailing comma after the last item [...] AHK v1 code
This is the wrong forum.

[] and {} already allow trailing commas in v2.

(However, there's a trivial bug which occurs when you use an even number of trailing commas.)

Re: Object declaration syntax

Posted: 22 Jan 2018, 06:01
by jeeswg
Many thanks lexikos. Here is an AHK v2 version of the script above, which doesn't need any temporary dummy keys.

Code: Select all

q:: ;create arrays via continuation sections (AHK v2 code)
multiLineArray :=
(LTrim Join Q
[
  "item1",
  "item2",
  "item3",
]
)

multiLineObject :=
(LTrim Join Q
{
  key1: "value1",
  key2: "value2",
  key3: "value3",
}
)

vOutput := ""
for vKey, vValue in multiLineArray
	vOutput .= vKey " " vValue "`r`n"
MsgBox(vOutput)

vOutput := ""
for vKey, vValue in multiLineObject
	vOutput .= vKey " " vValue "`r`n"
MsgBox(vOutput)
return

Re: Object declaration syntax

Posted: 22 Jan 2018, 22:40
by formicant
lexikos wrote: Be aware that there is currently a limit of 512 tokens per expression, where [, ], {, }, "item1", key1, : and , each count as one token. When you create large data structures with a single object literal, it is more likely you will encounter this limit.
Yes, I’ve already encountered this, so I moved to JSON (using the JSON library by Cocobelgica). Pity.
Is it planned to remove this limitation in future AHK v2 releases?

Re: Object declaration syntax

Posted: 23 Jan 2018, 03:19
by lexikos
It is planned, but not necessarily for v2.0.

Re: Object declaration syntax  Topic is solved

Posted: 23 Jan 2018, 17:07
by lexikos
v2.0-a085-996f0b5 supports natural line continuation (note that an opening (/[/{ must be on the first line).

Re: Object declaration syntax

Posted: 23 Jan 2018, 17:54
by buliasz
After last update this code won't compile:

Code: Select all

class MyClass {
	__New(paramA, paramB) {
	}
}
It shows error: "Error: Not a valid method, class or property definition."
I need method called on new object creation. How can I do it now?

Re: Object declaration syntax

Posted: 24 Jan 2018, 05:37
by lexikos
Fixed in v2.0-a086.

Re: Object declaration syntax

Posted: 24 Jan 2018, 07:03
by buliasz
Thank you :)

Re: Object declaration syntax

Posted: 24 Jan 2018, 14:25
by Helgef
Hello

Code: Select all

multiLineArray :=
[
  "item1",
  "item2",
  "item3",
]
I would prefer it without the comma before and after the line break, eg,

Code: Select all

multiLineArray :=
[
  "item1"
  "item2"
  "item3"
]

:offtopic:
Continuation by enclosure:
Interesting :wave:.
I expected this to work,

Code: Select all

var := true	? 	(
				msgbox(1),
				1
			 	)
			: 	(
				msgbox(2),
				2
				)
Spoiler

I wouldn't expect the msgbox in

Code: Select all

var :=	(
		"hello
		world"
		)
msgbox instr(var, A_Space)
to say 6 (there is no space in the script code between hello and world).

Cheers.

Re: Object declaration syntax

Posted: 24 Jan 2018, 23:01
by lexikos
Helgef wrote:I would prefer it without the comma before and after the line break, eg,
That would be new multi-line syntax, not merely line continuation/a new application of the current syntax. It is valid to have a single item or parameter span multiple lines.
I expected this to work
I have some changes in mind which will fix this.

On this topic, I consider making the continuation operators context-aware; i.e. so they only work with actual expressions, not directives, hotstrings or in quoted strings:

Code: Select all

x := "foo
  + bar"
I also consider allowing continuation operators at the end of the line (as for multiLineArray :=), but I'm not sure what issues there will be.
I wouldn't expect the msgbox in [...] to say 6
My intention was to prohibit multi-line strings in this context, but I forgot. The pre-processing code does not handle them correctly (that is, it does not balance the symbols correctly if you mix them with one-ended strings). There is also indentation, but it is not clear whether this is intended to be part of the string (which is one of the reasons I did not intend to allow it).
there is no space in the script code between hello and world
There is a newline (which is converted to a space). If the pre-processing code joined the lines together with no delimiter, some common expressions would break.

Re: Object declaration syntax

Posted: 25 Jan 2018, 03:57
by Helgef
It is valid to have a single item or parameter span multiple lines.
I had imagined that one would then use the usual way of doing line continuation, eg,

Code: Select all

a := 
[
	"item1"
	"item2"
	. "item2_continued"
	"item3"
]
I also consider allowing continuation operators at the end of the line (as for multiLineArray :=)
:thumbup:

Cheers

Re: Object declaration syntax

Posted: 27 Jan 2018, 21:23
by lexikos
v2.0-a087 fixes a number of line continuation issues.

Re: Object declaration syntax

Posted: 28 Jan 2018, 15:43
by buliasz
In v2.0-a087 new bug appeared. It was not easy to reproduce, as it appears only in included files (#include file.ahk), and surprisingly it doesn't appear in the main runned .ahk file.
Here is example code, which will result with an error on script start-up, with the message: "Error: Functions cannot contain functions."
main_file.ahk source:

Code: Select all

#include _included_file.ahk
_included_file.ahk source:

Code: Select all

Test1() {
	if (1 > 2) {
	} else{
		MsgBox "Bug"
	}
}

Test2() {
}
But if you'll try to run directly _included_file.ahk it will go without problems.

And another surprise: if you insert lacking space after the "else" keyword, the script will work correctly. It seems that internal AHK routine skips some of the source brackets in unclear conditions.

Ps. I really like these last changes with brackets. It was something I hoped for long time, that will be done.

Re: Object declaration syntax

Posted: 29 Jan 2018, 02:44
by lexikos
v2.0-a088 fixes else{, try{ and finally{.

Any inconsistency between #includes and the main file was coincidence caused by use of an uninitialized variable.

Your bug report and sample code made it very easy to locate the cause. Thanks.