Arc Forumnew | comments | leaders | submitlogin
1 point by akkartik 4466 days ago | link | parent | on: Replace loop with xloop

What do people think of how tokens looks with afn vs loop? https://github.com/arclanguage/anarki/commit/1dd646ddcb
3 points by rocketnia 4466 days ago | link | parent | on: How do you use a hash field in a macro?

The reader parses the comma to make (unquote someobj!field) before ssyntax processing even occurs. I just wrote a long comment to describe the whole process, but this is the main point.
5 points by rocketnia 4466 days ago | link | parent | on: How do you use a hash field in a macro?

For a step-by-step look at things...

  (mac somemacro (someobj)
    `(if ,someobj!field t nil))
When we enter any code at the REPL, it causes three phases to occur: Reading, compilation, and execution.[1]

The read phase processes the ( ) ` , symbols and gets this data structure of cons lists and symbols:

  (mac somemacro (someobj)
    (quasiquote (if (unquote someobj!field) t nil)))
Note that someobj!field is a single symbol whose name contains an exclamation point character.

At this point you can probably see the problem already. What you may have expected was ((unquote someobj) (quote field)), but what we got was (unquote someobj!field). This is technically because Arc doesn't implement ssyntax at the reader level; instead it uses Racket's reader without modification, and then it processes the ssyntax in the next phase.

Even though the issue should already be clear, I'm going to go through the rest of the process to illustrate macroexpansion.

At this point the compilation phase starts. It expands the (mac ...) macro call, and then it re-processes whatever that macro expands to. As it goes along, at some point it also processes the (quasiquote ...) special form, and it expands the someobj!field syntax. The result of expanding someobj!field is (someobj 'field), and since this isn't a special form or macro, it's compiled as a function call.

The overall result is Racket code. In case it helps show what's going on, I just went to http://tryarc.org/ and ran the following command:

  ($ (ac '(macro somemacro (someobj) `(if ,someobj!field t nil)) (list)))
This produced a bunch of Racket code, which looks like this if I format it nicely:

  ((lambda ()
     (ar-funcall3 _sref _sig (quote (someobj)) (quote somemacro))
     ((lambda ()
        (if (not (ar-false? (ar-funcall1 _bound (quote somemacro))))
          ((lambda ()
             (ar-funcall2 _disp "*** redefining " (ar-funcall0 _stderr))
             (ar-funcall2 _disp (quote somemacro) (ar-funcall0 _stderr))
             (ar-funcall2 _disp #\newline (ar-funcall0 _stderr))))
          (quote nil))
        (begin
          (let ((zz
                  (ar-funcall2 _annotate (quote mac)
                    (let ((| somemacro|
                            (lambda (someobj)
                              (quasiquote
                                (if (unquote (ar-funcall1 someobj (quote field)))
                                  t
                                  nil)))))
                      | somemacro|))))
            (namespace-set-variable-value! (quote _somemacro) zz)
            zz))))))
Personally, I never think about the raw Racket code. Instead I pretend the result of compilation is Arc code again, just without any macro calls or ssyntax:

  ((fn ()
     (sref sig (quote (someobj)) (quote somemacro))
     ((fn ()
        (if (bound (quote somemacro))
          ((fn ()
             (disp "*** redefining " (stderr))
             (disp (quote somemacro) (stderr))
             (disp #\newline (stderr))))
          (quote nil))
        (assign somemacro
          (annotate (quote mac)
            (fn (someobj)
              (quasiquote
                (if (unquote (someobj (quote field)))
                  t
                  nil)))))))))
Either way, you can see the original (if ... t nil) is still in there somewhere. :)

Finally, this Racket code is executed. It modifies the global environment via Racket's namespace-set-variable-value! and puts a macro there. The macro is simply stored as a tagged value where the tag is 'mac and the content is a function. Then the result of execution is printed to the REPL as "#(tagged mac #<procedure: somemacro>)", and the REPL prompt appears again.

Later on, we execute the following command:

  (somemacro oo)
The reader parses this to make this s-expression:

  (somemacro oo)
Then the compilation phase starts. It starts to expand the (somemacro ...) macro call. To do this, it invokes the macro implementation we defined earlier. It passes in this list of s-expressions:

  (oo)
The macro's implementation is the function that resulted from this Racket code:

  (lambda (someobj)
    (quasiquote
      (if (unquote (ar-funcall1 someobj (quote field)))
        t
        nil)))
Or alternately, in my imagination, it's the result of this macroless Arc code:

  (fn (someobj)
    (quasiquote
      (if (unquote (someobj (quote field)))
        t
        nil)))
When this function is called, someobj's value is the symbol named "oo". When we try to call the symbol, we get an error.

The compilation phase terminates prematurely, and it displays the error on the console. The execution phase is skipped, since there's nothing to execute. Then the REPL prompt appears again.

I hope this gives people a good picture of the semantics of macroexpansion and ssyntax.

[1] Technically we might add printing and looping phases to get a full Read-Eval-Print-Loop. The eval step of the REPL does compilation followed by execution.

---

As I said above, the confusing point is probably that the reader doesn't give the result that you might expect when it sees ",someobj!field". On the one hand, this is a technical limitation of the fact that Arc uses Racket's reader which doesn't process ssyntax. On the other hand, I think it's debatable if this interpretation of the syntax is better or worse than the alternative.

2 points by zck 4466 days ago | link | parent | on: How do you use a hash field in a macro?

Oh, I think I see what's going on. It's that the ssyntax-expansion of the code binds the comma more "out" than one expects.
2 points by akkartik 4466 days ago | link | parent | on: How do you use a hash field in a macro?

I didn't think to try macex1 :)

The ssyntax is a red herring here, since the behavior is the same even if you don't use ssyntax like in my previous comment. I'd also bet that it's the same in common lisp. Just a consequence of macros operating in name space rather than value space. Though this is a kinda subtle consequence of that; I had to run that type example I mentioned before to fully grok what was going on.

2 points by zck 4467 days ago | link | parent | on: How do you use a hash field in a macro?

How did you figure that out? I found I couldn't macex1 it, because it was already erroring. I guess it's related to when ssexpansion happens in relation to macroexpansion?
2 points by malisper 4467 days ago | link | parent | on: How do you use a hash field in a macro?

The arguments to a macro aren't evaluated. Because of this, someobj has the value of the symbol oo and not the table like the way you wanted. Akkartik's explanation covers the rest of the details.
5 points by akkartik 4467 days ago | link | parent | on: How do you use a hash field in a macro?

Expanding ssyntax, your macro is:

  (mac somemacro (someobj)
    `(if ,(someobj 'field) t nil))
This tries to call (oo 'field) during macroexpansion. But at that time oo is just a name. See here:

  (mac foo (x) type.x)

  arc> (foo oo)
  #<procedure: sym>
What happened here was that the type of oo was expanded to sym, and then sym was eval'd in the caller's scope to return a function (thanks to arc being a lisp-1).

The point is, your macro is trying to call a symbol as a function. Instead, this will do what you want:

  (mac somemacro (someobj)
    `(if (,someobj 'field) t nil))
4 points by zck 4467 days ago | link | parent | on: How do you use a hash field in a macro?

It's related to ssyntax in combination with macros. I can reproduce your bug. Here's how to fix it:

    arc> (mac somemacro (someobj)
                  `(if (,someobj 'field) t nil))
    *** redefining somemacro
    #(tagged mac #<procedure: somemacro>)
    arc> (somemacro oo)
    nil
I'm not sure entirely why the original code has a problem, though.

I just noticed your question about contributing a logo. What's your background, Max?

pg talks about that chair in Taste for Makers (http://www.paulgraham.com/taste.html), under "Good design is often slightly funny."

Yeah I've seen that image too. It's older, and predates the public release of Arc by a few years. The current logo here came even later. Probably just an abortive attempt.

Thank you for the reply and a warm welcome) I thought it was a chair because of the images on wikipedia page and here http://www.paulgraham.com/arc.html

I got interested in Arc after reading "Hackers & Painters", can't tell anything about my impressions because I don't know much about the language yet, I've discovered it only recently. I'll definitely learn more about it and then I will have something to say)


Also, you look like you're new to the Arc Forum. Welcome! I've been trying to notice when I see someone new, so we can grow the community. What brings you to Arc? What are your impressions so far?

It's not a chair, it's a lowercase a.

Interestingly, back when I was first playing around with Arc, I also thought the logo was odd. I designed a new one based around combining the letter A with the concept of an arch (http://www.paulgraham.com/arcfaq.html).

You can see my logo, with a favicon-sized image, here: http://imgur.com/a/RMGu4#sSFHTHt It uses the same colors as the existing one, and has the black border around the outside.

On the off chance anyone developing Arc sees it and wants to use it, that would be awesome, as long as it's properly licensed -- I'm not sure what the proper free license is for things that aren't code. Creative Commons withe the attribution and share-alike clauses? http://creativecommons.org/licenses/by-sa/4.0/

2 points by heated 4470 days ago | link | parent | on: A FizzBuzz solution in Arc

Ok
3 points by shader 4470 days ago | link | parent | on: Streams

I feel like we need to extend the documentation on arclanguage.github.io to include the extra libraries on anarki, to improve discoverability.
1 point by akkartik 4474 days ago | link | parent | on: Streams

Now that anarki has its first suite of tests using your harness, I've designated all prior tests as "old tests" to encourage us to move away from our patchwork of prior solutions.

https://github.com/arclanguage/anarki/commit/a30d51ce87


javascript

Brendan?

> “Ordinary programmers” will not use new languages that look too different from “mainstream” languages.

I wonder if that's true. How would the programming language landscape look today if Guido, Matz, Brendan, etc would have made lisps instead?

1 point by svetlyak40wt 4475 days ago | link | parent | on: A FizzBuzz solution in Arc

That is not fair in this case. Please, write example code in terms of Arc3.1 primitives.
1 point by rocketnia 4475 days ago | link | parent | on: Did arc language project alive?

Nice one. :-p
2 points by shader 4475 days ago | link | parent | on: Did arc language project alive?

What do you mean by "definitions"...

Interesting direction to take it. It would be interesting to know how he implemented it, so that he can still consider it to be a lisp. In particular that '#include' syntax sticks out a bit.

I also found it ironic how conflicted he is over its relationship with lisp.


Wart isn't that different from arc, it still shows its roots.

  for x 1 (x < 10) ++x
    prn x

  map prn '(1 2 3 4 5 6 7 8 9 10)

  def (f n)
    prn n
    if (n < 10)
     (f n+1)
  f.1
Unlike smile it needs those parens around the if condition.

Edit 13 hours later: Ack, I was wrong. Wart would drop the parens just fine!

  if n < 10
   (f n+1)
I'm not sure I like it, but the design of infix fundamentally supports it by having higher precedence than function calls. If the infix operands grow complex it can get hard to read without parens.

  if (function-call n x1 x2 x3) < 10
    (f n+1)
  # still works, but yuck..

Rather than compare it to arc, I found it tantalizing to think about how I'd implement that syntax. It looks like he's built objects for modules/namespaces, ranges, etc. But he's somehow supporting infix without spaces and also names like print-line. How does it work?! :)

Edit 8 minutes later: Also, the square brackets around the call to [f 1] are strange. If they're mandatory, there's something there I don't follow.


I just came up with an example of my version of an "80% solution": http://www.reddit.com/r/vim/comments/22ixkq/navigate_around_...

It's not packaged up, all the internals are hanging out, some assembly is required. But it enumerates the scenarios I considered so that others can understand precisely what I was trying to achieve and hopefully build on it if their needs are concordant.


This was just sent to me by a friend. I'm wondering what everyone else's take on this flavor is.

It would be interesting in seeing other examples of the same functions for comparison in e.g. wart, etc.

Also, here's my take on the first few in arc:

  (for x 1 10
    prn.x)

  (map [prn _] '(1 2 3 4 5 6 7 8 9 10))

  (def f (n)
    prn.n
    (if (< n 10) (f:+ n 1)))
  (f 1)
 
To me, the arc looks better, though I may just be biased. The syntax is probably more confusing at first glance for a newcomer.
2 points by akkartik 4475 days ago | link | parent | on: A FizzBuzz solution in Arc

Cool; added. https://github.com/arclanguage/anarki/commit/e893c94e5d
More