Arc Forumnew | comments | leaders | submit | almkglor's commentslogin
1 point by almkglor 6470 days ago | link | parent | on: Bug in (markdown)

Hmm. Maybe post the original source of the post? I mean the input string to markdown ^^. Kinda hard to parse through markdown without seeing the data it's supposed to be working on.

-----

2 points by almkglor 6470 days ago | link | parent | on: Arc challenge: 8 Queens Problem

  (def valid? (stack)
    (let i 0
      (if (or (pos stack.0 cdr.stack)
              (some [do (++ i) (is i (abs:- _ stack.0))] cdr.stack))
        nil
        t)))

-----

1 point by map 6470 days ago | link

  (def valid? (stack)
    (let i 0
      (if (or (pos stack.0 cdr.stack)
              (some [is ++.i (abs:- stack.0 _)] cdr.stack))
        nil
        t)))

  (def queens (stack n)
    (if (is n 8)
      (do (prall rev.stack "[ ") (prn " ]"))
      (for rank 1 8
        (push rank stack)
        (if (valid? stack)
            (queens stack (+ n 1)))
        (pop stack))))

  (queens '() 0)

-----

1 point by almkglor 6470 days ago | link | parent | on: Web Scaffolding

Looks interesting. Haven't yet grokked the how-to-use, but then I'm supposed to be working right now, not hacking ^^.

Some nitpicks:

1. scaffold.arc / inst-entity1 uses global variables. Is this deliberate? Why?

2. Personally I would recommend using the following interface to inst-entity1:

  (def inst-entity1 (temname scaffold scaff rinf)
    ...)
  (mac inst-entity (temname scaff . rinf)
    `(inst-entity1 ,temname ,scaff ',scaff ',rinf))
However, I'm not 100% sure why you're using global variables in inst-entity1 in the first place - is there some special reason?

3. docstrings would be nice ^^.

4. The actual code seems to use addtemscaff (not addscaff) and rname (not ename). Or am I looking at the wrong code?

Edit:

5. You seem to be storing the code added by addtemscaff as lists of expressions. Why not store them in a function? That way we can capture variables into an environment instead of forcing the user to always use globals.

6. The (each v tablist.scaffold ...) could probably be transformed to (ontable k v scaffold ...)

-----

1 point by drcode 6470 days ago | link

> 1. scaffold.arc / inst-entity1 uses global variables. Is this deliberate? Why?

The arc eval doesn't seem to support local environments or passing of environments, so this is the only way to pass in anaphoric variables I could find on my first pass. This function could probably be rewritten without eval and with proper scoped anaphoric variables, but given what is happening in the code this requires serious macro-fu. I do sort of know what I'm doing here- The evals and global vars don't make me feel good either... I will clean this up eventually, but won't complain if someone else figures out how to do it first :)

> 2. Personally I would recommend using the following interface to inst-entity1:

  (def inst-entity1 (temname scaffold scaff rinf)
    ...)
  (mac inst-entity (temname scaff . rinf)
    `(inst-entity1 ,temname ,scaff ',scaff ',rinf))
Yeah, you're probably right here... my brain is hurting right now... once it's doing better I will look into it...

-----

1 point by almkglor 6470 days ago | link

> requires serious macro-fu

True, that's what it looks like. It seems nearer to a macro-defining-macrosystem rather than plain macros, actually. Should be a challenge ^^.

-----

1 point by treef 6470 days ago | link

Its not always good to have macros writing macros one has to maintain it :)

-----

1 point by almkglor 6470 days ago | link

Yes, but at least I don't have to write the macro directly, ne? ^^

-----

1 point by drcode 6470 days ago | link

> 5. You seem to be storing the code added by addtemscaff as lists of expressions. Why not store them in a function? That way we can capture variables into an environment instead of forcing the user to always use globals.

I am planning on adding a command for debugging scaffolds, where the instances of the scaffold are instantiated and pretty-printed to make writing scaffolds less uber-meta. Having functions would prevent this- But you are right that using functions might be the Right Thing. I'll give it some thought.

> 6. The (each v tablist.scaffold ...) could probably be transformed to (ontable k v scaffold ...)

Yes I think you're right. This is definetely "release early, release often" type code, so there's lots of room for improvement.

-----

1 point by almkglor 6470 days ago | link

> a command for debugging scaffolds, where the instances of the scaffold are instantiated and pretty-printed ... Having functions would prevent this

Looks like we should really be solving the correct problem: make function code pretty-printable ^^. Yes, I think I'll solve this using attachments again... ^^ Go attachments! http://arclanguage.com/item?id=3698

Edit: Which reminds me, I haven't actully grokked this scaffolding thing at all yet. I'll be home in maybe 3-4 hours, hopefully I can get the weekend for this, unless I do something stupid, like track down where the girl I'm trying to see is hiding ^^.

-----

1 point by drcode 6470 days ago | link

Numbers 1, 2, 4, 5, and 6 are now resolved. (#6 is resolved because my new code makes ontable impossible :-)

I used your advice to store functions- Used properly, this will not affect the debug code I had in mind afterall.

-----

1 point by drcode 6470 days ago | link

#4 is fixed now.

-----

1 point by almkglor 6470 days ago | link | parent | on: Arc challenge: 8 Queens Problem

  arc> (help prall)
  (from "arc.arc")
  [fn]  (prall elts (o init ) (o sep , ))
   Prints several arguments with an initial header and separated by a
      given separator. 
Above function also exists in Arc2.

Instead of (point return ...(return ...)) try using (catch ...(throw ...)).

Final nitpick: I think it's rtm, not rm, although, well, I dunno. ^^

-----

1 point by lojic 6470 days ago | link

Have you tried prall to print the output in the OP? It's awkward.

-----

1 point by map 6470 days ago | link

  arc> (help prall)
  Error: "reference to undefined identifier: _help"

-----

1 point by nex3 6470 days ago | link

help is a macro defined on Anarki.

-----

11 points by almkglor 6471 days ago | link | parent | on: Arc has no return statement?

For arc-wiki:

  (breakable:each x xs
   (if ...
       (break x)))
breakable is simply:

  (mac breakable (expr)
   `(point break ,expr))
point is simply:

  (mac point (name . body)
    " Creates a form which may be exited by calling `name' from within `body'. "
    (w/uniq g
      `(ccc (fn (,g)
              (let ,name [,g _]
                ,@body)))))
breakable: works on any expression, not just loops and other control structures. Basically, if you need something to suddenly return a value without continuing, just add breakable: to the point you want to do so and use (break ...) to break out.

Maybe should have called it 'brittle or 'fire-extinguisher ^^

-----

2 points by lojic 6471 days ago | link

I wonder how ccc in Arc/Scheme compares to return in Ruby with respect to efficiency. Hopefully ccc is very lightweight. It really does make me question why return wasn't defined to be part of the language.

-----

8 points by almkglor 6471 days ago | link

Plenty efficient. Try reading the original lambda papers: http://library.readscheme.org/page1.html

The one you need to read is "Lambda: the Ultimate GOTO" http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-...

Basically the most important realization is that the return address on the stack may be modeled as the address for a different procedure, which by a staggering coincidence just so happens to point to the code after the function call. So basically a return is itself equivalent to a function call.

-----

7 points by sacado 6471 days ago | link

ccc is one of the strangest things in Scheme (and Arc now). Hard to get everything behind it, but it can be used to implement return statements, try-catch à la C++/Java, coroutines à la Lua, generators à la Python and of course continuation-based web apps à la Arc...

A very strange beast, and as far as I know the thing Scheme has that CL hasn't (and cannot trivially implement).

-----

5 points by KirinDave 6471 days ago | link

It should be no surprise continuations could do all these things. Continuations are the fundamental unit of all control flow in programming.

-----

4 points by sjs 6470 days ago | link

Arc doesn't use ccc for web apps, just good old closures.

-----

7 points by almkglor 6470 days ago | link

Actually, the form of closure used by Arc is highly similar to a continuation passing style, so although it doesn't use 'ccc, it does use continuations.

-----

2 points by eds 6471 days ago | link

cl-cont is a library that implements closures and runs on many CL implementations. So it's not a matter of CL can't do it, CL just has to use a library to do it.

-----

4 points by jbert 6470 days ago | link

I think there are conceptual problems mixing unwind-protect-like constructs and call/cc.

The cl-cont lib appears to only support a subset of CL (in particular unwind-protect is not supported).

So cl-cont doesn't demonstrate that CL can support it, only that a restricted subset of CL can.

I don't know if it is possible to sensibly accommodate unwind-protect and call/cc in the same language, it seems smarter people than I have avoided doing so.

-----

4 points by randallsquared 6470 days ago | link

Scheme's dynamic-wind serves the same purpose as unwind-protect (except with entry conditions as well, since a continuation could suddenly return into your protected code), and plays nicely with continuations. I'm not sure about the details, though.

-----

1 point by jbert 6470 days ago | link

Thanks for that, pretty interesting. I guess that makes writing entry and exit conditions a little more interesting, since they could end up being invoked multiple times.

-----

3 points by lojic 6471 days ago | link

That's good to here. Thanks for the links - great reference material.

-----

1 point by treef 6469 days ago | link

i am learning how to write scheme compilers now it it looks like you just jump around your CCC's like GOTO labels - very fascinating and lower over head then functions calls (if you compile to machine level)

-----

1 point by lojic 6471 days ago | link

Thanks. And from your comment ( http://arclanguage.com/item?id=4432 ) on the 8 Queens thread, the Ruby snippet in the OP above could be implemented as:

  (def foo (xs)
    (point return
           (each x xs
                 (if (> x 3)
                     (return x)))
           nil))

  (prn (foo '(1 2 3 4 5)))

-----

2 points by almkglor 6471 days ago | link

Yes. Although breakable: is significantly more concise.

Edit: Another alternative to breakable: ... break is catch: ... throw ^^

-----

4 points by lojic 6471 days ago | link

But breakable isn't in Arc :)

-----

2 points by almkglor 6471 days ago | link

It's only six more nodes of code ~.~;

That said catch-throw is in ArcN, although they do have different intended usages. breakable: is supposed to be used as a modifier for existing control structures, while (catch ...) is supposed to be a control structure in its own right.

-----

3 points by em 6468 days ago | link

Why the gensym?

(mac point (name . body) `(ccc (fn (,name) ,@body)))

-----

1 point by almkglor 6468 days ago | link

dunno ^^. Maybe pg making a thinko ^^

-----

2 points by almkglor 6471 days ago | link | parent | on: Arc challenge: 8 Queens Problem

better is point:

  (def a ()
    (point return
      (each i '(1 2 3)
        (if (< i 2)
          (return i)))
      nil)))
That said, the breakable: macro simply compiles down to (point break ...)

-----

1 point by almkglor 6471 days ago | link | parent | on: HTTP header case bug

Supposedly you can use the "git rebase -i origin/master" command as described in the CONVENTIONS file. It doesn't seem to work on me, however; I get the message "Usage: /usr/bin/git-rebase [-v] [--onto <newbase>] <upstream> [<branch>]"; looking at my online documentation does not reveal a -i option. ^^

-----

1 point by sjs 6470 days ago | link

You probably need a newer git. People recommend using git HEAD and I haven't had problems with it so far.

  cd ~/src
  git clone git://git.kernel.org/pub/scm/git/git.git
  cd git
  make prefix=$HOME/apps all doc info
  make prefix=$HOME/apps install install-doc install-info

-----

1 point by almkglor 6471 days ago | link | parent | on: macros: w/collect and w/m-collect

I like 'loop syntax better ^^

-----


It might have been easier to just do something like this for default values of optional arguments:

  (dsb (&o (p 100)) foo
    (body))

  =>

  ;      put default values here
  (with (p 100
         ,tree foo)
    ; do the checking here
    (if ,tree
      (= p (car tree)))
    (body))
Edit: Personally I'd do a recursive expansion of the optional/keyword part, successively deciding at each sublist whether it should go to an optional or a keyword argument, or if the sublist is empty, to stop parsing. This would probably reduce significantly the overhead of nth, which I think needs to measure the length of the argument list each time. Will think of an alternative method of expressing dsb in a recursive manner which would hopefully just significantly increase the apparent complexity of the generated code while gaining a minor boost in efficiency.

-----

1 point by kennytilton 6471 days ago | link

"Personally I'd do a recursive expansion of the optional/keyword part"

I'll be honest, I am just a simple application programmer, I was stunned for example by the expansion of withs.

And I am just a muddy Common Lisper, I am not smart like the Lisp-1 guys, I do not know how to express the number 3 as a half-dozen nested lambda forms. So...

...that's a long way of saying I think you are right, there is almost definitely a nicer lambda-based solution out there. I would say I would love to see it except I doubt I would understand, I have been to Lisp-1 talks and never understood a word, I've stopped going.

But I would enjoy seeing a recursive solution, your approach sounds promising and even easy to read, more than I can say for mine.

-----

1 point by almkglor 6471 days ago | link

NON-recursive modification of your solution ^^.

Turns out that 'withs is recursive enough for this ^^.

  (mac dsb (params data . body)
    (let (reqs keys opts) (dsb-params-parse params)
      (w/uniq (tree kvs)
        (withs (optfn
                (afn (l)
                  `()))
          ; turn reqs into the argument list, adding
          ; the ,tree as a rest argument
          (if (no reqs)
              (= reqs tree)
              ((afn (l)
                 (aif (cdr l)
                      (self it)
                      (= (cdr l) tree)))
               reqs))
          `(withs (,reqs ,data
                   ,@(mappend [list (carif _)
                                    `(do1 (if ,tree
                                              (car ,tree)
                                              ,(cadrif _))
                                          (= ,tree (cdr ,tree)))]
                              opts)
                   ,kvs (pair ,tree)
                   ,@(mappend [list (carif _)
                                    ; don't use aif - dsb might be
                                    ; used itself in an aif context
                                    (w/uniq it
                                      `(let ,it (assoc ',(carif _) ,kvs)
                                            (if ,it
                                                (cadr ,it)
                                                ,(cadrif _))))]
                              keys))
            ,@body)))))
Yep, I concede. The recursive solution won't easily handle the cases in http://arclanguage.org/item?id=4423 . So this is really the best way to do it ^^.

-----

1 point by almkglor 6471 days ago | link

Ha, ha, yeah right, I don't even use any lisplike programming languages in an application I've ever passed to a client (using a lisplike to generate an application in a non-lisplike is another statement).

...that's a long way of saying no, I'm not even a simple application programmer, I bet you've built more Lisp code that actually reached application level.

Anyway I'll be doing my hacking now, will come back in a few dozen minutes.

-----

1 point by almkglor 6471 days ago | link

Hmm. The current problem I'm facing is with the defaulting expression: what should we do in the following case:

  (dsb (&o (m 100) (p m)) ...)
Or even worse:

  (let var 42
    (dsb (&o (p var) var) ...))
Hmm. Thinking... thinking....

-----

1 point by kennytilton 6471 days ago | link

[WARNING: Common Lisp follows, but I do not think the Arc/CL differences change anything]

No coffee yet, but why is the first one problematic?

  (destructuring-bind (&optional (m 100)(p m)) nil
    (list m p))
  -> (100 100)
In this case, the second optional parameter VAR simply shadows the VAR introduced by LET, so it is not a hard case:

  (let ((var 42))
    (destructuring-bind (&optional (m var) var) nil 
       (list m var)))
-> (42 nil)

Where VAR is used as the default for M, hey, there better be one out there outside the DSB to eat.

-----

1 point by almkglor 6471 days ago | link

It's problematic for a recursive solution. ^^ So is the second. ^^ In the end I decided that the sketch up of your solution is better, since 'withs is, after all, recursive ^^

-----

3 points by almkglor 6471 days ago | link | parent | on: Dynamic Binding

nice ^^. Finally someone else is also using the "foo: modifier" approach for macros.

-----

1 point by nlavine 6471 days ago | link

It seems like the right way to go. And hopefully the fn-transformer function will make it easier for others to do the same thing : ].

-----

More