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

Because it uses "lib/object.arc", import will of course only work on my fork, but I plan to change that soon, so it'll work on normal ar as well.

I'll also note that it's missing some features, and is a bit broken in some ways, but I have a plan to fix that. I also noticed that it seems to be a bit slower (than using load), but that could be because I'm using a hash table rather than a Racket namespace. I'll switch over to Racket namespaces later and see if it helps any.

However, for basic stuff, it works. As an example, let's suppose you wanted to load up "arc3.1/pprint.arc", which creates a bunch of functions, like ppr. But now let's also suppose that some of those functions clash with other functions in your namespace... if you just use `load`, you'll get a namespace collision and stuff will break. Import to the rescue!

  >>> ppr
  error: reference to undefined identifier: ppr

  >>> (import pprint "arc3.1/pprint.arc")
  nil

  >>> pprint!ppr
  #<procedure>

  >>> (pprint!ppr "foobar")
  "foobar"nil

  >>> ppr
  error: reference to undefined identifier: ppr
What import does is create a new namespace, then load everything inside that namespace. You'll note that it did not pollute the current namespace, since ppr is still undefined even after calling import.

But you can still call functions in the pprint namespace by using table notation. There are some neat things you can do with this. Aside from the obvious one of loading libraries into separate namespaces so they don't collide, you could load the same library twice, or you could load multiple libraries into the same namespace, while still keeping it separate from your namespace:

  (= foo (new-namespace))

  (w/namespace foo
    (load "lib/bar.arc")
    (load "lib/qux.arc"))
Now the namespace foo contains both bar.arc and qux.arc, but neither of them have polluted your namespace.

By the way, in addition to namespaces, it actually supports anything with type 'table, so the following works:

  >>> (w/namespace (table)
        (eval '(+ 10 5)))
  undefined variable: +

  >>> (w/namespace (obj + +)
        (eval '(+ 10 5)))
  15
And calling (eval ... foo) is a shortcut for (w/namespace foo (eval ...))

  >>> (eval '(+ 10 5) (obj + +))
  15
When you call `new-namespace`, it defaults to the current namespace (I plan to change that), but you can pass in an argument to use a custom namespace:

  (= foo (new-namespace (table)))
You can think of new-namespace as creating a "proxy" or a "clone" of an existing object. If you understand JavaScript prototypes, it's exactly like that. This allows you to load stuff into a namespace without it clobbering anything else.


1 point by Pauan 4924 days ago | link

I would just like to point out that this is only possible (as a library) because ar is so damn hackable. Big thanks to aw for making ar.

---

I'd also like to note something here. Because you can create custom namespaces, there is the theoretical ability to create a "safe namespace" that would not be able to access things like "system" or similar destructive things.

Then, if you ever wanted to load up a library, rather than inspecting it to make sure it doesn't do anything bad, you could just load it into the safe namespace. This won't protect against things like infinite loops, or programs designed to consume a lot of CPU/RAM, but it will protect against the obvious stuff like (system "rm -rf /") and such.

I haven't added in support for that just yet, but it is planned.

---

Also, __built-ins* is a terrible name, and I plan to change it. :P

-----

2 points by aw 4924 days ago | link

"ar is so damn hackable"

heh, can I quote you on that? :)

-----

1 point by Pauan 4924 days ago | link

Yes. And it'll be even more true when ar gets defcall. I mean, really, implementing dynamic variables, optional args/destructuring, ssyntax, objects, and namespaces/import as plain-old Arc code is impressive. Very impressive. In fact, I don't know of any other language that can do that, though I've heard Smalltalk is very flexible.

Since most of the Arc compiler is actually in the Arc namespace (combined with having access to Racket), I get the feeling that you could do almost anything with ar, which is most definitely not true of Arc/3.1.

-----