Arc Forumnew | comments | leaders | submitlogin

Stick around! We like submissions :)

https://www.laarc.io/l/dev|programming for general programming stuff

lisp: https://www.laarc.io/l/lisp

essays+classics: https://www.laarc.io/l/essays|classics

videos: https://www.laarc.io/l/videos

And you can make your own tags: https://www.laarc.io/submitlink?l=whatever%20foo%20bar

(That would post a link to /l/whatever, /l/foo, and /l/bar.)


The code is about 100 lines: https://github.com/laarc/laarc/blob/master/news.arc#L3506-L3...

Every pixel is a form with a button.

3 points by krapp 2413 days ago | link | parent | on: Show Arc: seamless interop with racket

>or wild ideas that I don't really expect anyone to act on in the short term

Those are the best kind of ideas!


I like it, but to be honest, I find tags more interesting than the drawing tool.

I'm also stealing your color scheme once we get themes working here... yours and every other clone I can find ;)

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

I've left a code review at: https://github.com/arclanguage/anarki/pull/161#pullrequestre...

Basically, I think it's a bad idea to change `ac` into something which sometimes compiles Arc code and sometimes does something more like code-walking over s-expressions. I think Anarki's existing "$ ... unquote" syntax already serves this purpose and uses the same kind of code-walking but does so with a better separation of concerns.

Moreover, the way you're taking out the |foo| syntax so you can redefine it to be a variant of $ seems like a net loss.

(Some of my other comments on that review are less fundamental objections: Style nitpicks, observations of bugs, or wild ideas that I don't really expect anyone to act on in the short term.)

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

Good point! (%arc ...) and (%rkt ...) already work, actually. (I couldn't decide between %arc vs %do and %rkt vs %scm)
3 points by i4cu 2414 days ago | link | parent | on: Show Arc: seamless interop with racket

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 :)

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

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

2 points by i4cu 2414 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).
2 points by akkartik 2414 days ago | link | parent | on: Show Arc: seamless interop with racket

I wonder if it's possible to end up with a list ending in #f rather than nil.
3 points by shawn 2415 days ago | link | parent | on: Show Arc: seamless interop with racket

Basically, arc shares a global namespace with racket. (def foo (x) (+ x 1)) results in a function named foo, not _foo.

If an expression starts with a symbol bound to a racket syntax transformer, then the arc compiler switches to "racket-style" output.

  (begin "everything in here is racket code...")
If you want to switch back to arc, you can use (%do ...)

  arc> (begin (require racket) (%do (+ "foo" 42)))
  "foo42"
The last change is that pairwise expressions like (< 1 2) now return #t or #f, not 't or '(). Meaning you can pass arc predicates like `even` into racket functions that expect predicates.

It's pretty convenient to call any racket function without worrying about interop.


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


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


Languages that have decent bindings to a database also have global variables that still have uses, and that can be lost when you restart the server or do other sorts of loading manipulations. There's a category of state that you want coupled to the state of the codebase.

Yes, you can definitely try to make these different categories of state less error-prone by architectural changes. But I don't think other languages do this well either. Mainstream languages, at least. I know there's research on transparent persistence where every global mutation is automatically persisted, and that's interesting. But I'm not aware of obvious and mature tooling ideas here that one can just bolt on to Arc.

All that said, database bindings would certainly be useful to bolt on to Arc.


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.


Sure, but losing data you don't want to lose because you reloaded a source code file does seem like more of an architectural than language issue. It would be a code smell in any other language.

My comment was slightly facetious but the more I think about it the more I'm wondering whether something like redis or php's apc wouldn't be a good idea - and not just as a lib file but integrated into Racket's processes for dealing with arc data directly.

It could serve both as a global data store and a basis for namespacing code in the future (see my other rambling comment about namespaces), since a "namespace" could just be a table key internally.


To be fair, not all the things we use global variables for would end up in a persistent store. Some of them we want to stay in sync with code.

If only there were some general purpose way to store stateful data separately from source code.

Like a... "base" for "data."


When I was playing around with ns.arc, one of the things I tried was namespacing a table of functions and treating it like a class.

I think two changes would be better for modularity than changing assignment, however:

First, limit the ability of macros to overwrite existing symbols to the file in which the macro is called. This would allow modular or imported code to use macros without worrying about global namespace collisions, or needing to do anything special with assignments.

Second, and related to the first, would be to implicitly namespace based on file location. Currently, Arc uses a single namespace, and a reference to a root directory that's used to disambiguate relative paths called with (require).

We would ignore the root folder and use the remaining path and file name as the namespace.

This would allow explicitly resolving possible namespace collisions by referring to the namespace where necessary, the way it's done in other languages (at least in C++.) So if you had, say, a macro in news.arc with body as a parameter, first, it wouldn't mutate body in html.arc, and you could refer to (html!body) directly to disambiguate, using the same syntax for namespaces as tables.

An added benefit would be that imported code from a repo (adding a vendor path) would work as is namespaced as vendor/file or vendor/app/file.

It wouldn't be necessary to declare namespaces in most cases then. We could use the existing with statement to declare or extend namespaces instead of something like (declare-sub-namespace), similar to 'using' in C++

    (w/namespace foo
      (= bar (table))

    (foo!bar)

Right. I started work on making anarki reloadable: https://github.com/arclanguage/anarki/pull/158

A couple of other likely-crappy abstractions that I'd made long ago in similar vein:

once-only: execute arbitrary code but only the first time it's encountered. https://github.com/akkartik/readwarp/blob/master/utils.arc#1

init: like assign, but only if name isn't already bound. For arbitrary variables besides tables. https://github.com/akkartik/readwarp/blob/master/utils.arc#L...

inittab: probably same as your proposal, just a different name. Even uses `or=` under the hood. https://github.com/akkartik/readwarp/blob/master/utils.arc#L...


Thanks for answering. That makes the intentions pretty clear. :)

Another thing... Have you considered initializing the application state in one file and the hardcoded constants and functions in another, so that when you're changing the code, you can reload the constants file without the state file getting involved at all?


I also notice that the scope of this refactoring (= ...) into (^ ...) or (or= ...) is the same kind of refactoring that would help make Anarki a more modular language. Usually (= foo* (table)) is a sign that the code is really trying to create a makeshift sub-namespace. If intentions like this conveyed more explicitly with operations like (declare-sub-namespace foo*), then developing more useful module systems for Anarki would be a simpler task.

In the longer term, how do you figure it'd be good for Anarki control whether something gets overwritten or not?

Definitely leave it up to the user.

Some variables (like constants) should always be overwritten, and so the user should write `(= foo* 42)` for those.

Other variables (like tables containing state) should only be set once on startup.

Like, maybe we'd eventually want a `load-force` operation that loads a file in an "overwriting way." At that time, if we simply have `load-force` interpret all `or=` as `=`, then it might clobber too many uses of `or=`, so my advice to use `or=` for this will have turned out to be regrettable.

Perhaps, though FWIW I haven't needed a force-reload type operation. That's accomplished via restarting the server.

The only drawback for `or=` is that if you have code like this:

  (= foo* (table)
     bar* (table)
     ...)
then you'd have to reindent the whole expression if you change from `=` to `or=`.

That's not a big deal though. I think I prefer `or=`.


What you're describing is almost like what `or=` does already, just without causing an error if the variable starts out undefined. Maybe it can just be a change to `or=` rather than taking up the ^ character's real estate.

The way you're using it sounds a lot like `defvar` in Common Lisp. I've never used this technique, but it sounds useful for experimental programming like modifying a server, modifying an editor, modifying a music loop (live coding) without undergoing Arc's long load times each time. ;)

Any language with user-defined macros is gonna have some trouble with its compile time or load time, since it's positively designed to run arbitrarily slow user-defined code at that time. So as long as macros at all are part of a 100-year language, then some way to reload pieces of code without undergoing the process of loading all the rest of this code must play a certain part as well. So `defvar` style can be handy, but in a more pure language we might look to incremental computation research or something.

In the longer term, how do you figure it'd be good for Anarki control whether something gets overwritten or not? Seems to me like in a perfect world, you'd sometimes want to interpret the same definition as an overwriting definition or a non-overwriting definition without changing its syntax or anything. :-p Like, maybe we'd eventually want a `load-force` operation that loads a file in an "overwriting way." At that time, if we simply have `load-force` interpret all `or=` as `=`, then it might clobber too many uses of `or=`, so my advice to use `or=` for this will have turned out to be regrettable.

But the paradox is easily resolved if, for instance, the "overwriting way" doesn't make sense to you anyway. Like, maybe you'd just restart the whole (e.g.) server in that case, or go out of the way to rewrite every `defvar` into a `defparameter` (or in your case `^` into `=`) by hand.

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

I have one. I plan on plowing through it soon.
2 points by rocketnia 2419 days ago | link | parent | on: Running in DrRacket?

Interesting, 'cause I even tested it at a powershell prompt to make sure before I posted. What problems were you seeing?
2 points by krapp 2419 days ago | link | parent | on: Hacker News API not well designed

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.

3 points by nupa 2419 days ago | link | parent | on: Running in DrRacket?

Thanks! And yes I'm on windows, although that command didn't work at first -- protip, you can't run it from a powershell prompt, it has to be a cmd prompt. Weird.
2 points by i4cu 2419 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.

More