I've used it in production at multi-national organizations.
In fact that's how I learned to code. 10 years ago I was a business analyst who couldn't get the dev group to work on my projects in a timely fashion. The ability to use arc was in reach for me, even though I had no programming experience at all.
I actually wrote and released 2 internal apps and 1 external app that had good use (a few hundred users using it daily/weekly to get their jobs done). This was in production for a few years until I left in 2012. I'm pretty sure they're not using these apps anymore.
> What sorts of systems would it excel in and what sorts would it be unsuitable for?
I think its primary strength is the short learning curve. I also I think it's unsuitable for anything which needs to use existing db connections. Even though I did hacks to make that work it's the primary reason my apps could not be adopted by the dev group.
> What could be done to alleviate for Arc’s lack of features?
* better db integration
Or if there's no interest in db integration then make it focused on compiling to js for mobile devices where db integration is less of an issue.
> In fact that's how I learned to code. 10 years ago...
It's kind of ironic my first post was about a most recent topic:
"After playing for a bit I noticed my "set x" functions were
clobbering each other...so I started converting all my function to use
"why wouldn't the ARChitects of LISP or ARC make a set like
function that is global within a function ?
This definitely not great, but having to use 'with' is not the real issue for me. In fact if you read through the code you'll notice that this style is often used deliberately (i.e. some people might argue that it's a feature).
I think the bigger issue is that global vars can be used without any errors or conflict warnings. So someone else can create code which sets globals which then gets loaded via libs and will pollute your program. So you could have lib#1 set var 'x' only for it to get clobbered by lib#2's version of var 'x' and arc just ignores this. That's bad. Really bad.
>So you could have lib#1 set var 'x' only for it to get clobbered by lib#2's version of var 'x' and arc just ignores this. That's bad. Really bad.
And how often is it intended behavior? How often does one want to have a macro parameter or apparently "local" variable overwrite an existing symbol globally and arbitrarily?
I can see it being useful in the case of "hot patching" code to just redefine a function, but that's still kind of crazy, since now the source code and running code are no longer the same. Might as well just edit the file and reload it, and have one source of truth.
It seems like an anti-feature. Something that seemed like a good idea in theory, but which in practice does more harm than good.
I'm not following the two of you on precisely what this anti-feature is. Assigning to local variables using '=' does not create new global variables. Can you share a code sample showing what you're talking about?
>This is where js would be handy - right? Personally I would just update the dom element and send a http post in the background.
If it's to be done in JS, might as well implement a drawing tool in an actual canvas element.
I've seen tutorials that are reasonably simple. The complicated part would be actually saving it. It is possible to export a canvas as a png and upload it with an AJAX request but I don't know how cross-browser compatible that is.
We started out by making an EventSource endpoint and using JS EventSource object to get updates. Seemed to work great.
Pushed it live.
To everyone on the site. Not just to the people on /l/place. Oops. Mistake #1.
Mistake #2: I was aware that Arc kills threads that take longer than 30 seconds, but I was unaware that EventSource automatically tries to reconnect. Welcome to the DoS party.
With no way to tell the clients to stop. Mistake #3.
It was only live for about 10 minutes, but it took around two hours before the last few clients finally refreshed their browser and stopped DoSing the endpoint. The server absorbed the extra traffic like a champ, but the server logs were ridiculous for about an hour. Lots of "client took too long" error messages spit out by Arc every second.
Sooo yeah, submitting changes via JS is easy. Getting updates is the hard part.
Could poll. But then that's still hammering the server. Moreso than it already is.
It's probably a feature that it's painful to use. Only the determined will use it for art.
That said, if anyone has ideas for how to tweak arc for performance for this scenario – and remember to calculate how much memory is used by how many simultaneous sockets are open – I'd be willing to try again.
> I was aware that Arc kills threads that take longer than 30 seconds...
> Sooo yeah, submitting changes via JS is easy. Getting updates is the hard part.
That's why I suggested a post request...
Just deliver the page and create an api end point, on the server, that gives you the last x changes from the change log.
With that ajax request, you could return these net updates for the client and use client side js to apply them to the dom. You could even create a trivial js debounce algo to throttle requests if you wanted to go even further.
I will say; I did a page reload and noticed the color pick was still in place and had to go hunt for the x. I expected it to reset, but I'm not sure if you see that as a bug or a feature :)
also, it looks like the client side is pure js... Is Lumen not up to that task? just curious if you tried that as it might be nice if, someday, we could get to the point where this kind of stuff could be done in arc.
Otherwise hitching the code to a third-party db, as a requirement, would really limit what could be done with the language and would create all kinds of problems. You would be locked into the db platform as a hardened limitation. You would inherit the complexity of external forces (i.e. what if some other app deletes or messes with the db). What about securing the access/ports on the db.. etc..
It's always possible, but I think you would have to implement something internal where you can properly isolate and fully support all platforms the language does.
Seems likes namespaces would solve these problems the right way.
Yes. Currently, the options we have for stateful data are file I/O, which doesn't work perfectly, or tables that can lose their state if the file they're in gets reloaded. I'm suggesting something like Redis or APC, but implemented in Arc at the language level, to separate that state from the source code.
I was also thinking (in vague, "sketch on the back of a coffee-stained napkin" detail) that it could also be used to flag variables for mutability and for namespacing. In that if you added "x" from foo.arc it would automatically be namespaced by filename and accessible elsewhere as "foo!x",so it wouldn't conflict with "x" in bar.arc.
>Otherwise hitching the code to a third-party db, as a requirement, would really limit what could be done with the language and would create all kinds of problems.
Yeah, but to be fair, Arc is already hitched to Racket, which appears to support SQL and SQLite, so maybe third party wrappers for that wouldn't be a bad idea as well... sometime in the future when things are organized enough that we can have a robust third party ecosystem.
There are several idiosyncrasies in action there: I'm choosing not to indent values by the length of their keys, I'm choosing not to indent them further than their keys at all (or vice versa), I am grouping them on the same line when I can, and I'm putting in padding lines between every entry just because some of the keys and values are on separate lines.
Oh, and I'm not indenting things by the length of the "##obj" operation itself, just by two spaces in every case, but that's a more general rule I go by.
As far as Lisp code in general is concerned, those seem like personal preferences. I don't expect anyone to indent this quite the same way. Maybe people could take a shot at it and see if a consensus emerges here. :)
Now suppose I could only use `##object`:
(v bytes (##object (v string #<procedure:...ne/anarki/ac.rkt:1128:21>)))
(v int #<procedure:integer->char>)
(v num #<procedure:...ne/anarki/ac.rkt:1133:21>)))
(v queue #<procedure:...t/private/kw.rkt:592:14>)
(v string #<procedure:...ne/anarki/ac.rkt:1127:21>)
(v sym #<procedure:...t/private/kw.rkt:592:14>)
(v table #<procedure:...t/private/kw.rkt:592:14>)))
This saves some lines by not needing whitespace to group keys with their objects. In even larger examples it can cost some lines since it introduces twice as much indentation at every level, so that might be a wash. What really makes a difference here is that all those pairs of parentheses can be pretty-printed just like function calls, so things that process the "##object" syntax don't need to make special considerations for pretty-printing it.
"Assuming you're attempting to have ordered tables"
In this thread, the original post's example used unordered tables. It doesn't matter to this design. Ordered tables and unordered tables can coexist with different ## names.