Arc Forumnew | comments | leaders | submitlogin
5 points by fallintothis 5105 days ago | link | parent

It's entirely possible. Here's a proof-of-concept patch that seems to accomplish most of the t and nil rebinding.

  $ diff -u old-ac.scm new-ac.scm
  --- old-ac.scm  2010-05-03 09:04:07.000000000 -0700
  +++ new-ac.scm  2010-05-03 10:11:33.000000000 -0700
  @@ -17,7 +17,9 @@
   (define (ac s env)
     (cond ((string? s) (ac-string s env))
           ((literal? s) s)
  -        ((eqv? s 'nil) (list 'quote 'nil))
  +        ((eqv? s 'nil) (if (bound? 'nil)         ;XXX
  +                           (ac-var-ref 'nil env)
  +                           (list 'quote 'nil)))
           ((ssyntax? s) (ac (expand-ssyntax s) env))
           ((symbol? s) (ac-var-ref s env))
           ((ssyntax? (xcar s)) (ac (cons (expand-ssyntax (car s)) (cdr s)) env))
  @@ -396,8 +398,8 @@
     (if (symbol? a)
         (let ((b (ac b1 (ac-dbname! a env))))
           (list 'let `((zz ,b))
  -               (cond ((eqv? a 'nil) (err "Can't rebind nil"))
  -                     ((eqv? a 't) (err "Can't rebind t"))
  +               (cond ;((eqv? a 'nil) (err "Can't rebind nil"))
  +                     ;((eqv? a 't) (err "Can't rebind t"))
                        ((lex? a env) `(set! ,a zz))
                        (#t `(namespace-set-variable-value! ',(ac-global-name a)
                                                            zz)))
  @@ -747,7 +749,7 @@
   (xdef is (lambda args (pairwise ar-is2 args)))

   (xdef err err)
  -(xdef nil 'nil)
  +;(xdef nil 'nil)
   (xdef t   't)

   (define (all test seq)
The ;XXX in ac marks code that special-cases nil so as previous uses don't break -- i.e., so I didn't have to change every nil to 'nil in arc.arc et al. For example, the literal nils in map1 and so forth:

  arc> (map1 [+ _ 1] (list 1 2 3))
  (2 3 4)                         
  arc> (if nil 'a 'b)
  b
  arc> (if 'nil 'a 'b)
  b
  arc> (= nil 'blah-blah-i-am-true-blah)
  blah-blah-i-am-true-blah
  arc> (map1 [+ _ 1] (list 1 2 3)) ; literal nil still treated like empty list
  (2 3 4)
  arc> (if nil 'a 'b)
  a
  arc> (if 'nil 'a 'b)
  b
It's a pretty horrible solution:

  $ rlwrap mzscheme -f as.scm
  arc> (def f (x) (cons x nil))
  #<procedure: f>
  arc> (f 5)
  (5)
  arc> (= nil 10)
  10
  arc> (f 5)
  (5)
  arc> (def g (x) (cons x nil))
  #<procedure: g>
  arc> (g 5)
  (5 . 10)
But as I said, just a proof of concept.

More importantly, do you actually have a reason you want to rebind the canonical false value? I mean, basically all it could do is break. At least t is only boolean true because it's a symbol other than 'nil. Even with the special case above, you have macro issues:

  arc> (if (or (> 1 2) (> 3 4)) 'a 'b)
  b
  arc> (= nil "At a certain point, this just gets silly...")
  "At a certain point, this just gets silly..."
  arc> (if (or (> 1 2) (> 3 4)) 'a 'b)
  a
Unless you gut Arc to use 'nil (or something else) as its false/empty-list value, you'll break anything that uses literal nils. And after gutting, all you gain is, what, the ability to use one more variable name? I think that's a different sort of restriction than being unable to redefine built-in functions.

Essentially, your suggestion is to treat literals as variables. But that's the point of nil and 2 and #\a and "this is a string": they're how you spell the basic constants out of which you build programs. I could philosophize about whether users should have the "freedom" to change what 2 means, but it devolves into the stuff of jokes (http://www.thinkgeek.com/tshirts-apparel/unisex/generic/60f5...).



1 point by evanrmurphy 5105 days ago | link

Thanks for the excellent responses by yourself and waterhouse. I'll likely come back to this discussion several times in the near future (I want to try your patch), for now just a brief reply:

> More importantly, do you actually have a reason you want to rebind the canonical false value? I mean, basically all it could do is break. At least t is only boolean true because it's a symbol other than 'nil.

I don't have particular reason to redefine canonical false yet, but I did like the implications of all this on numbers for alists and would be very curious to hear reactions to that - maybe the idea is flawed or I need to explain it better [http://www.arclanguage.org/item?id=11714].

However, even if there were no immediate need to redefine 'nil, numeric symbols etc., I detect an ugliness with their redefinition being prohibited. I simply do not understand why ints would be untouchable when 'car, 'cdr, 'eval etc. - the true axioms of the language - can be reassigned in a heartbeat. If it has to be that only some of these symbols are sacred, I think it should be the axioms, not some literals. (Admittedly, there is some overlap, especially in 'nil territory.) Otherwise, it'd be cleaner to make everything rebindable or nothing so, and the former seems more in the spirit of Arc.

-----

2 points by fallintothis 5105 days ago | link

I detect an ugliness with their redefinition being prohibited.

But there's still a conceptual difference: numbers, strings, and characters are not variables to be redefined, but are syntax for constant values -- just like parentheses are syntax for "begin a list" and "end a list". It's like saying you should be allowed to change how the word "hello" is spelled.

Likewise, Arc works to make nil a literal value, (mostly) like a character or a string. Thus, redefining it is nonsensical. t isn't really a literal value, because any non-nil value is boolean true anyway. So, I agree that treating t as a variable could be allowed without breaking the current conceptual model.

I did like the implications of all this on numbers for alists and would be very curious to hear reactions to that

The reason 2 is the same as '2 isn't so much that quote special-cases numbers, it's that quote delays evaluation (which doesn't really happen for 2). On its own, foo evaluates to whatever it's bound to, so 'foo delays that. Compare with 2, which is "self-evaluating" -- as soon as we read it in, we know it's the number 2. Then '2 delays the evaluation of syntax that already had meaning before quote touched it. Hence, '2 is still just the number 2. Similarly for '#\a and '"a string".

You could make quote a special-casing operator, so '2 is different from 2 just because it's useful, but that doesn't let you redefine 2.

You could also change Arc so that there would be a layer between reading 2 and going "hey, that's the number 2". Then '2 would be more sensible and each 2 in your code could be a lookup to some value defaulting to...well, the number 2, I guess. But how do you distinguish 2-the-numeric-value and 2-the-variable if they're both spelled the exact same way? In the face of redefinition, (is (+ 1 1) 2) isn't an identity that would hold. What about extending this to less inductively-defined data types? How do you change #\a back to normal after (= #\a #\b)? Does it make (is "abc" "bbc") true? What if you first did (= "abc" "foo")?

The idea isn't just different, it creates a radically new language. That doesn't mean it's without merit. Off the top of my head, Common Lisp has reader macros that allow some syntax to be redefined, and PLOT (http://users.rcn.com/david-moon/PLOT/) lets you redefine syntax dynamically, though I'm not sure to what extent. But it's arguably one the first types of restrictions mentioned in http://www.paulgraham.com/ilc03.html (I don't mean to appeal to authority; it could just explain why Arc doesn't do this).

-----