Arc Forumnew | comments | leaders | submit | aw's commentslogin
3 points by aw 5140 days ago | link | parent | on: Beginner - Programming without Prior Knowledge

The Arc tutorial: http://ycombinator.com/arc/tut.txt

Practice the examples in the tutorial yourself: http://tryarc.org/

-----

2 points by aw 5147 days ago | link | parent | on: Syntax.for(lisp)

secret formatting instructions: http://arclanguage.org/formatdoc

-----

1 point by aw 5149 days ago | link | parent | on: On Modules

Ah, so when a macro gets evaluated, it gets evaluated in its namespace? That's clever!

-----

1 point by Pauan 5149 days ago | link

Yes. At runtime. Even ignoring the inefficiency of expanding macros at runtime, there's one other thing that concerns me, and that's anaphoric macros.

If somebody writes a macro like "aif" or "aand" or whatever, you want the variable "it" to refer to the caller's namespace, but all the other variables to refer to the definer's namespace...

I think this is a solvable problem, but I think it'll require more complexity to solve.

By the way, I think I can add in a system where you can selectively choose which variables should be expanded in your namespace, and which ones shouldn't. Something like this:

  (import foo)

  (w/names (it)
    (foo!something))
This says that the variable "it" should be expanded into your namespace, and all other variables should be expanded in foo's namespace.

Interestingly enough, if I implemented such a system, you could then overwrite certain variables in a macro's body:

  (def helper (x)
    (+ x 50))

  (foo!something) -> 15 ; uses foo's version of helper

  (w/names (helper) ; uses my version of helper
    (foo!something)) -> 60

-----

1 point by Pauan 5149 days ago | link

Actually, there's another thing that also concerns me... Consider this macro:

  (def foo args
    (apply prn args))

  (mac bar (x . args)
    `(foo (string ,x) ,@args))
If you call bar, you want the variables "x" and "args" to be expanded in your namespace, but everything else to be expanded in bar's namespace.

-----

1 point by aw 5149 days ago | link | parent | on: On Modules

Have you published import.arc somewhere?

-----

1 point by Pauan 5149 days ago | link

Yes. It's in the "lib" branch of my fork:

https://github.com/Pauan/ar/blob/lib/import.arc

It's a bit messy right now, though.

---

Also, `import` is still using `load`, rather than `use`. So you'd use something like this:

  (import foo "../path/to/foo.arc")
Rather than this:

  (import foo)
This has both advantages and disadvantages. What I'd like to do is have (import foo) behave like (use foo), but with namespace isolation. And then we could have an (import-as foo "../path/to/foo.arc") for more precise control.

---

I'd also like to note that "import.arc" is still basically alpha-state, so I make absolutely no guarantees about whether it'll work or not. My suggestion would be to try it, and if something breaks, tell me about it so I can try to fix it.

Basically, it's a prototype that attempts to demonstrate that the concept is both possible and feasible.

-----

1 point by aw 5153 days ago | link | parent | on: Pauan's racket discovery: procedure-rename

I think your discovery is important enough to warrant mentioning on the forum, since it is A) useful, and B) something that most people didn't know about. (At least, I knew about string->uninterned-symbol, but not procedure-rename).

-----

1 point by aw 5154 days ago | link | parent | on: Modules Unsolved

Yeah... what 'latemac made me face up to is that my trick means that macros aren't transforming code to code any more. I'm not sure I know why, but I feel uneasy.

One question is can we come up with something better than making symbols qualified by namespace (such as how e.g. Clojure does it). It seems to me that making symbols namespace qualified is less convoluted than needing to use 'latemac with my function value trick, unless there's a problem I'm not realizing about namespace qualified symbols. What do you think?

-----

2 points by rocketnia 5152 days ago | link

"[...]unless there's a problem I'm not realizing about namespace qualified symbols. What do you think?"

Well, my opinion on namespaces is that they don't really fix anything if they're human-guessable prefixes; the prefixes themselves can collide, in which case I'd want the namespaces themselves to be in namespaces to resolve the collision. :-p That can be a vicious cycle (where do the namespace namespaces get resolved?), but there are a few decisive ways to resolve it:

- Name the namespace after a GUID or cryptographic signature, rather than something prone to human over-abbreviation.

- Name the namespace after an entry in some directory people already have to keep collision-free, like a file system path or a domain name.

- Don't plan on serializing or unserializing the namespace at all, and "name" it using something which has a unique identity at run time, such as an uninterned symbol.

At any rate, keep in mind that if all symbols are namespaced, then things like ssyntax will need to be able to handle that, and anaphoric variables will get either more complicated to make, more complicated to use, or both.

Doesn't have to be that complicated. I think it would be cool to let 'awhen be defined like this:

  (mac awhen (test . then)
    `(let ,leak!it ,test
       (when ,leak!it
         ,@then)))
Here, 'mac and 'leak can be two macros which share information using an anaphoric variable of their own, say 'caller-namespace. They could expand to this:

  ; overly verbose for clarity :-p
  (low-level-mac awhen caller-namespace (test . then)
    `(let ,(tag-with-namespace caller-namespace 'it) ,test
       (when ,(tag-with-namespace caller-namespace 'it)
         ,@then)))
takes a breath

Another thing to keep in mind is that just because symbols in different namespaces are distinct doesn't mean they need to refer to different variables. If I import 'foo, I'd like for the 'foo in my namespace and the 'foo in the library's namespace are both aliases for the same variable. That way I can just say (extend foo ...) to affect things in the library which use 'foo, instead of having to drill into the namespace using something like (extend the-ns/foo ...).

-----

1 point by aw 5152 days ago | link

If I import 'foo, I'd like for the 'foo in my namespace and the 'foo in the library's namespace are both aliases for the same variable.

I like that.

leak!it

yes, there will need to be some mechanism to say that when my macro expands into a "bar", do I mean my bar or your bar? (Scheme's hygienic macros cleverly chooses which one you want most of the time, but makes it far too awkward to override the choice when it gets it wrong).

namespaces [...] don't really fix anything if they're human-guessable prefixes

Yeah.

-----

1 point by aw 5151 days ago | link

> let ,leak!it ,test

How does the caller's symbols such as passed in through "test" end up in the caller's namespace? I suppose all symbols would need to be tagged with a namespace? For example, if I said:

  (awhen x (prn x))
"x" would need to end up in my namespace after awhen was expanded.

-----

1 point by rocketnia 5148 days ago | link

Oh, I guess there's a couple of things I left out when I wrote that example.

To answer your question, the parameters to 'awhen would be wrapped up such that they were automatically associated with the place they came from. (Hmm, I guess that's a bit troublesome in itself, since it means they're essentially like Racket syntax objects, which need to be unwrapped to get at their original structure.)

More difficult to resolve: Somehow, the output of 'awhen oughta be wrapped up so that it's associated with the envioronment where 'awhen was defined. (And maybe this should be done more explicitly than it is in that example. Actually, while I was writing the example, I didn't remember this at all.)

In my current design for Penknife macros (toward the top of https://github.com/rocketnia/penknife/blob/1e5f3dd6cd86a2450..., a file in my Penknife draft[1]), both qq and leak are quasiquotes that anaphorically use lexical parameters of the macro call. They both use plainqq, and leak annotates the result so that it corresponds with the caller's namespace, while qq annotates it so it corresponds with the namespace surrounding the macro.

The hard part is that for qq to have a namespace to refer to, Penknife macros capture the local namespace they're defined in. That's not straightforward to translate to Racket; I basically end up making a shadowing namespace data structure at the start of each function call. On the other hand, it's probably sufficient to capture the global namespace. I was kinda just doing this for elegance's sake, since I kinda consider even a file-global namespace to be a local one, with imports as the local variables.

Got all that? I think I may have overexplained minutia this time around. ^^;

[1] There it is, my Penknife draft. :) I committed it to a branch a while ago, but I haven't really made a big deal out of that fact. Note that it doesn't work--it's not tested at all--and also note that the link's likely to break if and when I get back to it, finish it up, and treat it as the master branch.

-----


This sounds like a fun project for the Google Chrome Native Client ^_^ (http://code.google.com/chrome/nativeclient/)

-----


When you say "widely available", do you mean available on a lot of platforms?

-----

1 point by rntz 5160 days ago | link

Yes.

On looking into the matter, it seems Racket is available on Windows and OS X, so that's basically taken care of. Hopefully its source compiles on non-x86{,_64} platforms as well, but I don't really develop for those.

-----

1 point by waterhouse 5160 days ago | link

I'd suggest just trying to compile it on whatever machine you might have in mind.

  git clone http://git.racket-lang.org/plt.git
  cd plt/src
  ./configure
  make
  make install  # this builds executables and docs in place; takes a longish while

-----

1 point by aw 5175 days ago | link | parent | on: Arc2js, an Arc to JavaScript compiler

This looks useful.

-----

1 point by aw 5187 days ago | link | parent | on: extend vs message passing, redux

Using extend or defrule with a test for type seems like a common pattern... perhaps we should extract that into its own macro.

-----

1 point by rocketnia 5187 days ago | link

Pauan and I were talking about something like that at https://convore.com/arc-runtime-project/getting-critical-cha..., but it was specific to defcall. I wonder if the idea of a type-table case could make sense for lots of operations.

In Lathe/arc, I filter on the first argument's type using "ontype" or multiple first arguments' types using "ontypes":

  (use-fromwds-as rc (+ lathe-dir* "orc/orc.arc"))
  (= my (nspace))
  
  ; These are already defined in orc.arc, but I'm redefining them here
  ; for the sake of example.
  
  (rc:ontypes rc.oiso2 (a b) (cons cons) my.cons
    (and (rc.oiso2 car.a car.b) (rc.oiso2 cdr.a cdr.b)))
  
  (rc:ontype rc.otestify () fn my.fn
    self)
  
  ; General pattern:
  ;
  ; (rc:ontypes <rulebook> <parameters>
  ;     (<type of a leading parameter> ...) <rule label (optional)>
  ;   <implementation>)
  ;
  ; (rc:ontype <rulebook> <parameters other than the first>
  ;     <type of the first parameter> <rule label (optional)>
  ;   <implementation, where "self" is the first parameter>)
https://github.com/rocketnia/lathe/blob/master/arc/orc/orc.a...

In orc.arc, this comes with an inheritance system I don't use much, but I've found I use 'ontype itself a lot when defining new types. Porting the inheritance system would be hard without porting Lathe's rule precedence system along with it.

In lathe.js, I recently tried adding lathe.instanceofRule( ... ), which defines rules that check the type of their first argument. This was largely a failure, as it clutters up the signature line so much that I end up spreading it over three lines of code, when often I could have had a one-line signature and a one-line explicit check. I haven't given up on it completely, though, since it decreases my token count slightly. :-p

-----

1 point by akkartik 5187 days ago | link

Do you mean like defgeneric?

Update: I've been mulling adding 'def :type' to wart for some time, so that I can say (def prn(x) :type 'integer ..) rather than (def prn(x) :case (isa x 'integer) ..).:

  (extend-macro def(name params &body body) :case (iso :type (car body))
    `(def ,name ,params :case (isa ,(car params) ,(cadr body))
       ,@(cddr body)))
But I often want to dispatch on different args. I'm not sure the first or last arg are sufficiently common to merit a shortcut.

-----

1 point by Pauan 5187 days ago | link

In my experience, it's usually the first argument, so I think having a :type would be useful, and in the cases where it isn't, you could fall back to :case (isa ...)

But of course, that's up to you.

-----

2 points by akkartik 5176 days ago | link

Yeah after holding off for a week I decided it would be useful.

https://github.com/akkartik/wart/commit/9559f27eec3994d9779b...

Update 2 hours later: Turns out if isa can handle a list of types, so can :type.

https://github.com/akkartik/wart/commit/1a8400dfebb16bd154da...

-----

More