I'd approach this by using AJAX to replace the contents of the chat without refreshing the whole page. An iframe is a good approach too.
Once you get things working, it might be nice to switch to push techniques at some point: http://en.wikipedia.org/wiki/Comet_(programming) That way you don't have to reload the whole conversation every N seconds. This probably isn't important enough to lose sleep over, though. ^_^
Is the Arclanguage forum or HN (or something similiar) open-source?
Whatever you're using for Arc probably includes news.arc and app.arc, and those are released as specified in the "copyright" file:
This software is copyright (c) Paul Graham and Robert Morris. Permission
to use it is granted under the Perl Foundations's Artistic License 2.0.
In essence, it's a license that allows a lot of freedom but states that you can only distribute a modified version "provided that you clearly document how it differs from the Standard Version." I think the point is so that people who consider your modifications to be shoddy work or copyright infringement don't go complaining to Paul Graham or Robert Morris.
This is a very nice forum I have to say, great edititing and automatic code recognition! Never seen something as good as that.
You're one of the luckier ones, I guess. :) Complete editing instructions are at http://arclanguage.org/formatdoc in case you're interested.
I'd approach this by using AJAX to replace the contents of the chat without refreshing the whole page. An iframe is a good approach too.
Is that possible to do _in Arc_ (By something with tag ?) or do I need something else as well? I'm really not very expirienced and would have no idea how to combine my Arc-Sourcecode with something completely external... or how to implement these Comet-techniques.
Is it actually possible to make normal Frames or iFrames with the tag-macro?
Thanks for news.arc, I haven't seen it for some reason, seems like it's worth reading.
1. chatlog?room=1&max=20 , this service returns the conversation data you would like placed in your div having an id of 'chatlog'. The room is the id for a conversation and max is the number of items you want returned from the conversation history.
2. checkchat?room=1, this service checks to see if there's been an update in the chatlog since the last time the user checked. So you need to store the last time checked, and compare that to the timestamp of when the chatlog, for that room, was last updated. Comparing the two will return either Y or N. Y will trigger the update. There's javascript noted below that will auto check this for you.
Javascript:
(def get+xmlhttp (url)
(string
"function GetData(){
if (window.XMLHttpRequest){
var xmlHttp = new XMLHttpRequest ();}
if (window.ActiveXObject){
var xmlHttp = new ActiveXObject(\"Microsoft.XMLHTTP\");}
xmlHttp.open (\"GET\",\"" url "\", false);
xmlHttp.send (null);
var targetNode = document.getElementById (\"chatlog\");
targetNode.innerHTML = xmlHttp.responseText;};"))
(def checkif+xmlhttp (url)
(string
"function CheckChatLog(){
if (window.XMLHttpRequest){
var textHttp = new XMLHttpRequest ();}
if (window.ActiveXObject){
var textHttp = new ActiveXObject(\"Microsoft.XMLHTTP\");}
textHttp.open (\"GET\",\"" url "\", false);
textHttp.send (null);
if (textHttp.responseText == \"Y\") GetData();};
window.setInterval(\"CheckChatLog()\",5000);"))
The 'CheckChatLog' function checks the 'checkchat' service to see if there's been an update. If there has been, then 'GetData' is called which pushes the data into your 'chatlog' div.
Notice 'checkif+xmlhttp' has 'window.setInterval', so the js will periodically run 'CheckChatLog' for you - you may want to tweak the 5000 time interval.
I hope that's useful. I created one a year or so ago, which haven't touched it since, so if something doesn't make sense, ask away.
Doing an ajax get will require javascript. Look at votejs* in news.arc.
Frames and iframes can be rendered using tag but you'll need to update html.arc to recognize their html attributes. Surprisingly this isn't fixed in anarki, but see if you can figure out what to do at http://github.com/nex3/arc/blob/3201b34f3ed89e6305b0d99066e4...
On Frames: As the starttags <frameset attributes...> and <frame attbibutes...> aren't the same as the end tags, I'd have to do macros like (mac tab...), or ?
This should be possible... and then add the attributes, yeah. I will try it soon, thanks.
When I have a frame, how can I tell the code, to autorefresh it and only it?
And does a frame need a .html-file to read? or can scr="...", the attribute of a frame, be the name of a (defop xyz...)?
Interestingly, it does seem like [currying] would work fine with keyword arguments.
Very interesting observation! XD It's inspiring....
Well, CSS has the slickest keyword argument API I've ever seen. The declaration "border: 2px solid black;" conveys the same information as a whole lot of other declarations like "border-top-width: 2px;", "border-bottom-style: solid;", etc. What if the "border" keyword were definable as a library?
; Haskellish syntax with liberties taken
border width style color f = f -: border-width width
-: border-style style
-: border-color color
border-width width f = f -: border-top-width width
-: border-bottom-width width
-: border-left-width width
-: border-right-width width
Type Border-Top-Width ; singleton type
border-top-width value f = f -: keyword Border-Top-Width value
The premise behind -: is that it's a low-precedence left-associative binary operator such that (a -: b) is just (b a). (I don't know if Haskell has something like that already....)
The "keyword" function is axiomatic to the language. It takes a key value, a value to associate with it, and a function, and it returns the result of currying that function with that keyword information, overwriting the previous association for that key if necessary.
As for defining a function that does something with the keyword arguments it gets this way... I'm out of steam for now. What do you think?
EDIT: Hmm. With currying, we consider two-argument functions to be indistinguishable from functions that return functions, right? If a programmer naturally wants to write a two-argument function that takes keyword arguments, should that be a keyword-taking function that returns a plain function, a plain function that returns a keyword-taking function, or what? What about keyword-taking functions that naturally have zero arguments? Maybe currying and keyword arguments aren't very compatible after all, or maybe they just need a different evaluation model. (Maybe keywords should be dynamic variables observed using an "I'll consume this whole subspace of keywords, thanks" syntax?)
I think that's the way to go if you like currying. Otherwise it's sort of a technique for peeling oranges in a language full of apples.
Nevertheless, I've thought about currying a bit myself, just 'cause it comes up on this forum so much. The following code is the culmination of where I usually end up, in my mind: http://gist.github.com/644503.
In a nutshell, the technique is to have functions keep track of some arity information so that they can be used in lisp-style calls as well as being transformable into curried versions. Using 'defcall in Anarki or Rainbow, we can define a new Arc type that behaves like a function but carries the necessary information.
Once my code is loaded, you can use >.2 and <.1 just as you'd like. I overwrite them explicitly so that they're of type 'curryable instead of 'fn, and you can do the same thing to other functions as desired, just as long as the currying code doesn't depend on them (so that you don't get infinite loops). You can also curry functions you haven't overwritten, using cur.3.union.is to describe the arity on a call-by-call basis.
I've never bothered to put this into code before just 'cause I don't have a lot of oranges to deal with from day to day, but maybe it'll be useful for you. ^_^
Incidentally, I'm pretty sure (< x) has its current behavior so that (apply < lst) has a simple description: It always returns t if 'lst is increasing and nil if it isn't.
That being said, redefining '< this way isn't all that bad. The result of (apply < '(1)) ends up being a procedure, which still counts as a true value!
That being said, there may still be a problem if humans consistently have trouble simplifying (map >.2 '(1 2 3 4 5)). :-p
I've been considering using ssyntax in parameter lists to set apart special behavior in parameter lists, with destructuring being the normal behavior. (I was inspired by aw and someone else using (def foo (string:x) ...) syntax for coercing parameters, but I can't find that thread....)
Anyway, here's one of the takes on optional arguments I've been pondering:
(a b c .o opt1 nil opt2 3)
This is pretty similar to the Common Lisp approach, and you can even use &optional instead of .o for added similarity. :-p The main advantage in my mind is that it's less of an abstraction leak; Arc doesn't really support argument lists of the form ((o a) b), so a function with optional arguments has only one extra conceptual boundary in its argument list, and you should only have to punctuate it there.
For a more customizable approach (especially if you do want ((o a) b) to work after all), I added a backtracking pattern matching library to Lathe a while back (http://arclanguage.org/item?id=11956) just for the purpose of making destructuring more customizable. I didn't end up doing anything with it after that, but if and when I did, parameter lists would probably look like this:
(pfn (a b c (.o opt1) (.o opt2 3))
...)
The parameter list here would be wrapped up as '(struct (a b c (.o opt1) (.o opt2 3))) and compiled via the library to determine the variables it binds and what code it uses to bind them. In particular, the library would identify the 'struct operator as a "patmac," and it would use that patmac's implementation like a macro to determine what the rest of the expression meant. In the process, the expressions '(atom a), '(atom b), '(atom c), '(o opt1), and '(o opt2 3)--without the dots--would be sent off to another library that implemented a "list-patmac" system for monadic parsing of sequences.
As I mentioned, I never got this far. The second library doesn't exist at this point, and I haven't added even one patmac since I finished the proof of concept and made that post. It's not like it would be hard to get to this point in the design, but I've just been focusing on niftier things. ^_^;
So there you go, one straightforward syntax and one general-purpose syntax. The ultimate elegance struggle, eh? :-p
If the behavior were in a different utility named 'v+ or something, you wouldn't have a "two libraries extending the same case" conflict (just a "two libraries defining the same variable" one :-p ), and you'd also be able to have (v+ '(1 0 0) '(0 1 0)) be '(1 1 0) without conflicting with Arc's existing result of '(1 0 0 0 1 0).
Using 'extend generally also has the drawback that existing code that expects to get an error from something like (+ 1 '(1 2 3)) won't get that error anymore. This is less of a problem when using a tagged type that people are very unlikely to be using already, but numbers and lists are especially common.
After hammering on your approach a little, here's what I get. ^_^ I like to maintain the fact that Arc's '+ is left-associative, so I don't give myself as much leeway with the additional arguments.
; We're going to have a meaning for number-plus-list, so we override
; the default number behavior, which assumes that only numbers can be
; added to numbers.
(extend + args (let (a b) args (and number.a number.b))
(let (a b . rest) args
(apply + (do.orig a b) rest)))
(extend + args (let (a b) args (and cdr.args number.a alist.b))
(let (n xs . rest) args
(apply + (map [+ n _] xs) rest)))
Saying (treewise cons [only.+ _ n] xs) is a bit more wordy than necessary here, but it's still a good way to accomplish (+ n xs) inline, without extending '+.
Oh, hey, if 'treewise could tell that it had a cyclic data structure, it would also be a more robust option... but that's not the case yet. Should it be?
Never thought of that. I mean, the P part of the vanilla Arc REPL breaks on them, and I've never been compelled to use cycles. When are cyclic lists used? I guess if you're representing certain graphs?
I upvoted you 'cause Semi-Arc's doing what you want it to do (which is what really matters), but I'd like to mention that I actually kinda appreciate the way Arc accepts mismatched destructuring lengths.
I've seen other people's code use a (let (a b c) nil ...) idiom as a shortcut for (with (a nil b nil c nil) ...). As for me, I like being able to design multiple types so that they can be used in an ad-hoc polymorphic way like this:
Both these techniques could still be used in an Arc implementation with a stricter treatment of destructuring: The first could be done by defining a 'w/nil macro, and the second could be expressed as (let (x y . rest) rep.point ...). In your favor, the strict treatment makes it easier to write functions that do complain if the length is incorrect, encouraging fail-fast code. However, as far as portability is concerned, the "N args expected" errors are a quirk of Semi-Arc.
I'm going to try out Semi-Arc right now. ^_^ I'm sure I'll have some error reports for you in a moment. Hopefully not too many! :-p