Arc Forumnew | comments | leaders | submit | rntz's commentslogin
5 points by rntz 5378 days ago | link | parent | on: ~ applied to variables

That's a bad idea. Not because it is intrinsically wrong, but because it leads to a bad habit, namely, using an operator whose meaning depends upon the type of the thing you are applying it to.[1] In this case, you're making the meaning of ~ change on non-function objects. Suppose you're writing a function 'foo, one of whose arguments is 'x. Then:

a) foo might call ~x on an argument. Then you want ~x to mean what it does currently. But x need not be a function -- it could be a hashtable, since hashtables can act as lookup-functions, or a list. So suddenly ~x is simply incorrect.

b) foo might not care whether x is a function or not; but then you can't use ~x on it, because then if you pass in a function for x to foo, it will behave incorrectly. But if you accustom yourself to using ~x to mean (no x) when x isn't a function, you might accidentally write ~x when you really do mean no.x.

Admittedly, both of these can be avoided through careful programming, but the point of ssyntax is as a convenient abbreviation for common operations, to avoid even the minimal cost of parsing parentheses and a function name when using them. This totally defeats the purpose.

[1] Note that this is different from, but can overlap with, polymorphism, where the implementation of the operator you are applying depends upon the type of the object. The meaning of an operation and its implementation can be separated; an example polymorphic operation which has the same meaning is addition: addition of integers, of floating-point numbers, and of vectors of integers are all implemented differently, but mean the same thing. An example of meaning-non-preserving polymorphism is the use of the left-shift operation on a stream in C++ to print an object to it.

-----

1 point by garply 5378 days ago | link

Thanks for taking the time to dissect the downsides of what I'm increasingly convinced is a bad idea. I agree with your reasoning, particularly with regard to the scenarios involving hashtables and lists.

Nonetheless, variable negation is something I imagine we all encounter with relative frequency, what do you guys think of a negation symbol equivalent to "no." (i.e., ¬)?

Since "!" is used elsewhere, "^" strikes me as a natural choice, probably because I associate it with set complements for POSIX regular expressions.

-----

3 points by rntz 5410 days ago | link | parent | on: Arc.arc vs lib/util.arc

The problem with moving things into arc.arc is that it increases the difference between anarki's arc.arc and pg's arc.arc, which makes maintaining anarki when pg updates arc.arc a PITA. I speak from personal experience. It may seem like a good idea to you to move stuff into arc.arc, but it makes the community's life harder in the long run.

-----

2 points by garply 5410 days ago | link

I'm not proposing hacking existing functions. Basically everything should be able to be maintained by running a diff between the 2 arc.arcs and pasting the extra functions in the Anarki version into pg's new arc.arc. What difficulties did you encounter last time?

-----

3 points by rntz 5432 days ago | link | parent | on: Why make-br-fn?

Nitpicking: that's not ssexpansion. Ssexpansion is short for symbol-syntax expansion, in which the occurrence of special characters in symbols tells the arc compiler to transform them, things like foo.bar -> (foo bar), foo!bar -> (foo 'bar). The brace transformation is actually accomplished via changing the reader table of the underlying scheme, and so is translated at read-time rather than compile-time.

This is important if, eg, you're writing scheme code to integrate into the arc runtime in some fashion; normally, in plt scheme, braces [] and parentheses () are interchangeable; but arc changes the way [] is parsed, so you basically have to avoid using them in scheme code. Whereas ssyntax is parsed by the arc compiler, not the reader, so you don't need to worry about it.

-----

1 point by evanrmurphy 5432 days ago | link

Ah, you're right! I had thought it was ssexpansion because of

  arc> (ssexpand '[_])
  (fn (_) (_))
but it turns out to expand even without ssexpand:

  arc> '[_]
  (fn (_) (_))
Thanks for the clarification. ^_^

-----

1 point by rntz 5432 days ago | link | parent | on: Why make-br-fn?

I implemented that feature (multiple automatic parameters, with alphabetic ordering, so [cons _y _x] = (fn (_x _y) (cons _y _x))) in anarki. I don't know for sure, but I would assume it's still there.

-----

5 points by rntz 5470 days ago | link | parent | on: Adding local scope to arc

While the idea of "flattening out" binding forms appeals to me, since complex arc and lisp function bodies in general tend to become very nested, I don't really like the way this macro conflates flattening binding forms with automatic parenthisisation of sequential "statements". I don't see why I shouldn't just write this:

    (def shuffle-numbers (min max)
      (scope
        w/table arr @
        (for i 0 (- max min)
          (= arr.i (+i min)))
        (down i (- max min 1)
          (swap arr.i (arr (rand (+ 1 i)))))))
At the very least, I don't like the way @ "magically" differentiates between binding forms and sequential forms based on the contents of binding-function-list* . It would be better IMO to have two different special symbols - one for binding forms, one for sequential evaluation.

Although, as far as magic goes, there's a neat trick that you could do using the 'sig table, which stores signatures (that is, the parameter lists) of functions and macros. You could have 'scope or some similar macro (let's say 'magic-scope) use 'sig to look up the parameter lists of the binding macros it encounters, and use them to determine "where to put the @s". So you'd just write, for example:

    (magic-scope
      w/uniq (foo bar)
      let xyzzy (+ plugh quux)
      `(,xyzzy (,foo ,bar)))
With your macro as is, you'd have to add 'w/uniq to binding-function-list* and also insert @s, like so:

    (scope
      w/uniq (foo bar) @
      let xyzzy (+ plugh quux) @
      `(,xyzzy (,foo ,bar)))

-----

4 points by rntz 5470 days ago | link

I've been toying with clojure recently, and there are two macros, -> and ->>, which essentially "thread" expressions through a series of forms, like so:

  (-> x (f a) (g b))
  ; macroexpands to
  (g (f x a) b)
  
  (->> x (f a) (g b))
  ; macroexpands to
  (g b (f a x))
It occurs to me that (magic-)scope is very similar to a reversed-argument form of ->>; let's call it '<<-:

  (<<-
    (w/uniq (foo bar))
    (let xyzzy (+ plugh quux))
    `(,xyzzy (,foo ,bar)))
which is equivalent to (but for this use case, more readable than):

  (->> `(xyzzy (,foo ,bar)) (let xyzzy (+ plugh quux)) (w/uniq (foo bar)))
both of which macroexpand to:

  (w/uniq (foo bar)
    (let xyzzy (+ plugh quux)
      `(,xyzzy (,foo ,bar))))
This <<- form has the advantage of not depending on any sig/binding-function-list* magic, at the expense of a few sets of parentheses. And, as I mentioned, it has a nice symmetry with ->/->>, both of which are useful macros in their own right.

-----

2 points by rntz 5523 days ago | link | parent | on: What does 'nil buy us?

It doesn't. It's just an arbitrary choice between using 'nil and '(). It turns out that using '() is easier when writing arc on top of mzscheme, but that pg decided to go with 'nil - why, who knows? Probably a holdover from the CL implementation, or it matches better with his way of thinking about these things.

In particular, it is completely possible to use () underneath as the list-terminator/false value and still have 'nil be arc-recognized "syntax" for (). See aw's nil-to-() hack, for example.

-----

1 point by akkartik 5519 days ago | link

I'm having trouble finding this nil-to-() hack. Link please?

-----

2 points by fallintothis 5519 days ago | link

http://hacks.catdancer.ws/nil-impl-by-null.html

-----

1 point by akkartik 5519 days ago | link

I basically went through the same process 2 days ago! And yes it works.

-----


You mention in the article a 'setforms entry for 'global, and say that you need to do the equivalent of (eval `(= x ,something)), but that something can't refer to anything not in the global environment, and therefore you need another global to "ferry" the value over. This is not necessary. You can just compute the value locally and bind it to some variable, let's say foo, and then (eval `(= x ',foo)).

Also, you mention that if 'my is a module, then (my:foo a b c) will expand to something like (gs1234-foo a b c), and this is useful because (my.foo a b c) expands to ((my foo) a b c), which the arc compiler won't understand is a macro invocation even if gs1234-foo is bound to a macro. I encountered precisely this problem when trying to build a module system, and I solved it by making arc try to macroexpand lists in functional position, and then re-macroexpand if the result was a symbol -- which allows (my.foo a b c) to work. See http://arclanguage.org/item?id=7448, although the pastebin link in the grandchild has since expired. I'm not sure whether I committed this change to anarki, and whether, if I did, it survived the transition to arc3. It's pretty simple to do, though.

-----

2 points by rocketnia 5547 days ago | link

(eval `(= x ',foo))

Oh yeah, that does the trick. At one point I was considering doing that in my macros for hygiene, but then I realized I preferred hackability to hygiene so my code could be consistent with arc.arc, so I abandoned that idea... and somehow forgot you could even do that. XD So that should make the implementation of 'global a bit tidier--maybe even a bit less necessary.

making arc try to macroexpand lists in functional position, and then re-macroexpand if the result was a symbol

Yeah, I considered that, but as long as I could make namespaced macros work without resorting to a patch, I figured I should do that instead, since it made the code more flexible to whatever Arc implementations and patch configurations people wanted to use.

-----

1 point by rntz 5590 days ago | link | parent | on: Poll: All things not arc?

There's Lambda the Ultimate (lambda-the-ultimate.org). That's not so much for experiments in programming as it is for PL theory discussion - fairly heavy on the academics, but very good.

-----

1 point by rocketnia 5587 days ago | link

Oh yeah, Lambda the Ultimate. I've read a few threads there, and I should probably check it out more often, since I can learn a lot very quickly that way.

But yeah, it's not a place programmers come to talk about random general-purpose snippets of code they've made, the way this is. I'm sure there are lots of sites like that too, but I guess I like the balance between that and PL design which this community seems to pursue. ^^

-----

1 point by rntz 5591 days ago | link | parent | on: Improved ppr (bodops* fix)

All the bugs that I can recall finding are fixed.

-----

1 point by rntz 5598 days ago | link | parent | on: Arcc: arc compiler in arc (self-hosting)

Sad to say, I'm not planning on maintaining this at all. I simply don't have the time now that I'm back at school, and my interest in Arc has been waning for some time now. If I did plan on maintaining it, I'd certainly give some thought to version numbering.

-----

1 point by aw 5598 days ago | link

OK, I'll just refer to a particular version by its git commit id such as "601d219618c189554417082517066491e1386f35" :-)

-----

1 point by shader 5579 days ago | link

It's standard to refer to a git commit id by only the first few digits of the number.

So don't worry! You can call it merely "601d2" instead ;)

-----

More