Arc Forumnew | comments | leaders | submitlogin
2 points by GenArx 3778 days ago | link | parent | on: NEWBIE:: new to Lisp, new to Arc.

:) i just gor back here. now trying your steps above Sir. Thank you. As far as i'm concerned i'm also sharing my resources to everyone, Arc deserves a major attention now.
1 point by akkartik 3778 days ago | link | parent | on: NEWBIE:: new to Lisp, new to Arc.

Oh, interesting. I just tried to join that group (since I can't see what you post there otherwise).

Another option is to email me your directions. I think I'd find them very useful.

3 points by akkartik 3778 days ago | link | parent | on: NEWBIE:: new to Lisp, new to Arc.

Thanks for asking, GenArx. We've never had good support for Windows since the people here don't use it much, but your heartfelt questions got me to dust off an old Windows machine and try to install Arc on it. I'm going through this process now, and will try to write up better instructions once I succeed. So far I've successfully installed Racket (click on the 'download' link at http://racket-lang.org) and Git on Windows (run the installer at https://git-scm.com/download/win). Can you do those steps while I figure out what to do next?

Let's keep chatting offline. There might be issues I run into that you know how to deal with, or vice versa. Can you send me an email? My address is on my profile.

Edit 16 minutes later: I've gotten Arc running on Windows. Here are the instructions I followed:

0. Install Racket and Git like above.

1. Open Git Bash from the Windows menu and run this command:

    git clone https://github.com/arclanguage/anarki
2. Open Racket from the Windows menu and run these commands one by one:

    (current-directory (find-system-path 'home-dir))
    (current-directory "anarki")
    (load "boot.scm")
    (tl)
Now you should be at the Arc prompt and ready to try out some programs.

I'm sure there are other issues once I start running programs, but at least the core loaded without errors and I can now help fix other issues as we run into them.

2 points by GenArx 3778 days ago | link | parent | on: NEWBIE:: new to Lisp, new to Arc.

for any newbie here like me who never had the experience of linux but Windows... my adventure so far is summarized here. All contents are taken from the forum and all over the places i've been around the web.

A complete and downloadable tutorials on Arc language available at facebook.com/groups/epspost/ > contains installation files and tutorials with a step-by-step instructions for setup and installation for Windows users. Complete downloading 4 Part Files and then use 7zip to extract and combine them in one single folder called "Arc Learning Compilation from EPSpost"

> these Arc adventures includes arc3.1 / racket // mzscheme


I can't speak for jazzdev, but I bet the code in sml.arc is just meant to be a more convenient way to generate XML from Arc.

  ; SXML
  (tagname (@ (attr "value") (attr2 "value2"))
    (tagname2)
    (tagname3 "data"))
  
  ; sml.arc's "old format"
  (tagname (@ attr "value" attr2 "value2")
    (tagname2)
    (tagname3 "data"))
  
  ; sml.arc's current example
  (tagname attr "value" attr2 "value2"
    (tagname2)
    (tagname3 "data"))
Meanwhile, Racket's batteries-included tools go their own way (http://docs.racket-lang.org/pollen/second-tutorial.html?q=x-...):

  ; X-expressions
  (tagname ((attr "value") (attr2 "value2"))
    (tagname2)
    (tagname3 "data"))
Several Racket libraries are tagged "sxml," but I wonder which formats they use exactly.

As for SXML, I think it's pretty nice that the SXML standard actually has well-defined ways to use doctypes, namespaces, processing instructions, and comments. That makes it more capable of representing an actual XML document. The spec is only a few pages long, and half of that is preamble, so it would be pretty simple to implement it faithfully.

All in all, I think I'd like to write code in a style like sml.arc, but then normalize it to something like SXML.


I think there is one way to consider Arc to be a language with good hygiene: We can program so that if we ever use a name as a global variable, we never use it as a local variable, and vice versa. As long as an Arc problem follows this rule and the usual (w/uniq ...) idiom, it won't encounter hygiene issues.

Paul Graham has this to say about hygiene in the tutorial:

  Some people worry unduly about this kind of bug.  It caused the
  Scheme committee to adopt a plan for "hygienic" macros that was
  probably a mistake.  It seems to me that the solution is not to
  encourage the noob illusion that macro calls are function calls.
  People writing macros need to remember that macros live in the land
  of names.  Naturally in the land of names you have to worry about
  using the wrong names, just as in the land of values you have to
  remember not to use the wrong values-- for example, not to use zero
  as a divisor.
However, he's only careful about one direction of variable capture. Here's one example from the tutorial where he doesn't mind capturing the names let, repeat, push, and rev:

  (mac n-of (n expr)
    (w/uniq ga
      `(let ,ga nil
         (repeat ,n (push ,expr ,ga))
         (rev ,ga))))
I think he gets away with this because he's following that rule I mentioned, keeping a careful separation between the names of locals and globals.

It seems we don't particularly follow that rule here on the Arc Forum. For instance, a few of us have agreed that a certain behavior in Arc 3.1 is a bug: When we make a function call to a local variable, we don't want a global macro of the same name to take effect, which is what happens in Arc 3.1. If we were keeping locals and globals separate, we wouldn't even encounter this problem.

Which means that if we want to write macros that are hygienic, we can't write them in quite the way we see in arc.arc or the tutorial. If we're dedicated to hygiene, we might even want to rewrite arc.arc to fix its hygiene issues... but that's practically the whole language, so it effectively starts to be a new language project. The Anarki arc2.hygiene branch, Penknife, ar, Semi-Arc, and Nulan are several examples of Arc-based or Arc-inspired projects that pursued some kind of hygiene.

If we don't mind the lack of hygiene in arc.arc but only care about proper hygiene for our own new macros, it is possible to be diligent about hygiene in plain Arc 3.1 or Anarki:

  (mac n-of (n expr)
    (w/uniq ga
      (rep.let ga nil
         (rep.repeat n (rep.push expr ga))
         `(',rev ,ga))))
Coding this way looks a little arcane and loses some of Arc's brevity, but one of the techniques here is to embed a the rev function into the syntax as a first-class value. By putting most of the macro implementation into an embedded function, it can become rather familiar-looking again:

  (mac n-of (n expr)
    `( ',(fn (n expr)
             (let a nil
               (repeat n (push (expr) a))
               rev.a))
       ,n
       (fn () ,expr)))
Here's a macro that makes this even more convenient:

  (mac qq-with args
    (let (body . rev-bindings) rev.args
      (let (vars vals) (apply map list (pair rev.rev-bindings))
        `(',list `',(fn ,vars ,body) ,@vals))))
  
  (mac n-of (n expr)
    (qq-with n n expr `(fn () ,expr)
      (let a nil
        (repeat n (push (expr) a))
        rev.a)))
I think if I programmed much in Arc again, I'd start by defining that macro or something like it. :)

As it is, right now I'm just settling into a macro system I designed. I don't have convenient gensym side effects like Arc does, and I want the generated code to be serializable (not containing opaque first-class functions), so my options are limited. I still can and do implement macros, but the implementation of each macro is pretty verbose.


I was quite addicted to poker (no-limit hold 'em) for a couple of years (2005-2008) until it became hard to play online in the US. Now I just play with play money on some mobile app every few months :) It's not true that when people play badly they always lose money. It took me a while to realize that my compass of how well I was playing had to come from within. Otherwise the worst thing that could happen to me was to play badly and win a hand. I'd then be giving away money for a long time, going on tilt, etc. But yeah you're right that in the long run the better player wins, particularly in cash games. Tournaments seem like more of a lottery (maybe I'm just not very good).

I'm constantly looking for people to hack with as well. Some ideas:

a) We could work on anarki. For example, try out the latest version sometime when you have time and let me know if mktemp broke again on Windows. Help kinnard and me expand the install instructions for Anarki to Windows. Neither of us knows how to run Arc there, so this would be very valuable. These small-ish ideas might be the start of a larger project.

b) Other than that I spend a lot of time these days working on an Arc-inspired project that looks nothing like lisp: http://github.com/akkartik/mu. My background: http://arclanguage.org/item?id=17597. Problem statement: http://akkartik.name/about. Writeup on the current state of the solution: http://akkartik.name/post/mu. Let me know how far down that list you were moved to read :)


Hi akkartik, thanks for the update. I'm not using cygwin, but raw racket for windows, sublime and terminals. But I've not run Arc since a while - december or so. Actually, I growing more and more interested by poker. It's kind of the perfect answer to the frustration I got in software - mostly due to my struggle to find a job with great programmers and also my struggle to find great co-hackers. In poker, I win money when the others are wrong; guess how I like that this days...

Programming is my life. I like to think I'm a master of it. But I'm completely alone. Also I hate my jobs, I hate big companies, I hate bullshit, I hate TDD, I hate code reviews, I hate estimations; it's a pain man.

Poker, while definitely not as deep as software, is the exact opposite. They do TDD? I take money. They do code reviews? I take money. bullshit? a fountain of money...

But there is Arc. The most beautiful language I've ever used. I could build so much with it. Wow it could be so awesome. But, let's be honest, it's now or never. Btw, I think I have an idea to fix email. What's missing is a delivery date (of the task / answer / content) set by the sender or the receiver, which would allow to sort emails. Anyway, I'm throwing a bottle in the ocean. If you have a project you want to do using arc (or another language that would fit the task better), let me know.

1 point by kinnard 3779 days ago | link | parent | on: ASK: Best way to learn Lisp?

I'd describe myself as a bottom-up thinker. [But I'm unopposed to the description "top-down" because . . . "which way is up?"] I like to work from axioms to outcomes. I'm frustrated under other conditions.

Hi highCs, this is off-topic but I was thinking about you just yesterday. I updated your bugfix at http://arclanguage.com/item?id=19310. Could you pull anarki and let me know if it's still working for you on Windows? Many thanks.

We were also wondering what your setup looks like. Are you using cygwin when you run Arc on Windows?


No, they're conflicting philosophies.

Hilarious to see creating programming languages motivated by shaving fewer yaks. Language design is the ultimate yak shave.

VS SML? https://github.com/arclanguage/anarki/blob/master/lib/sml.ar...
2 points by zck 3780 days ago | link | parent | on: ASK: Best way to learn Lisp?

If you're interested in Arc, sure, go for it. It's a lot of fun, and the things it does are very well designed.

If you want suggestions as to which Lisp might fit your philosophical ideals, it would help to talk about what the ideals are.


Arc is designed for good programmers. It gives you raw power. Like you could kill yourself with it. Arc is to programming language what unix is to OSes. It doesn't try to protect yourself from doing bad things but gives you the maximum power instead.

The advantages of the language are numerous: raw macro, short names, incredible library, awesome operators, right choice of data structures, etc.

In short, it's more beautiful and agile than racket.


Can non-hygienic macros be easily made hygienic in arc?

I think I'm just beginning to understand some of the benefits/risks of hygienic macros, but I'm not quite there.
3 points by kinnard 3781 days ago | link | parent | on: ASK: Best way to learn Lisp?

I suppose I'm learning lisp for more idealistic/philosophical rather than professional reasons. Though it seems there are compelling professional outcomes nonetheless.
2 points by zck 3781 days ago | link | parent | on: ASK: Best way to learn Lisp?

What are your goals? Although the people here are pretty helpful, there isn't much out there, resource-wise, for Arc. This is both in terms of documentation and libraries.

Are you interested in hacking a Lisp itself? Then Arc is a good choice. Are you interested in learning a Lisp you can find companies using? Arc is suboptimal.


For me the big reason is differences in the way macros are ordered. Racket is a scheme so its macros are hygienic and require a little bit greater ceremony in creating. More seriously, they have phase ordering, which creates constraints about what code you can call from within macros: https://docs.racket-lang.org/guide/phases.html

Arc is more like Common Lisp in that you can call whatever you want while expanding a macro, and if you make a mistake you might end up with an infinite regress of macroexpansion or something like that. Its macros are not hygienic which again creates room for certain kinds of bugs, but some of us here tend to think of those as learning experiences ^_^ whose benefits outweigh their pain.

Another minor difference is that Arc is a lisp-1 like Scheme and unlike Common Lisp.

2 points by rocketnia 3790 days ago | link | parent | on: ASK: is arc used in production?

"If so, then you might not even need macros at all to create the "," behavior."

I never said the overloading of "," was accomplished with macros.

The example I gave was of a macro whose name was overloaded in a type-directed way, similarly to the way "," is overloaded in Idris. (Maybe the macro itself is named ",".) My point is that if the macro system is designed to support that kind of overloading, then sometimes a macro call will depend on intermediate results obtained by the typechecker, so we can't run the macroexpander in a phase of its own.

---

For the sake of remembering Idris more accurately, I checked out the Idris docs to look for the particular "macro system" I was dealing with.

It turns out what I mean by the "macro system" in Idris is its system of elaborator extensions (http://docs.idris-lang.org/en/latest/reference/elaborator-re...). The elaborator's purpose is to fill in holes in the program, like the holes that remain when someone calls a function without supplying its implicit arguments.[1]

It's pretty natural to handle name overloading in the same phase as implicit arguments, because it's effectively a special case. Thanks to dependent types and implicit arguments, instead of having two differently typed functions named (,), you could have one function that implicitly takes a boolean:

  (,) : {isType : Bool} ->
    if isType then (... -> Type) else (... -> (a, b))
  (,) = ...
The elaborator phase is complex enough that I don't understand how to use it yet, but I think almost all that complexity belongs to implicit arguments. Name overloading is probably seamless relative to that.

Another "macro system" I encountered in the docs was Idris's system of syntax extensions (http://docs.idris-lang.org/en/latest/tutorial/syntax.html). As far as I can tell, these apply before the elaborator and typechecker, but they might not be able to run arbitrary code or break hygiene. Maybe someday they'll gain those abilities and become a Nulan-like macro system.

[1] Implicit arguments effectively generalize type classes. Idris still has something like type class declarations, which it calls "interfaces," but I bet this is primarily so a programmer can define the interface type and the method lookup functions together in one fell swoop.

2 points by Pauan 3792 days ago | link | parent | on: ASK: is arc used in production?

I thought about this some more.

I have no experience with Idris or dependent types, so I may be completely wrong.

But from my understanding, a dependent type system allows for types to include values (which are evaluated at compile-time).

If so, then you might not even need macros at all to create the "," behavior.

Instead, you create a typeclass which will dispatch to the appropriate behavior:

  data Pair a b = pair a b

  interface Comma a b c where
    comma : a -> b -> c

  Comma Type Type Type where
    comma = Pair

  Comma a b (Pair a b) where
    comma = pair
Now whenever you use the "comma" function, it will dispatch depending on whether its arguments are Types or not:

  -- Type
  comma Integer Integer

  -- (Pair Integer Integer)
  comma 1 2
And since types may include arbitrary expressions, you can of course use the "comma" function inside of a type:

  foo : a -> b -> (comma a b)
Note: all of the above code is completely untested and probably wrong, but you get the idea.

Basically, your language needs first-class types, and the ability to run arbitrary expressions at compile-time (even within types), and then you can use an ordinary typeclass to get the desired type dispatch. No macros needed.

2 points by Pauan 3795 days ago | link | parent | on: ASK: is arc used in production?

You're right, if you allow for users to overload multiple macros onto the same name based upon type, then it gets very messy.

But I think if your language allows for that, it's inconsistent with the way that macros work.

If you want powerful Arc-style macros, then the macro must be run before any types are known.

Any system which allows for that kind of type-based dispatch is different from a Lisp-style macro system, and is probably less powerful.

For example, you won't be able to create macros which create new variable bindings (like "let", "with", etc.) because the type of the variable is not known until after the macro is run.

I'm not sure what a system like that would look like, or if I would even call it a macro system.

I think it makes more sense to have two separate systems: a macro system that deals with syntax only, and an overloading system that deals with types. That's what Nulan does.

But perhaps there is room for a third system, somewhere in between the two: that third system could do type-directed syntax manipulation.

3 points by rocketnia 3795 days ago | link | parent | on: ASK: is arc used in production?

"Macros deal with things at the syntax level, far earlier than any kind of type overloading."

If the macro itself is being referred to by an overloaded name, then the name needs to be resolved before we know which macro to call.

(I'm not sure if macros' names can be overloaded in Idris; I'm just guessing. Actually, I don't know if Idris lets users define overloaded names. I just know a few built-in names like (,) are overloaded.)

---

"If you mean that the primitives should appear to be macros (even though they're implemented with compiler magic), then I agree with you."

Yeah, that's what I mean. :)

3 points by Pauan 3796 days ago | link | parent | on: ASK: is arc used in production?

I don't think name overloading is a problem, at least not in Nulan.

Macros deal with things at the syntax level, far earlier than any kind of type overloading.

As far as the macro is concerned, it simply sees the syntax

  (*list [ (*symbol ",") (*integer 1) (*integer 2) ])
It doesn't care what the type is, or the meaning, or anything like that. In some cases, the macro doesn't even know whether the symbol is bound or not!

Basically, I view type inference/checking/overloading occurring in a phase after macro expansion.

Is there any benefit to mixing the type overloading phase and the macro expansion phase?

----

It occurs to me that you might not be referring to a macro which expands to syntax, but instead using the syntax within the macro body itself.

In Nulan, that isn't a problem either. A macro is essentially a function from Code to Code, so the macro body is compiled/macro expanded/type checked just as if it were a function.

Thus any type overloading will happen inside the macro body, before the macro is ever run.

That does mean that the type checker must be able to overload based solely on the types found within the macro body. In other words, it cannot dynamically dispatch.

----

I don't think it's possible for the primitives to be macros, for the simple reason that the language needs axioms.

If you mean that the primitives should appear to be macros (even though they're implemented with compiler magic), then I agree with you.

4 points by rocketnia 3796 days ago | link | parent | on: Arc implementation in C++

Whoa, less than 24 hours old. :)

It looks like the author forked their existing project Arcadia[1] to make Arc++, and difference has something to do with the memory management strategy (adopting C++'s shared_ptr).

[1] https://github.com/kimtg/arcadia

3 points by rocketnia 3796 days ago | link | parent | on: ASK: is arc used in production?

Yeah! There's a certain way that it's really clear that macros and statically typed code can work together; just run the macros before interpreting the static types. Thanks for demonstrating that. I do think this can do everything Arc can do, like you say.

There are a couple of ways I think that can get more complicated:

In languages that resolve overloaded names in a type-directed way, I think the reconciling of static types and macros gets quite a bit more challenging due to the underlying challenge of reconciling name resolution with macros.

For instance, I think Idris has different meanings for the name (,) depending on if it occurs as a value of type (Type -> Type -> Type) or a value of type (a -> b -> (a, b)). In one case it's a constructor of tuple types (a, b), and in another case it's a constructor of tuple values (a, b).

Idris's macro system actually seems to have some special support for invoking the typechecker explicitly from macro code, which I think helps resolve names like those. I haven't actually succeeded in writing macros in Idris yet, and it seems to be a complicated system, so I'm not sure about what I'm saying.

Secondly, one potential goal of a macro system is that all the language's existing primitive syntaxes can turn out to be macros. That way, future versions of the language don't have to inherit all the crufty syntaxes of the versions before; they can stuff those into an optional library. If the language has sophisticated compile-time systems for type inference, term elaboration, name resolution, syntax highlighting, autocompletion, etc., then hopefully the macro system is expressive enough that the built-in syntaxes are indistinguishable from well-written macros.

Arc already gives us things like (macex ...) that can distinguish macros from built-in special forms, so maybe seamlessness isn't a priority in Arc. But if it were, and Arc had static types, we would probably want Arc to have type inference as well, which could complicate the macro system.

A lot depends on what Paul Graham expects from "true macros."

3 points by Pauan 3797 days ago | link | parent | on: ASK: is arc used in production?

> static typing seems to preclude true macros

I may be wrong on this, but it seems to me that static typing does not prevent macros at all (true or otherwise).

I switched Nulan to use static typing, yet it's using the same kind of macro system that it used when it was dynamically typed.

As far as I can tell, a macro is simply a compile-time function that accepts code and returns code. If so, then its static type is "Code -> Code".

In Nulan, the Code type might be defined like this:

  (TYPE Code
  | (*integer Integer)
  | (*number Number)
  | (*string String)
  | (*symbol String)
  | (*gensym Integer)
  | (*list (List Code)))
In other words, it can be an integer, number, string, symbol, gensym, or list of Code.

Within the macro's body, you can pattern match on the Code, you can map/filter on it just like in Arc, you can dynamically return Code, etc.

In Nulan, this is made easy with the & syntax, which is just a shorthand for the Code type:

  # These two are equivalent
  &1

  (*integer 1)


  # These two are equivalent
  &(foo 1 2)

  (*list [ (*symbol "foo") (*integer 1) (*integer 2) ])


  # These two are equivalent
  &(foo ~a ~b)

  (*list [ (*symbol "foo") a b ])
And the & syntax works when pattern matching as well:

  # These two are equivalent
  (MATCH foo
  | &(foo 1 2)
      ...)

  (MATCH foo
  | (*list [ (*symbol "foo") (*integer 1) (*integer 2) ])
      ...)


  # These two are equivalent
  (MATCH foo
  | &(foo ~a ~@b)
      ...)

  (MATCH foo
  | (*list [ (*symbol "foo") a @b ])
      ...)
As far as I can tell, this allows Nulan macros to do everything that Arc macros can do, even with a static type system.
3 points by rocketnia 3797 days ago | link | parent | on: ASK: Is arc better than clojure?

This StackOverflow answer ends with "I'd recommend a real anaphoric macro" and gives an example: http://stackoverflow.com/questions/9764377/how-to-avoid-anap...

Based on that, I found this way to write aand, which seems to work at http://www.tutorialspoint.com/execute_clojure_online.php:

  (defmacro aand
    ([] true)
    ([x] x)
    ([x & next]
     `(let [~'it ~x]
        (if ~'it (aand ~@next) ~'it))))
  
  (prn (aand "woo" (list it it) (list it it it)))
It looks like Clojure macros can capture variables in the other direction too, like Arc:

  (defmacro capture-it
    ([] 'it))
  
  (prn (let [it "woo"] (capture-it)))

That looks like a system of linear equations:

  1 * larger - 5/2 * smaller = 0
  2 * larger - 2 * smaller = 12
One algorithm for solving these is Gaussian elimination. If you're using Anarki (https://github.com/arclanguage/anarki), there's already a ready-made implementation in math.arc!

  arc> (load "lib/math.arc")
  nil
  arc> (gauss-elim '((1 -5/2) (2 -2)) '(0 12))
  (10 4)
There's probably no way you could have known where to find this unless you asked, so thanks for the question. Please let us know if you have further questions about how to use this, or if you'd like to know more about any of these concepts.
More