What you could do is, you could create an "opaque" function which gives access to your theorem data. Then wrap that function in an 'annotate form.
(def theorem (f)
(if (check-that-f-is-valid-theorem f)
(annotate 'theorem
(fn (cmd)
(case cmd
get
f
something-else
(do-something-on f))))
(error "Not a valid theorem")))
For that matter, since Arc is around "exploratory programming", in principle Arc will not allow anything that limits what the user can do.
In practice, most users are too busy working on stuff to bother doing something as stupid as (annotate 'theorem something_which_is_not_a_theorem) anyway.
lol
Exploratory programming is fine, but I don't need to explore anymore what a theorem is :-)
> "Arc will not allow anything that limits what the user can do"
Obviously this is not true, as Arc limits me such that I cannot create a safe theorem type. What this means is that I cannot let the user directly interact with Arc when building an interactive theorem prover; I have to wrap some kind of protective layer around it, which would probably hinder lots of the exploring!
> All images should be sized down to a particular maximum size, and flickr style thumbnails should be generated for the gallery view.
Arc has exactly 0 support for this. Maybe add this to TODO list of libraries for Arc?
> How do we tell if the file is not an image?
Check the binary file for each of the common formats?
> What do you do then?
If it's not an image, summarily delete it and tell the user that it didn't match one of the supported formats.
> What if the file is really big, and eats up our bandwidth / disk space?
Set a limit on HTTP PUT or POST. If it exceeds a certain size, complain to the user.
Note however that the Arc Server does not support PUT operations yet.
> Do we have any support for truly temporary files?
/tmp ?
> We wouldn't want one user's file to upload over another, when we're still trying to shrink and process it. How do we avoid orphaning images if users re-upload things?
Tough. Not sure what you exactly mean with this though.
> Should user icons be considered the same sort of thing as gallery images?
Not sure what you mean by this either. What do you mean by "user icons"?
> Should we store anything relating to the images in our database at all?
What support do you need for image processing beyond (system "ImageMagick ...")?
But seriously, if you're planning to implement an image processing library, take a look at the Common Lisp bindings to ImageMagick: http://common-lisp.net/project/cl-magick/
>> We wouldn't want one user's file to upload over another, when we're still trying to shrink and process it. How do we avoid orphaning images if users re-upload things?
>Tough. Not sure what you exactly mean with this though.
>> Should user icons be considered the same sort of thing as gallery images?
>Not sure what you mean by this either. What do you mean by "user icons"?
Most forums and art sites let their users upload a little picture, which is placed by each of their comments or posts. The difference between this and a normal image on the site is that, while other pictures may exist in different forms (e.g. full view / original, medium size, and thumbnail), user icons often only show up in one small standard size, and the original image they were shrunken from is not saved.
It's not easy. We can't make it into a primitive, because CPS conversion assumes that primitives will never need access to continuations, and thus does not transform primitive calls to CPS form.
- call the APPLY() function, which just POPs the two elements, PUSHes all the elements of the arg list one after one, then call the closure (maybe after changing the continuation argument of that closure by hand, at runtime) ?
That's a runtime behavior, for sure, and probably a few cases should be hard-coded in the generated C file. E.g., (apply + '(1 2)) should be translated to (+ 1 2), then to 3, if nothing bad (redefinition of '+ or 'apply by the user) happened. But in the general case, you can't know.
Anyway, we will eventually have to implement an interpreter in the generated code, to deal with dynamic stuff. Maybe closures should be made available through a hashtable mapping their name(s) to actual code, and not only through a hard-coded array as it is now ?
> - call the APPLY() function, which just POPs the two elements, PUSHes all the elements of the arg list one after one, then call the closure (maybe after changing the continuation argument of that closure by hand, at runtime) ?
Which continuation argument do you pass?
Suppose it's like this:
(%car (%apply foo bar))
Then foo is:
(set foo
(fn (a b)
(ccc
(fn (k)
(a k b)))))
Question: How does '%apply get access to the continuation, in order to pass to 'foo, which passes it to 'ccc ?
Remember, calling a function consists of the following steps:
1. Push the closure
2. Push the continuation
3. Push the arguments
The problem is step 2: continuation.
Possibly we need to insert the default 'apply during the same step as inserting the default 'ccc ? Then we could define '%apply as accepting the function, the continuation, and a plain list of arguments.
> Anyway, we will eventually have to implement an interpreter in the generated code, to deal with dynamic stuff. Maybe closures should be made available through a hashtable mapping their name(s) to actual code, and not only through a hard-coded array as it is now ?
s/closure/global variable/, maybe?
I think what we could do is, we add a pointer to an obj in the symbol structure. If the symbol is in the GLOBAL() array, this pointer points to that entry, otherwise to a malloc()'ed location.
None yet. What's currently blocking us badly is handling macros in the code for compilation. Like any decent Lisp program, arc2c makes quite a bit of use of macros.
Unfortunately macros require us to embed an Arc interpreter in the compiler itself, and we can't use the builtin 'eval because we don't want the macros under compilation to accidentally bash global functions/variables used by the compiler itself.
You'll have to contact sacado if you're interested in chipping in, we haven't figured out how to make a git on github publicly pushable.
I picked that habit up from some of the examples in the forum, and it works for me. Is there a reason why one would really want multiple return values?
The one nice thing about multiple values that I don't think returning lists accomplishes is that if you have a function that doesn't expect to receive multiple values, it will just use the first value returned. For example, in CL, #'truncate returns two values, the quotient and the remainder. But if you pass the return values of #'truncate to #'+, it just pretends you only passed a single value.
* (truncate 5 3)
1
2
* (+ (truncate 5 3) 6)
7
I don't know of any way to make this work implicitly with returning lists... you would need to explicitly test if you were receiving a list and then destructure it accordingly. (Please correct me if you know of a better way around this.)
Anyway, I suppose that the programmer knows what the output is of a certain function, and not be surprised if a function churns out a list rather than two values ;).
What if your function originally just returned one value, but at some later point you realize that a second value would be useful in some situations?
With multiple return values you can just extend it without breaking existing clients. If, on the other hand, you add a list wrapper around the returned values, all call sites must be changed to take car of the list.
That would be useful indeed. The flip side of the coin might be something that was sort of mentioned in 'on lisp'. If all functions return only one value (be it a list or a single value) by default, you can write a general memoize layer around functions that doesn't have to check how many multiple return values are returned.
I also noticed a carif function in arc. If you are worried about single values that will become lists in the future, you might start using carif in your current clients.
Returning multiple values puts multiple non-GC'd values on the stack. This is fast, but capturing and using those values is somewhat inconvenient for the programmer. Returning a cons creates one other cons in the heap that will need to be GC'd for each additional value returned.
In theory we could do this with arc2c. However, I'm not 100% sure this is necessary with a "really good" optimizing compiler.
We could defer destructuring of arguments in arc2c to as late as possible, so that we could do some amount of optimizing away 'cons cells when the cells themselves are used only for returning multiple values. Which is arguably difficult, since each stage in arc2c expects arguments to be in undestructured form, i.e. (let (foo bar) niaw ...) => (let tmp niaw (with (foo (car tmp) bar (cadr tmp)))). If arguments are kept in non-destructured form, we would need to modify the way that function parameters are stored (to handle (o foo (expression))) and check each stage in the compiler.
Edit: When optimizing raymyers' treeparse, I actually transformed parsers to CPS form in order to return multiple values without all the construction and deconstruction of 'cons cells, which helped reduce some of the overhead.
In my experience peekc doesn't seem to work properly (i.e. as advertised) at all.
I assume you're doing peekc so that you can do something else while waiting for a character? If that is what you're trying to do, I suggest you use threads:
(first time I work with threads) readmud only reads one character at a time, and I want it to just keep on writing as long as there is data. I'll try to add a thread that calls readmud again the moment it returns something sensible.
Partial success. The reading bit seems to function fine (if slow ;), and I now can use arc while in the background the muds' output is being read, but still cannot write. Did add mzscheme's flush-out (but perhaps in some wrong way. Will look at it during the next work-break ;).
Err. How do you expect the keys to be sorted? Is #\p < (bite #\p) ? You have to specify your own sort function, replacing < with a (fn (a b) ...) specifying how you want it to be sorted.
That points me in the right direction at least. I'd have wanted that everything in the list is just seen as a string, so "#\p" would indeed be smaller than "(bite #\p)" if the character "#" has a lower ascii code than "(".
coerce looked promising, but i'm not sure how to force a list like (bite #\p) into the string "(bite #\p)".