Page 1 of 4

Map shorthand

Posted: 18 Aug 2019, 09:41
by kczx3
Any consideration to implementing a shorthand for initializing a Map?

You could borrow syntax from PHP maybe.

Code: Select all

myMap := [
    "name" => "Tedd",
    "age" => 34
]

Re: Map shorthand

Posted: 18 Aug 2019, 11:09
by Helgef
Hi.
Perhaps something like {name, "Tedd", age, 37} or [name : "Tedd", age : 37]. I think map() is pretty short though.

Cheers.

Re: Map shorthand

Posted: 18 Aug 2019, 12:14
by kczx3
Agreed, though I definitely prefer the literal notation. I like your second suggestion best actually. Since objects and arrays are unique now, I think that would work.

Re: Map shorthand

Posted: 18 Aug 2019, 18:03
by swagfag
something visually distinguishing is needed to tie keys to values and separate pairs from one another, thats for sure

Code: Select all

myMap := [
    "name" => "Tedd",
    "age" => 34
]
i dont think this could work

Code: Select all

myMap := [
    name => "Tedd"
]
did i define a Map with 1 key(the value of name) paired to "Tedd" or did i define an Array with a one argument lambda returning "Tedd"?

Re: Map shorthand

Posted: 18 Aug 2019, 18:55
by kczx3
Good point

Re: Map shorthand

Posted: 18 Aug 2019, 23:49
by jeeswg
For readability and avoiding pressing " too many times:

Code: Select all

oMap := StrSplitMap("key1,value1,key2,value2,key3,value3", ",")
oMap := StrSplitMap("1,1,2,2,3,3", ",")
oMap := StrSplitMap("1.0,1.0,2.0,2.0,3.0,3.0", ",")
vOutput := ""
for vKey, vValue in oMap
	vOutput .= vKey " " vValue " " Type(vKey) " " Type(vValue) "`r`n"
Clipboard := vOutput
MsgBox(vOutput)
return

;StrSplitToMap
StrSplitMap(oParams*)
{
	oArray := StrSplit(oParams*)
	for vKey, vValue in oArray
	{
		if (vValue is "Integer")
			oArray[vKey] := Integer(vValue)
		else if (vValue is "Float") && !(A_Index & 1)
			oArray[vKey] := Float(vValue)
	}
	return Map(oArray*)
}

;StrSplitToMapSimple
StrSplitMapSimple(oParams*)
{
	return Map(StrSplit(oParams*)*)
}

Re: Map shorthand

Posted: 19 Aug 2019, 03:30
by lexikos
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.

["a" => "b"] becomes longer than Map("a", "b") once you write more than three key-value pairs, or sooner if you use spaces around the delimiter.

In my opinion, the main advantage of dedicated syntax (comparing the original Object() to {}) is the visual pairing. We are already using : for this purpose, so it seems like the logical choice. It is also reminiscent of assignment. 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.

Re: Map shorthand

Posted: 19 Aug 2019, 07:04
by kczx3
I see. So same as object literals except for using square brackets. I think that'd look nice.

Re: Map shorthand

Posted: 20 Aug 2019, 06:37
by swagfag
what about taking {} away from Object and giving it to Map.

Code: Select all

myMap := {
    name: "Tedd",
    age: 34
}
or quoted, optionally

if u want variables:

Code: Select all

myMap := {
    (name): "Tedd",
    (age): 34
}
if u want to make objects, use the Object(params*) constructor
i imagine, more often than not ud want to use maps. but how often would u need to make objects? and wouldnt the preferred best practice in this case be to declare a class, rather than cobbling props and methods together

Re: Map shorthand

Posted: 20 Aug 2019, 07:32
by kczx3
Valid point. Most people are going to use Map now instead of Object. And the class syntax is much more intuitive to me.

Re: Map shorthand

Posted: 20 Aug 2019, 08:15
by Helgef
I'm not sure about that, I'd rather see extended shorthand syntax for objects to allow method definitions, eg { m() => expr, prop : val }. Perhaps with local classes, {} would see much less use as shorthand objects.

Cheers.

Re: Map shorthand

Posted: 20 Aug 2019, 08:36
by kczx3
Helgef wrote:
20 Aug 2019, 08:15
Perhaps with local classes, {} would see much less use as shorthand objects.
Forgot about that.

Re: Map shorthand

Posted: 20 Aug 2019, 10:04
by nnnik
Regardless in the end having an expression as key is inevitable.

Code: Select all

myMap := {
    name: "Tedd",
    age: 34
}
^ this syntax conceals the fact that keys can be any kind of expression/value.
A map that is intended to map value a to value as a general purpose dictionary should not have some sort of bias towards strings.
I thought you disliked the command syntax swagfag. Or is the usage of () over %% enough to conceal the fact that we are essentially continuing the legacy of legacy syntax in v2 with this shorthand?
We will end up with all sorts of strange situations and many problems where some keys cannot be used because they resemble an expression too much or have to be escaped with ` or similar again.
I feel that we should free ourselves as much as possible from that weight in v2:

Code: Select all

arr := {("(key)"):value} ;marvelous :)
arr := {%"%key%"%} ;even better :D
I think in the end

Code: Select all

obj := object()
would be enough of a shorthand to create a new object. (unless I missed something and that got removed)
We will also have a highly similar notation to JSON which would make the transition for many people from the developer scene a lot easier.
Just my 2 cents.

Cheers

Re: Map shorthand

Posted: 20 Aug 2019, 10:21
by swagfag
no, not at all. which is why i bothered enough to add:
swagfag wrote:
20 Aug 2019, 06:37
or quoted, optionally

Re: Map shorthand

Posted: 20 Aug 2019, 10:25
by nnnik
swagfag wrote:
20 Aug 2019, 10:21
no, not at all. which is why i bothered enough to add:
swagfag wrote:
20 Aug 2019, 06:37
or quoted, optionally
:oops:

Re: Map shorthand

Posted: 21 Aug 2019, 03:52
by lexikos
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.
lexikos wrote: {a: b, c: d} is most often used to create ad-hoc objects with known properties, so these should be properties.
...
Associative arrays most often start out empty, so new syntax for an "associative array literal" seems unnecessary. The primary advantage of {x: y} is that the property names do not need to be quoted - this is consistent with obj.x and not with obj["x"]. On the other hand, the current rules also allow {"x": y} and any other expression which isn't a plain variable. Perhaps properties can require a literal_identifier: or %variable_identifier%: while array elements require [index]:.

https://github.com/Lexikos/Object.ahk

Re: Map shorthand

Posted: 21 Aug 2019, 05:57
by nnnik
I never create objects ad-hoc with known properties.
I use objects mostly for lookup tables - which sometimes contain objects as key.
From what I understood from this topic a few users dont use {} for quick anonymous creation either.
Simply put I define all my classes explicitly.
Defining an object with {} that contains methods is awkward and using actual property syntax is not possible afaics.
On the other hand the {} syntax is qualified to quickly create a map with initialized data.

Could you please reconsider?

Re: Map shorthand

Posted: 21 Aug 2019, 10:10
by swagfag
not claiming to have a firm grasp on this prototypal inheritance thing, but i wouldnt normally create ad-hoc objects either. whats the point, really? the only reason i can think of, is if u needed an object and not leak it to users by confining it to a given scope. but if that were the case, whats the point of having the shorthand syntax? if u only needed it for its properties, to use it as a faux-map, u could have just used a Map instead. if u wanted to use it as a class, then ud have to additionally .DefineProp() and .DefineMethod() a bunch of times, which kinda defeats the point of the shorthand syntax imo.

if u take {} away, then defining such a thing becomes somewhat verbose, ex:

Code: Select all

adHoc := Object('dumbProp', 'plainString')
adHoc.DefineProp('smartProp', Object('get', this => "Today's date is " FormatTime(A_Now, 'MM/dd/yyyy'), 
									 'set', (this, value) => MsgBox('Immutable property')))
adHoc.DefineMethod('printProps', Func('printProps'))
printProps(this) {
	for name, value in this.OwnProps()
		MsgBox name ": " value
}
versus

Code: Select all

adHoc := {dumbProp: 'plainString'}
adHoc.DefineProp('smartProp', {get: this => "Today's date is " FormatTime(A_Now, 'MM/dd/yyyy'), 
							   set: (this, value) => MsgBox('Immutable property')})
adHoc.DefineMethod('printProps', Func('printProps'))
printProps(this) {
	for name, value in this.OwnProps()
		MsgBox name ": " value
}

Re: Map shorthand

Posted: 21 Aug 2019, 10:30
by kczx3
Apparently I started something here.

I want to make it clear that my intention was not to say that I'm not happy with the recent changes. They are an awesome addition to the language and I very much look forward to using them.

My thinking is along the lines of nnnik I believe. I don't think that anyone really creates an ad-hoc object using {} where they define methods and whatnot for it to then be instantiated using new. Most often they are just to create dictionaries, and in my case, usually small ones with only a few keys.

If I really want an object to have more than very limited functionality, I would define a class and I think having an explicit/verbose syntax for that is warranted.

Re: Map shorthand

Posted: 21 Aug 2019, 11:16
by swagfag
i doubt its anybody's intention to rip on the update. its a dope af update, after all. we're just talking

and just now ive figured that if u were to give {} to Map, u could have .DefineProp() accept a map instead: adHoc.DefineProp('smartProp', {'get': theGetterFunc, 'set': theSetterFunc}), so the only difference to how it is currently are the quotes.

that still leaves us with "what to do about adHoc := Object('dumbProp', 'plainString')?" - u could have a .DefineProp(MapOfDumbProps) single-arg overload that accepts a map for setting "plain" properties

Code: Select all

adHoc := Object()
adHoc.DefineProp({'dumbProp': 'plainString'})