Arc Forumnew | comments | leaders | submit | Zak's commentslogin
2 points by Zak 3944 days ago | link | parent | on: Where are we going?

>It doesn't have TCO due to JVM limitations

This is only half-true. Clojure cannot automagically convert a self-call in the tail position in to iteration, but it does have the recur form to provide essentially the same semantics. I've also found it useful that recur throws an exception if used outside of the tail position, making it obvious which recursive forms consume stack space and which do not.


2 points by Zak 4195 days ago | link | parent | on: Learning Arc?

I'll second the recommendation for Scheme in general and PLT Scheme in particular. Arc is built on top of PLT Scheme at the moment. Another great book is The Structure and Interpretation of Computer Programs (


5 points by Zak 4220 days ago | link | parent | on: Lispy web development alternatives

I've deployed a couple sites for customers on Hunchentoot, one using CLSQL with PostgreSQL. Unfortunately, that one's covered by an NDA. The other, I can talk about, but I won't post the URL as the nature of the application means that random people using it would only serve to irritate the customer.

It's a web-based file transfer system allowing anyone to send files to the customer's employees and the employees to send files to anybody. It sits behind Apache using mod_proxy and gets its main template by loading a Wordpress page over http. Wordpress can play nicely with it since the html template library does everything in comments.


Hunchentoot is really nice and hackable. One highlight: I added an :around method on dispatch-request to check to see if an IP is banned, and handle the request appropriately.

Like most Lisp web systems, you can get a REPL on a running server. I use detachtty for this.

You have a few options for how to install the app (lisp source, fasls, core images and with some lisps, a self-contained executable). They all work.

It's not a framework. You can do things how you want to without having to fight with your libraries.


I had some problems deploying on a VPS (Mediatemple DV plan, to be specific). SBCL and CMUCL didn't want to run, complaining about a memory allocation error. Limiting memory usage with the --dynamic-space-size argument works, but means setting a static memory limit for your app. I haven't had problems on two other VPS hosts, but some other people have.

You'll want to

  (setq cl-ppcre:*use-bmh-matchers* nil)
or you may run out of memory anyway. In fact, you'll probably want to do that most times you use cl-ppcre.

It's not a framework. You'll have to decide how to do everything, often choosing between several libraries with no obvious best choice, or writing it yourself.


Cool function, but perhaps not the best name for it. ac.scm is already an Arc -> Scheme compiler. You've added a function that recompiles a function using optimizations for a user-specified type signature. A name like signature or optimize might be better.


5 points by Zak 4280 days ago | link | parent | on: Score one for Arc

A couple years ago, I saw a description of Arc's let syntax and immediately thought it was the Right Thing. I added an implementation to my util.lisp file that goes in to just about everything I write:

    (defmacro let1 (var val &body body)
      `(let ((,var ,val))
I use it far more than CL's let.


4 points by Zak 4290 days ago | link | parent | on: New version

What is c-lisp? Do you mean GNU CLISP, an implementation of the Common Lisp language? Do you mean Common Lisp in general? I think the main reason for using Scheme as a host instead of CL is that Arc is more similar to Scheme than CL.


4 points by koder 4289 days ago | link

hi zak, i meant common lisp (CL), i thought Paul more inrested in CL and he didn't like to do his work in Scheme!


2 points by Zak 4299 days ago | link | parent | on: Arc for non programmers

I have to recommend avoiding newLisp; it's actually a very old-fashioned Lisp and most likely an evolutionary dead-end. Clojure is another new Lisp dialect that seems like it's worth a look. It runs on the JVM, which could be a big win in the short-term.


3 points by Zak 4299 days ago | link | parent | on: Multi-var function literal shorthand

I thought about using numbers like that too, but when I posted this I was too tired to remember why that might be a better idea. You're right - it would make more sense to use numbers, and if you're writing a function that's long enough that numbers would make it hard to read, use fn. Zero-indexed numbers with sigils to designate the place in the arg list are better.

  ([- $1 $2 $0] 1 3 2])
translates to

  ((fn ($0 $1 $2)
      (- $1 $2 $0))  1 3 2))
I don't like binding the sigil by itself to the second arg - it's starting to look like Perl. I'd even be in favor of eliminating the underscore and only using the sigil-number notation, with the special case that the sigil by itself is arg 0.


1 point by dreeves 4294 days ago | link

That's what mathematica does:

(#1 - #2 - #3)&[3,2,1]

with # equivalent to #1.

(By the way, mathematica is all s-expressions (or rather, equivalently, McCarthy's m-expressions) underneath. You can call FullForm on any expression to strip away the syntactic sugar, eg, FullForm[a+b] => Plus[a,b]. Note the f[a,b] instead of (f a b). A nice thing about the commas is that you can throw in infix wherever it's convenient, like If[x>2+2, B, b] instead of If[Greater[x,Plus[2,2]], B, b]. The best lisp solution I've seen for that is curly sweet-expressions: )


1 point by jimbokun 4298 days ago | link

([- (_ 1) (_ 2) (_ 0)] '(1 3 2))

What about that?


1 point by Zak 4298 days ago | link

Adding parens to make it more "lispy"? I don't see the point, really. Also, why are you passing it a quoted list instead of the actual values you want?


1 point by jimbokun 4298 days ago | link

Because this actually works in the current version of Arc. Maybe not quite as concise as the proposed syntax, but probably as close as you can get without adding syntax (at least that I can think of).

So you need to weigh the cost of adding more syntax to the language for the savings of "$1" vs. "(_ 1)".


1 point by nex3 4298 days ago | link

Note that the latter is more than twice the size of the former, and that you'd also need to put the arguments to [] into a list prior to passing them into the fn. I'd say $1 is a pretty big win in terms of conciseness.


3 points by Zak 4302 days ago | link | parent | on: Suggestion: partial application by default

Note also that I don't want to have to call par when the function takes a fixed number of arguments. I want to be able to do this:

  (= foo (cons 'bar))
  => #<procedure: foo>
  (foo 'baz)
  => (bar . baz)


1 point by sjs 4302 days ago | link

I think this would be great, but it'll take some work. For example right now Arc compiles s-exps to mzscheme, so it would need to change mzscheme's semantics (not sure if this is even practical or possible). Arc most likely needs to stand on its own a little more before this will be feasible.


1 point by Zak 4302 days ago | link | parent | on: Suggestion: partial application by default

Probably not, but it's still useful as a generic way to write generator functions. Your par macro isn't working as expected for me. Is this a bug, or am I using it wrong?

  (def accgen (n) (par ++ n))
  #<procedure: accgen>
  arc> (= foo (accgen 5))
  arc> (foo 8)
  Error: "Function call on inappropriate object #3(tagged mac #<procedure>) (5 8)"


1 point by rkts 4302 days ago | link

Well, I was thinking par would be call-by-value. So your accumulator would have to be something like

  (def ref (x) (obj contents x))

  (def ++ref (x (o by 1)) (++ (x 'contents) by))

  (def accgen (n) (par ++ref (ref n)))
I don't know if a call-by-reference par could be implemented using macros. I also don't know that that's a good idea, since it could lead to bugs when mutation is involved.

  (= fns nil)

  (= x 1)
  (push (par + x) fns)

  (= x 2)
  (push (par + x) fns)

  (= x 3)
  (push (par + x) fns)

  (map [_ 1] fns) => (4 4 4)  ; probably not what you want
Edit: I think the issue is that we have slightly different definitions of partial application. You are thinking of it as a sort of syntactic sugar on top of closures, whereas I (being primarily an ML programmer) am used to thinking of partial application as a function call. So that's why we have different intuitions about how it should work.


1 point by rkts 4302 days ago | link

By the way, why are you bothering with generators? Arc being an exploratory language, the idea seems to be to use lists for everything, at least at first. Iterators/generators are often a premature optimization.


1 point by sjs 4302 days ago | link

Did you mean to write (def accgen (n) (par + n))?


3 points by Zak 4302 days ago | link

I did not: an accumulator increments. See