"I linked you to the reference, which is targeted at people who already generally know what's going on but need specific information. Here's a guide entry: http://docs.racket-lang.org/guide/define-struct.html "
Oh neat. I guess I was expecting documentation somewhat more like Python, where they're more likely to tell you that kinda stuff in the docs, rather than requiring you to go read the tutorial. :P That could come in handy, thanks.
---
"Racket structs are not the same as hash tables. For instance, they can have inheritance [...]"
Cough. Prototypes. Cough.
---
"[...] They're not especially orthogonal features, but structs are specifically for custom data types, while hash tables are for associations."
Except in Arubic you do use tables to make custom data types. :P Besides, that's not really the point. I'm not saying structs need to be implemented as hash tables, just that you could call them like as if they were hash tables. So rather than using (exn-message foo) you'd use (foo 'message).
Arc overloads function calling on tables, lists, strings, etc. So why couldn't they have done that with Racket? I guess one reason would be for type checking... Racket seems to be the kinda language where they prefer strong types. In which case, okay, I can't really argue against that, if that's Racket's goal. Still feels clunky to me.
Interestingly enough... the way things are going with Arubic, it looks like I'm essentially copying Lua. Lua puts a strong emphasis on tables, similar to how Lisps put a strong emphasis on lists. It also has prototypical inheritance. It also uses foo.x as syntax sugar for foo["x"], which is similar to Arc:
(foo 'x)
foo.'x
JavaScript also shares those properties with Lua, so I guess you could also say I'm copying JavaScript... but only the parts I like, which are primarily objects and prototypical inheritance (Arc already has lambdas and closures).
"Actually, I think that kind of let block is more consistent with the goals of Racket. It makes it easier for Racket to give detailed error messages when part of the let is missing."
How so? How does (let ((a 1) (b 2))) give more information than (let (a 1 b 2))?
Besides, I'm talking about the `let` in Scheme, so the whole "it makes sense in Racket!" thing doesn't really apply. :P How does it make sense in Scheme?
"I guess I was expecting documentation somewhat more like Python, where they're more likely to tell you that kinda stuff in the docs, rather than requiring you to go read the tutorial. :P"
It's not an organizational thing. Here's where they explain it the reference:
A struct form with n fields defines up to 4+2n names:
- [...]
- id-field-id, for each field; an accessor procedure that takes an instance of
the structure type and extracts the value for the corresponding field.
The reference even links to the guide, for what it's worth.
Depending on the context, the idea of a hash table with a prototype may be a contradiction in terms. For instance, if by "hash table" we refer to exactly the hash table implementation Racket has today, then it simply has no prototypes. :-p
There are contexts where it does make sense, particularly when talking about hypothetical languages, but if a single language tried to make sense of every idea people had for it, it'd be pretty darn bloated. ^_^
---
"I'm not saying structs need to be implemented as hash tables, just that you could call them like as if they were hash tables. So rather than using (exn-message foo) you'd use (foo 'message).
"Arc overloads function calling on tables, lists, strings, etc. So why couldn't they have done that with Racket?"
That page tries to demonstrate how Racket's 'syntax-parse and syntax classes make it possible to write macros with readable implementations and good, consistent error messages. The example it uses is a reimplementation of 'let.
In my own opinion, what that page actually demonstrates is how a misplaced emphasis on readable implementations (code-as-the-spec) can lead to more complexity and less readable code overall. :-p
But to be fair, for lots of people (especially people who are learning programming, a big target audience of Racket), the better error messages improve the maintenance experience much more than verbosity detracts from it. I occasionally ask random not-necessarily-programmer people what they want in a programming language, just to get some ideas, and the second most common response is "Better error messages." (The most common response is "How should I know?!" :-p )
---
"Besides, I'm talking about the `let` in Scheme, so the whole "it makes sense in Racket!" thing doesn't really apply. :P How does it make sense in Scheme?"
Beats me. :) IMO, Arc simply makes more sense than Scheme, and that's fine since Scheme came first.
"Depending on the context, the idea of a hash table with a prototype may be a contradiction in terms. For instance, if by "hash table" we refer to exactly the hash table implementation Racket has today, then it simply has no prototypes. :-p
There are contexts where it does make sense, particularly when talking about hypothetical languages, but if a single language tried to make sense of every idea people had for it, it'd be pretty darn bloated. ^_^"
How so? JavaScript and Lua both add prototypes to tables/objects. It's possible to implement it in Arc right now, it's just not possible to make them blend seamlessly into the language, which is one thing I plan to fix with Arubic.
A prototype isn't defined by it's implementation, it's defined by it's idea. You could define an alist or plist to be a prototype, or an AVL tree, or who knows what else. Heck, I was using functions to represent prototypes earlier. :P There are only two requirements for prototypes in my mind: message passing, and, when data is not found in the data structure, it will check it's parent rather than failing[1].
To put it another way, you can use delegation and message passing to implement the concept of prototypes. And since we're talking about Arubic here, I can implement prototypes with just about any compound data type. :P
So when I mentioned prototypes, I was referring to the fact that it is indeed possible to give inheritance to hash tables, and so although you're right that structs are not the same as hash tables (at least in Racket), I'm pointing out that they could be the same, which is the direction I'm going in Arubic.
Actually, you could probably treat hash tables as prototypes in Racket too, but you would need to use special functions to access them:
(proto-get foo 'bar)
(proto-set foo 'bar 'qux)
---
"Actually, they do. A Racket struct can implement the 'prop:procedure structure type property to specify how it should behave when called like a procedure.
In fact, it can also implement 'prop:dict to behave like a dictionary. Hash tables and association lists are other things that can be used as dictionaries."
Ah, I see, so it's basically a bigger and more complicated version of the message passing in Arubic. I still prefer Arubic. :P
---
* [1]: Technically speaking, you could implement prototypes by copying the data, rather than using delegation... but when I refer to prototypes, it is referring to the delegation-based model, as that's what JavaScript and Lua use.
Also, I do draw a distinction between classes and prototypes, even though both use message passing and inheritance. The distinction isn't a very huge one, though. Instances inherit from a class, and a class inherits from other classes. Interestingly enough, it's possible to emulate classes using prototypes, but not possible to emulate prototypes using (static) classes... thus you could say that prototypes are a superset of classes.
It is possible to emulate prototypes in a language with dynamic classes though, like Python. It just requires you to create a new class at runtime, then create a new instance. So every class would have precisely one instance. This is still kinda kludgy, though... for instance, Python requires some special properties to be defined on classes... you can't add them to instances.