2013/4/4 Taylan Ulrich B. <taylanbayirli@gmail.com>
Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> - firstly, guile's hash tables are maps, not dictionaries, so they are
> insensitive to order. This behaviour is desired if we want to use them
> to represent sets or maps; however, PHP arrays, and -- as I presume --
> JavaScript objects -- store the information about the order of their
> elements. Lisp-style sollution would be to store them as assoc lists,
> which in turn have linear access time.

From json.org (which is official):
"An object is an unordered set of name/value pairs."

(Object means dictionary/map in JSON terminology.)

I think this is consistent with common expectations from a dictionary
data structure.  At least in my experience.  Should the ordering be
important, a supplementary key-vector (or list) could be used easily
enough in my opinion; bundling that functionality into hash-tables is
probably not worth it unless it is trivial to implement.

Well, I see why the representation based on hash tables is adequate for JSON. There are, however, situations, when one wants to have an ordered set, and it's good to have choice. Clojure, for instance, offers such choice, and from the perspective of a programmer it's better to have a choice.
 
> - secondly, there is no default notation to create hash tables nor
> sets; using them forces
> a programmer to drop homoiconicity, as their default print
> representation is #<hash-table 1c8a940 1/31> or something even uglier.
> I think that this is done properly in Clojure.

That is not what homoiconicity means.  There are more data types that
lack a proper external representation; most notably procedures.  For
transmission of data, converting to an alist and back is probably good
enough; this can also be used as a "hack" for having "literal"
dictionaries in code: (alist->dictionary '(...))

Of course it can. However it's not convenient. I use emacs+geiser and when I want to see the content of a variable -- if it's a list or some other basic type -- I just point a cursor on it and I get the value in a minibuffer. When I want to see the content of hash-table, I need to explicitly evaluate (hash-map->list cons my-hash-table), which seems unnecessary When a hash-table is nested, it turns into a nightmare. If there was a more reader-friendly representation of hashes, it would be far more convenient. I could come up with some representation myself, and use it in my programs, but I guess that this problem is more serious and requires more attention.

All in all, you don't write vector->list and list->vector to get a nice printable representation of vectors -- there was an issue, and it has been solved. Racket has its printable representation of hashes, which is much nicer than the one of guile (although still not perfect).

So again, this is probably nothing that needs be implemented urgently.
 
Judging by the speed at which subsequent Reports on algorithmic language Scheme are released, schemers don't seem know the word "urgent" :) Which is good.
However, I think it is an important matter. I also think that it is no good for scheme implementations to diverge from one another, if there is no good reason for that.
 
Note that easy-to-use hash tables are what win the market for PHP, despite many drawbacks of that language.

> - thirdly, refering to hashes (as well as assoc lists, goops' object
> slots, vector/array elements) is truly cumbersome. I once wrote a
> hash-read-extension that allowed to refer to hashes/arrays/slots...
> using uniform notation #[object key], and to allow for nested
> references like #[ ... #[#[object key1] key2 ] ... ] using simpified
> notation #[object : key1 : key2 : ... ]. The implementation is rather
> inefficient when it comes to performance, but makes coding much more
> efficient, and it can be found here, if anyone's interested:
> https://bitbucket.org/panicz/slayer/src/33cf0116da95dea6928ab1011994569b5a5181ad/extra/ref.
> scm?at=goose-3d
> One could ask: why can't vectors, arrays, objects and hashes simply be
> applicable? (Of course, it is possible to implement applicable
> collections even now, but at a cost of loosing their print
> representation)

SRFI-105 is probably the preferable solution to this problem, since it's
an SRFI.  Guile already supports it, but I don't know how many accessors
are built-in; it should be trivial to implement any you want though.

I know of no other implementation of Scheme than Guile which supports SRFI-105. And I guess that the implementators will remain reluctant with regard to it, as it introduces more randomness to the way the code can be written.
On the other hand, what are the argumets against making hash-tables, vectors et al. applicable, assuming that "programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary"?

> - lastly, guile's support for hash tables is limited -- there ain't
> even a built-in function that would return the size of a hash-table.
> My implementation is inefficient (linear time), and it looks like
> this:
> (define (hash-size hash-map)
> (length (hash-values hash-map)))

I don't know how exactly hash-tables are implemented in Guile, but one
probably needs to walk through the whole structure to count the size;
then the most efficient simple implementation of `hash-size' is one
which walks through it only once:

(hash-fold (lambda (key value size) (1+ size)) 0 hash-table)

Other than that, the size could be kept in the internal representation
of the hash-table, but I'm not sure of the pay-offs.

Plainly, the size is kept in the internal representation of the hash table:

typedef struct scm_t_hashtable {
unsigned long n_items;        /* number of items in table */
...

cf. http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=libguile/hashtab.h;h=82ed22e66eb1f5045793cfc55cca0be040d4aab1;hb=HEAD#l66

It would be really cheap&easy to get it from there. I just wanted to show that hash-tables are neglected in Scheme in general, and in Guile in particular.

Best regards!
M.