If you want to go this way (and I suspect that there may be a better way),
rather than using eval, I would look at serial-lambda from
web-server/lang/serial-lambda, which lets you create closures (like the
values produced by lambda) that could be put into a TEXT field using
serialize and write. The benefit is that once you read and deserialize, you
have a value that can be directly applied to arguments or called as a
thunk, not source code that needs to be evaluated.

For one approach to security, see web-server/stuffers/hmac-sha1
<http://docs.racket-lang.org/web-server/stateless.html#%28part._.H.M.A.C-.S.H.A1_.Signing%29>.
There are probably additional considerations in your case, but it would at
least ensure that your serialized closures in the database are not forged.

But I wonder why you need to save these "tasks" to disk. Unless they need
to persist across runs of the application, it seems like you might be
better served using threads (and possibly custodians
<http://docs.racket-lang.org/reference/custodians.html> and/or will
executors <http://docs.racket-lang.org/reference/willexecutor.html>, which
I haven't had much cause to play with yet). For example, to do something in
5 minutes, you could write:
(thread
 (λ ()
   (sleep (* 60 5))
   ;; do work
   ))
Then you could leave all the work of making sure your "tasks" actually run
at the appropriate moment to Racket. (In fact, even if some of your tasks
do need to persist across runs of your application, you could still use
this approach for actually running them if you include a step in your
startup sequence to re-spawn any tasks that remain in your database.)

On Sat, Oct 29, 2016 at 6:27 AM Tony Garnock-Jones <to...@ccs.neu.edu>
wrote:

> On 10/28/2016 08:21 PM, David Storrs wrote:
> > Is it possible to take (e.g.) a procedure object and decompose it back
> > into its original source code?
>
> I don't believe this is possible without murky unsafe programming, but...
>
> > One (bad) idea that came to mind was to simply shove some Racket code
> > into a TEXT field in the database, then eval it when the time comes.
>
> ... this isn't actually so bad. From what you write, I think you're
> already seeing the potential pitfalls: what should be in scope of the
> code to be eval'd?
>
> > Now, this is horrible for a lot of reasons (security and error
> > handling being two of them)
>
> Security will be a problem no matter what, but I don't see that error
> handling gives undue difficulty! What am I missing?
>
> > suppose I already had a function that did what I needed and I
> > wanted to use that
>
> Instead of storing a list-representing-code-to-eval, you could store
>
>  - the name of a module
>  - the name of a function
>  - a list of argument values
>
> and use `dynamic-require` in your task runner to find the given function:
>
>   > (dynamic-require 'racket/list 'filter-map)
>   #<procedure:filter-map>
>
> and then `apply` with the arguments...
>
> Erlang uses essentially this approach in many places where actually
> passing a closure around would be problematic (e.g.: code upgrades;
> serialization to databases; etc). Erlang terminology is to call the
> triple of module name, function name, and arguments an "MFA".
>
> Cheers,
>   Tony
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to