Map literals in ASH (potential feature)

heeheehee

Developer
Staff member
EDIT: The syntax I decided to go with (arbitrarily) looks something like value[key] { key_expr : value_expr[, ...] };. Patch attached to this post. Note that said syntax can be swapped out fairly easily.

I'm considering playing around some more with ASH's internals in my spare time, and I wanted to know a) how many people want this feature, and b) what the desired syntax is.

Examples of existing styles:

JSON
Code:
{ "key1":"value1",
  "key2":"value2" }

Perl/Ruby (and more, I'm sure)
Code:
{ 'key1' => 'value1',
  'key2' => 'value2' }

C# (well, okay, this barely counts):
Code:
new Dictionary<string, string>
{
    { "key1", "value1" }, 
    { "key2", "value2" }
};

Lua:
Code:
{ key1="value1", key2="value2" }

Python named tuples:
Code:
{ key1="value1", key2="value2" )

Granted, we don't have to look at existing implementations in current languages. We could do something totally crazy like <Key1|Val1; Key2|Val2>, but that'd probably confuse everyone involved, since that'd add new meanings to four (!) pre-existing symbols.

Thoughts?
 

Attachments

  • mapliterals.patch
    4.2 KB · Views: 44
Last edited:

jasonharper

Developer
Most of those examples are from dynamically-typed languages; they're completely unsuitable for a language like ASH that requires every expression to have a definite type at compile time. (And if you want to suggest deriving the type from the types of the supplied keys and values, keep in mind that the literal still has to have a defined type even if it contains zero key/value pairs.)

The most ASHy way of doing this would obviously be:
Code:
typedef string[string] strmap;
strmap myMap = $strmap[key1, value1, key2, value2];
 

heeheehee

Developer
Staff member
Eh. There are potential problems with the JSON syntax, since you'd need to establish the type somehow -- the key point that Jason was making was this: suppose you have a polymorphic function, and you pass in as an argument a map literal. Which form of the function gets called?

I'm not a huge fan of Jason's proposal, since it seems awkward to use the same syntax that's used for plural typed constants for a subtly different use case..

Also, for arrays, we technically have the plural typed constants, which _are_ implemented internally as ArrayLists and preserve iteration order (you can even include a string multiple times), so that's basically moot.

Currently pondering something where you declare the type up front, like
Code:
string [string] { "key1" : "value", variable_key: variable_value };
But that's definitely not very ASHy (I've also toyed around with the idea of anonymous functions in this form). I do like the ability here to specify arbitrary expressions (esp. since the comma is unused in ASH outside of lists), but that's also not at all ASHy.

Language extension is difficult to do well.
 

heeheehee

Developer
Staff member
Blarg, it's far too late for me to be up. Anyways. Patch attached with syntax proposed in my most recent post -- one possible improvement (off the top of my head) would be to get ASH to recognize that an expression can end with a closing brace (instead of the hack where I changed currentToken() to not return null).

Currently only works with map literals, but meh. Array literals are of questionable utility (plural typed constants preserve iteration order -- in fact, internally they're implemented as ArrayLists), and record constructors already exist.

If this patch is found to be acceptable, I might start working on function references (which is really just a more convenient way to use call) or perhaps adding null to ASH (... which would break existing scripts if I'm not careful).
 

Attachments

  • mapliterals.patch
    2.7 KB · Views: 38
Last edited:

heeheehee

Developer
Staff member
The patch is not attached, which I guess just confirms the first part of your message.

Yeah, I realized this as I was about to fall asleep, then decided that sleeping was more useful at the time. Edited it in.

edit: Sample usage:
Code:
> ash item[int, int] map = item[int, int] {4: item[int] {4: $item[eyepatch]} };

Returned: aggregate item [int, int]
4 => aggregate item [int]
  4 => eyepatch
 
Last edited:

heeheehee

Developer
Staff member
Been experimenting a bit more with said patch (attached in post #7) a bit more, and it, uh, breaks some existing scripts -- evidently it is currently valid in ASH to use a type as a variable name. I'd personally be in favor of changing this behavior, but I'm not in charge of making decisions around here. :)
 

Veracity

Developer
Staff member
You can have a float called int? That'll never be confusing :)
Nope. Internal types are reserved keywords.

Yeah, internal types and functions should have been reserved keywords.
You didn't try it out before making this statement, did you? Pity.

Function names, built-in or user-defined, are not reserved keywords, since there is no ambiguity in a name used as a variable and a name used as a function.

I assume that user defined types - typedefs and record names - are not precluded from being variable or function names. By analogy with the built-in types, presumably they should be.
 

heeheehee

Developer
Staff member
Evidently "item" and "effect" were not reserved. At least, one of the scripts I was using had those as variable names. That was the entire basis of my statement; I apologize for not making that more evident.

edit: rather, this happens when it's the key of a foreach loop? I'm not entirely sure what the triggers are.

Edit: demonstrated via the following:
Code:
 > ash boolean[int] a = $ints[1,2,3]; foreach item in a { print(item);}
1
2
3
Returned: void

Might have a patch up soon. For now, I'll file a bug report (perhaps with patch when/if I write one).
 
Last edited:

Veracity

Developer
Staff member
Code:
		reservedWords.add( "item" );
		...
		reservedWords.add( "effect" );
So, perhaps the bug is that foreach is not enforcing that.

Edit: Yes. Revision 11386 fixes that.
 
Last edited:

Bale

Minion
Well, of course it was always intended to be a bug. I was always careful not to use keywords. foreach ty,in,rec in factors is obviously dumb since he's using "in" as a keyword and a variable in the same statement. Though knowing zarqon, he might have done that on purpose just to get away with it. He and good programming practice enjoy waving to each other as they pass in opposite directions.
 

zarqon

Well-known member
That was an oversight, not me being idiosyncratic. :) I was just abbreviating the words "type", "int", and "record", since using their full forms as key variables would -- obviously -- be stupid.
 
Top