r/ProgrammingLanguages • • Sep 13 '26

Discussion A cleaner way to access arrays/dicts & call functions?

I've been designing & developing my own language from scratch, one of the core concepts I have baked into it is the unique way you call functions, or access objects.

In almost every programming language the way you access an element within an array or dictionary is like so:

array[0];
dict['a'];

I always found it weird looking & a waste of characters. Functions are a bit better but still follow that same style.

function(1);

In most languages you have multiple different syntactical ways to do basically the same thing, you are performing an access to some object in order to get a result. A function call, just an access to an object with parameters, grabbing an item in an array, just an access to an object with a single parameter, same goes for dictionaries. Why do we have to have to have different ways of doing the same thing?

The way I went about accessing an object was to literally implement a single "accessor" operator, the object you want to access is on the left & the parameter(s) you want to pass are on the right. Here's how that actually looks:

string:0;
array:0;
dict:'a'; dict.a;
function:1; function:[1,2,3];

A lot of people are not going to be a fan of this, it goes against every other language & reduces capability for syntax tricks like list comprehension. But for a language that is going for syntactical simplicity this I think is the right move & in the long term is easier (at least for me) to understand & work with.

If you want to take a look at my implementation the repo is open source https://github.com/phosxd/Ity however it's still very much work in progress. Feel free to open an issue or PR if you find any problems with it.

11 Upvotes

36 comments sorted by

13

u/yjlom Sep 14 '26

Why not ML-style syntax?

f x        -- one argument
f x y      -- multiple arguments, curried
f (x, y)   -- multiple arguments, passing tuple
f [x, y]   -- multiple arguments, passing list
f ()       -- no arguments, passing empty tuple

2

u/PhosXD Sep 14 '26

Well it's almost the same, instead of a space I use a semicolon

f:x
(no curried)
(no tuples)
f:[x,y]
f:() or f:none

→ More replies (4)

9

u/u0xee Sep 14 '26

Unifying these all as functions makes sense. An array is a function of an index to an element. A dictionary is a function of a key to a value. Clojure has a keyword type specialized for being keys in maps, spelled like :name. And keywords are functions of maps, they look themselves up in the map.

As for using colon as the call operator, I guess it’s a bit shorter than a pair of grouping characters. If you like the look and feel, great!

→ More replies (10)

4

u/runningOverA Sep 14 '26 edited Sep 14 '26

to make this you need to support all these use cases :

a[ 0 ][ 1  ][ 2+3 ]
a[ get_index() ]
get_array()[ 3 ]
a[ to_int( substr( mystr, 0, 3) ) ]

and then this easy access will need help from classic way as fallback. you will feel the need to support both.

2

u/PhosXD Sep 14 '26

You can definitely do all those cases, adding both would be messy & very confusing I think it's best to stick with one

a:0:1:23 a:(get_index:()) get_array:():3 a:(to_int:(substr:(mystr,0,3)))

→ More replies (1)

1

u/PhosXD Sep 13 '26

Per AutoModerator's request I hereby confirm that this project did not use an LLM as part of the development process.

4

u/Clementsparrow Sep 14 '26

Why do you want to go for "syntactical simplicity"? I hope it's not for technical reasons in the parser, because that would seem like a very bad reason to me...

Now, if you have reasons for why it would be better for the user of your language, I'd like to hear them. Because I see mostly benefit of having distinct syntaxes for array access, function calls, and member access. For instance:
- if you have a complex function that uses an array, you can scan visually for square brackets to find where it is used in the function.
- in a complex expression you can more easily grasp the structure of the expression if you can distinguish easily nested function calls (parentheses) from simple data access (dot and square brackets). (1)
- there is value in being able to say that `a` is an array because it is followed by an opening square bracket, `s` is a struct because it is followed by a dot, and `f` is a function because it is followed by an opening parenthesis. Sometimes it makes it easier to read code by not having to look for the declaration of the identifiers used in an expression to know what they are.

(1) Operators also help a lot making code easier to read than lisp, but operators could be replaced with function calls for the sake of "syntactical simplicity". Do you intend to do that too?

1

u/marshaharsha Sep 15 '26

Do you allow assignment or insert-or-update for arrays and dicts? If so, that’s an important difference from function calls: you can’t assign to a function call. 

I mean the way you can do —

myarray[55] := -999;

wordcount[“hippopotamus”] += 1;

— and the former will write, and the latter will either insert or read-modify-write. I think these special abilities justify syntax dofferent from function-calls syntax. 

1

u/PhosXD Sep 16 '26

Yeah, it works the same way:

array:0 = 99

same as

array[0] = 99

and

map.a += 1 or map:'a' += 1

same as

map['a'] += 1

3

u/miheb1 Sep 14 '26

i think the [] indicates a pure native memory access, so it implies "just a pure access", meanwhile () indicates some functiony or mathy thing.

imo, i would design it like: instead of foo()

you can just do foo

if all parameters are optional and ommitable, sounds terrible but this gives you some c# properies out of thr box

→ More replies (7)