Arc Forumnew | comments | leaders | submitlogin
Multiple assignment, a symbol for the list function, and {} for hash tables
4 points by Amferreira 5880 days ago | 13 comments
I know this is all syntactic sugar, but syntactic sugar for common stuff is nice.

Multiple assigment: (= (x y) (list 1 2))

And I think a symbol should be chosen for the list function. The reason being that we have 3 ways of defining a list at the moment: list, where all elements are evaluated, except for quoted ones. quote, where no element is evaluated. quasi-quote, where all elements are not evaluated unless preceded with a , or ,@

I can't think of a good reason not to give the list function a symbol as well. Not sure which symbol should be used.

If { and } aren't already being used, they could be used for hash tables. It would also allow hashtables to be printable in a way that can be read back in.

Something that should be researched is if having an array type is not a premature optimization. An array is basically a hashtable with number as keys. For speed, a hybrid array/hashtable could be used in the implementation, like in Lua. If people really want to define bounds for an array (to detect errors in code, for instance), there could be a function that prevents new keys from being assigned to a hashtable without destroying it/calling a function that allows new keys to be added.



4 points by fallintothis 5880 days ago | link

Multiple assigment: (= (x y) (list 1 2))

This, however, conflicts with regular assignment. It's ambiguous in that it's quite context-dependent. For instance:

  arc> (= y '(1 2 3))
  (1 2 3)
  arc> y
  (1 2 3)
  arc> (= (car y) (list 1 2)) ;we're accessing y, not assigning to car
  (1 2)
  arc> y
  ((1 2) 2 3)
  arc> ;but what of this?  x isn't a function, though
       ;the syntax is kind of inconsistent if used for both purposes
  (= (x y) (list 1 2))
  Error: "reference to undefined identifier: _x"
However, you can still do multiple assignment; just not destructuring assignment:

  arc> (= x 1 y 2)
  2
  arc> x
  1
  arc> y
  2
You could instead define, e.g.:

  (mac ds= (vars vals)
    `(set ,@(apply + nil (map list vars vals))))
Then:

  arc> (ds= (x y) (1 2))
  2
  arc> x
  1
  arc> y
  2
Which, confidentially, doesn't work for using literal lists in the 'vals position as you did, but that should still be doable. Could also use '= instead of 'set, if you still wanted to do something like:

  arc> (ds= (x y) ((list 1 2 3) (list 4 5 6)))
  (4 5 6)
  arc> x
  (1 2 3)
  arc> y
  (4 5 6)
  arc> (ds= ((car x) (cdr y)) ('a 2))
  2
  arc> x
  (a 2 3)
  arc> y
  (4 . 2)

I do like the idea of conceptually merging hash tables and arrays, or at least think it should be explored.

-----

3 points by Amferreira 5879 days ago | link

You are right, I had forgot about (= (car y) (list 1 2)).

-----

2 points by drcode 5880 days ago | link

The first idea, as previously mentioned, conflicts with destructuring. Plus, global variables shouldn't be assigned to much, anyway. Local variable assignment already handles this issue pretty well, with "let", "with" and "withs".

As for the second issue, lists are not a primitive type in Lisp: They are made out of cons cells. I think a "cons" symbol should take priority. Once we have that worked out and it proves useful a "list" symbol might make sense.

-----

2 points by almkglor 5880 days ago | link

As fallintothis mentioned, destructuring assignment conflicts, badly, with 'scar/scdr and 'sref assignment.

> Something that should be researched is if having an array type is not a premature optimization.

It is. Lua-like array+hashtable implementations should be standard stuff for dynamic languages already IMO.

-----

1 point by stefano 5880 days ago | link

I like the idea of using { and } for hash tables. But without taking {} (they could be useful in the future) we could use a syntax like #h(key val ...). E.g:

  #h(a 1 b 2)
instead of

  {a 1 b 2}

-----

4 points by drcode 5880 days ago | link

In my own view, the payoff here isn't really enough relative to

  (obj a 1 b 2)

-----

3 points by Amferreira 5880 days ago | link

Yes, but then you can't print hash tables in a way that is also readable, and unambiguous with a list. Right now: arc> (= codes (obj "Boston" 'bos "San Francisco" 'sfo "Paris" 'cdg)) #hash(("Boston" . bos) ("Paris" . cdg) ("San Francisco" . sfo))

Could be: arc> (= codes {("Boston" 'bos) ("San Francisco" 'sfo) ("Paris" 'cdg)} {("Boston" 'bos) ("San Francisco" 'sfo) ("Paris" 'cdg)}

If the () are required or not is up for discussion, keys/values could be positional like obj.

Note that printing (obj a 1 b 2) as (obj a 1 b 2) is ambiguous with printing the list '(obj a 1 b 2)

-----

2 points by drcode 5879 days ago | link

I think you have a good point here. I'll have to think about this line of thinking some more.

-----

2 points by almkglor 5879 days ago | link

Doesn't mzscheme already properly support:

   #hash((a . 1) (b . 2))

?

-----

2 points by absz 5878 days ago | link

Yes, but Arc (or at least Anarki) does not:

  arc> #hash((a . 1) (b . 2))
  Error: "Type: unknown type #f"
We can, however, read it in, but this doesn't work either, since it creates immutable hash tables:

  arc> (= h (read "#hash((a . 1) (b . 2))"))
  #hash((b . 2) (a . 1))
  arc> h!b
  2
  arc> (= h!b 3)
  Error: "hash-table-put!: expects type <mutable hash-table> as 1st argument,
  given: #hash((b . 2) (a . 1)); other arguments were: b 3"
Fixing these would probably be worthwhile.

-----

1 point by stefano 5879 days ago | link

You're right! I didn't know it.

-----

1 point by Darmani 5880 days ago | link

We actually already have destructuring, at least for function calls.

  arc>(let (a b) '(1 2)
        (prn a)
        (prn b))
  1
  2

-----

1 point by jrockway 5877 days ago | link

Multiple assigment: (= (x y) (list 1 2))

Does arc not have a destructuring bind?

-----