Arc Forumnew | comments | leaders | submit | fallintothis's commentslogin

#\x is just the character literal for the letter x -- each element of a string being a character. What the parent means is that you forgot to put a quotation mark before the mentioned line. You don't need to use #\ in this context, but in writing it makes more sense than saying you forgot a " before bottle".

-----

1 point by forensic 6237 days ago | link

Thank you sir. It is clear to me now.

-----

1 point by fallintothis 6258 days ago | link | parent | on: Referential transparency

Not sure if this is exactly like the bug noted in the top comments of arc.arc, but it seems to me that perhaps it could be boiled down to the problem of inserting literal objects into macroexpansions:

  arc> (= pusher cons)
  #<primitive:cons>
  arc> (pusher 'a 'b)
  (a . b)
  arc> (mac my-push (e ls)
         (let pusher-alias pusher
           `(,pusher-alias ,e ,ls)))
  #3(tagged mac #<procedure>)
  arc> (let pusher (fn (x ls) (+ ls (list x)))
         (prn (my-push 'a '(b c d)))
         (prn (pusher 'd '(a b c))))
  Error: "Bad object in expression #<primitive:cons>"
  arc> (macex '(my-push 'a '(b c d)))
  (#<primitive:cons> (quote a) (quote (b c d)))
  arc> (mac my-push (e ls)
         (let pusher-alias pusher
           `(list ',pusher-alias ,e ,ls)))
  *** redefining my-push
  #3(tagged mac #<procedure>)
  arc> (let pusher (fn (x ls) (+ ls (list x)))
         (prn (my-push 'a '(b c d)))
         (prn (pusher 'd '(a b c))))
  (#<primitive:cons> a (b c d))
  (a b c d)
As you note, this solution then turns into combing through and aliasing every free variable -- doing so automatically would then be the makings for some hygiene, ostensibly. This is an area of contention, as I'm sure you're well aware. It still crops up fairly frequently, generally from someone vying for such a system. But as it stands, Arc doesn't seem to be going for hygienic macros (except perhaps as a library).

-----

1 point by xrchz 6258 days ago | link

is it possible for a macro library to provide hygienic macros? I suppose you could port the "portable syntax case" implementation from scheme to arc... but I don't know how much help, if any, you'll need from the expander

-----

1 point by rincewind 6257 days ago | link

how do you know that a variable is free at macro expansion time?

-----

1 point by stefano 6257 days ago | link

You would need help from the compiler. Basically a macro would be called with a list of bound variables as an extra argument. For a compiler, this would be quite easy. Now a macro would look like:

  (mac my-mac (non-free-var-list my-arg1 ...)
    ...)
instead of:

  (mac my-mac (my-arg1 ...)
    ...)

-----

2 points by almkglor 6257 days ago | link

Why not just mod 'mac to something like (docstring extraction and name redefinition elided):

  (mac mac (name args . body)
    `(set ,name
       (annotate 'mac
         (fn ,(cons 'expansion-context args)
           ,@body))))
Then insert stuff in Scheme-side 'ac to use (apply macro the-free-list-or-whatever (cdr ex)) instead of (apply macro (cdr ex))

That way macros that need it can get it, while macros which don't need it can ignore it.

We can potentially define 'expansion-context as a table or function, and potentially we could allow an implementation to have expansion-context!line, say provide line number etc. information so that the macro can give decent error messages. Of course if we have a dorky backend (like mzscheme) then we can just have it return expansion-context!line as nil, because it can't somehow extract line numbers, but for implementations that can, then good.

edit: Oh and ye: the 'ac compiler on scheme-side really does keep a list of bound variables ^^

-----

1 point by rincewind 6257 days ago | link

This is a solution, but I consider this cheating, because it is nearly as tedious as manually inserting symeval around global functions.

w/var:do in my mexpr.arc is an example of a macro/dsl which can not take a free-var list as 1st arg (it could be changed, but that would make it useless)

and what about list in

  (let list (list 1 2 3) list)

-----


Multiple assigment: (= (x y) (list 1 2))

This, however, conflicts with regular assignment. It's ambiguous in that it's quite context-dependent. For instance:

  arc> (= y '(1 2 3))
  (1 2 3)
  arc> y
  (1 2 3)
  arc> (= (car y) (list 1 2)) ;we're accessing y, not assigning to car
  (1 2)
  arc> y
  ((1 2) 2 3)
  arc> ;but what of this?  x isn't a function, though
       ;the syntax is kind of inconsistent if used for both purposes
  (= (x y) (list 1 2))
  Error: "reference to undefined identifier: _x"
However, you can still do multiple assignment; just not destructuring assignment:

  arc> (= x 1 y 2)
  2
  arc> x
  1
  arc> y
  2
You could instead define, e.g.:

  (mac ds= (vars vals)
    `(set ,@(apply + nil (map list vars vals))))
Then:

  arc> (ds= (x y) (1 2))
  2
  arc> x
  1
  arc> y
  2
Which, confidentially, doesn't work for using literal lists in the 'vals position as you did, but that should still be doable. Could also use '= instead of 'set, if you still wanted to do something like:

  arc> (ds= (x y) ((list 1 2 3) (list 4 5 6)))
  (4 5 6)
  arc> x
  (1 2 3)
  arc> y
  (4 5 6)
  arc> (ds= ((car x) (cdr y)) ('a 2))
  2
  arc> x
  (a 2 3)
  arc> y
  (4 . 2)

I do like the idea of conceptually merging hash tables and arrays, or at least think it should be explored.

-----

3 points by Amferreira 6261 days ago | link

You are right, I had forgot about (= (car y) (list 1 2)).

-----

1 point by fallintothis 6277 days ago | link | parent | on: Is, lists, and strings

Because it's the common case. http://arclanguage.org/item?id=334

Views differ, but personally I don't like to think of strings as aggregate collections of characters (but then, I also don't really like the character as a data-type), so using 'is seems conceptually simpler. It makes sense to me, as often as I bandy about strings and compare them, that 'is treats them as a simply-compared type. Granted, they are not. It's something I guess I've gotten used to by using symbols, as drcode points out (yay, link to a post in the same thread!): http://arclanguage.org/item?id=7965. To each their own.

-----

3 points by eekee 6276 days ago | link

Ah, I guess my bit-twiddling background is showing, because I don't like to think of strings as single entities. Symbols exist for that and are more efficient all-round, if I understand right.

-----

1 point by fallintothis 6284 days ago | link | parent | on: Norvig's spelling corrector in Arc?

Not really. It's a simple regexp that Norvig uses.

Python:

  def words(text): return re.findall('[a-z]+', text.lower())
Arc:

  (def words (text) (tokens (downcase text) [~<= #\a _ #\z]))

-----


Why would it be? Are you that incapable of learning new things? I doubt it. The differences between releases, no less, is going to be smaller than the differences between Lisps and other languages as a whole. It strikes me as something rather foreign to say, being of the general form "I want to learn X, but I'm afraid that something new will come along." So? The learning process is continuous. It's like being worried that Python 2.5 is going to be obsoleted by Python 3.0. Of course it will; the point is to run a mental diff and adapt, which isn't difficult because at its core it's still Python. Now, if the question is whether to learn Arc or some more well-established dialect, I see you've already commented on this thread: http://arclanguage.org/item?id=7876. Although, the same logic applies in the whole Lisps vs Others thing -- choose one and go with it; the differences are easy to pick up when you have experience in a Lisp.

-----

3 points by ptn 6283 days ago | link

I am not incapable of learning new things, but it's foolish to waste time with something that will be obsolete in 3 months (or whatever insignificant time). I'd rather play with something a little more stable. Take into account that py3k came along after 16 years of Python. It breaks backward-compatibility and hackers must relearn a bunch of things, yes, but that only happened after a really long time. I'm concerned that this kind of major change will happen with every Arc release, which is the impression I get when I read pg's announcement ("we will continue to work as if we were the only users").

-----

6 points by fallintothis 6283 days ago | link

To be clear, I didn't mean offense with the comment about learning new things (hence saying "I doubt it").

Moreover, my point was that the differences between releases are relatively easy to cope with -- yes, even for py3k. Sure, there are a hefty number of changes, but they mostly occur in a more "library" level (if you will) rather than at the base language, and much of it is just cleaning up inconsistencies. It's not as though the entire "16 years of Python" flies out the window with an overhaul like this. It'll be something of a pain in the ass to update code, but it won't make your collected knowledge obsolete, per se.

On a less contentious matter, Arc is also a tiny language. Its changes won't be all that drastic at this point. This is little consolation, as the aim is probably to build up a respectable library base. To that end, my overarching point is that you should learn Lisp in a more platonic sense (hardly a waste of time, break-prone versions aside). This can be done with pretty much any dialect, for the record. Libraries may become obsolete, but this sort of philosophical knowledge will not.

Whether this entails using Arc needn't be a grueling decision: it's a small, simple dialect (cf the responses in the aforementioned thread), and still a Lisp. The impression I get from the announcement is more of a heads-up "we reserve the right to..." thing. Besides which, changes to Arc entail, to a significant enough extent, code written in Arc itself. What better way to understand and play with the language than to read over the definition of 'trav (as a real example of a change between arc1 and arc2; http://arclanguage.org/item?id=2504)? Regardless, as Arc stands it's stable enough for learning, but this education has far more impact than being some sort of fleeting "woops, new version, guess I don't understand Lisp anymore." I focus on this idealized learning-experience viewpoint because that's the reason I tend to play with other languages: to expand my mind.

If, however, it comes down to consistency that you'd like for a Lisp in a production environment, well:

It's not a coincidence that we wrote a language for exploratory programming rather than the sort where an army of programmers builds a big, bureaucratic piece of software for a big, bureaucratic organization.

-----

3 points by ptn 6283 days ago | link

No offense taken (shakes hand)

No matter how easy to cope with changes are, if they happen all the time, they are annoying. You are supposed to mess around with programs for a while to really get to know a language, but if at mid-point you are forced to stop and rewrite everything, it's like being stuck on 2nd gear.

However, I now understand three things: (1) Arc releases don't really come that often, (2) changes won't be neither numerous nor drastic and (3, really important) former versions of Arc will have taught you a bunch of valuable lessons. 3 is pretty obvious, but I was totally failing to see it. Thanks for that.

Guess I will learn Arc :)

P.S Arc's aim at this point is not to build a respectable library base, it is to improve the core language.

-----


"It has threads and a way to say a chunk of code should be executed atomically. No more than that at the moment. Nor is there any explicit notion of a processor. I'm not sure how that will turn out."

http://news.ycombinator.com/item?id=32801

-----

1 point by almkglor 6293 days ago | link

Re: "chunk of code should be executed atomically" - I'm not 100% sure but I think it's possible that (from the way 'atom is implemented) a sequence that is not protected within an 'atom scope will be able to see an "atomic" operation in progress.

Basically 'atom just acquires a Global Interpreter Lock around the function it executes. I'm not sure, but from the semantics of locking, I think that another thread may see the "atomic" operation step-by-step unless it is itself protected by 'atom (and then there is potential contention for a single global lock!)

Of course, mzscheme uses green threads, so maybe it won't work that way.

-----

1 point by prakash 6295 days ago | link

I'm not sure how that will turn out."

That's the part I want to know more about. Thanks for the link.

-----

2 points by fallintothis 6307 days ago | link | parent | on: Improve this function?

I thought at at first, but that won't produce the same answers. Take his test case:

  '(1 2 3 (3 4 5) (3 4 (1 2 3)))
Using the desired method, it's:

  (/ (+ 1
        2
        3
        (/ (+ 3 4 5) 3)
        (/ (+ 3 4 (/ (+ 1 2 3) 3)) 3))
     5) ;= 13/5
But by flattening the list, we get:

  (/ (+ 1 2 3 3 4 5 3 4 1 2 3) 11) ;= 31/11

-----

1 point by tokipin 6306 days ago | link

ah, didn't see the 'resolved' thingie

-----

1 point by fallintothis 6310 days ago | link | parent | on: Help needed with macro

Besides the other solutions noted that are more "classic" answers to the problem, I think it's important to ask: why does this have to be a macro? Using eval within a macro, in my experience, is often a sign that you don't need it; you want a function instead. I can't see any signs of the need here either. To say nothing of the soundness of the original solution's method, I believe that this would work:

  (def unzip (xs)
    (let ps (pair xs)
      (list (map car ps) (map cadr ps))))

  (def sum (xs)
    (apply + xs))

  (def biased-choice args
    (withs ((bs cs) (unzip args)
             r (rand (sum bs)))
      ((afn (bs cs i)
         (if (< r (sum (cut bs 0 i)))
             (cs (-- i))
             (self bs cs (++ i))))
       bs cs 1)))
If I'm mistaken for some reason, please beat some sense into me.

-----

1 point by skenney26 6310 days ago | link

The problem with using a function is all the arguments are evaluated.

  arc> (biased-choice 3 'black 3 'white 1 (pr 'blue))
  blueblack

-----

1 point by almkglor 6310 days ago | link

If all weights are ints:

  (mac biased-choice args
    (w/uniq (choice nums sum fns rsum)
      (givens (pairs        (pair args)
               weight-exps  (map [_ 0] pairs)
               choice-exps  (map [_ 1] pairs)
               )
        `(givens (,nums   (list ,@weight-exps)
                  ,sum    (apply + ,nums)
                  ,choice (rand sum)
                  ,fns    (list ,@(map [idfn `(fn () ,_)]
                                       choice-exps))
                  ,rsum   0)
           (while (< rsum choice)
             (zap + rsum (car nums))
             (zap cdr nums)
             (zap car fns))
           ((car fns))))))

The above macro supports that the weights are expressions instead of constants

(untested)

-----

1 point by almkglor 6309 days ago | link

ah crick: here's a working debugged version:

  (mac biased-choice args
    (w/uniq (choice nums sum fns rsum)
      (givens pairs        (pair args)
              weight-exps  (map [_ 0] pairs)
              choice-exps  (map [_ 1] pairs)
        `(withs (,nums   (list ,@weight-exps)
                 ,sum    (apply + ,nums)
                 ,choice (rand ,sum)
                 ,fns    (list t ,@(map [idfn `(fn () ,_)]
                                        choice-exps))
                 ,rsum   0)
           (while (<= ,rsum ,choice)
             (zap + ,rsum (car ,nums))
             (zap cdr ,nums)
             (zap cdr ,fns))
           ((car ,fns))))))
Also: the reason it needs ints is because of the 'rand function. We could also define a rand-float function which creates a random floating point number and use that instead:

  (def rand-float (lim) (* lim (rand)))

  (mac biased-choice args
    (w/uniq (choice nums sum fns rsum)
      (givens pairs        (pair args)
              weight-exps  (map [_ 0] pairs)
              choice-exps  (map [_ 1] pairs)
        `(withs (,nums   (list ,@weight-exps)
                 ,sum    (apply + ,nums)
                 ,choice (rand-int ,sum)
                 ,fns    (list t ,@(map [idfn `(fn () ,_)]
                                        choice-exps))
                 ,rsum   0)
           (while (<= ,rsum ,choice)
             (zap + ,rsum (car ,nums))
             (zap cdr ,nums)
             (zap cdr ,fns))
           ((car ,fns))))))
the above now works with weight expressions that return real numbers. Also as specified, only the chosen expression is executed; however, all weight expressions are executed.

-----

1 point by fallintothis 6310 days ago | link

Ah, I misread that you wanted something akin to random-elt rather than rand-choice -- i.e., you'd want to use this as a control structure, in which case a macro indeed is what you'd need. My bad. That's what I get for commenting on an empty stomach (well, empty brain is more like it, but excuses are entertaining).

-----

2 points by fallintothis 6364 days ago | link | parent | on: Predicates? and Mutators!

Previously mentioned many times, actually. This does not seem to be the current plan, as those characters could be reserved for future syntax: http://arclanguage.org/item?id=3145

-----

More