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

It's cool, but it's doing a new page request per interaction and the page load takes at least a second. It also has a looong painting operation. :(

This is where js would be handy - right? Personally I would just update the dom element and send a http post in the background.

I get that it's just a toy, but still it shows that languages* should have a good client side story too. Maybe some Lumen integration?

* that are for the web.

edit: reminds me of the million dollar homepage http://www.milliondollarhomepage.com/

reply

3 points by krapp 7 days ago | link

>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.

reply

2 points by shawn 7 days ago | link

We tried. It was almost a disaster.

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.

reply

3 points by i4cu 7 days ago | link

Reads like a really good horror story :)

> 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[1] algo to throttle requests if you wanted to go even further.

1. 'debounce' for those who don't know -> https://davidwalsh.name/javascript-debounce-function Only I'm suggesting it as a way to throttle ajax reqs.

reply

3 points by shawn 5 days ago | link

Yeah, it was worth the effort to make the drawing code client side. Someone showed up and made a software rasterizer.

Timelapse: https://www.youtube.com/watch?v=G0sG08jKCTI

reply

2 points by krapp 3 days ago | link

why not go all the way and render client-side in a canvas as well?

As it is, the more "pixels" you have, the slower the page loads. You could probably have just a single canvas and a single event handler.

You could preserve functionality for non-js users by using an imagemap (assuming browsers still even support those) or sticking the existing code in noscript tags.

reply

2 points by krapp 2 days ago | link

OK... I don't know where I got "single event handler from," that obviously wouldn't be true, but it would still be simpler than having each pixel be a separate HTML form....

reply

1 point by shawn 2 days ago | link

Wanna hop into discord and we can chat about the design? https://discord.gg/qaqkc9z

The repo's open, and I could help get you set up with it if you wanted to work on some of this. https://github.com/laarc/laarc

It should be a matter of:

  git clone https://github.com/laarc/laarc
  cd laarc
  make
  rlwrap bin/arc
  ((load "news.arc"))
and then http://localhost:8080/place

reply

2 points by krapp 2 days ago | link

Let me actually see if I can come up with a POC first, at least for the canvas and javascript. Realistically, since it's just GET requests that don't need authentication, I shouldn't even need laarc running, I can just send the same requests by AJAX.

reply

2 points by shawn 2 days ago | link

https://www.laarc.io/place.json is the API, by the way! I should probably mention that somewhere.

reply

2 points by shawn 6 days ago | link

Kay, it's all client side now. Have fun!

reply

3 points by i4cu 6 days ago | link

Much better.

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.

reply

3 points by shawn 5 days ago | link

Thanks for mentioning that. It's a bug.

The trick to clear the x is to scroll up and click on the color palette.

Here's a timelapse for the curious. https://www.youtube.com/watch?v=G0sG08jKCTI

reply

2 points by i4cu 9 days ago | link | parent | on: Show Arc: seamless interop with racket

This is awesome. :)

> If you want to switch back to arc, you can use (%do ...)

Personally I would prefer '.arc' or '%arc':

  arc> (begin (require racket) (.arc (+ "foo" 42)))

  "foo42"
Yeah it's one more char, but I think it makes the code more explicit, understandable and also extendable (i.e. '.racket' also becomes an option too - not that it's needed).

reply

2 points by krapp 9 days ago | link

>(i.e. '.racket' also becomes an option too - not that it's needed).

.arc / .racket (or .rkt) seems more intuitive than .arc / $

We could also keep the dollar sign in both cases, which I prefer aesthetically, because being familiar with javascript and C type languages, seeing a dot alone like that just seems weird.

reply

3 points by i4cu 9 days ago | link

yeah but the dot reads to me like a file extension so I immediately get it.

$arc would be ok too. I can get behind that :)

reply

2 points by shawn 9 days ago | link

Good point! (%arc ...) and (%rkt ...) already work, actually. (I couldn't decide between %arc vs %do and %rkt vs %scm)

reply


Are you suggesting a custom internal db?

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.

reply

3 points by krapp 10 days ago | link

> Are suggesting a custom internal db?

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.

reply

2 points by i4cu 10 days ago | link

> Arc is already hitched to Racket, which appears to support SQL and SQLite...

Well racket supports SQL and SQL lite as an option, but racket can also run on platforms that don't support them so it's not 'hitched'. i.e. compiling to run on micro-controllers, mobile devices etc.

reply

2 points by i4cu 14 days ago | link | parent | on: Hacker News API not well designed

Personally I thought this was awesome (It was referenced in one of the comments within the HN post):

https://hnpwa.com/

HN has become the modern day 'todo' dev requirement.

reply

2 points by krapp 14 days ago | link

I actually started and abandoned unfinished a Hacker News clone in Hack a while ago, and a client has always been vaguely on my todo list.

I wonder how many HN users have projects like that sitting somewhere.

reply

2 points by kinnard 14 days ago | link

I have one. I plan on plowing through it soon.

reply

2 points by i4cu 14 days ago | link | parent | on: Hacker News API not well designed

HN has been a huge success story in my eyes. It's been in operational/maintenance mode for a decade and loaded with high traffic use.

Personally, I think getting worked up over the API is just absurd. It has served its purpose well.

reply

1 point by kinnard 14 days ago | link

Apparently they mean to change that:

https://news.ycombinator.com/item?id=19058455

reply

1 point by i4cu 14 days ago | link

Continuous improvement is always a good thing.

reply


Personally, I don't think this is going to make the language more attractive. You've traded better printing for more verbose code.

  current-arc> (obj name "John Doe" age 23 id 73881)

  your-arc> (ob (v name "John Doe") (v age 23) (v id 73881))
maybe?:

  alt-arc> (ob name "John Doe" age 23 id 73881)
returns (Assuming you're attempting to have ordered tables?):

  (ob (v name "John Doe") (v age 23) (v id 73881))

reply

2 points by rocketnia 17 days ago | link

(I hope you don't mind if I change my mind and use `object` instead of `ob`. I just remembered `ob` is a pretty good local variable name for object values.)

Code could still use `obj`, even in the reader. These two things could be parsed as the same value:

  (##obj name "John Doe" age 23 id 73881)
  (##object (v name "John Doe") (v age 23) (v id 73881))
The reason I suggest interspersing extra brackets and v's, when the concise `obj` already exists, is to avoid idiosyncrasies of pretty-printing `obj` for larger examples.

Here's an example of how a nested table prints in the latest Anarki:

  arc> coerce*
  '#hash((bytes . #hash((string . #<procedure:...ne/anarki/ac.rkt:1128:21>)))
         (char
          .
          #hash((int . #<procedure:integer->char>)
                (num . #<procedure:...ne/anarki/ac.rkt:1133:21>)))
         (cons
          .
          #hash((queue . #<procedure:...t/private/kw.rkt:592:14>)
                (string . #<procedure:...ne/anarki/ac.rkt:1127:21>)
                (sym . #<procedure:...t/private/kw.rkt:592:14>)
                (table . #<procedure:...t/private/kw.rkt:592:14>)))
         (fn
  ...
As a human who can easily apply idiosyncratic rules, here's how I'd probably lay that out if I could only use (##obj ...):

  arc> coerce*
  '(##obj
     
     bytes (##obj string #<procedure:...ne/anarki/ac.rkt:1128:21>)
     
     char
     (##obj
       int #<procedure:integer->char>
       num #<procedure:...ne/anarki/ac.rkt:1133:21>)
     
     cons
     (##obj
       queue #<procedure:...t/private/kw.rkt:592:14>
       string #<procedure:...ne/anarki/ac.rkt:1127:21>
       sym #<procedure:...t/private/kw.rkt:592:14>
       table #<procedure:...t/private/kw.rkt:592:14>)
     
     fn
  ...
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`:

  arc> coerce*
  '(##object
     (v bytes (##object (v string #<procedure:...ne/anarki/ac.rkt:1128:21>)))
     (v char
       (##object
         (v int #<procedure:integer->char>)
         (v num #<procedure:...ne/anarki/ac.rkt:1133:21>)))
     (v cons
       (##object
         (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>)))
     (v fn
  ...
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.

reply


> should give a syntax error...

I don't agree. quoting a list is a way to protect the expression from evaluation, in this case because round brackets normally indicate an expression that needs to be called. A table literal {...} doesn't need protection from evaluation as a callable expression as it's just data and like any other data it should evaluate to itself. And, frankly, it would really suck having to protect that data everywhere in my code because someone wants a really nuanced use case to work.

Really what should happen is that [] should be implemented such that we don't need to protect lists of data.

reply

2 points by i4cu 18 days ago | link

> Really what should happen is that [] should be implemented such that we don't need to protect lists of data.

I should point out that I don't think this can happen since square brackets are reserved for other uses in Arc.

reply

2 points by rain1 18 days ago | link

I see what you mean, making it self evaluate seems like the best option.

reply

4 points by i4cu 19 days ago | link | parent | on: Racket-On-Chez Status: January 2019

Also posted on HN: https://news.ycombinator.com/item?id=19027400

I wonder what impact if any this might have on Arc. There are some noted compatibility differences between Racket versions:

  * no single-precision or extended-precision flonums;

  * some differences in the FFI related to memory management and blocking functions; and

  * no support for Racket’s C API.

reply


> Is there another name we can use for Common Lisp style namespaces?

realms ?

going for brevity here :)

reply

3 points by i4cu 24 days ago | link | parent | on: Arcon: Arc Conference at YC

That's a great idea. If you can get pg to keynote I'll definitely check my calendar against your event.

reply

More