Arc Forumnew | comments | leaders | submit | aw's commentslogin

Thank you!

-----


I think the question of configuration and dependencies is a very interesting one. I've also found that it can be too inflexible to have libraries declare their own dependencies (through the usual "import" or "require" statement at the top of the library). My new version of the hackinator (https://github.com/awwx/hack) isn't doing enough to be useful yet, but it's an attempt to describe dependencies between libraries in a declarative way outside of the libraries themselves.

It opens the door another issue though: If you end up making two instances of a language core or a library, what if you want a value from one to mean the same thing in the other, but that value's meaning depends on something each module generates for itself, like a gensym or a mutable data structure?

Without a more specific example I can only guess... that if you have two instances that both depend on the same thing, you can either have one instance import that thing from the other; or else factor out that thing into a third location that the two instances independently import.

-----

3 points by aw 5220 days ago | link | parent | on: Effort to make it easy to use in production?

There are a lot of smart people on the Arc forum. So if you want to use Arc, and you said, "you know, I could use Arc for my project if only I knew how to do X in Arc", there's a good chance someone will be able to help you.

For example, my lang hack (http://awwx.ws/lang2, also in Anarki) lets you call Python libraries from Arc, and as it happens I've heard that it has been used in production (http://news.ycombinator.com/item?id=1814558). If my lang hack does what you need you can use it, or if there's something missing that you would need you can tell me what's missing for you and maybe I can help.

But you do have to be able to explain what it is that you need. One person says "can I use Arc in production?" and by that they mean "I need X, Y, and Z" and another person says "what would it take for Arc to be easy to use in production?" and by that they mean "I need A, B, and C"... and they're completely different things.

-----

1 point by d0m 5219 days ago | link

I understand your point but still, I was more talking about a collective effort to try to make Arc easier to use by other programmers that don't necessarily want to hack up a new implementation. But yeah, "production" is really vague.

-----

1 point by zck 5219 days ago | link

For what it's worth, everything I use Arc for is the Arc3.1 codebase -- I don't use Anarki, or any of the other alternative Arcs. What makes you think you have to "hack up a new implementation"?

As a side note, I have no idea what you mean when you say "hacking in Hack". What is the second "hack" there?

-----

1 point by d0m 5219 days ago | link

Wops, meant to say "hacking in arc"

-----

1 point by aw 5219 days ago | link

What would help make Arc easier to use?

-----

1 point by d0m 5219 days ago | link

Hard to say. For my use only, it'd be to make it easy to integrate it with python/django a little bit like clojure do it with java. Ideally python could call arc, and arc could call python. (But again, this is just an example). To make it really easy, we could do something like: easy_install django-arc.. I'm sure that would encourage more people to use it. No?

-----

2 points by zck 5219 days ago | link

Why do you want to use Python and Arc? What are you not getting from Arc that it would get from Python, or that Clojure gets from Java?

Many of us are using Arc because it's not Python. Getting more people to use it by compromising on its benefits wouldn't be a good thing.

-----

2 points by aw 5219 days ago | link

I call Python from Arc when there's a Python library that would be useful to me.

-----

1 point by Pauan 5219 days ago | link

"Many of us are using Arc because it's not Python."

"I call Python from Arc when there's a Python library that would be useful to me."

Yup, I agree with both of those. Python is ew compared to Arc, but it does have some nice libraries.

Incidentally, I started on Arubic for fun, to learn more about how an Arc interpreter works, and also to enable nice integration with Python. Then I can finally use multi-expression lambdas with Python. :P

Oh yeah, and change some stuff that I felt Arc was lacking in.

Plus, I like Python better than Racket. So if I'm going to hack in one of the two...

---

"http://awwx.ws/lang2 "

Seems interesting, but kinda heavy-weight. If the Python version of Arubic were in better shape, I might recommend that, but it doesn't have a Python compatibility layer yet, and I've gotten sidetracked implementing Arubic in ar/Arc.

-----

3 points by rocketnia 5218 days ago | link

Seems like there's a significant disconnect in this thread.

I think d0m's saying: Why do Arc folks do things like X by making a new language? Shouldn't we put features in Arc itself, if it's going to be a language people will actually use?

I think aw's saying: Why not ask instead, "How can I do X in Arc?" In fact, here's a way I do X without making a new language.

I think Pauan's saying: I'd like to do X, and aw's approach seems clunky. I think a new language would be better.

---

As I see things, d0m, we pursue our own languages because there are certain improvements we want to make that take a complete rework of the language.

Python interop is a great example. Clojure-Java interop is possible because they both run on the same rather high-level platform, the JVM. Official Arc runs on the Racket runtime, and Python (at least CPython) is its own whole runtime, so there aren't many ways to bridge the gap except for the C FFIs and the kind of IPC aw's lang hack uses. One of the best ways to get a clean integration between Python and Arc would be to reimplement Arc and/or Python to run on the same high-level platform--and yet that means reimplementing a language, rather than improving an existing one.

Or does it? The reimplementations may already exist. If you could use Jython for your Python project, then you could probably achieve a good degree of interoperability with Jarc and Rainbow, which are high-quality Arc implementations for the JVM.

---

But really I think Python interop was only one example, and your point was any that features we could put into the main Arc language should be put there. In that case, you'll need to define what counts as Arc.

There's an official release of Arc, maintained by Paul Graham, but keep in mind that he only updates once in a blue moon and tends to leave out features that aren't obviously necessary to him. A brief language implementation is one of his primary goals for Arc.

We do have Anarki, a community fork of Arc, but keep in mind that Anarki is held back a little by a desire to be similar to official Arc, so that the next time Paul Graham releases an update, it's easy to merge it in. This similarity also makes Anarki a bit more useful in practice, since it's compatible with most official-Arc code people write.

We could probably relax that policy on Anarki, but what big changes should we allow? I'd make radical changes and turn it into Penknife. Pauan would make sorta big changes and turn it into Arubic. It could be useful to make radical implementation changes and turn it into aw's ar, and akkartik may want to radically reorganize the project's file tree.

All in all, Arc's philosophy isn't well-defined and persuasive enough to drive us all toward the same future. Although we do want to make big changes, it's easy for us to be unsure about them or disagree. So we tend to experiment with big ideas by implementing them in our own language projects, where at least we know what we like.

If it helps, think of it this way: We don't make our own languages just to let Arc stagnate. We make our own languages so that we can improve Arc in various ways all at once. This fracturing is kind of unfortunate, but we still do build upon each other's ideas, so we're just advancing the state of the Arc in an unusual way. ^_^

Still, I suppose it means we have a community that's a little hard for non-language-implementors to appreciate. There are some less vocal people who talk about Arc only for Arc, like thaddeus and kens, but even then the topic can diverge to how our fractured Arc variants deal with the issue. :-p But you know, I wouldn't have it any other way. Maybe if the community were larger, we could have separate forums for in-Arc and around-Arc discussions.

-----

2 points by aw 5218 days ago | link

I suspect that for the most common uses the disadvantages of providing language interoperability in the same process outweigh the advantages, and so personally I'd be surprised if implementing Python and Arc in the same runtime would have much impact on the uptake of Arc. I could be wrong of course... and then I'd be surprised :-)

With respect to there being lots of variants of Arc, I think about Arc as a personal programming language. Thus that it allows extensive personalization, and people publish many personal variants, is to my mind a feature not a bug.

This diversity of course raises its own issues: we're concerned not just with interoperability between Arc and other languages, but interoperability between variants of Arc! :-) But solving this provides a more powerful platform than one stuck with providing the lowest common denominator of standard language features to ensure interoperability.

I also think that the idea of personal programming languages remains largely unexplored territory. Thus if there is significant uptake of Arc, I imagine it may not come at the expense of other languages, but instead it could be for new uses. Because of this belief I tend not to pay much attention when someone says "Arc should have X because other languages have it", but I'm very interested when someone says "I'd like to use Arc myself, and I'd be able to if only it had X".

-----

1 point by rocketnia 5218 days ago | link

"I suspect that for the most common uses the disadvantages of providing language interoperability in the same process outweigh the advantages"

I've never thought of that. I'm used to using Racket stuff from Arc without hesitation, but then the stuff I use is provided with the Racket language, like parameters and regexes. Most of my non-Arc personal code is in Java or Groovy, and I'm very glad I can use it from Rainbow, but I haven't actually done that yet....

Still, I can personally attest that this kind of feature has played a role in my adoption of languages, regardless of whether I've used it. :)

-----

1 point by thaddeus 5218 days ago | link

Through-out this whole thread I've wanted to kick in and say: "boy I wish Arc was built on top the jvm, similar to Clojure's implementation", but then I also realize one might as well just switch to Clojure if that's what one wants.

Would have been be nice though. Smart move by Rich.

-----

1 point by aw 5218 days ago | link

Why do you wish Arc was built on top of the JVM?

-----

1 point by thaddeus 5218 days ago | link

The way clojure implemented it allows for seamless integration between libraries. With clojure I can load and easily make use of any java code out there. I can use cron job libraries, database libraries etc. etc. And I really don't require much java knowledge, just a basic API used to call the library/jar file. This gets people on-board, hence larger community, building all kinds of kewl apps/libraries... More solutions, more knowledge base... Just more options.

With arc, the language syntax and base libraries are awesome, but you scratch your head more often, wondering" well how the hell am I supposed to do that. " And these problems/features are not small roadblocks... For example, if I need to use Arc connecting to oracle? - good luck, it's not going to happen.

If arc were built atop the jvm, the way clojure is... These problems all go away.

-----

1 point by thaddeus 5217 days ago | link

@aw/

Thanks for the offer. I think real database connections to arc could only improve the adoption + user happiness levels, but I will suggest connecting to oracle was just an example for the point I was trying to make.

What I am suggesting is not new or even surprising. Arc has no depth for libraries. Rich solved this problem right from the get-go by having tight integration with java. Arc would have had similar success had it done the same thing - too bad really. And dropping into Scheme just doesn't cut it.

I'm suggesting users of arc will google things like 'arc oracle', or even 'scheme oracle' which returns jack. With Arc you get Nada for google answers + you get unanswered posts such as these.

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

However google 'clojure oracle':

http://en.wikibooks.org/wiki/Clojure_Programming/Examples/JD....

step-by-step recipes to connect to a myriad of databases. This was made possible through Clojures tight integration with java. Clojure can import java libraries with 1 simple import statement.

Let's not forget that Clojure is a newer language than Arc - correct?

Now, I'm just looking at the title of the thread "Effort to make it easy to use in production?", and thinking - yeah, I can understand, that's why I moved over to Clojure and its too bad Arc didn't do this.

Sure I'm no expert in the programming language industry, but if I were to come up with a new spiffy language I'd rather do what Rich did. Arc could have been built atop the jvm - correct? It was just easier not to, considering arc was not about being practical, it was about attaining some elusive mystical idealized syntax that will be practical in, possibly, a hundred years from now.

Sorry if this sounds like a rant, but it just seems like the original poster wasn't getting much love, and I can appreciate what and why he/she was asking.

-----

2 points by aw 5217 days ago | link

When I started work on my Arc runtime project, the first thing I looked at was what I thought would be the best platform to write the runtime on top of. Racket seemed to be moving away from Arc in some ways, so I didn't start with the assumption that Racket was going to be the right choice. I looked at a number of options, and concluded that as far as I could tell that Racket still had the best mix of features.

The JVM naturally has the advantage that it's easy to call Java libraries, but it has the disadvantage that it has no built-in support for tail call optimization or continuations. Since it's not particularly difficult to make use of libraries running in a different process, it would be easy enough for me to use Java libraries from an Arc implemented in Racket if I wanted to, and so I had no compelling reason to write ar on top of the JVM.

There is a long history of languages written for people who want to use the JVM but who also want to be able to use a less terrible language than Java: Jython, Groovy, Clojure, etc. Since Clojure is a particularly nice language, it didn't surprise me that it rapidly gained popularity among people who want to use the JVM.

For any particular project that I may be working on, there are a mix of features that I need for that project. If I were working on a project that primarily needed to call Java libraries and I didn't need the features unique to Arc, I would most likely use Clojure myself (or Rainbow or Jarc, if it turned out that one of those were suitable to my project). If I were working on a project where the features of Arc were important and I also needed to call some Java libraries, I'd likely write it in Arc calling out to Java libraries.

Since this is a forum for Arc, I answer questions primarily from the perspective of Arc. Since typically a hundred people will browse a forum for each person posting, I primarily answer questions for the majority reading. For example, if someone makes a statement that is wrong, I will say that they are wrong, so that someone else reading the forum isn't left with incorrect facts.

When someone complains about Arc, I tend to suspect that either there's something they want, or else they just feel like complaining. People wanting things is useful. If someone actually wants X and says so, and we come up with a solution for them, then we also help the hundred other people who want that thing as well. Other the other hand, and I'm not saying that anyone has actually done this, but if someone were to sit at a computer and type in a complaint that other people haven't done the work to make Arc a popular language faster than some other language has become popular, that doesn't strike me as being particularly useful.

I'm not against complaining. Complaining is often a useful first step towards finding a solution. However, while I'm not trying to pass judgement, I am trying to discern whether someone is complaining because they just want to complain or because they want a solution.

Again, when I answer a question, I answer a question primarily for people in general reading the forum; and from the perspective of people wanting to use Arc. Thus if Clojure is a better solution for you for most of the projects that you work on, that's fine, I agree you should use Clojure. However when I read "for example, if I need to use Arc connecting to oracle? - good luck, it's not going to happen" my immediate concern is that someone else is going to read that and might be left with the impression that it's prohibitory difficult to connect to oracle from Arc... which, while it's certainly harder to connect to oracle from Arc than it is from Clojure, isn't all that difficult.

-----

2 points by thaddeus 5217 days ago | link

Being difficult or easy is a relative thing. The hours of investment by grade-a developers contributing to making these production grade feature-x's in other languages leads me to feel pretty comfortable suggest that having them, or a dozen other similar feature-x's would not be all that easy.

Sure, if you have spent hundreds of hours doing low level hacking between racket<->arc you can suggest these things are not all that hard, but the reality is that many of these feature-x's are just not going to happen.

Chances are that mainstream features are not a priority for the members here... And that's my message to the OP: go use Clojure or something having the features you want. I say this from 2 years of following arc, the arc forum and its members. There are probably a dozen submissions/comments about db connects and FFI, yet to this day nothing works.

The people on this forum, who know me, know I like the arc language, often promote it and that I'm not here to tear it apart, but I'm going to be real about it and make sure the op gets the right message (from my perspective).

-----

1 point by thaddeus 5217 days ago | link

@aw/

> "If you like the Arc, then instead of complaining that other people aren't figuring out what you'd want to use for you, why not take the time to help and describe what you would need in a db connection library and FFI?"

I'm thinking if you re-read the thread starting from my first comment (http://arclanguage.org/item?id=14539), you'll hopefully come to understand that I haven't been complaining, but rather I have been defending/substantiating my suggestions and thoughts.

As for why I don't take time to describe some spec, well because I'm not asking for anything and I've chosen to spend the bulk of my time learning Clojure and building applications. I guess you could say I take my own advice.

> "If you want some love on the forum, there's an easy way to get that:make a useful contribution."

It's pretty obvious, based upon your replies, that you don't see my posts as valuable contributions, but maybe you'll come to understand these posts are intended to help the OP rationalize his topic, not to gain some form popularity/acceptance with or by you.

-----

1 point by aw 5217 days ago | link

oh, I don't mean to be impugning your intentions, and I apologize if I did so.

-----

1 point by aw 5217 days ago | link

If you like the Arc, then instead of complaining that other people aren't figuring out what you'd want to use for you, why not take the time to help and describe what you would need in a db connection library and FFI?

Or, you could add a page to the wiki describing the ways that Clojure is better than Arc.

If you want some love on the forum, there's an easy way to get that: make a useful contribution.

-----

1 point by aw 5218 days ago | link

Would you like to be able to use Arc to connect to oracle?

-----

1 point by rocketnia 5218 days ago | link

What about Rainbow and Jarc?

-----

1 point by thaddeus 5218 days ago | link

I have to go back and check them out... See how they load other jar files or if they do, but good idea - thnx

-----

1 point by rocketnia 5218 days ago | link

If the JARs are in the classpath, the classes are just as accessible as any standard platform class like java.util.Map. I give a demonstration here, where I explain the custom interface I built so I could sometimes use the same code on both platforms: http://rocketnia.wordpress.com/2010/06/01/lathes-arc-to-impl...

Since then, Jarc's actually added Rainbow compatibility functions, so you might be able to get away with writing code just for Rainbow without leaving Jarc too far behind. Rainbow's faster, but Jarc has a more straightforward implementation.

I recommend having one of the JARs be a language with eval, like Groovy, JRuby, or Clojure. Jarc and Rainbow convert certain values to/from Arc in ways that are nice most of the time but sometimes lose precision, like the distinction between Boolean.FALSE and null.

-----

3 points by akkartik 5218 days ago | link

Bravo. I'm bookmarking this comment. Next time we get a question about fragmentation I'll point to the final section.

---

I didn't plan to hack on programming languages when I started playing with arc. Creating new languages/implementations is an occupational hazard of hacking on arc. Or maybe it's a pleasant side effect that we get for free (a viral - and rapidly mutating - language). Depends on how you look at it.

---

I think it's beneficial that these variants aren't splitting off into their own communities. They're able to recombine features from each other. wart stole its iteratively-refined interpreter cond from ar. Pauan's gotten me thinking about message passing.

-----

1 point by aw 5219 days ago | link

Hmm, it sounds like there are three pieces to the puzzle:

a) Can one use Arc to call Python and call Python from Arc? Yes.

b) Could you, if you wanted to, learn how this is done and package it up in a way so that it would easy to use? Sure, you could do that, if that was a way that you'd like to contribute.

c) Would this encourage more people to use Arc? I don't know. This forum might be the wrong place to ask that question, since people here already use Arc.

-----


Yes, once a macro has been used then redefining helper functions won't affect code which has already been compiled. (New or reloaded code which uses the macro will get the redefined helper function).

It makes the helper functions act like macros in that way: redefining a macro won't affect code which has already been compiled either.

-----

3 points by rocketnia 5220 days ago | link

I like your approach a lot, aw, but I too noticed this issue. I think it can be overcome just by changing the idiom slightly.

First, some definitions:

  (def fn-latemac (mac-getter)
    (annotate 'mac
      (fn args `(,(mac-getter) ,@args))))
  
  ; Not to be hypocritical, let's implement 'latemac as if by using
  ; 'latemac.
  (mac latemac (globalvar)
    `(,(fn-latemac:fn () fn-latemac) (fn () ,globalvar)))
Now we can define your example 'foo and 'bar like this:

  (mac foo ()
    `(,latemac.do
       (,latemac.prn "this is macro foo expanding into bar")
       (,latemac.bar)))
  
  ; Oops, now let's define 'bar. Go go, late binding!
  (mac bar ()
    `(,latemac.prn "yo, this is macro bar"))
As you can see below, this already works in the current version of ar. ^_^

(For future reference, I'm using https://github.com/awwx/ar/commit/c375d77bd2dbf6ca8850fda5f6.... )

  arc> (foo)
  this is macro foo expanding into bar
  yo, this is macro bar
  "yo, this is macro bar"
  arc>
    (def bar ()
      (prn "hi, this is bar"))
  *** redefining bar
  #<procedure:g1590>
  arc> (foo)
  this is macro foo expanding into bar
  hi, this is bar
  "hi, this is bar"
Essentially, these are hygienic macros at this point. They use the syntactic closure technique for hygiene, in this case implemented using regular old lambda closures. ^_^ A syntactic closure approach has undesirable properties like making the expansion hard to code-walk or serialize, but those activities seem rare enough anyway, probably because they're already difficult. I think this'll do just fine as far as modules go.

-----


Of course you can make and publish any changes you want, it's open source so you don't need my permission to do anything :-). Perhaps you're asking whether I'll merge your changes into my version? A goal of ar to make Arc more hackable, so ideally ar would be powerful enough that someone could implement e.g. keyword arguments as a library. Smaller changes will often be easier to digest, so saying "I could implement keyword arguments if only ar had X" is more likely to win me over to thinking about the best way to add X to ar.

With respect to backwards compatibility... since ar is supposed to be hackable, one of the ways it should be hackable is to get it to produce a runtime that is mostly compatible with Arc 3.1. But on the other hand, if someone wants to implement a language which is completely incompatible with Arc 3.1, they should be able to do that as well.

-----

1 point by Pauan 5221 days ago | link

Yeah, I was asking more along the lines of "merging into official ar"; obviously I can do whatever I want in my personal fork. Or with Arubic.

---

"[...] ideally ar would be powerful enough that someone could implement e.g. keyword arguments as a library."

Would be awesome if we could figure out a way to do that.

---

""I could implement keyword arguments if only ar had X" is more likely to win me over to thinking about the best way to add X to ar."

I'll give some thought about the precise requirements for keyword args. Message passing too.

---

"With respect to backwards compatibility... since ar is supposed to be hackable, one of the ways it should be hackable is to get it to produce a runtime that is mostly compatible with Arc 3.1. But on the other hand, if someone wants to implement a language which is completely incompatible with Arc 3.1, they should be able to do that as well."

Yes, but if the changes need to be done in the core (and not as a library on top of the core), then backwards compatibility does become an issue, since you've already stated you're trying to be mostly-compatible with pgArc. Ideally, any backwards incompatible changes will be done to make ar as hackable as possible, lessening the need to change the core in the future.

-----

1 point by aw 5221 days ago | link

> "[...] ideally ar would be powerful enough that someone could implement e.g. keyword arguments as a library."

Would be awesome if we could figure out a way to do that.

The compiler is reflected into Arc so if all you need to do is make compiler changes you can do that by modifying "ac" or the functions it calls such as "ac-call". If the feature also needs to make runtime changes then we might need to add some hooks to the runtime to enable that.

-----

1 point by Pauan 5221 days ago | link

Hm... interesting. In that case, I might be able to implement Arubic as a bunch of extends and maybe some supporting functions... then Arubic would basically be a thin skin over ar. I'll look into it.

-----

1 point by aw 5221 days ago | link

This is a goal of ar: I don't know if it's actually possible or not, but ideally you should be able to implement Arubic as a library on top of ar :-)

-----


(note that this is completely different than my experiment yesterday with Arc-style macros in Racket, in case you were wondering)

-----


Yes. (That's what I meant by "the helper functions can be defined with a plain 'define' instead having to use 'define-for-syntax'")

But it then doesn't work with modules for the same reason. So it's not a solution yet, it just pushes around what doesn't work from one place to another.

-----

1 point by aw 5222 days ago | link

Hmm, we should think about whether we'd want to use Racket modules anyway. Racket macros are more expressive (albeit harder to write) than Arc macros because they operate on syntax objects. But Racket modules don't seem very expressive to me: they aren't first class objects and they aren't parameterizable.

I'm guessing that a module system in the spirit of Arc would correspond more to Racket namespaces. Maybe I ought to be able to say something like:

  (module arc
    (load "foo.arc")
    (bar))
which creates a new namespace, populates it with values from the arc namespace, evaluates the expressions within that namespace, and returns the namespace. Or something like that.

-----

1 point by Pauan 5221 days ago | link

Which, incidentally, is already possible with namespaces + eval accepting a second parameter:

  (mac module (name . body)
    `(let ,name (new-namespace)
       (eval '(do ,@body) ,name)
       ,name))
Such a tiny change (namespaces + eval) has a lot of power, I think. Personally, I'd prefer this:

  (w/namespace (new-namespace)
    (load "foo.arc")
    (bar))
Because then you can do this:

  (import foo "foo.arc"
          bar "bar.arc")

  (w/namespace foo
    ...)

  (w/namespace bar
    (load ...)
    (load ...)
    ...)

  (w/namespace (current-namespace)
    ...)
  
  (w/namespace (current-environment)
    ...)

  (w/namespace (table)
    ...)
But it's not a big deal, since both `module` and `w/namespace` are easy to write as macros. So you can use whichever you want. :D

-----

1 point by aw 5221 days ago | link

So it's not a solution yet

On the other hand, if namespace modules do turn out to be a good idea, then it doesn't matter that it doesn't work with Racket modules :)

-----

1 point by aw 5226 days ago | link | parent | on: Catching and inspecting exceptions

I finally remembered this morning that Arc already does have a mechanism for passing a value up through multiple layers of code execution by using continuations: point (and the derived macro catch/throw).

point can be used in the kind of situation that you might want to use Racket's raise for. In fact, you can think of point as a macro that creates a "raise" function.

Python doesn't have continuations, so the only way to break out of multiple layers of function calls at once is by catching and throwing an exception.

There are situations where something happens in a program that we expect to happen (at least sometimes), and we need to stop doing what we're currently doing and start doing something else, and often pass some data along that we need.

However, I noticed in production code written in Python where throwing and catching an exception is used to implement this, it's not uncommon for the implementation to also catch other exceptions that the programmer didn't expect... leading to real errors arising from bugs not being reported.

So I think for this scenario at least, using point/catch/throw is a better mechanism because it's explicitly only catching the things you plan to throw, and thus leaves handling unexpected conditions (things you didn't plan for, and so are actual bugs in your program) to the error handling mechanism, where you want debugging information like the source code line location and so on.

Which in turns leads me to suspect that perhaps errsafe is the wrong choice for handling errors opening a file... but that would be the subject of a different post :)

-----

1 point by Pauan 5226 days ago | link

Yes, I agree with you. catch/throw does seem better than using exceptions for everything. Python's infatuation with exceptions doesn't seem like the best course of action.

However, that does raise one question: should we have exceptions at all?

Note: I do actually want to use `err` in my program, because I want all execution to halt. I just want it to halt after all the errors are finished, rather than after only one error.

Perhaps I should use (quit) instead... does that automatically close any files opened by Arc?

-----

2 points by aw 5226 days ago | link

Perhaps I should use (quit) instead... does that automatically close any files opened by Arc?

Yes. quit exits the process, and the operating system closes all open files when the process terminates.

However, that does raise one question: should we have exceptions at all?

We still do want a mechanism for reporting actual program errors. Things that are truly bugs. For example, a division by zero exception is always avoidable by not passing 0 as the divisor. I dislike using a try-catch mechanism in my program for checking for things like dividing by zero, because I end up catching other cases of dividing by zero that I didn't intend to, which are actual bugs. So if I expect I might have 0 as a divisor, I prefer to check for it explicitly before calling /. Thus (when I write programs the way I like to), any actual division by zero exceptions that get thrown are in fact actual bugs. Which I then want to capture and report with lots and lots and lots of debugging information.

-----


(x 1 y 2) -> (x: 1 y: 2)

Do we need the colons? That is, if we leave them off, is there anything that doesn't work?

Association lists could be (x 1 y 2) instead of ((x 1) (y 2)), and ('(x 1 y 2) 'y) could be implemented to return 2.

I have a hack that implements ('((x 1) (y 2)) 'y) to return 2 so that I can use a!y with association lists; it would work as well if association lists were represented without the extra parentheses.

-----

1 point by Pauan 5227 days ago | link

"Do we need the colons? That is, if we leave them off, is there anything that doesn't work?"

Yes! It's necessary to distinguish between keyword args and normal args:

  (foo x y :a 3 :b 4)
Sure, you could define keyword args to be separate... but I like the idea of unifying them, since they serve such a similar purpose. Plus, I like that there's a syntatic difference between a list that is used for sequential lookup, and a list that's used for key/value lookup. You may disagree.

In any case, you can freely mix alists, plists, plists with keyword symbols, and ordinary tables in your own code. The question of this post is: should keyword plists be supported at all?

I'm leaning toward yes, assuming we can solve the questions I presented. And then, rather than making data types tables, I could make them keyword plists, which is probably better since the number of keys is usually small.

-----

1 point by waterhouse 5227 days ago | link

> Association lists could be (x 1 y 2) instead of ((x 1) (y 2))

Nice, I never consciously realized that. (I suppose we've been seeing it all along in replacing (let ((a 1) (b 2))) with (with (a 1 b 2)), but I never thought about remaking alists that way.) I think the single drawback of actually doing that is that O(n) lookup is now O(2n). [Obviously, if lookup time is a bottleneck, you probably should replace the alists with something else, like... tables! or AVL trees.]

-----

1 point by Pauan 5227 days ago | link

It's an old concept, known as plists[1]. Common Lisp has them, and uses the same syntax that I'm proposing.

By the way, one benefit of alists is that you can iterate over them easier:

  (each '(k v) '((a 1) (b 2) (c 3))
    ...)
Compared to the following, with a plist:

  (each '(k v) (pair '(a 1 b 2 c 3))
    ...)
Which, incidentally, uses `pair` to create an alist, then iterate over that... I was thinking about how to solve this, and figured a form of destructuring might help:

  (each :(k v) '(:a 1 :b 2 :c 3)
    ...)

  ; or this...?

  (each (:k v) '(:a 1 :b 2 :c 3)
    ...)
But that's still kinda up in the air at this point.

---

* [1]: http://www.gigamonkeys.com/book/practical-a-simple-database....

http://www.ida.liu.se/imported/cltl/clm/node108.html

http://www.augustana.ab.ca/~mohrj/courses/common/csc370/lect...

(Search for "property" to jump to the relevant portions.)

-----

1 point by Pauan 5227 days ago | link

Oh! By the way, I could define it so plists work with and without keyword symbols:

  ('(x 1 y 2) 'y)    -> 2
  ('(:x 1 :y 2) 'y)  -> 2
  ('(:x 1 :y 2) ':y) -> 2
This would also let you use arbitrary lists as indexes:

  ('((a b) 1 (c d) 2) '(c d)) -> 2

-----

1 point by aw 5228 days ago | link | parent | on: Catching and inspecting exceptions

Aside from using raise which probably would be better anyway, I wonder if there would be any reason not to have on-err pass the "details" (the exn-message) of the exception object to the on-err error handler, instead of the exception object itself.

-----

1 point by rocketnia 5228 days ago | link

I think the message can only be a string, which makes it a bit difficult to do interesting things in the handler.

-----

1 point by aw 5228 days ago | link

yes, right now in Arc 3.1 if I catch (err "foo") with on-err, I have to use details to extract the string "foo", but with your idea of using raise we'd get the string "foo".

So in this way your idea and my idea would work out the same: both would pass the string "foo" to the handler when (err "foo") was used.

A difference would be primitive errors generated by Racket, with my approach the handler would get the string like "/: division by zero" while with your implementation the handler would still get the exception object.

I don't think we'd want it to matter if errors are generated internally by Arc or Racket, so assuming that we do want to continue to raise errors in Arc with (err "foo") then I'm guessing we'd want to special case Racket exceptions and pass the exn-message string to the handler so that it would end up working the same way.

By the way I don't think you do want to use call-with-exception-handler; if the handler returns then then Racket invokes the next exception handler in the chain, so it's like re-raising the exception. But the with-handlers form works fine with arbitrary values raised by raise.

-----

1 point by rocketnia 5227 days ago | link

"I don't think we'd want it to matter if errors are generated internally by Arc or Racket, so assuming that we do want to continue to raise errors in Arc with (err "foo") then I'm guessing we'd want to special case Racket exceptions and pass the exn-message string to the handler so that it would end up working the same way."

That actually makes me wonder if Arc should have access to 'raise as a separate function from 'err. After all, if we catch a Racket exception as a string, we lose information.

For all I know, losing that information isn't so bad. I almost always design code so it never throws exceptions that should be caught, so I don't know what information is useful to have in an exception. I've only encountered two places it makes sense to capture an exception:

- When the exception implements an escape continuation, in which case the necessary information is the unique identity of the catch point.

- When the program is something like a REPL or server that handles multiple commands and should typically recover from an error encountered in any one command. In this case, the necessary information is whether the error should be considered severe enough to take down or restart the particular command loop in progress. The usual approach to representing this information is a hierarchy of types such that, if you say exn:fail is okay, you implicitly say exn:fail:contract:divide-by-zero is okay. Is there a better approach?

---

By the way I don't think you do want to use call-with-exception-handler; if the handler returns[...]

That handler doesn't return, but good point.

Reading over the reference some more (http://docs.racket-lang.org/reference/exns.html), it looks like there are some potential things to consider with breaks:

"...the exn:break exception typically should not be caught..."

"Before any predicate or handler procedure is invoked, the continuation of the entire with-handlers expression is restored, but also parameterize-breaked to disable breaks."

Would it be better or worse to switch to 'with-handlers*, which doesn't disable breaks?

-----

More