Arc Forumnew | comments | leaders | submitlogin
1 point by rocketnia 4816 days ago | link | parent

"If the interpreter never throws errors it lets you build other languages atop it without abstraction leakage."

I don't see the advantage. If calling 'car on a non-cons gives me a value that I can't tell was caused by an error, then if I want a leak-proof abstraction I'll do anything I can to detect the error in a separate step from calling 'car, just as I would if 'car raised an exception.

An exception with an error message is at least nice for detecting that there's a problem and troubleshooting it, even if the message is as obscure as "Can't take car of 1".

---

"TCO is just an optimization and has nothing to do with the evaluation model ^_^."

Tell that to my lathe.js and chops.js, which I'm having trouble getting to work on Firefox because its JavaScript stack is small. XD I have a lot of ifsomething( ... ) utilities that take callbacks and tail-call them (CPS), and that pattern just doesn't seem to work out. :-p

Anyway, I'm not complaining about JavaScript necessarily. I knew about the lack of TCO from the outset. Whatever way this forces me to redesign lathe.js will help with Penknife, which I don't expect to have TCO either (for straightforwardness's sake, and because unfortunately Penknife/Lathe/'extend rulebooks don't call their rules in tail position anyway).

---

"I don't even know what sort of support I want for early returns."

That can be implemented in a standard library as long as there are exceptions that can hold arbitrary contents. I implement early returns in lathe.js's point(), for instance--which, since it isn't a standard part of JS, means it doesn't necessarily interact well with other people's exception-handling code. :-p

---

"I don't understand continuations well enough to implement them."

What you're doing with pushing and popping lexical and dynamic scopes seems about halfway to continuations. If you also push expressions on a stack and evaluate them in a separate loop, the combination of scope stacks and an expression stack is basically a continuation. To capture a continuation, copy the stack(s); to call it, restore the stack(s) and push a return value. Something like that anyway. :-p (If you don't understand continuations from a language user perspective, I guess I don't expect this explanation to help.)

I haven't tried to implement partial evaluation/specialization yet, but I expect it to kinda work the same way. To specialize a function, start some fresh stack(s) for it with special dummy values in place of the arguments, somehow step the calculation forward as far as possible (without doing I/O--including variable lookup--or doing any inspection of the dummy values), and copy the stack(s) back off as the result. I think it'd be pretty difficult. ><;

---

"What would unifying strings and syms accomplish?"

For me it's more like: What does separating them accomplish? The way I use Arc, they're both interned, immutable, finite sequences of arbitrary characters. The fact that they have different types means the meaning of a single character sequence can be overloaded ("nil", especially), but for the most part I just coerce them back and forth to appease the language.

---

"But maybe it's just my C++ roots showing."

I didn't know you had C++ roots until now. :)



1 point by akkartik 4816 days ago | link

"If calling 'car on a non-cons gives me a value that I can't tell was caused by an error, then if I want a leak-proof abstraction I'll do anything I can to detect the error in a separate step from calling 'car, just as I would if 'car raised an exception."

Yeah you're right, I was making no sense. Or at least I've forgotten the concrete situation I was (over) reacting to.

Wart does throw a message: 'car of non-cons: 1'. It's just a warning, it doesn't halt execution, but I'm still contradicting myself by that decision.

-----

1 point by Pauan 4816 days ago | link

I'll note that in my code I frequently have to use errsafe, because the thing may not be a cons. For instance, suppose you had a table called "foo". I've been using this pattern a lot recently:

  (if (foo:car x) ...)
But that will break if x isn't a cons, so I have to do this:

  (if (errsafe:foo:car x) ...)
So I don't think it's necessarily a bad idea for car/cdr to return a value rather than throw an error... but I can see why some people would prefer it to throw an error. For me personally, I think my code would benefit more from car/cdr returning nil, rather than throwing an error.

-----

1 point by rocketnia 4815 days ago | link

I'd use this:

  (if (foo acons&car.x) ...)
...except maybe I wouldn't, 'cause I think Rainbow treats a&b.c as (andf a b.c).

-----

1 point by akkartik 4816 days ago | link

"they're both interned, immutable, finite sequences of arbitrary characters."

There aren't constraints against it, but I tend to think of strings as binding-less things. They're closer to numbers in that respect.

I often use syms when I mean strings (one less keystroke, no need to hit <shift>). But I only convert strings to syms inside macros.

-----