Arc Forumnew | comments | leaders | submitlogin
1 point by Pauan 4758 days ago | link | parent

"Because that just sends arguments to another function, and that function tries to extract them,"

Hm... well, I still don't get what you're saying, but I'll try implementing it and see if it's a problem or not.

---

"But how does the 'attr function extract its first argument?"

In a worst case scenario, it can be a built-in and use Python magic to avoid the paradox. Having one built-in (attr) is still waaaay better than having a ton of other built-ins (car, cons, cdr, maptable, etc.)

---

"Clojure has its own kinda wordy form of table destructuring. An Arc macro can do better than that when it's only trying to do non-recursive destructuring."

JavaScript also has a form of object destructuring [1]:

  {a, b} = {a: "foo", b: "bar"}

  // or was it like this...?

  [a, b] = {a: "foo", b: "bar"}
I think something that simple would help 99% of the time, so that's okay with me.

---

"Personally, I'd probably go for 'def-extension-type and blissfully ignore the internal representation altogether (except when I'm reading things at the REPL, hm...)."

That's all well and good for high-level coding, but somebody's going to have to determine what the low-level data type will be. I'm going with a table, in py-arc, thanks to our discussions.

---

"It's what 'extend does too. The tagging is just done in a meta way. The way I see things now, the meaning of a value is only the op-understands-value relationships it supports (duck typing?), so extending an op is a valid way to change (tag) the meaning of a value."

Ah, but the key difference is: where is the operator stored? Right now we're only using global functions as operators, but we could also store them as functions in a table. This is better in some situations... and extend is better in other situations.

So yeah, I'm leaning toward duck typing as well, and actually getting rid of the `type` function completely. My idea is that the "type" of something is based solely on it's prototype: `table` would be both a prototype and a constructor of tables (at the same time). You can then create new prototypes that inherit from `table`, and voila, they're tables.

This is sorta-kinda like how JavaScript does it, except JavaScript actually screwed up prototypes, so we can do a lot better in Arc. For starters, in JavaScript you can access the prototype, but you can't change it. That's definitely gonna change: in Arc, you should be able to dynamically change the prototype.

Something's a table, but want it to be a cons? Just change it's 'prototype attribute and bam, it now inherits from cons. Anyways, then the `isa` function would test for inheritance, rather than type. So rather than saying (isa foo 'table) you'd say (isa foo table), which would mean, "does foo inherit from table?" [2].

As far as I can see, the only downside is that isa would now be O(n) rather than O(1), but the prototype chain should be small enough that it won't make a big difference in ordinary programs.

---

"I think you gotta encode behavior in some type or other. I see two ways to avoid functions: You could have tables hold s-expressions and interpret them, or you could have tables encode the behavior themselves. The latter would make tables objects, and they'd be indistinguishable (on a high level) from message-passing closures."

I'm kinda leaning toward the second approach. Even in a worst case scenario, having two built-in primitives that can't be created in Arc (tables and fns) is still better than the current situation.

---

* [1]: https://developer.mozilla.org/en/New_in_JavaScript_1.7#Destr...

* [2]: I'll note that `isa` would probably be used rarely... just as I rarely use `instanceof` in JavaScript. It's only there on the off chance that somebody really does care what "type" something is.



3 points by Pauan 4758 days ago | link

"JavaScript also has a form of object destructuring [1]:"

Okay, I just realized something... what if we changed destructuring so it worked on tables too? Then this would work:

  (let '(a b c) (obj a 1 b 2 c 3)
    ...)
This would also allow us to get a clunky form of keyword arguments:

  (def foo ('(a b c))
    (prn a b c))

  (foo (obj c 1 b 2)) -> nil 2 1
Which could be made nicer with a little sugar...

  (foo :c 1 :b 2) -> nil 2 1
  (foo {c 1 b 2}) -> nil 2 1
One advantage of this approach is that you can pass either lists or tables to the function:

  (foo '(1 2 3)) -> 1 2 3

-----