Arc Forumnew | comments | leaders | submit | almkglor's commentslogin
3 points by almkglor 6301 days ago | link | parent | on: Mutual recursive lambdas in a with?

http://arclanguage.org/item?id=7387

-----

3 points by almkglor 6302 days ago | link | parent | on: Alists vs table

Or use this instead: http://arclanguage.com/item?id=7365

-----

1 point by rincewind 6302 days ago | link

the lookup time in alists is O(n). What about proto-tables? Is the key hashed again for lookup in every prototype?

-----

1 point by almkglor 6301 days ago | link

O(M) where M is the depth of the find, or the nested prototype depth if it's not found.

Yes, the key is rehashed.

But really, the point is that proto-tables are quite a bit easier to use: you still retain the table lookup syntax tb.key

-----


Cool ^^ The number is jarring especially in a mathematical context but ultimately necessary, since we cannot detect the arity of functions.

Arc has absolutely no axioms for introspecting into function objects - it can only detect if the object is a function, and nothing else. I hope to rectify this in the Arc dialect I'll build for SNAP - there should be a ways to decompose a function to a function code object (potentially serializable!) and the closured data, as well as determine other bits about the function.

-----

1 point by almkglor 6306 days ago | link | parent | on: Help needed with macro

> (Why does the mappend expression work? Aren't the values of the biases unavailable during macro-expansion?)

They are if the biases are constant numbers.

See my solution above instead for a way of making it work with non-constant biases

-----

1 point by skenney26 6305 days ago | link

This version still needs some massaging but it works with non-constant biases:

  (mac bias args
    (let bs (map car (pair args))
     `(let r (rand (+ ,@bs))
        (if ,@(let i 0
                (rev (accum a
                       (each c (map cadr (pair args))
                         (a `(< r (+ ,@(cut bs 0 (++ i)))))
                         (a c)))))))))


  arc> (with (a 1 b 2 c 3) (bias a 'red b 'white c 'blue))
  white

-----

3 points by rkts 6305 days ago | link

Your macro has problems with variable capture and multiple evaluation (see chapters 9-10 of On Lisp). Here's a version that should work properly:

  (mac bias args
    (w/uniq r
      (withs (ws (map car  (pair args))
              xs (map cadr (pair args))
              us (map [uniq] ws))
        `(with ,(mappend list us ws)
           (let ,r (rand (+ ,@us))
             (if ,@(mappend
                     (fn (u x) `((< (-- ,r ,u) 0) ,x))
                     us xs)))))))
IMO, though, the use of a macro here is a premature optimization. I think you should try to get a function working first, and then wrap a macro around it if you know that's what you need. See my comment http://arclanguage.org/item?id=7760 for an example of such a wrapper macro (in CL, but the Arc is similar).

-----

1 point by skenney26 6303 days ago | link

  (mac bias args
    (w/uniq (bs r)
     `(withs (,bs (list ,@(map car (pair args)))
              ,r  (rand (apply + ,bs)))
        (if ,@(mappend
                (fn (c) `((< (-- ,r (pop ,bs)) 0) ,c))
                (map cadr (pair args)))))))

-----

1 point by skenney26 6304 days ago | link

Interesting solution. I like the clever use of --

-----

1 point by almkglor 6305 days ago | link

I still suggest you take a look at how I do it http://arclanguage.com/item?id=7765 , which (1) avoids multiple evaluation, and (2) avoids variable capture.

(1) is the hard part here, which is why I had to use a list.

-----

1 point by almkglor 6307 days ago | link | parent | on: Help needed with macro

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 6307 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 almkglor 6308 days ago | link | parent | on: Help needed with macro

The sort is indeed unnecessary, and the solution above is indeed the classic solution to the weighted random choice

-----

1 point by almkglor 6308 days ago | link | parent | on: Just a thought

Alternatively, we could define compose as being:

  (= compose
     (reducer
       (fn () (err "compose requires at least one argument"))
       (fn (e) e)
       (fn (a b) (<base>compose a b))))

  (def reducer (f0 f1 f2)
    (fn rest
      (if
        (no rest)
          (f0)
        (no:cdr rest)
          (f1:car rest)
          ((afn (acc l)
             (if l
                 (self (f2 acc (car l)) (cdr l))
                 acc))
           (f2 (car rest) (cadr rest)) (cddr rest)))))
(as I proposed here: http://snapvm.blogspot.com/2008/08/base-functions.html)

Then we can redefine <base>compose as:

  (defm <base>compose ((t a int) (t b int))
    (annotate 'composed-int
      (cons a b)))
  (defm <base>compose ((t a composed-int) (t b int))
    (annotate 'composed-int
      (cons a b)))
Then we can redefine the call* table as an overloading of the <base>call function:

  (defm <base>call ((t l cons) (t v composed-int))
    (let (first second) (rep v)
      ((l first) second)))
> 2. Allow the reader to treat a parenthesized item as an item that supports intrasymbol syntax.

This is probably going to conflict with (a . d) format

-----


Currently macros are part of the desugar phase - macroexpansion and intrasymbol syntax expansion are done in the same step. This allows a macro to return symbol syntax, which might be expanded into a macro call too.

-----


No. Consider this: http://arclanguage.com/item?id=5570

In particular, you should notice that the syntax there involves some intrasymbol syntax, which it expects to have visible.

Specifically, if you make intrasymbol syntax part of the reader, you get the following potential problem:

intrasymbol syntax will have to be completely regular across the entire Arc environment. You can't do tricks like I did in 'w/html, where div.bar doesn't mean (div bar) but rather means "the <div> element with the bar id". Yes, you could probably modify w/html so that it can understand (div bar): but what if the programmer wants to, say, redefine the intrasymbol syntax for foo#bar to mean, say (en-number foo bar), then suddenly w/html will break. And what if programmer B wants to, say, redefine foo#bar to mean (number-en foo bar)? How will anything that uses a slightly different intrasymbol syntax work with that?

-----

3 points by CatDancer 6310 days ago | link

Well, you know how the reader expands ' ` , @ etc.?

  arc> '`(a ,b ,@c)
  (quasiquote (a (unquote b) (unquote-splicing c)))
so why not have

  arc> 'foo.bar
  (dot foo bar)
then if you want to write a macro that treats . or # differently, you can do that.

-----

1 point by almkglor 6310 days ago | link

Programmer A decides he or she wants to specially treat #\@. Programmer B decides he or she doesn't. Now, load Programmer B's code into Programmer A's environment. Oh, and Programmer B has been writing a lot of functions with "@" in their names.

If you're not going to allow #\@ to be specially treated, why should you specially treat #\., #\!, #\~ or #\: ?

#\' and friends, after all, aren't intrasymbol syntax. In fact, #\. is treated differently from within the context of a symbol from within the context of a list.

This is where "code is spec" fails, bad. Me, I say, someone has to choose one or the other, define it as "this is spec!", and everyone follows it. Your move, PG?

-----

1 point by stefano 6310 days ago | link

If the reader can be configured (e.g. by specifying wich read table to use) then two modules that uses different reading conventions can coexist by simply using their own configuration.

-----

1 point by almkglor 6310 days ago | link

Now programmer C wants to use both programmer A's module and programmer B's module. Which readtable does he use so that he can freely intermix macros from A with macros from B, which have different expectations on the reader?

Reader hacking is nice, but I don't see it often in CL libraries (note: counterexamples are welcomed; it's not like I've made an exhaustive search for them). Any reader hack must make the cut of being a good, generic enough meaning that it will always be used by everyone; take for example the Arc-type [ ... _ ... ] syntax

-----

1 point by stefano 6309 days ago | link

A and B should provide macros to let C write:

  (with-A what%ever)
  ...
  (with-B what%ever)
CLSQL modifies the read table to let you write embedded SQL queries such as [select "A" [where [= ...]]] and similar (I've never studied the exact syntax, but this should give you the idea). The special reader in CLSQL can be activated/disactived through function calls that modifies the default reader.

-----

1 point by almkglor 6309 days ago | link

But B doesn't want to treat #\@ or whatever syntax specially. Why should B bend over backwards to support this?

For that matter: what if C wants to use a macro in A within the context of a macro in B or vice versa?

  (with-A
    (macro-A
       @foo
       (with-B
         (macro-B
           (prn "this is:" '@foo)))))
?

> The special reader in CLSQL can be activated/disactived through function calls that modifies the default reader.

Not a bad idea. Difficult in SNAP though - which default reader? I'd have to add yet another process-local variable.

-----

2 points by cchooper 6304 days ago | link

It looks like CLSQL needs reader macros to switch the syntax on and off locally. If Arc had reader macros, then you could do this:

  #.(with-A (mac macro-A ..blah..blah..in special A syntax))
Assuming 'with-A is a function that set the read table locally, and macro-A uses quasi-quote to generate its result, this will produce a macro that produces standard Arc syntax, even though it's written in A syntax.

With reader macros, 'w/html could be implemented even if de-sugaring were moved to the reader, although you'd have to call it with #. all the time.

It makes sense to me that macros should always expand to vanilla Arc syntax (or maybe even pure s-exps without any ssyntax) so that they are portable across environments.

-----

1 point by drcode 6310 days ago | link

I like that idea. If I ever get around to writing something like this I may do it that way.

-----

2 points by almkglor 6315 days ago | link | parent | on: Proposed new axiom: symeval

Depends on how the module system is constructed. If modules are first class objects and not a set of symbols like CL packages are, then the module name itself may be shadowed by a local, i.e. 'cplx itself could fall victim.

> Perhaps we could have a type of macro which adds these module-specifying prefixes to your function calls when the macro is expanded

If modules were based on symbols, like CL packages are, then: http://arclanguage.com/item?id=7616

-----

More