Arc Forumnew | comments | leaders | submitlogin
1 point by rocketnia 4759 days ago | link | parent

"Okay, I just found exn-message... this really is a lot clunkier than it could be. sigh I feel kinda silly now, but I'm gonna leave this post here, in case somebody else has the same problem. I had already looked at the Exceptions documentation, but somehow missed that function. To my credit, the documentation for exn-message is pretty much... nonexistent. I accidentally learned about it while reading ac.scm."

In the documentation for the 'exn struct (http://docs.racket-lang.org/reference/exns.html?q=exn#(def._...), they show that the fields are "message" and "continuation-marks". They don't document 'exn-message and 'exn-continuation-marks because those are just generic struct getters. It's as though 'struct is a macro and 'exn-message and 'exn-continuation-marks are generated automatically, but I think it's a bit more integrated into the module system than that.

There are several other variables a (struct ...) form automatically generates, and they're described here: http://docs.racket-lang.org/reference/define-struct.html

I'm not trying to claim the Racket documentation is easy to read or anything, but I hope this helps you out in the future. ^_^

---

"this really isn't helping my gut feeling that Scheme is too bloated and hard to work with. :P"

That may be true, but Racket is much more complicated than Scheme has to be, and that's not a mistake.

http://racket-lang.org/new-name.html

Sure, it has parentheses, uses the keyword lambda, provides lexical scope, and emphasizes macros — but don't be fooled. PLT Scheme is no minimalist embodiment of 1930s math or 1970s technology. PLT Scheme is a cover for a gang of academic hackers who want to fuse cutting-edge programming-language research with everyday programming. They draw you in with the promise of a simple and polite little Scheme, but soon you'll find yourself using modules, contracts, keyword arguments, classes, static types, and even curly braces.

Incidentally, the very same concern for comprehensiveness, practicality, and compatibility that (I believe) has damaged the purity of Racket's design makes it a nice platform for implementing Arc. That's no mistake either; Racket is designed to support lots of sublanguages besides Scheme, like Typed Racket, the stateless servlet language, etc.



1 point by Pauan 4759 days ago | link

"In the documentation for the 'exn struct [...]"

Yes... I picked up on that... after stumbling upon exn-message in ac.scm. I did try skimming the struct documentation as well, but it doesn't seem to tell you how to access the fields.

From what I can tell with exn-message, if you create a struct "foo", with a field "bar", it will automatically create a function "foo-bar" to access it?

That's really unintuitive/clunky in my opinion. Especially compared to say... Arc, where it would just be (foo 'bar).

---

"That may be true, but Racket is much more complicated than Scheme has to be, and that's not a mistake."

Yes, but Racket feels like it's more complicated than it needs to be. Then again, perhaps there's somebody out there that needs this fancy-pants exception stuff. :P

And even though Scheme may be more minimal, it still has a few parts that seem bloated, like (let ((a 1) (b 2))) which is pretty unfortunate since I would expect `let` blocks to be pretty common! Thus, I see Arc as being more minimal than Scheme, in some regards.

-----

1 point by rocketnia 4759 days ago | link

"From what I can see with exn-message, if you create a struct "foo", with a field "bar", it will automatically create a function "foo-bar" to access it?"

I think that's what it says, though it isn't especially clear about it.

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

---

"Especially compared to say... Arc, where it would just be (foo 'bar)."

Racket structs are not the same as hash tables. For instance, they can have inheritance, and they can override 'equal? using 'prop:equal+hash (http://docs.racket-lang.org/reference/structures.html). They're not especially orthogonal features, but structs are specifically for custom data types, while hash tables are for associations.

For extra fun, Racket also has classes (http://docs.racket-lang.org/guide/classes.html). :-p

---

"And even though Scheme may have been designed for minimalism, it still has a few parts that seem bloated, like (let ((a 1) (b 2))) which is pretty unfortunate since I would expect `let` blocks to be pretty common!"

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.

Of course, the Arc approach is to make the syntax get out of the way so we can identify the error before it gets to the compiler. :-p

-----

1 point by Pauan 4759 days ago | link

"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).

I've also considered combining tables and lists together, somehow... something like this: http://arclanguage.org/item?id=4237

---

"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?

-----

1 point by rocketnia 4758 days ago | link

"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.

But yeah, the reference is very succinct, and the docs are altogether too scattered. Even regular Racket programmers feel that way: http://www.mail-archive.com/dev@racket-lang.org/msg00957.htm...

---

"Cough. Prototypes. Cough."

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?"

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 (http://docs.racket-lang.org/reference/procedures.html?q=prop...).

In fact, it can also implement 'prop:dict to behave like a dictionary (http://docs.racket-lang.org/reference/dicts.html?q=prop%3A#(...). Hash tables and association lists are other things that can be used as dictionaries.

---

"How does (let ((a 1) (b 2))) give more information than (let (a 1 b 2))?"

I'm not altogether sure myself, but here's what the docs have to say: http://docs.racket-lang.org/syntax/stxparse-intro.html

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.

-----

1 point by Pauan 4758 days ago | link

"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.

-----