I was under the (possibly mistaken) impression that arc didn't support the recent versions of MzScheme because their variables aren't. Has that been changed?
I think that running Nginx as a frontend to Arc is relevant since there may be issues related specifically with the interaction between the two. Of course there might not be, but how would you know until you got into it? For example I'm running Perlbal as a frontend to Arc, and it gets messed up when Arc send a response without carriage returns in the headers but has a carriage returns in the beginning of the body. That's something that it's unlikely that anyone else is going to run into.
And if you're thinking of a Arc -> coffee-script tool, who knows, there might be some things that even if coffee-script is cool in general, might be unusual or problematic in the context of Arc.
I suppose "talk about anything as long as you include an obligatory Arc reference" might be going too far :-) but I suspect the line is further out than you've drawn it ^_^
I'd go farther - it doesn't even have to include an obligatory arc reference. The number of users here is small enough that the usual rules are less important. Especially if it's occasional (the front page is still mostly arc) and from someone we recognize, I think the handful of people here prob won't mind (or they'll respond to this if they do ;)
I'm finding out that creating a new destination site is crazy hard to do. The internet is mature; all of us have our habits, and it takes a lot to change. Just go where your audience is. If they don't like what you say they'll let you know, and you can then iterate.
hmmm. Good point. I suppose if no one replies to my 'other' items here, then a side forum probably would not work anyhow. And if I don't get replies to most of them - I'll probably get the hint (at least one would hope)... :)
At this point, I think that more posts is probably a good thing, even if they're only slightly related to arc.
A lot of people like me probably don't check all that often because there isn't much going on. If we can increase the number of comments/submissions to a slightly higher level, it will probably encourage more return visits, and better community interaction. Sure, the quality should be kept high and this is the arc forum. But by all means, submit "other" posts, if only so that there's a reason to check more frequently. That would give the arc community a greater appearance of life, and allow the posts and questions that "really matter" to get more attention as well.
notice how I have a choice as to whether I want things evaluated or used as-is in the "w/foo" macro that I'm creating. I only used one comma with "param", and so it was delivered as-is into the generated macro. I used two commas with "name", and so it was evaluated, and its value "foo" was inserted.
If in a two level quasiquote an unquote one level down was immediately evaluated then I'd have no way of inserting the ",param" into the macro I'm creating. And at the time that my outer "implicit" macro runs, "param" doesn't even exist yet.
You're totally right about the way it works (except for your example; the generated macro actually has (defvar-impl ,'foo) which is effectively the same), but being able to choose isn't the issue, I think.
If quasiquote didn't account for nesting, all we'd have to do is this:
To clarify a bit, the ,', idiom doesn't have the same effect in both cases. It essentially breaks out of nested quasiquotes and breaks into non-nested ones. This is thanks to the fact that in the nested case the inner unquote applies first, and in the non-nested case the outer unquote applies first.
We can even simulate this non-nested behavior right now by writing our quasiquotes within ssyntax, so as to hide the inner ones from the quasiquote compiler:
(And for what it's worth, this change should affect the generated macro by removing the extraneous ,' in (defvar-impl ,'foo).)
~~~
With this in mind, why do we use nested quasiquotes? I'm guessing it's because code is easier to edit this way. We get to wrap a quasiquote template in another template (or to reverse that process) without having to go through and edit every single unquote form. We only edit the unquotes that break out of the wrapping, and we'd have to edit those anyway.
It's annoying that arc's t is reserved, I use t a lot as a temporary variable in other programming languages.
Actually Arc's t is not reserved:
arc> (let t 3 (+ t 4))
7
arc> t
t
t is merely a global variable; and you're free to make a local variable which happens to have the same name as a global variable.
You can do the same with function names, as functions are a global variable which contain an fn:
arc> (map even '(1 2 3 4))
(nil t nil t)
arc> (let map 3 (+ map 4))
7
arc> (map even '(1 2 3 4))
(nil t nil t)
The only place where you'll run into trouble is if you attempt to "call" a local variable that has the same name as a macro:
arc> (let foo even (foo 4))
t
arc> (let each even (each 4))
Error: "procedure each: expects at least 2 arguments, given 1: 4"
Here "each" being a macro trumps "each" as a local variable.
My turn to a comment on lisp. Let Blub, y = lisp, tables "How can you get anything done in Blub? It doesn't even have y."
I'm not familiar with Lua's tables, but in general when I've wanted to add something to Arc I've found it easy to do. So if I want to write a program in Arc but Arc doesn't have Y, I implement Y, and then I write my program.
I don't know if this is legal because I've copied some error messages from arc
If you were copying more Arc source than would be covered by fair use, the easiest thing to do would be to simply put your derived version under the same license as Arc, the Perl Foundations's Artistic License 2.0 (http://www.perlfoundation.org/artistic_license_2_0)
You'd want to avoid relicensing the Arc source (or a portion of it) under the MIT License as that license doesn't provide the end-user protections required by the Artistic license in paragraph 4 section c ii.
However I wouldn't worry about a couple of error messages :-)
Except you can't destructively update it. So it's really more of a global constant. This is an important caveat because it affects locally scoped ts, too.
arc> (= t 1)
Error: "Can't rebind t"
arc> (= nil 1)
Error: "Can't rebind nil"
arc> (let t 4 (+ t 1))
5
arc> (let t 4 (++ t))
Error: "Can't rebind t"
I imagine that's what made it seem reserved. You still probably shouldn't name variables t or nil.
Hmm, good point. Since it does no harm to change t when it is a local variable, I'd remove the restriction for that case.
I might even drop the restriction altogether, as it doesn't seem to have much useful purpose. I can break Arc just as badly by rebinding "car" or other variables, so why this particular effort to keep me from hurting myself?
Arc doesn't have Y, I implement Y, and then I write my program.
Its a bit long so I put it here: http://pastebin.org/94450
This is how awesome tables are. :) I see how lisps can implement many features... but I can't see how those features could include adding to the syntax...
However I wouldn't worry about a couple of error messages :-)
Okay I won't. :)
edit: in the pastebin post on line 14, by 'it' I mean 'OO'
I see how lisps can implement many features... but I can't see how those features could include adding to the syntax...
Actually, that's an interesting feature of several Lisps: reader macros. For example, in Arc you can make anonymous single-argument functions with some special syntax.
arc> [+ _ 1]
#<procedure>
arc> ([+ _ 1] 1)
2
In Common Lisp, you are resigned to the more verbose
[1]> (lambda (x) (+ x 1))
#<FUNCTION :LAMBDA (X) (+ X 1)>
[2]> ((lambda (x) (+ x 1)) 1)
2
What if we want the bracket syntax in Common Lisp? We can extend the parser to dispatch on certain characters, hence "reader macros":
Now when Common Lisp sees an open bracket, it will read from the stream until a closing bracket is found, then shove that all into a (lambda (_) (...)) form.
Arc doesn't have reader macros (though uses Scheme's for bracket functions; see brackets.scm), but they're an interesting way to work in new syntax (though it probably won't be much fancier than Lisp's already-minimal syntax).
Arc does, however, extend syntax in certain ways. I gave an overview of this so-dubbed ssyntax in another post: http://arclanguage.org/item?id=11179.
This is how awesome tables are.
1. Arc doesn't have destructuring assignment built in, though macros make it easy (see http://arclanguage.org/item?id=8122; it's a bit old, so set is now called assign). Otherwise, the standard approach is
arc> (= h (table))
#hash()
arc> (= h!a 1 h!b 2 h!c 3)
3
arc> h
#hash((b . 2) (c . 3) (a . 1))
2. In Lua, I gather that
t = { a = 1, b = 2, c = 3 }
is the same as
t = { ["a"] = 1, ["b"] = 2, ["c"] = 3 }
In Arc, this looks more like strings versus symbols (a datatype I don't think Lua has). Symbols are simply-compared blobs of text, so you often use them as keys in hash tables (e.g., that's what I did in 1). Macros give you a shortcut for this common case.
arc> (= h (obj a 1 b 2 c 3))
#hash((b . 2) (c . 3) (a . 1))
3. obj works by quoting the keys you pass in. Quoting literal data will just return that data, so strings can be used in obj, too.
arc> (= h (obj "a" 1 "b" 2 "c" 3))
#hash(("c" . 3) ("a" . 1) ("b" . 2))
4. We can't use ssyntax here as in 1 because of its inherent limitations. But we can still do
The standard libraries, e.g string, math, etc are tables. e.g math.sin, math.cos.
I wish Arc even had modules. :) But you could do the same thing, in principle.
arc> (= math (obj sin sin cos cos tan tan))
#hash((tan . #<procedure:tan>) (cos . #<procedure:cos>) (sin . #<procedure:sin>))
arc> (math!sin 3.14)
0.0015926529164868282
In fact, Arc uses this approach for sig.
arc> (type sig)
table
arc> (sig 'rand-key) ; looks like a fn call, but it's a hash lookup
(h)
arc> (n-of 5 (rand-key sig))
(urlend urform admin-gate caris trues)
Tables can have any value as keys besides strings, that includes functions and even other tables.
I think that goes for hash tables in general: anything that's hashable. ;)
arc> (def f (x) (+ x 1))
#<procedure: f>
arc> (= h (table))
#hash()
arc> (= (h f) 5)
5
arc> h
#hash((#<procedure: f> . 5))
arc> (h f)
5
arc> (= h2 (obj a 1 b 2 c 3))
#hash((b . 2) (c . 3) (a . 1))
arc> (= (h h2) 'hi)
hi
arc> h
#hash((#<procedure: f> . 5) (#hash((b . 2) (c . 3) (a . 1)) . hi))
arc> (h h2)
hi
lua doesn't come with it [OO] by default, but you can implement it with tables in a dozen lines
That's how Arc's "object system" works.
arc> (deftem object a 1 b 2 c 3)
((a #<procedure: gs1820>) (b #<procedure: gs1820>) (c #<procedure: gs1820>))
arc> (inst 'object 'a 5 'c 10)
#hash((b . 2) (c . 10) (a . 5))
A table can have a `metatable` (mt).
I think I understand what you're saying (it sounds a lot like Python's operator overloading), but I'd probably need to use Lua to appreciate it.
Here's a linked list created with a table.
Aha. I was expecting this earlier: in Lua, you can use tables to make arrays. It's all pretty unified syntactically, whereas Lisps tend to add functionality with Yet Another Macro (instead of overloading syntax).
arc> (def array values
(w/table a (on value values (= (a index) value))))
#<procedure: array>
arc> (array 'a 'b 'c)
#hash((0 . a) (1 . b) (2 . c))
arc> (array 'a (array 'b (array 'c (array))))
#hash((0 . a) (1 . #hash((0 . b) (1 . #hash((0 . c) (1 . #hash()))))))
If Arc had reader macros, we could make {...} expand into (array ...). But saying "hey, you could bolt that on with a function" is a bit disingenuous: we're still comparing apples and oranges.
Okay you got me. Lisp can do all that, too ;). About reader macroes: If arc had them and you really liked the {} syntax, would to write a macro for it? And what if you're writing an arc library, would it collide if other people did something else with their braces?
(it sounds a lot like Python's operator overloading)
re mt: (+ t t1) would fail because they aren't numbers. But if they overloaded the + operator then it would do something instead. Yes it's like python's op-overload but a bit better because of __index and __newindex.
But it's more important whether a language can do something nicely, which I don't necessarily claim Lisp can. After all, Turing machines can do all that, too. :)
would it collide if other people did something else with their braces?
You could hypothetically package the reader changes into their own modules so that you'd need to explicitly say which braces you're using, modules keep their changes local, etc. Anyone know of work done on this front?
Yes it's like python's op-overload but a bit better because of __index and __newindex.
So are __index and __newindex roughly like in the following (silly) Python code?
$ python
Python 2.5.4 (r254:67916, Jan 24 2010, 12:18:00)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo:
... def __init__(self, x):
... self.x = x
... def __getitem__(self, index):
... return self.x + index
... def __setitem__(self, index, value):
... self.y = index + value
...
>>> bar = foo(5)
>>> bar[10]
15
>>> bar[20] = 5
>>> bar.y
25
If so, I imagine that overloading table operators in Lua becomes all the more powerful since tables are so ubiquitous. Thanks for the explanations.
You could hypothetically package the reader changes into their own modules so that you'd need to explicitly say which braces you're using, modules keep their changes local, etc. Anyone know of work done on this front?
Hmm, giving the job of custom readers to modules strikes me as making implementing both modules and custom readers complicated and difficult; and makes unnecessary impositions on the programmer: I might well want to implement one part of my module using one syntax and another part of my module using a different syntax.
On the other hand I think being able to choose your custom reader by source code file would simple to use, simple to understand, easy to implement, would make it easy to customize your editor or IDE to understand your different syntaxes by file, and means that modules can also be easily implemented as they could do their work entirely after the source code has been read in.
I wonder if modules could be implemented with namespaces? You want to call my function foo which calls my function bar, but you don't necessarily want to have to name it "foo" in your own code and you want to be able to have your own "bar" without breaking my function foo. I'll have to think about that one.
I wonder if modules could be implemented with namespaces?
I guess I use the words "module" and "namespace" interchangeably. I'm not sure what else "module" ("package", "namespace", sometimes "library" (loosely), etc.) would mean.
(use "braces-for-set-builder-notation.arc")
(load "a.arc")
(def set-I-really-want ()
{ (* v v) for v in (vals (table-I-really-want)) })
You wouldn't want a.arc's use of braces for tables to leak into b.arc, which uses braces for set-builder notation (which you further don't want to clobber the braces in the definition of table-I-really-want).
With a fancier module system, you might even have
b.arc
(qualify "braces-for-set-builder-notation.arc" s)
(load "a.arc") ; doesn't qualify its braces for tables
(def set-I-really-want ()
s{ (* v v) for v in (vals (table-I-really-want)) })
(def another-table-I-want ()
{foo 5 bar 10 baz 15})
Though there shouldn't be a reason you couldn't do something like
c.arc
(use "braces-for-table.arc")
(def some-table ()
{x 5 y 10})
(use "braces-for-set-builder-notation.arc")
; braces hereafter are for set-builder notation
(def some-set ()
{ x for x in (vals sig) })
As Arc lacks a proper module system, you can already see the clobber-some effects of definitions being global/unqualified. APIs leak all over the place:
arc> (load "sscontract.arc") ; only really needs to provide sscontract
nil
arc> (priority #\!) ; but the user gets all of the implementation details!
1
Similarly, I don't want to load some library and have implementation-detail reader macros polluting the reader. (If the library's specifically for reader macros, then of course that's okay.)
Even some simple public/private control would be nice. I've played around with this in Arc before. E.g.,
(let localize nil
(assign localize
(fn (expr fs)
(when (caris expr 'def)
(if (~mem (cadr expr) fs)
`(assign ,(cadr expr) (fn ,@(cddr expr)))
expr))))
(mac provide (fs . body)
(let private (trues [and (caris _ 'def)
(~mem (cadr _) fs)
(cadr _)]
body)
`(let ,private nil
,@(map [localize _ fs] body))))
)
arc> (macex1 '(provide (f g)
(def f (x) (h (+ x 1)))
(def g (x) (+ (h x) 1))
(def h (x) (* x x))))
(let (h) nil
(def f (x) (h (+ x 1)))
(def g (x) (+ (h x) 1))
(assign h (fn (x) (* x x))))
arc> (def foo () (prn "outer foo") nil)
#<procedure: foo>
arc> (provide (bar)
(def foo () (prn "inner foo") nil)
(def bar () (prn "bar") (foo)))
#<procedure: bar> ; note: no redef warning, since def changed to assign
arc> (bar)
bar
inner foo
nil
arc> (foo)
outer foo
nil
But this particular approach doesn't interact with macros nicely, doesn't let you qualify namespaces, isn't general, etc. So it's really suboptimal.
I find this line really interesting. If I'm reading it right, you can alter the metatable (operator overloading) on the fly? So you could pass in a table as a parameter, set a metatable, play with some operators, then set a different metatable to overload operators differently?
In Python, the operators are kind of tied to specific classes. I guess you can go about casting and converting and inheriting and monkeypatching and such, but I don't think it's as straightforward as just setting a new metatable. Admittedly, I can't think of when I've ever needed to alter operator-overloading dynamically like that, so I've never really tried. Do you know if it's useful in Lua code? Or am I completely off-base here?
Hmm, the only times I've used it as where I'd be casting objects in other languages... I've used it to 'cast' between 'tables' doing similar things. like `my1.rect` to `my2.rect`, if they both use .x, .y, .width and .height to store their coordinates. (Not sure that's a good practice because they can change.) Yes, you can alter metatables any time, but I don't do it that often.
but I can't see how those features could include adding to the syntax...
I'm not sure if this is what you mean, but if you want to create your own syntax, one option is to use http://awwx.ws/extend-readtable0. What this does is allow you to specify a particular character that you want to trigger a call to your own parser. When the reader sees that character, it calls your parser, which reads your syntax from the input and returns the Arc value that you want your syntax to generate.
Line 14 of srv.arc in arc3.1 switches the user id that Arc (mzscheme) is running under.
The purpose of this is to allow port 80 to be opened by mzscheme, and then to switch to a non-privileged user to run the server under.
If you don't need to open port 80, or you're going to run the Arc server as root, simply remove that line.
Alternatively, choose a user id to run the Arc server under, make the Arc directory and all its files owned by that user, and change the "2" in the setuid command to the numeric user id of that user.
First time I've had a chance to look at this as I've been traveling -- wow -- very cool!
I was wondering if you would consider publishing this with a version number... such as this release might be 3.1-0, and then if you fix a bug or make an update the next version might be 3.1-1, and then if an Arc 3.2 comes out and you port that your version might be 3.2-0, etc.
You can do this in git simply by tagging your branch (e.g. tag arcc3.1-0 or whatever) and then I can pull the source by tag, and/or you could publish your tar file with a name like arcc3.1-0.tar.gz
The version numbering scheme doesn't matter to me; what I'm looking for is a way to say "my hack here works with rntz's arcc version X", and to be to distinguish that from some earlier or later version of your port.
Sad to say, I'm not planning on maintaining this at all. I simply don't have the time now that I'm back at school, and my interest in Arc has been waning for some time now. If I did plan on maintaining it, I'd certainly give some thought to version numbering.
Yeah, I thought the "like," "love!" etc. were a bit weird-looking myself at first, even if they were nicely minimalistic.
Since this is functionally the same as a system that rates things from 0 to 3 stars (or 1 to 4 stars, although I don't like 1-to-4 'cause it fools me into thinking there's a 50%), I think actual stars would be a less surprising interface. That would also be nicer to red-green colorblind users.
On another note, I may have found a few bugs. (In case you're keeping a log, my seed for this session was "emshort.wordpress.com". I'm not using the feedback feature, 'cause I don't know if that's buggy too!) I went through several pages I don't remember, pressed the older and newer buttons, and ended up finding a link to "Notion Ink Adam tablet hands on (Pixel Qi Display)" in my recent activity even though I hadn't seen that yet. All I can guess is that either it was someone else's recent activity or else it was what I was going to get had I clicked past the article I was at. Since I couldn't press "newer" (naturally, since I don't have any history newer than the present), I pressed "older" dozens and dozens of times and annoyed myself, and then I rated the tablet article, and suddenly I realized I could press "newer" and started to do that. I expected to annoy myself again, but instead I guess I pressed the button too fast or a packet got lost or something, 'cause the loading graphic came on and stayed there. The loading graphic wasn't centered either; personally, I think that's a bug. :-p Finally, I forwarded a copied and pasted this writeup into the feedback form and sent it off along with a link to this post (so you know you can reply to me here).
Ah, I figured out the problem - the history requests were shared across all users, so if somebody else makes a request while you're browsing, you see the history for their station when you hit older or newer
:}
(This is, of course, in addition to the failed request at the end, and the layout issues)