Map shorthand

Discuss the future of the AutoHotkey language
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Map shorthand

23 Aug 2019, 18:26

- I suppose it boils down to: should {} be used for properties or keys. I'm neutral.
- lexikos gave good reasons for it being properties; and converting old scripts to use Map() instead of {} has been pretty easy.
- My one query would be, when doing JSON definitions in other languages, is that typically to create properties, or to create keys? (Although even if it is keys, properties for {} still might be OK/better.)
JSON Example
https://json.org/example.html
- Another consideration would be some mode where keys and properties are equivalent, to replicate partially or fully the AHK v1 behaviour. I.e. you define the object, and then use a one-liner to apply the mode.
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: Map shorthand

23 Aug 2019, 21:32

Code: Select all

return {x: left, y: top, w: right-left, h: bottom-top}
This is an ad-hoc object. There is no good reason to use a Map for this. There are good reasons not to: semantics (these are properties, not array elements), case-sensitivity and access syntax (which reflects semantics).
nnnik wrote:I never create objects ad-hoc with known properties.
I don't believe it, but putting that aside;

Do you regularly create associative arrays and need to populate them with a fixed list of key-value pairs at the point of creation?

If I know that a given key or name will be used and it needs an initial value when the object is created, there is probably always something setting it apart from every other key-value pair. In other words, it's a property or attribute of the collection, not an item within the collection. There are bound to be exceptions, but for those we don't need shorthand syntax.

The main purpose of separating array elements from properties is to prevent the kind of conflicts that occur when keys are not known in advance, such as words like "delete", "count" or "base" coming from a document (or script) or other external source.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Map shorthand

24 Aug 2019, 22:32

I mostly create classes for stuff like that.
I really mainly use the shorthand syntax for lookup tables
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Map shorthand

24 Aug 2019, 23:02

- I agree with both of those sentences.
- In my newly converted main scripts/libs:
- Every time I use Map, it's for a blank map, or a lookup table.
- The half-dozen times I use {} to create an object, the object is empty initially, and I add in the properties one by one. Only twice did I create a one-line ad-hoc object, but separating the property assignments, might be better:

Code: Select all

oTL := {x:(vIndexX<0)?0:vIndexX,y:(vIndexY<0)?0:vIndexY}
oBR := {x:(vIndexX>vImgW)?vImgW:vIndexX,y:(vIndexY>vImgH)?vImgH:vIndexY}

oTL := {}
oTL.x := (vIndexX<0) ? 0 : vIndexX
oTL.y := (vIndexY<0) ? 0 : vIndexY
oBR := {}
oBR.x := (vIndexX>vImgW) ? vImgW : vIndexX
oBR.y := (vIndexY>vImgH) ? vImgH : vIndexY
- For classes, I usually use class definitions, only twice did I create a class as an ad-hoc object, in order to change the array's/map's default value:

Code: Select all

;AHK v1 only:
oMap := {base:{__Get:Func("Abs").Bind(0)}}
oArray := {base:{__Get:Func("Abs").Bind(0)}}
- I wouldn't find it confusing if 'key' in {key:value} didn't use quotes cf. 'key' in obj["key"] := value.
- So on that basis, {} would be more useful as an alias for Map() than for Object().
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Map shorthand

25 Aug 2019, 03:12

ok, so what i gather from this is use Map when:
  • u care about key case-sensitivity
  • u want objects as keys
  • u need a key called base
in any other case continue using objects, business as usual
i was under the impression that Map was meant to supersede this very usage, and Object()'s purpose would then be solely to act as a base to inherit from/attach properties AND methods to
but i guess not
Last edited by swagfag on 29 Oct 2019, 07:34, edited 1 time in total.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Map shorthand

19 Oct 2019, 20:20

fincs wrote:
19 Oct 2019, 17:44
[...] I still think that { ... } not yielding anything other than a Map is misleading, since this is JSON-like syntax (and amusingly, JSON mandates quoted strings for keys which reinforces this view). If any of the Map shorthand proposals goes through, we would have three literal object syntaxes: one for arrays, one for maps and one for object. While I don't necessarily disagree here with the current design and I do think it makes sense to have a flexible type that provides the backbone for properties (and methods); I suspect maps vs objects might be a superficial source of confusion for inexperienced users (the fact that they have different syntax definitely helps though). We might see some users compelled to abuse objects as if they were a different way to achieve the same end result provided by maps.
I agree that anyone familiar with JSON could be confused, but I use object literals far more often than I would use non-empty map literals. {} is almost always used with literal names, which make no sense for a map. I am willing to consider suggestions for alternative syntax (for objects and maps).

On the other hand, JavaScript uses {} for objects, not maps, which don't really have first-class syntax support.

If any part of the syntax resembles JavaScript, JavaScript users (uneducated in the ways of AutoHotkey) are likely to be confused since objects do not work the same way.

As for "abusing" objects as maps, they'd have to use obj.%key%, which is not as obvious as obj[key]. Using an object to group a set of known attributes (properties) or related variables is not abuse. As I've explained before, (putting aside non-string keys) map is primarily for cases where keys are not known in advance and could conflict with properties.

If the keys are not known in advance, they are not going to be hard-coded. The syntax for accessing map elements is optimized for this, whereas the syntax for accessing properties is optimized for hard-coded names. Names in AutoHotkey are case-insensitive, therefore property names are case-insensitive. Map keys can be arbitrary (and normalizing case is easy), therefore map keys are case-sensitive. (However, I intend to add a case-insensitive mode or type.)

@swagfag
It doesn't seem like you read and/or understand my previous post.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Map shorthand

20 Oct 2019, 13:24

@lexikos u are mistaken on both counts

having gone through all my production scripts i can safely conclude that the only reason why ud ever want to use a Map is if u needed the keys to be case-sensitive. The other far unlikelier reason is if u had a key called "base". The fact that u can also have properties about the collection isnt reason enough(without too much effort u can also separate a bunch of properties about an object from the rest of the used-to-be-properties-but-have-now-become-keys)

only on one occasion did i have to switch to a Map and in that case it was purely because of case-sensitivity - replacing an instance of scripting.dictionary

the remaining associative arrays ive left as objects. forloop iteration is a bit hamfisted, having to call .OwnProps() every time. so is lookup with .%var%, but anyway i can probably live with that

i guess Maps arent gonna see as much usage as once originally thought, at least not enough to warrant introducing special syntax
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Map shorthand

21 Oct 2019, 00:55

You could also just use maps everytime and not have to worry if you coincidentially hit one of the magic object names.
Recommends AHK Studio
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Map shorthand

21 Oct 2019, 02:23

still an imperfect solution and one not without downsides, access now becomes more complicated/tiresome, u have to make sure the case matches or StrLower everything beforehand, pair semantics are lost on Map's constructor(i guess u can newline but meh)
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Map shorthand

21 Oct 2019, 04:03

You cannot know which words or strings might be used in every other script, or sometimes even your own. If "base", "__Item" or any custom property names are rarely used, that means that on rare occasions, scripts will misbehave. The example I gave was actually a real one that I have encountered multiple times.
such as words like "delete", "count" or "base" coming from a document (or script) or other external source.
If you were to misuse an object's properties to index the words in some object-based scripts, the documentation, this page, or an English dictionary, it is very likely that there will be a conflict.

I intend to add a case-insensitive type or mode soon, although it is trivial to implement a basic case-insensitive map using the case-sensitive map.

Code: Select all

m := MapI.new()
m["base"] := 10
MsgBox m["BASE"]

class MapI extends Map {
    __Item[key] {
        get => base.__Item[StrLower(key)]
        set => base.__Item[StrLower(key)] := value
    }
}
As I've probably said (in different ways) multiple times now, "pairing syntax" is only useful if you have pairs to set when you create the object. If you do, that's often because they are literally a set of related properties (or variables), like in your myMap example, where "name" and "age" are properties of a person.

The distinction to be made is whether you have a limited set of known names rather than a variable number of arbitrary keys, as I already said in different words.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Map shorthand

21 Oct 2019, 06:58

I just don't see why you would advise the usage of a feature that breaks under rare circumstances but supplies features that are used just as rarely over another feature of the language that works consistently.

It's like you want to make this language difficult on people.
Recommends AHK Studio
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Map shorthand

21 Oct 2019, 08:19

nnnik wrote:
21 Oct 2019, 06:58
I just don't see why you would advise the usage of a feature that breaks under rare circumstances but supplies features that are used just as rarely over another feature of the language that works consistently.
i'm confused as to what you are implying. from what i can tell, lexikos is arguing AGAINST the usage of a feature the breaks under rare circumstances (that feature being using Objects), and he is saying you should use a Map instead for these rare cases.

probably most of the time people would just be using regular objects since most normal usage would be to define properties of an object. i don't even know when or why i'd use a map. i can't think of a usage when i'm faced with an "variable number of arbitrary keynames" unless i'm trying to import a literal "dictionary" into a script

nnnik wrote:
21 Oct 2019, 06:58
It's like you want to make this language difficult on people.
i don't think that's what he wants, but that's how its trending, at least to me. but maybe i'm not as good of a programmer as you guys

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Map shorthand

27 Oct 2019, 11:59

i made a mistake earlier, u in fact can use other objects as keys in objects, so heres the revised "should i use a Map?" flowchart:
  • do u need case-sensitive keys? yes: use a Map, no: go next check
  • do u need a key called base? yes: use a Map, no: go next check
  • use an object
just read https://www.autohotkey.com/boards/viewtopic.php?p=289656#p289656
Last edited by swagfag on 29 Oct 2019, 07:35, edited 2 times in total.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Map shorthand

29 Oct 2019, 02:41

swagfag wrote:i made a mistake earlier
I think you made more than one mistake. :roll:

1. Maps have keys. Objects have property names.
2. Property names must be strings. If you use a number, it will be converted to a string. If you use an object, it is converted to an empty string, as per the v1 rule:
If an object is used in any context where an object is not expected, it is treated as an empty string.
However, that's a bug. It should throw an exception.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Map shorthand

29 Oct 2019, 07:38

damn it, i had only tested it with a single keys, leading me to believe the v1 behavior was retained(in reality, the objects were being converted to empty strings as u say). i shouldve stuck with my original post
well anyways, glad we could at least finally get to the bottom of this
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Map shorthand

30 Oct 2019, 01:46

Well I will present an alternative for everyone who just likes to keep it simple:
Need to associate keys with values? Use maps.
Recommends AHK Studio
buliasz
Posts: 26
Joined: 10 Oct 2016, 14:31
Contact:

Re: Map shorthand

31 Oct 2019, 19:29

In my opinion "key": "value" syntax is most readable one for maps (with colon in the middle), so I would use something like this:

Code: Select all

map := [
	"key1" : "value1",
	"key2" : "value2",
	...
]
Or this:

Code: Select all

map := Map() {
	"key1": "value1",
	"key2": "value2",
	...
}
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Map shorthand

01 Nov 2019, 05:45

@buliasz
lexikos wrote:
19 Aug 2019, 03:30
One problem is that [] creates an empty Array and {} creates an empty Object, so overloading based on whether there are key-value pairs vs. just values would not completely work.
The second case overlaps with function definitions. Function definition expressions, where full functions are defined and referenced within an expression, are not supported yet but are planned.


The use of : for pairing parameters of {} (which is just Object() in disguise) is trivial to extend to other functions, as in Map("key": "value") or DllCall("IsWindow", ptr: aHwnd), but it's a bit odd to have special syntax for specific functions. It also overlaps with potential support for named parameters in general, which could potentially be utilized by DllCall in the same manner, but maybe not Map, because...
lexikos wrote:
19 Aug 2019, 03:30
It is unlikely that any "shorthand" syntax I add for Map will allow quote marks to be omitted. Object notation allows it because they are "properties", and the usual syntax for accessing them does not use quote marks. (Now it makes more sense to require the quote marks to be omitted for properties.) Map, on the other hand, always requires quote marks around literal keys.
Named parameters

One new idea is to have a separate function calling syntax specifically for a list of pairs, where each item is merely a parameter, but must be specified in pairs. For example, Map{"key": "value"}.

An older idea...
myCol {Prop: 4, [1]: "first"} could be translated to (myCol.Prop := 4, myCol[1] := "first", myCol). That is, it could be shorthand for changing multiple properties/elements, and would naturally also work for Collection.new() {...}. However, it might be difficult to parse in cases like getObject() {Prop: "to set"} which look like function definitions.
Source: Object.ahk/Class.md at master · Lexikos/Object.ahk
A slight change to reduce ambiguity: myCol.{Prop: 4, [1]: "first"}. However, it would probably be clearer as myCol.{Prop := 4, [1] := "first"}. It could be extended to obj1.{prop, [index]} := obj2 to copy obj2.prop and obj2[index] to obj1. This is all theoretical and likely to complicated for the current parser.

Some other options I've considered:
  • {{ ... }}, which isn't otherwise valid (or ambiguous) because the outer {} has only one item.
  • #{ ... }, which has the (misleading) connotation that it is creating a "hash" (technically, hash table, which Map is currently not).
With something like Metalua, but for AutoHotkey, we could easily trial syntax ideas...

But I still think dedicated syntax for Map is unnecessary.

If you want to make a clear distinction between keys and values, you can always use a normal assignment.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Map shorthand

01 Nov 2019, 06:49

But I still think dedicated syntax for Map is unnecessary.
I agree. Especially if more maps, eg hash or case insensitive ones, are added in the future, any short hand syntax would either be very limited or perhaps not very short.
A slight change to reduce ambiguity: myCol.{Prop: 4, [1]: "first"}.
This is interesting, I like it better than the subsequent versions.

Cheers.
iseahound
Posts: 1434
Joined: 13 Aug 2016, 21:04
Contact:

Re: Map shorthand

22 Apr 2021, 19:14

Is there really no easy way to construct key: value pairs?

Code: Select all

MapObj.__New(Key, Value, Key2, Value2, ...)
:monkeysee:

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 37 guests