My tentacles have only found two decent hashtable-oriented languages: JavaScript >~1.5 and Io.
I'm not sure whether or not you'd find it "decent", but you might consider adding Lua to your list. It's small, relatively fast, and uses hashtables as its composite data structure. It also has some other neat stuff, like tail-calls and coroutines.
I will second the suggestion of Lua. Here's my raw beginner's introduction to Lua tables:
The basic structure is the hashtable. You can use any first-class value as a key (number, string, function, another table) and similarly any first-class value as a value. Creating a table is done with the table constructor "{ }" ('> ' is the repl prompt):
> a = { }
So now we have an empty table named 'a'. Let's say we wanted to have a table containing a list of colors - this is represented in Lua as a table with ascending integers as the keys. (Starting at 1, rather than 0, which is a bit unconventional)
If we use strings as keys, we start seeing some of the syntactical sugar Lua offers. Let's look at favorite foods:
faves = { bob = 'pizza', george = 'cake', mary = 'pie' }
Note that no quotation marks are needed around string keys. (Well, unless the key is a language keyword. That's a bit annoying, but is related to the single-pass compilation, which is valuable. { if = 'can't do it' } fails. { ["if"] = "can do it" } succeeds.)
We can use numeric indices along with string ones in the same table:
mixed = { 'a', 'b', 'c'; state = 'NC', city = 'Charlotte', county = 'Mecklenburg' }
If we want to access values from a table, we can use a subscript notation.
> print(a[1])
red
> print(faves['bob'])
pizza
Here's a winner though. If we want to subscript a string, we just use the dot notation.
> print(faves.mary)
pie
What happens if we subscript a nonexistent entry in a table?
> print(faves.james)
nil
No error is thrown, which is handy. Tables are defined as having the unique value nil as the value for all nonexisting keys. In fact, if you wanted to remove an entry from the table, you just set the key to nil:
faves.george = nil -- the cake is a lie! And the key 'george' is removed.
One nice thing about Lua tables is that they are extremely regular. There aren't special cases in their behavior. They're easy to construct, inspect, and manipulate. They are the fundamental data type of the language, and everything is done in terms of tables. Objects are created out of tables. Namespaces are tables. Modules are tables. Configuration files are tables. It's an extremely clean and convenient design.
In addition to the tables, you get first-class functions:
> function a() print 'hello' end
> a()
hello
Is syntax sugar for:
> a = function() print 'hello' end
> a()
hello
These syntax sweeteners we've seen work together, too:
> function a.foo() print 'world' end
> print(a["foo"])
function: 0x807f2e8
> a.foo()
world
Ok, we're almost to objects. The next sugar we see is the ':' notation.
> a = { color = blue }
> function a:fave_color()
> print('My favorite color is ' .. self.color) -- .. is concatenation
> end
If a function is defined with the ':' notation then it has an implicit local value called 'self' which is set to the containing table.
> a:fave_color()
My favorite color is blue
At this point it's pretty easy to create simple prototype-based objects.
What brings even more power to the table is that we can define custom behavior on each one. We can set a 'metatable' which defines how the table responds to subscripting, the various mathematical operators, and being called in the functional position. In a quick script I worked on I implemented a prototype-based class system in under 20 lines of code, all with the power of metatables.
Lua tables are very powerful and though similar to the ones in Javascript are even cleaner and more pleasant to work with.
Anyway, it's all nifty stuff. Other features you get: fast incremental garbage collection, first-class functions, asymmetric coroutines (isomorphic to one-shot continuations), lexical scoping, closures. Lua is also one of the fastest interpreted languages and has an excellent API for binding to C if you want to do something performance sensitive, or want to use a library written in C. The language itself is written in 100% pure ANSI C. It runs on everything from embedded microprocessors to mainframes, in lego robots and on space satellites. And the community is very friendly.
If you want macros, there are several community-run variants of the language with macro facilities... I haven't gotten very deep into those though.
Good documentation for getting started:
http://www.lua.org -- official lua home page
http://www.lua-users.org -- lua community wiki
http://www.lua.org/docs.html -- lua documentation
http://www.lua.org/manual/5.1/ -- lua language reference
http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/hopl.pdf -- a fascinating article on the history and features of lua
Check Lua out and see how you like it. I find it to be a very pleasant language which is fun to work in.
I'm not sure whether or not you'd find it "decent", but you might consider adding Lua to your list. It's small, relatively fast, and uses hashtables as its composite data structure. It also has some other neat stuff, like tail-calls and coroutines.