I get the error myself as well, but for me it is generally caused by navigating away from a page before arc is finished serving it. I think it is because arc tries to continue writing to the output-port associated with the tcp-port, but the connection has been broken so that port no longer works.
It hasn't caused any problems though, so I've ignored it for the most part.
According to arcfn.com and the code that it references, it looks like it's supposed to default to stdin, but it's written in such a way to require at least one argument. If you pass nil, it reads from stdin because of the default.
Which requires at least on argument. It should probably be changed so that that argument is actually optional, but I don't know how. I should read up on my mzscheme ;)
I'm not certain - I haven't tested it, but it looks right. Unless scheme and arc have different ideas of false, which could cause more problems. Maybe it should just be:
hmmm. It seems that mzscheme (at least the version that I'm running arc on, 360) doesn't support optional args. I guess I'll have to do it some other way.
It's fairly tedious to be doing this in Scheme, isn't it? We might let Scheme handle implementing the low level readc, and then in Arc redefine readc to be a more advanced function that can take an optional argument:
(mac redef (name parms . body)
" Redefine a function. The old function definition may be used within
`body' as the name `old'. "
`(do (tostring
(let old (varif ,name nilfn)
(= ,name (fn ,parms ,@body))))
,name))
It's the same as yours, except (a) it suppresses the warning on re-assigning an identifier, and (b) it calls the original function old.
btw, why is there no peekb? Or any other functions that work on bytes?
As part of the design process of finding the shortest Arc implementation, pg is careful not to include functions that he isn't actually using for news. This leads to some surprises (car, cdr, cadr, cddr, but no cdar?) but also removes cruft that builds up implementing things that people might need some day but turn out not to.
It turns out not to be a problem, since Arc is so concise it's really easy to extend, and so people quickly implement the things they need that pg happens not to be using for news.
I find I prefer the Arc approach, since libraries that try to provide everything I might need often have so much stuff that ironically they make it harder to implement what I actually need.
If you need the change right away you can patch ac.scm yourself, or, if you don't mind waiting, pg will eventually have a new arc3.tar containing the update.
Both Adlai's and rntz's version do what I was trying to do.
However, I was looking for a way to assign a value to the variable referenced by the one I was passed. i.e.
(= v 'b)
(= (val v) 6) ; unknown function/macro val which returns contents of v so that '= can assign 6 to 'b.
This would allow the expression above to be:
(each v '(a b c) (= (val v) (readb))) ;assigns three bytes from standard in to 'a, 'b, and 'c respectively.
Whether this is done by overloading 'unquote to work like that outside of a quasiquote, or making something called 'val, I don't know. Maybe it could be done by making val or unquote a setform? That would solve this problem, but I think it might be more useful if it worked in more places than just assignment.
If b is a lexical variable, eval won't help, since it isn't run in the lexical scope in which it's called. An Arc lexical variable will get compiled to an MzScheme lexical variable, and I don't know of a way to refer to an MzScheme lexical variable by name determined at run time. If there isn't, I suspect your only hope might be to modify the Arc compiler to generate code like
(case v
((a) (set! a n))
((b) (set! b n))
((c) (set! c n))
((d) (set! d n))
...
for all the lexical variables available at that point.
You know, if you used a input-port instead of a string, then next-char and bump-j would just be peekc and readc. I don't know if that would make you're life much easier, but it's an idea.
Right, a port encapsulates some state (where you're reading from, what your position is in the input), and then Arc uses a Scheme parameter (stdin) so that the input port doesn't need to be passed to every function that calls some function that calls some function that calls read or readc. So like you say I could use an input-port if that did what I needed, or I could implement my own thing if that turned out to be necessary.
I think it's too much work in many cases for others to bother free-riding your service with tools like citrix. If they like it that much, you're doing well!
Here are a few things though that might help keep the free-riding down.
1) Have a reason to need separate user names. I don't know what your service is, but you can almost always add some sort of 'identity' to it that people will want to keep for themselves.
2) Prevent people from loggin in too much from other locations. In many cases, people will want to keep their PC to themselves, so you can block free riding by checking cookies and ip addresses.
3) Charge more for overuse. Even if this is unlikely to actually catch people (i.e. the limits are set rather high) it can still make the person who's paying for the account less likely to share it with others.
4) Give a limited time free trial. This will cause people to create their own profile that they may be "invested" in, and want to keep. They will be less inclined to use someone else's account after they have their own, and if you price it well enough, they may be interested in buying it.
5) Price it well, and have reasonable expectations about how this will turn out. Odds are you will have some free-riding. Charge enough to cover your costs, and just deal with it. In many cases, the amount of discomfort it would cause your users and time it will cost you to cut down on free-riding will be higher than the damage you are preventing. Think carefully before you make drastic changes to your system to prevent "stealing".
I would suggest that you implement your service, and then see whether it's actually worth it to implement restrictions. It may be that you don't actually get that much in the way of free-riding. Or the free-riding could possibly be considered a cost of advertising. In the end, it's up to you.
I think that char-char is supposed to be next char ;)
Other than that, I'm not good enough yet at writing parsers in arc to help you much. Your original was already pretty short, though there were a few spots that you could have used the . operator more (car, cdr, etc.)
I am also working on a parser too, though, so whatever you discover will certainly be helpful ;)
in is just a input-port that I would already have bound, or passed in. If you'll notice, that was just a standalone expression, with no context, to illustrate what I was trying to do.
Thanks for the code, that was exactly what I was thinking of. Too bad there isn't a macro or function that just returns the value of a variable in such a way that it can be assigned to. Can anyone think of how to implement such a thing?
i.e.:
(= v 'a)
(= (val v) 6) ;the variable a is now assigned the value 6.
Basically an (unquote) without the wrapping quote ;)
Well, there's always 'eval, but it has issues and stigmas, and I've read that other Lispers look at you funny when you use it your code...
'in is also a built-in macro in arc.arc. Since Arc is a Lisp-1 (grr...), you can't bind it to an input stream without potentially breaking some other code...
(mac in (x . choices)
(w/uniq g
`(let ,g ,x
(or ,@(map1 (fn (c) `(is ,g ,c)) choices)))))
Back to the symbol dereferencing question -- I think one reason that this kind of thing is shied away from is that it starts to smell an awful lot like pointers. However, the control over evaluating that you get with macros is more than enough to take care of symbol dereferencing problems like this.
Right. I forgot to check the symbol before I used it like I sometimes do, via 'help or 'src (Anarki).
Is there anything wrong with "pointers"? As in this case, they can often be quite useful, and make the code (at least to me) simpler. Maybe I just think in pointers, and need to learn to use destructuring binding more. That won't work unless you know all of the variable names in advance, but I guess that's what a hash table is for :)
The only problem with your naming system is that colons are already taken as syntactic sugar for function composition. If you're interested in package systems for arc, you could look into what almkglor did on Anarki. It was a pretty thorough overhaul of most of arc, but I don't think it's supported anymore.
Strictly speaking, it doesn't need to be so thorough.
It's possible to make the contexting system be less aggressive about putting symbols in packages.
As an explanation, contexting performs the following transform:
; Arc-F code!
(in-package foo)
(using <arc>v3)
(interface v1 public)
(def private (x)
x)
(def public (y)
(private y))
; equivalent transform!
t
t
t
(<arc>def <foo>private (<foo>x)
<foo>x)
(<arc>def <foo>public (<foo>y)
(<foo>private <foo>y))
Because of its aggression, everything gets to be a pretty thoroughly pushed to some package.
However, you can reduce the aggression instead, at the cost of declaring private functions:
; Anarki-on-arc3 code!
(in-package foo)
(using <arc>v3)
(internal private)
(interface v1 public)
(def private (x)
x)
(def public (y)
(private y))
; equivalent code!
t
t
t
t
(def <foo>private (x)
x)
(def <foo>public (y)
(<foo>private x))
In short, instead of assigning unpackaged symbols to the current package, it leaves unpackaged symbols. This retains as much back-portability with ArcN as feasible.
However you still need to force contexting in your REPL/load, i.e. RCEPL, read-contextify-eval-print loop.
I won't be working on Arc-F, since I have my own project now, and stefano is squeezing me to get a REPL on it some time soon ^^