Arc Forumnew | comments | leaders | submit | shader's commentslogin
1 point by shader 4088 days ago | link | parent | on: Shader:plz help

Force-stop shouldn't be what drops the www. The repo reset should only happen during the git push process. Otherwise I don't think it touches what's in the repo dir.

In any case, I think all of the stuff in the www folder should probably be moved to the data directory, so it doesn't get wiped regularly. I just haven't done it yet; partly because I didn't know exactly where I would put it.

Feel free to make a change to put it where you want it, and then send a pull request.

-----

2 points by shader 4089 days ago | link | parent | on: Shader:plz help

The arc git repo is cloned under app-root/data, but it's not used as the root directory for the web application in case the user has other files they want to load.

I'll admit, the readme isn't the best. I mostly copied it from the original and changed the relevant bits.

Unfortunately, certain files like adminfile* should probably not be relative to the repo directory, because it's likely to get wiped. I'm not sure where the right place to put it would be though. Maybe data/config?

-----

3 points by shader 4089 days ago | link | parent | on: Shader:plz help

Apparently the current version of arc uses (+ srvdir* "admins") as the adminfile*

Thus, the path you should be using is "repo/www/admins". The www directory should already exist. You can of course change this by setting either of those variables (srvdir* or adminfile*) in repo/main.arc. It might be best to relocate that data to the other directory, or it might be deleted on accident when updating later.

Also, I'm not sure that the openshift restart command actually restarted properly; it didn't seem to notice the admin changes until I actually did a force-stop and then start. Maybe I was mistaken, but you could try that if your www/admins file doesn't seem to stick.

-----

1 point by akkartik 4089 days ago | link

Ah, so this was the culprit :/ https://github.com/arclanguage/anarki/commit/510419a584

The root cause is that when we made anarki open to incompatible changes we didn't think it would be automatically pulled into VMs like openshift or docker. You can only use a shifting substrate like anarki if you can control when to take in updates.

I'm not sure what to do about this. What do you think?

-----

2 points by shader 4088 days ago | link

It's true that the constantly shifting nature of anarki has caused all of us more than a few issues in the past. There's even been more than one breaking change since I started supporting OpenShift. But I think that keeping anarki open to change is a good thing, and I don't want to get it locked down. You end up with issues like the python2.7 vs 3 fiasco.

On the other hand, it's probably a good idea to regularly catalog the changes, and employ some sort of semantic version tagging. Then it could be up to other users when they should upgrade, and they can be better informed of why.

-----

1 point by akkartik 4088 days ago | link

Absolutely, I'd be the last person to suggest the backwards-incompatible changes (most of them mine :) stop. No, I meant, is there some way we can configure things like openshift to pick up at specific tags? Maybe you could hardcode to checkout to a specific hash? I don't know what the consequences would be, though. For example, if people want to hack on the code inside openshift. Thoughts?

Another approach may be for you to maintain a fork of anarki and clone from it instead of anarki directly. That way we wouldn't be dealing with detached heads inside openshift, and it'll still require a manual step to upgrade.

-----

1 point by shader 4088 days ago | link

It shouldn't be that hard to clone the latest anarki, and then checkout a specific tag. I just didn't bother because we haven't been using tags much that I know of.

Of course, my script only installs anarki once; it doesn't upgrade it out from under the user. The only issues are if something changes that affects the actual openshift base, like when you changed the boot script a few months ago.

-----

1 point by tvvocold 4088 days ago | link

Thx, shader,that works.another question is how can i add something like about or copyright in app?like the bottom of http://news.dbanotes.net/ or hacker news?

-----


How would you build a declarative continuous state system on top of arc? Or would it be better to start from scratch?

And what kind of metaprogramming models besides function/macro/fexpr do you see working on top of such a system?

It seems like it could either be a really 'alien' programming model that requires very different approaches, or a simple set of wrappers on top of existing models. I don't know enough about it yet.

-----

3 points by rocketnia 4173 days ago | link

Good questions! I keep wanting to tie this stuff back to Arc somehow, so that people here can care, lol, but it's hard to see where to start.

I'll assume we're talking about something like RDP, but not quite RDP. David Barbour's goals for RDP include safe distributed programming, secure mashups, and sometimes even type-directed reduction of boilerplate. Thus RDP isn't necessarily RDP without an appropriate static type system, and we proabably don't need to commit to that part here.

Let's just call what we're talking about "continuous reactive" code, or "continuous" for short. :)

I'll answer out of order a bit.

---

"And what kind of metaprogramming models besides function/macro/fexpr do you see working on top of such a system?"

All of these actually keep making sense in a continuous system. The only things that can't technically be carried over are certain kinds of side effects.

Here's a more complete description of the differences:

- Most imperative side effects don't make sense. If (do (= x 1) (= x 0)) is executed continuously at every instant, then at no time is x just 1 or just 0. Continuous reactive programming needs its own particular side effects to deal with continuously displaying things, continuously maintaining connections to things, continuously monitoring the current state of the mouse, etc. Instead of mutation, continuous reactive code can use demand monitors, which aggregate sets of values. Similarly, we would have to avoid effects related to first-class continuations, threads, etc., unless we can make sense of them.

- Since all the effects at a given instant are simultaneous, the data/control flow doesn't need to be processed in a particular order, and it can naturally be concurrent, which in turn means each concurrent part can be undisturbed for a good period of time without needing to be recomputed. This means certain constructs like (if ...) stick out as expensive operations, since they must synchronize their inputs and outputs rather than letting them pass through concurrently.

- Eval and function calls are pretty weird operations. In a continuous program, the entire data flow graph exists like a constantly marching trail of ants, sometimes switching between different conditional branches. I think a dynamic call causes that trail of ants to sometimes snap between different iterations of a fractal pattern. My current implementation[1] supports "functions" but doesn't support arbitrary recursion, because I keep every possible trail instantiated regardless of whether it's currently in use. It's like all the functions are inlined whether we like it or not. (I actually kinda like it.)

- If we care about secure mashups, passing a big context object around tends to be a bad idea, especially if it's implicit. Fexprs may need a redesign in order to avoid passing authority to code that doesn't need it.

---

"How would you build a declarative continuous state system on top of arc? Or would it be better to start from scratch?"

(Building the execution semantics is probably a bigger challenge than building the state resources, so I'll assume that's what you mean.)

While starting from scratch would keep things simpler, I don't think it's necessary, as long as there's some bridge to manage the continuous side from the procedural side and/or vice versa. A single language could have dedicated syntaxes (e.g. lisp special forms) both for procedural code and for continuous code.

I've actually been thinking about how a single (fn ...) syntax could be used for both. Pure code is a special case of error-free continuous impure code, and that in turn is a special case of error-free procedural code, so a single abstraction might cover it all.

However, dynamic errors make things more interesting. In procedural Arc code, (do (foo) (err "oops 1") (bar) (err "oops 2")) would not execute (bar) because that comes after an error has occurred. In continuous code, all of the code is executed at every instant, so there is no "after" to speak of, and (bar) executes at the same time as both errors occur. (Actually, David's approach would be to terminate the computation as soon as possible and try to roll back any effects that have occurred in the meantime, so in that case (bar) would not usually be seen to execute.)

This is enough of a jarring discrepancy that I've tabled the idea of unifying the (fn ...) syntax in the procedural language I'm working on.[2] I think it's something that can be done, but it's more complex than I first thought.

Anyway, suppose we have two different syntaxes, or suppose (as David prefers) we don't have a continuous (fn ...) syntax at all but instead use concatentive programming techniques.[3]

Either way, it's painful to bridging between one style of computation and another.

Procedural code managing continuous code: Procedural code has to deal with continuous signal input similarly to how it would traditionally deal with keyboard and mouse input, and it has to deal with continuous signal output kind of like drawing to a canvas. This means writing 2-5 imperative code blocks for every bridge, at least until some common bridge patterns can be abstracted away.

Continuous code managing procedural code: One way to use continuous code to trigger an imperative action would be to build a continuously updating collection of the imperative actions we want performed, annotating each one with a timestamp so it's clear when it's supposed to happen exactly. This is cumbersome enough that I haven't tried it yet, but it's basically the kind of FFI layer that a continuous-only language would need in order to play nicely with existing OSes and protocols.

The Web is a good example of a system that already has bridges like what we'd need. An HTML document can have continuously existing tags and attributes that cause JavaScript code to be executed at certain times. In turn, JavaScript code can insert and remove declarative HTML and CSS as it goes along.

Sorry for using so many JS metaphors. :) Aside from Rainbow's UI experiments, I don't know of any Arc applications which continuously monitor or display something.

---

[1] Underreact: https://github.com/rocketnia/underreact

[2] Penknife, which currently is hidden away inside Era and not described in the readme: https://github.com/rocketnia/era

[3] Either way, I've pretty much made this in JavaScript already,[1] but my (fn ...) syntax is a bit cumbersome because I'm using strings for variable identifiers, and my concatenative syntax is even more cumbersome because it has to pass around explicit first-class type annotations with no type inference. I think there's room to improve on this, especially in something like Arc that has macros.

-----

2 points by rocketnia 4173 days ago | link

In case anyone wonders what's wrong with (if ...), I've put together a demonstration of translating Arc-like code into the flavor of generalized arrows[4] David and I use for implementing this stuff:

  (if foo
    (bar baz)
    qux)
  
  
     (  |         +   |       )        |   |   |
     ( foo(true)  +  foo(nil) )       bar baz qux
  =======================Disjoin=====================
  foo(true) bar  baz  qux   +   foo(nil) bar baz qux
   |         |    |    |    +    |        |   |   |
  Drop      Drop Drop  |    +   Drop     =Apply= Drop
                       |    +               |
                       =========Merge========
                                  |
In this graph, sum types (A + B) are edges separated by + and product types (A * B) are simply juxtaposed edges. I've labeled the edges around Disjoin to show which signals go where.

The "Disjoin" operation is the distributive law on product and sum types, taking ((A + B) * C) to ((A * C) + (B * C)). In simple cases, it has to synchronize C with a combination of A and B so it knows which output to send C's packets down.

The "Merge" operation takes (A + A) to A, forgetting which branch it was on. In simple cases, it has to synchronize the original two signals becuase the output should only be inactive when both inputs are inactive. If we're using dynamic typing, we may also need to check the inputs dynamically to make sure their periods of activity don't overlap.

Overall, one call to (if ...) causes multiple synchronization points in the code.

You might wonder what Arc could use here if not (if ...), and my guess is it could use a structured data type with associated special forms that can be implemented with implicit concurrency:

  (def left (x) (annotate 'left x))
  (def right (x) (annotate 'right x))
  
  ; Sum types distribute over product types.
  ; ((A + B) * C) -> ((A * C) + (B * C))
  (disjoin (left a) c)   -->  (left (list a c))
  (disjoin (right b) c)  -->  (right (list b c))
  (disjoin other c)      -->  (err "Can't disjoin")
  
  ; Sum types are commutative.
  ; (A + B) -> (B + A)
  (mirror (left a))   -->  (right a)
  (mirror (right b))  -->  (left b)
  (mirror other)      -->  (err "Can't mirror")
  
  ; Sum types are associative.
  ; ((A + B) + C) -> (A + (B + C))
  (assocsl (left (left a)))    --> (left a)
  (assocsl (left (right b)))   --> (right (left b))
  (assocsl (right c))          --> (right (right c))
  (assocsl other)              --> (err "Can't assocsl")
  ; (A + (B + C)) -> ((A + B) + C)
  (assocsr (left a))           --> (left (left a))
  (assocsr (right (left b)))   --> (left (right b))
  (assocsr (right (right c)))  --> (right c)
  (assocsr other)              --> (err "Can't assocsr")
  
  ; (A + A) -> A
  (merge (left a))   -->  a
  (merge (right a))  -->  a
  (merge other)      -->  (err "Can't merge")
  
  ; (A -> C) -> (B -> D) -> ((A + B) -> (C + D))
  ((lift-sum l r) (left a))   -->  (left (l a))
  ((lift-sum l r) (right b))  -->  (right (r b))
  ((lift-sum l r) other)      -->  (err "Can't lift-sum")
This is quite a bundle of special forms to add, and I'm probably forgetting a few. I'm not exactly sure how to implement them, especially considering they would have to deal with Arc's arbitrary recursion. ^_^;

[4] http://www.megacz.com/berkeley/garrows/

-----

2 points by tvvocold 4161 days ago | link

hi,shader:i have a new problem with arc,but i donot know how to contact u...is it ok to post Q here?

-----

1 point by akkartik 4161 days ago | link

Yes, posting here is best. Sorry I think I missed one of your emails? Was out of town for a while.

-----

2 points by tvvocold 4161 days ago | link

Thx,i have almost done my arc site,but when a user forgot his password and he need to reset by email,but cannot get the email...i wanna know how to add email feature in arc site? by the way,i use mailgun.com to send and they give me HTTP API.like this http://documentation.mailgun.com/quickstart.html#sending-mes...

-----

1 point by akkartik 4160 days ago | link

Anarki doesn't have mailgun support yet. It will reset passwords if your server supports sending email using the local unix sendmail command. So I can think of two options:

a) Does mailgun provide a sendmail command that you can download? If so, just installing that might be all you need.

b) Anarki has rudimentary support for GET and POST on arbitrary urls.

  arc> (get-url "http://google.com")
  ("<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\"><TITLE>301 Moved</TITLE></HEAD><BODY><H1>301 Moved</H1>The document has moved<A HREF=\"http://www.google.com/\">here</A>.</BODY></HTML>")
Can you try to figure out the right URL to put into the get-url call or similar post-url call? They're implemented in lib/web.arc, and feel free to ask us questions to help get you on your way.

-----

2 points by shader 4188 days ago | link | parent | on: A working Arc in Javascript?

That arc-js looks very promising, though also somewhat incompatible with the existing libraries.

For instance, the basic fizzbuzz example provided on the main page looks very similar, but doesn't actually run in anarki. Maybe that's anarki's fault, but the syntax of the for loop is different.

I do like the idea of arc ported to js though; makes getting access to mongodb easier, at the very least :)

-----

2 points by akkartik 4188 days ago | link

That's my fault, I'm afraid. I changed anarki's for to up: https://github.com/arclanguage/anarki/commit/eb1f971b84 (backstory: http://arclanguage.org/item?id=18496; http://arclanguage.org/item?id=18501)

In general, worrying about compatibility in the arc/anarki neighborhood is a fool's errand. Not worth doing. Just do what makes sense, and don't be afraid to be different.

-----

1 point by shader 4188 days ago | link

Yeah...

In this particular case it would be nice to have consistency on both ends. Though I guess the best way to achieve that is probably with node.

-----

2 points by shader 4190 days ago | link | parent | on: A working Arc in Javascript?

I haven't gotten that far yet, but I was thinking it would be neat to hack something on top of wat.js until it could support arc.arc. It may not be the right way to create a fully compatible arc implementation, but it is certainly one of the smaller bases to build a javascript based lisp on. It also has a lot of the fundamental language features I wish arc had, like first class environments and fexprs, right out of the box.

The only drawback would be speed; a more directly compiled lisp would probably have better performance.

-----

2 points by lark 4190 days ago | link

When I looked at wat.js it didn't have macros. That was a bigger drawback than speed, because then you can't generate any HTML. An Arc in Javascript could get away with implementing less, like ignoring continuations and garbage collection.

-----

2 points by shader 4190 days ago | link

I'm pretty sure it has macros. Even if it didn't, their effects are easily duplicated with fexprs.

Rather, a macro can be described as an extension of the compiler, while a fexpr is an extension of the interpreter. In a compiled language, macros can be an optimization tool, because they can perform arbitrary computation at compile time.

In wat.js, which I believe is interpreted, macros provide relatively little value. They can still perform slightly better, because they only need to be expanded once. To quote directly from manuel:

"To fexprs I also add macros. When a macro is used as the operator of a form, the form's code gets changed to the macro's output when the macro is first called, a technique I learned from here. I like macros because they make syntactic abstraction cost-free - with fexprs alone there is always an interpretative overhead. Still, Wat macros, like fexprs, do not work with quoted identifiers, but with first-class values, so many hygiene problems are avoided."

So generating HTML with the same kind of dsl that arc uses should be fairly painless. Either that, or I misunderstood what you were saying entirely.

-----

1 point by lark 4190 days ago | link

I must have missed the macros then. The biggest problem I had with wat-js is that... I couldn't figure out how to run it. I wish it had a single shell script that you ran and brought up a repl. So one doesn't have to spent time copy-pasting stuff from a text file into an html file and firing up a browser, or typing their code within double quotes or doing anything else.

Yes I was talking about https://github.com/manuel/wat-js

-----

2 points by akkartik 4190 days ago | link

wat-js seems to have some instructions in the readme. Did you try them?

-----

2 points by lark 4190 days ago | link

I tried them now and was able to get up a Wat VM. But I haven't been able to figure out how to run macros in there.

I wish there were examples. Snippets you can copy paste that do lots of useful stuff like http://ycombinator.com/arc/tut.txt. It shouldn't take anyone more than 10secs to find how to do things. It's disheartening to hear such good work remains unused only because there are no examples but I suspect it's the truth. That's what happened to me.

Language designers think some cool esoteric feature is the killer feature of a language but a more useful feature might be examples: an implementation of an application developers want, like Arc did by providing a webserver and a blog.arc. If you are writing a language, ship a useful app with it, like C did with UNIX.

-----

3 points by shader 4190 days ago | link

I would look at the boot.js file. It's kind of like arc.arc is for arc, in that it is a lisp-based bootstrap of all of the basic functions made available in the default environment.

It should give you basic examples of how to write code in wat, as well as show you which functions are defined. Of course, most of them don't actually have examples in the file, as it's merely defining the standard library, but it's a start. There's also test.wat, and the authors blog: http://axisofeval.blogspot.com/search/label/wat (which unfortunately mostly uses the underlying json representation for most of its code).

And the 'killer feature' of wat.js is not that it has first class environments or fexpr, which are admittedly very cool, but that the core language implementation that supports all of these and more is only a few hundred lines of code. There's more in the repository of course, but all of that is to provide the standard library or add sexpression parsing, etc. This makes wat a very good minimal platform for building a custom language.

-----

1 point by akkartik 4190 days ago | link

Are you talking about https://github.com/manuel/wat-js or something else?

-----


So, are there anything like restarts available for Racket/arc?

And what is the status of the various CL implementations of arc? I know there were a few, but remember little else.

-----

3 points by rocketnia 4196 days ago | link

"So, are there anything like restarts available for Racket/arc?"

I'm pretty sure the answer is no, for now.

With the right use of Racket's 'parameterize and 'current-parameterization, we could build a system that works like Common Lisp's conditions and restarts. (Global variables are an alternative to 'parameterize, but they'll have more awkward interactions with continuations and threads.)

I've only played with CL once or twice, but I seem to recall one of the nicest parts about conditions and restarts is that when a condition isn't caught at the REPL, the user gets a sub-prompt they can use to invoke a restart. Threads might give us something close to this behavior, if we make the REPL's catch-all condition handler block the thread while the user chooses a restart.

Unfortunately, all preexisting Racket/Arc errors will still use the exception system rather than this homemade condition system. In order to make conditions the main error mechanism, we might have to modify the way Arc compiles to Racket so that it traps exceptions and turns them into conditions.

Finally, CL's condition handlers use its subclassing system to find the most specific handler. Arc doesn't have hierarchical dynamic typing like that, or at least not in the main language, so it might not make sense to handle conditions that way.

Altogether this is quite a few feature interactions that would need to be considered, and we'd end up with quite a different REPL experience--maybe even a qualitatively different language. How do we know if it's worth it?

-----

2 points by shader 4196 days ago | link

"How do we know if it's worth it?"

It's probably not. Restarts (and similar) just seemed like a really useful tool for use in production environments. Anything that makes error handling more powerful, flexible, or understandable is a good thing. But changing arc to support it might be a bit much, at least at this point.

I do think it would be good if we could improve arc's error handling though. Or at least error reporting on the repl.

Arc doesn't have hierarchical dynamic typing like that...

I had created a hierarchical typing system for arc once, by just changing the tagged symbol to a list of symbols that is treated as the type hierarchy, but I think I lost the code... I'll have to see if I can find it.

-----

1 point by akkartik 4196 days ago | link

Well, arc has delimited continuations from racket, and I gather you can do anything with them. But if you figure out how, you come tell us :)

I think the CL implementations must have happened when I was away from the forum. Wart started out as a common lisp implementation of arc: http://arclanguage.org/item?id=12814; https://github.com/akkartik/wart/tree/sbcl. But again, I did this without ever grokking conditions and restarts. The OP was actually quite illuminating for me.

-----

1 point by shader 4196 days ago | link

Well then, maybe I was just imagining things. Would be interesting to have a CL implementation of arc.

Though, I'd probably end up implementing something closer to wat.js with the arc library.

What was the reason pg decided not to go with CL for the base of arc? I remember seeing him say it somewhere...

-----

2 points by malisper 4196 days ago | link

He originally did write it using Common Lisp[0].

I'm not sure why he changed it though. There must have been some benefit (maybe the lisp-1 vs lisp-2) which made it easier to write arc.

[0]http://www.paulgraham.com/hundred.html

-----

2 points by shader 4199 days ago | link | parent | on: MongoDB support in arc?

So, I had one idea for supporting #:symbols

Would anyone mind if I changed ssyntax so that ':symbol expanded into the same thing as #:symbol? ":" currently doesn't mean very much as the first character of a symbol. In fact, I think that currently ':symbol == 'symbol.

-----

2 points by shader 4199 days ago | link

After hacking on this for a bit, I determined that adding ((keyword? s) s) to the primary ac cond was necessary either way. So, after adding that the #:symbol syntax works as well, since we're mostly just using the racket reader.

Still, I think that the :symbol syntax is a little cleaner and also matches common lisp. Any reason I shouldn't add it?

-----

3 points by rocketnia 4198 days ago | link

"After hacking on this for a bit, I determined that adding ((keyword? s) s) to the primary ac cond was necessary either way."

That's not necessary either. If you want an Arc expression that evaluates to a keyword, you can already just do this:

  arc> '#:foo
  #:foo
Even so, getting first-class keywords probably won't help as much as you might like:

(Example output from http://tryarc.org/.)

  arc> (= k-idfn ($:lambda (#:k v) v))
  #<procedure:zz>
  arc> (k-idfn '#:k "hello")
  Error: "struct procedure:zz: expects 0 arguments plus an argument with keyword #:k, given 2: #:k "hello""
This function expects 0 positional arguments and a #:k keyword argument. However, we've passed it 2 positional arguments, one of which is #:k and one of which is "hello". We haven't passed it any keyword arguments at all, let alone one with the keyword #:k.

We pretty much have two ways to call this function successfully.[1] First, we can write the function call itself as Racket code, taking advantage of Racket's function call syntax compiler to parse the keywords:

  arc> (let call-k ($:lambda (f v) (f #:k v)) (call-k k-idfn "hello"))
  "hello"
Second, we can build the keyword mapping in a first-class way and use Racket's 'keyword-apply:

  arc> ($.keyword-apply k-idfn ($.list '#:k) ($.list "hello") ($.list))
  "hello"
(Here I've used ($.list ...) as a way to construct ()-terminated instead of nil-terminated lists.)

Note that keyword-apply requires the keywords to be given in a specific order based on their UTF-8 bytes.

If we do a lot of this in the code, I'm thinking we could benefit from one of three things:

- An Arc function that takes an Arc table like (obj k (list "hello")) and calls Racket's 'keyword-apply it to the sorted keywords it expects.

- An Arc macro that looks like a function call, e.g. ($kw-call k-ifn #:k "hello"), but finds any occurrences of keywords and generates the appropriate Racket function call.

- A patch to Arc's own function call syntax so that it parses Racket-style keyword arguments.

I think these solutions would be more effective than shaving one or two heiroglyphics off of '#:k.

---

Not even Racket allows #:k as an expression by itself. It has to be written '#:k. After all, even if #:k evaluated to itself, (list #:k "hello") would not give you a list containing #:k and "hello", since it would try to pass a keyword argument instead.

You might wonder why Racket chose a design with such hoops to jump through. Well, I can't speak for them, but personally I'd give several shallow and hand-wavy reasons:

- It aligns with a certain mental model where positional args are an ordered list and keyword args are an orderless map. (This is the mental model I learned a long time ago in Groovy, so I like it.)

- It lets Racket treat (foo #:a 1 #:b #:c 3) as a compile-time error.

- It lets Racket treat missing/extra keyword args and missing/extra positional args as the same kind of error.

- It means keyword args don't have to be described in terms of positional args. It would be possible to design a lisp that only has Racket-style keyword args, with no positional args whatsoever.

- It means when a programmer wants to get a procedure's arity information dynamically, the result can include information about the keyword args it supports, rather than just the positional args it supports.

---

[1] Hmm, maybe there's a third way to call it successfully:

  arc> (= successfully ($:lambda (#:k v) v))

-----

2 points by shader 4198 days ago | link

My original goal was not to shave characters off of '#:key. I apparently misunderstood how they were supposed to work, and thought that arc wasn't compatible with them. I ended up doing the cosmetic change as part of my process of figuring out how to hack it onto arc.

If what you're saying about '#:key vs #:key is true though, then my test cases were incorrect and I was trying to make something work that shouldn't have.

So, what's the right way to hack on arc to support calling racket functions with keyword args? Or would it be better to make a more arc-idiomatic mongo driver, and how?

-----

2 points by rocketnia 4197 days ago | link

Oops, I think you've been seeing something I wasn't seeing.

It turns out I'm getting much different results on a local setup than I was getting in tryarc.org. Since Arc 3.1 and Anarki use (require mzscheme), all sorts of things are replaced with doppelgangers that doesn't support keyword args, including the function application syntax #%app. In fact the lack of keyword arguments is one of the only things (require mzscheme) is good for. This is something tryarc.org changes, apparently.

MzScheme docs: http://docs.racket-lang.org/mzscheme/index.html

---

"So, what's the right way to hack on arc to support calling racket functions with keyword args?"

I wouldn't say it's "the right way," but we could put the functionality of Racket's 'keyword-apply in a function that takes an Arc table, and then we'd pretty much never need to worry about keywords other than that.

I have an implementation for this, which I should be able to commit with some unit tests now that I know what's going on with MzScheme.

...Actually it might take me a few days to get around to that, so here's the code if anyone wants to use it right away:

  (def $kw-apply (func kwargs . posargs)
    
    ; Convert the last element of posargs (the first-class list) into a
    ; Racket list. If posargs is completely empty, pretend the last
    ; element is an empty list just like Arc's 'apply already does.
    (zap [rev:aif rev._
           (cons (apply $.list car.it) cdr.it)
           (list:$.list)]
         posargs)
    
    (let (ks vs)
         (apply map list  ; Transpose.
           (sort (compare $.keyword<? !0)
             (map [list ($.string->keyword:+ "" (or _.0 "nil")) _.1.0]
               tablist.kwargs)))
      (apply $.keyword-apply func (apply $.list ks) (apply $.list vs)
        posargs)))
Use it like so:

  ($kw-apply my-func
    
    ; keyword args
    (obj a list.1 b list.2 message (list "hello"))
    
    ; positional args
    1 2 3 (list 4 5))
I'm using a table of singleton lists so that we can pass the symbol 'nil as an argument value.

---

"Or would it be better to make a more arc-idiomatic mongo driver, and how?"

I actually have some opinion about "the best way" for this. :)

I think Arc-idiomatic approaches serve no particular purpose, since Arc is a tool for general-purpose computation.[1] I would want a database driver to be idiomatic only for the database itself, so that it serves the more specific purpose of storing data. This can then be accompanied with sugary helper utilities, as long as they're optional.

It seems many ORMs want to bake the sugar into the interface, or they make sugar that has tiny escape hatches for poking at the underlying interface. If sugar is the only thing a programmer (usually) sees, I look at it as though it's a full-on database design of its own... which is rarely favorable since it usually inherits most of the complexity and obligations of the original.

[1] Well, while Arc is a general-purpose tool, it's specifically a language, so Arc-idiomatic approaches serve the particular purpose of making features more accessible to language users.

-----

3 points by shader 4197 days ago | link

Do we actually need the mzscheme dependency? Any reason we couldn't switch to a full racket base?

---

Interesting. I'll have to play around with that. And study it a bit more to figure out how it works. If I understand your description correctly, the reason you're using lists is so that 'nil is interpreted as no value, while '(nil) is interpreted as intentionally passing the value 'nil? How does the function know the difference?

---

Interesting opinion. Unless I misunderstood you, I would have felt the opposite way. Normally, I would expect the purpose of the data interaction layer to be separating the implementation details from the code, so that if changes need to be made to what backend storage system you can just trade it out.

Maybe that is what you mean though, and that's supposed to be a distinction between the "driver" and an additional abstraction layer. Though your comment about ORMs including sugar confuses that a bit. I don't really want sugar per se, just abstraction away from how I'm actually storing the data, within reason anyway.

-----

2 points by rocketnia 4197 days ago | link

"Do we actually need the mzscheme dependency? Any reason we couldn't switch to a full racket base?"

There's always a reason, but these days Anarki has broke all my code enough times that that shouldn't be a concern. :)

I think this would be a positive change.

---

"...the reason you're using lists is so that 'nil is interpreted as no value, while '(nil) is interpreted as intentionally passing the value 'nil? How does the function know the difference?"

Arc doesn't support nil as an element of a table. Setting a table entry to nil removes it. Therefore '$kw-apply will only see non-nil values anyway.

As pg says: "In situations where the values you're storing might be nil, you just enclose all the values in lists." http://arclanguage.org/item?id=493

When I was using Arc heavily, I defined a utility (sobj ...) that was just like (obj ...) but it wrapped everything in a singleton list. That may have been the only extra utility I needed.

I could write (each (k (v)) tab ...) in place of (each (k v) tab ...). I could write tab!key.0 in place of tab!key. I could write (iflet (v) tab!key ...) in place of (iflet v tab!key ...).

It was surprisingly unintrusive, even pleasant.

---

"Normally, I would expect the purpose of the data interaction layer to be separating the implementation details from the code, so that if changes need to be made to what backend storage system you can just trade it out."

I like the sound of that, but I think it's always a bit leaky, unless the result is a full database design that lets people happily forget there's another database underneath.

-----

1 point by akkartik 4198 days ago | link

Oh, is the mongodb library using keyword args? I'm used to lisp where keyword syms can exist outside lambda lists.

-----

2 points by shader 4198 days ago | link

It seems to, though much of that is the ODBC layer, which I'm not sure I like anyway. It generates some constructors and getters and setters that use keywords, and I don't think that fits particularly well with the arc style.

Unfortunately, some of the database options are also keyword based, but maybe wrappers could be made for the few cases that matter? Sadly, I am also a beginner with mongo, so I don't really know what I need or how to do it.

-----

1 point by akkartik 4199 days ago | link

On tryarc (so not anarki):

  arc> ':abc
  :abc
But yeah, feel free. I've often wanted :foo to eval to itself just like in common lisp. Currently I use 'else where I would use :else in wart.

-----

2 points by shader 4199 days ago | link

Interesting. Well, I can push what I currently have, and if necessary remove it later.

Also, one issue is that after adding ssyntax support, :symbol is printed as #:symbol, since they're the same. Should I be adding a special case for that?

-----

1 point by akkartik 4199 days ago | link

Thanks! Looks great. I made one tweak: https://github.com/arclanguage/anarki/commit/c416f3a36f. And I've migrated 'else to :else. I can live with printing keywords in racket syntax. No need to add complexity for something so cosmetic. (Analogous to my thinking on nil: http://www.arclanguage.org/item?id=11864; http://arclanguage.org/item?id=12661; http://arclanguage.org/item?id=12814)

-----


Oh the irony. I had just decided to do this myself, and fixed the issues involved. Since it seems that there are more people interested in doing this, I have created a github cartridge upgrade derived from RayRacine's here: https://github.com/shader/arc-openshift

Hopefully the README file has good enough directions for getting started. If not, reply here or put an issue on that github repo and I'll fix it.

By the way, that SO post seems to have been taken down.

-----

2 points by tvvocold 4199 days ago | link

thx,bro

as ur step.i successed.my site is :http://diy-tvvocold.rhcloud.com/news

but i cant sign up..why?

i try bash :

  ./arc.sh
  ./arc.sh: line 17: type: rlwrap: not found
  ./arc.sh: line 21: racket: command not found
what is wrong,and how to fix?

best wishes!

-----

2 points by shader 4199 days ago | link

That's a bug I'm currently fixing. It happens because arc uses the pattern of creating a temporary file and then moving it, instead of directly writing to an existing file. The only problem is that the /tmp directory on the rhcloud gears is not on the same file system. So it fails to move the file.

I'll push the fix as soon as I finish it.

-----

2 points by shader 4199 days ago | link

As for the bash issue, running arc.sh directly fails for two reasons:

1) rlwrap is not installed

2) racket has not been added to your path

If you want to run the arc script, you can do it manually by moving to the app-root/data folder and executing:

  racket*/bin/racket -f arc/as.scm

-----

1 point by tvvocold 4199 days ago | link

just fix it by set the env....so i run the bash,,,and now i still cant sign up or login...why?miss something like sql?

-----

2 points by shader 4199 days ago | link

Ok, I finished the fix. You need to do a few things in order to get it working:

1) Update the anarki installation on openshift:

  rhc ssh <app>
  cd ${OPENSHIFT_DATA_DIR}arc
  git pull
2) Merge in the latest changes to my arc-openshift repo, which contains the tmpdir* fix.

3) Push to openshift, and wait ~20 seconds for it to reload.

You should now be able to register and create new posts.

-----

2 points by tvvocold 4198 days ago | link

thx,bro,u really rock...so i rebuild a new site http://news-tvvocold.rhcloud.com and i can sign up and login in...but i can't submit still...why that? follew ur instructions i cant push (stuck at 5th step)so i use this

  ##git remote add upstream -m master git://github.com/shader/arc-openshift.git
  ##git pull -s recursive -X theirs upstream master
Am i doing it wrong or miss something?

when i try

  arc> (nsv)
  rm: cannot remove"arc/news/story/*.tmp": No such file or directory
  load items: 
  ranking stories.
  tcp-listen: listen failed
    port number: 8080
    system error: Permission denied; errno=13
    context...:
     zz
     /var/lib/openshift/53755de6500446c100000b1a/app-root/data/arc/ac.scm:1227:4
and i repeat again :arc> (nsv) rm: cannot remove"arc/news/story/.tmp": No such file or directory load items: ranking stories. user break context...: /var/lib/openshift/53755de6500446c100000b1a/app-root/data/arc/ac.scm:1084:20 recur recur user break context...: /var/lib/openshift/53755de6500446c100000b1a/app-root/data/arc/ac.scm:1084:20 recur recur tcp-listen: listen failed port number: 8080 system error: Permission denied; errno=13 context...: zz /var/lib/openshift/53755de6500446c100000b1a/app-root/data/arc/ac.scm:1227:4

if u update the full instructions that will be great and grateful,,,thx very much! (add this will be helpful

  ##export PATH=$PATH:/var/lib/openshift//app-root/data/racket-6.0.1/bin:$PATH
)

-----

4 points by shader 4198 days ago | link

I'm not sure why you can't submit. I tested it on mine, and submission worked for me once I fixed the login issue.

For the git issues, I found a mistake in the instructions. The 'add remote' line should be:

  git remote add arc-openshift git://github.com/shader/arc-openshift.git
Since I copied it from RayRacine's rackos, it had accidentally said to add the remote as 'rackos', which makes the following lines incorrect. Maybe that wasn't your issue though. Any more details?

As for your repl test, you are directly calling '(nsv), which defaults to binding on port 8080 for all ips, which is against the OpenShift policy. What you want instead is:

  (nsv '("127.8.109.xxx" 8080))
Where 127... is your OPENSHIFT_DIY_IP. You can see how it works if you look in main.arc. You may need to correct your current directory as well.

Another alternative would be to just load main.arc from the terminal, which would automatically start the server exactly as the post-deploy script does, but in a way that lets you see all of the errors:

  (thread:load "../repo/main.arc")
Of course, you'll have to change the path depending on where you're running the arc interpreter from.

-----

1 point by tvvocold 4198 days ago | link

thank you very much.so i dicide to build a new site follow ur instructions. here's what i got...

  arc> (thread:load "../../repo/main.arc")
  #<thread>
  arc> rm: cannot remove"arc/news/story/*.tmp": No such file or directory load items;
  load items: 
  ranking stories.
  ready to serve port (127.10.233.1 8080)
  tcp-write: error writing
    system error: Broken pipe; errno=32
    context...:
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/arc/ac.scm:945:0: printwith
      map1
      map1
      pr
      handle-request-thread
      handle-request-thread
  tcp-write: error writing
    system error: Broken pipe; errno=32
    context...:
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/racket-6.0.1/collects/racket/private/map.rkt:26:19: loop
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/arc/ac.scm:1479:0: ar-close
      handle-request-thread
  tcp-write: error writing
    system error: Broken pipe; errno=32
    context...:
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/racket-6.0.1/collects/racket/private/map.rkt:26:19: loop
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/arc/ac.scm:1479:0: ar-close
      th1
  tcp-write: error writing
    system error: Broken pipe; errno=32
    context...:
     /var/lib/openshift/5375a15d5973ca41a30002b1/app-root/data/arc/ac.scm:945:0: printwith
      map1
      map1
      pr
      handle-request-thread
      handle-request-thread
  tcp-write: error writing
    system error: Broken pipe; errno=32
    context...:
*----------------

that's what i got while i sign and submit.and when i closed the terminal the site shutdown too...503...

------that's what i do after followed by ur 8 step instructions in http://new-tvvocold.rhcloud.com/...and when i try my way in http://news-tvvocold.rhcloud.com,by use

  ##git remote add upstream -m master git://github.com/shader/arc-openshift.git
  ##git pull -s recursive -X theirs upstream master
i got it done....and i check ur and my site find that both of us cant submit a simple url like(www.google.com but http://google.com works) with a title ,but only can submit a textwith a title...that's a new problem...if u could tell me what is the right step after the 8step as ur instructions as well.that will be great!---best wishes!

-----

2 points by shader 4198 days ago | link

Did you perhaps get a 'Try again' message?

I tried on my site with the url "http://google.com, and that worked. However, doing just "google.com" does not, so it's apparently filtering for fully qualified urls.

As for your error message when run from the command line... I get the same "rm: cannot remove..." message, followed by "load items" and "ready to serve port..." all of which are correct. The only real error is after that part, but I'm not sure why you're getting it. That error looks like something that might happen on a timeout or broken connection with the client.

What were the results on the client side? Did you get a blank page?

-----

2 points by tvvocold 4198 days ago | link

i set it up http://xmeetu.tk welcome to visit!

but i try to echo “admin” > arc/admins ,and admin looks doesn't like admin...i cant delete other's post...

-----

3 points by shader 4198 days ago | link

It looks like you have to restart the app server in order to get it to reload the user information. If you have repl access though, you can just run (load-userinfo)

I do think that we need a way to connect to the repl of the running service, as well as update the code without requiring a full restart, as that takes >20s most of the time.

-----

2 points by tvvocold 4198 days ago | link

thx.but how to arc>? i stop the app ,cd arc, echo “admin” > arc/admins,,,arc> (load-userinfo) ,,,,and arc> (load "lib/news.arc"),,,rhc app-start news...what wrong?still cant find admins privilege in my page.

-----

3 points by shader 4198 days ago | link

You should only have to restart it once. Calling 'load-userinfo from the repl is redundant, unless you want to check the value of the admins* table to see if it worked or not.

Which arc directory are you putting it in? There's the one that is the anarki installation under app-root/data, and the other which stores web app data in app-root/repo. You need to put the admins file in the app-root/repo/arc directory, or it won't be found by the app server.

That's probably not the right place to keep it, but I haven't bothered to redirect all of the arc server directories, so that's where it goes for now.

-----

1 point by tvvocold 4197 days ago | link

done.thx ..u really rock!bro!can i know ur name or google+?

-----

2 points by tvvocold 4197 days ago | link

btw,where an i change the logo and copyright?

-----

2 points by shader 4197 days ago | link

You can change the images used by replacing them in the app-root/repo/static directory.

I'm not sure where the copyright message you're referring to is. To replace it, you'd have to figure out where in the anarki code it's being generated, and override it in main.arc.

-----

2 points by tvvocold 4196 days ago | link

what does main.arc do and news.arc do?

-----

3 points by shader 4196 days ago | link

news.arc is one of the libraries that comes with arc, and is a branch of the source for Hacker News and the Arc Forum. It defines all of the functions related specifically to the news site, and is what allows you to run a clone of the forum. It's located in the lib folder of the anarki repo.

main.arc is the launch script I included in my arc-openshift repository. It just sets a few variables, and then launches the news server with the right parameters. It's located in the root directory of the arc-openshift repo.

Other files of interest are the arc libraries srv.arc and app.arc. srv.arc sets up a web server, and app.arc adds extra utilities for things like user management, etc.

-----

3 points by tvvocold 4196 days ago | link

and what type of the database does arc use? and How can I prevent SQL-injection in arc?

-----

2 points by rocketnia 4196 days ago | link

The news.arc code writes to files. It doesn't use an SQL database.

---

Even without SQL, code injection is something to worry about. The Arc codebase is a breeding ground for exactly this kind of issue, since it rarely does string escaping. Let's see...

HTML injection (XSS attacks): This is the kind of injection news.arc primarily needs to worry about. Almost every string it passes around is used directly as an HTML code snippet. Fortunately, every user input is sanitized thanks to the form-generating utilities in app.arc.

Shell injection: Make sure that any directory paths passed to (ensure-dir ...) are already shell-escaped. (Arc also invokes the shell in a few other places, but those don't need any extra escaping.)

Format string injection: Be careful about file paths passed to (tofile ...). Everything after the last slash must be a valid 0-argument format string. The format string syntax is described at http://docs.racket-lang.org/reference/Writing.html.

Arc injection: The prompt.arc webapp is explicitly designed to let admin users evaluate their own Arc code on the server. If an attacker gained access to this page, it would be worse than any other kind of code injection. Because of this, I don't recommend running prompt.arc on a production site. (If it can't be helped, I recommend at least using HTTPS so admin login credentials and commands can't be intercepted by a man-in-the-middle attack.)

-----

1 point by akkartik 4196 days ago | link

I wrote about the database thing a while ago: http://arclanguage.org/item?id=17629 (you might need to click parent to see the question)

Edit: ah, didn't realize I was responding to you there!

-----

3 points by shader 4196 days ago | link

Yeah, that's something I'm trying to think about with the current project that I'm working on. Part of why I brought up mongodb support. Maybe something like datomic would be better.

Starting with simple files is actually really convenient and takes very little effort. Only fixing things that need fixing is a good way to make progress quickly, but it is a little disconcerting not to have many options to switch to.

Maybe building a simple arc-based database would be a good idea, but that also distracts from solving the actual problems I'm working on. Which did not initially include making a new database, as much fun as that would be.

I was working on a simple git-based data storage system for arc as part of my 'metagame' project. Not exactly designed for multi-server use though.

-----

1 point by zck 4200 days ago | link

The SO post was taken down for "not being about programming", IIRC. It also didn't help that it was incredibly vague.

-----


Personally, I'm of the opinion that tests and examples should probably be kept separately. Examples are intended to be evaluated and displayed for help as a part of the documentation, while tests are designed to prevent errors in the code and often need to be designed for that purpose. 'Not equal' is only one of many assertions one may wish to make about output, and as noted before, many things have side effects that are not so easily compared.

Merging the concept can be helpful, but requires more of the people making the examples in the first place. Also, just because a code snippet makes a good example does not mean it makes a good test, and vice versa.

I would prefer a solution where 'examples didn't include any predefined results at all, and they were all just evaluated during help. If desired, someone working with the unit test suite could write code that leveraged the examples, but it wouldn't be necessary. That way we could use good illustrative examples that may not make good tests, and good thorough tests that may not make good examples.

Just my two cents.

-----

1 point by akkartik 4204 days ago | link

Yeah you may well be right. Is it really not useful to also be able to see the result of an example call right there next to the code?

I certainly agree that the vocabulary of matchers is incomplete. And if we can't find a small basis set of them, this whole second alternative to tests start to seem inelegant.

Perhaps we should just tag some tests to be shown in help and call it a day. Though I like seeing the tests right next to each function. That seems useful even if we rip out the online help altogether. In fact, I started out writing examples when the macro was a noop. We could just inline all the tests, but then it would be overwhelming to have 20 tests for each function.. Ok, I'll stop rambling now. Summary of use cases:

a) Getting feedback that something broke when we make a change. (Unit tests currently do this.)

b) Seeing some examples as we read the code.

c) Online help at the repl.

d) Online help in the browser. (like kens's /ref/)

-----

2 points by shader 4203 days ago | link

I don't think including the tests alongside the code would help much; many tests are rather complicated, involving set up, take down, and more complex assertions than just 'eq. Not that one couldn't understand what it meant, just that it's not as clear as an example.

I hadn't thought of the use case for wanting examples while perusing the code itself, but I must admit that I find that somewhat uncommon. I don't often know which file a function is defined in, and rarely need it given the help support we have in the repl. If I do want to look at the code, the 'src utility shows the source of a function. If I want to edit it, I often use the help utilities to find the file anyway. So having the results only available via the repl wouldn't bother me any.

C and D can get by with just evaluating the examples and showing the output.

-----

1 point by akkartik 4203 days ago | link

Ok, so you'd be satisfied if we just included the examples in docstrings?

-----

2 points by shader 4203 days ago | link

No, unless you wanted to dynamically read the examples from the docstrings to evaluate them when the examples are queried, either directly or as part of help.

Actually, I don't know if the examples should be automatically displayed with 'help, or queried separately.

Either way, it would be nice to make them automatically evaluated, unless they can't be for whatever reason. It seems like that would be easiest to do with something like the existing examples macro, but if you think it would be doable with docstrings I guess that could work.

-----

1 point by akkartik 4203 days ago | link

Ah, ok. So you don't care about being able to see them next to the function, but you would like some way to see them at the repl along with their results. Let me know if I'm still missing something.

(Sorry I'm asking basic questions. The discussion has ranged far enough that I just want to circle back to nail down precisely what you're suggesting among all the use cases and possible UIs.)

-----

2 points by shader 4202 days ago | link

Well, that's what I'm suggesting. I don't see the other cases as essential, and the interface seems simpler that way. I'm lazy too, which means that if I'm making examples, I'd rather not have to provide the results. Not that I couldn't, but I'd like the option at least to do otherwise.

As always, you don't have to change anything just to meet my opinions. I'm used to being in the minority, in fact.

-----

1 point by akkartik 4202 days ago | link

Thanks! Just want to record your feedback for the record. We'll see if I do anything about it.

-----

1 point by akkartik 4201 days ago | link

(It's not yet clear what the majority opinion is here.)

-----

2 points by shader 4201 days ago | link

Maybe nobody else cares. It's a pretty small community at this point anyway, and I doubt everyone checks daily. I know I've gone through long periods without checking.

-----

More