Message Boards Message Boards

Self contained APIFunction. Collecting definitions

Posted 7 years ago

Cross posted on mathematica.stackexchange: https://mathematica.stackexchange.com/q/148207/5478

Background

After failed attempt (1) to create a complex API, by nicely linking my APIFunction to a cloud based package, I decided to go with the flow and trust that:

CloudDeploy[expr, ...] automatically deploys all definitions needed to evaluate expr, much like CloudSave.

Problem

but either it can't be trusted or I'm missing the point. It seems that definitions are collected by scanning right-hand-sides of related definitions but not left-hand-sides.

Example

ClearAll[foo, check];
check = IntegerQ;
foo[x_?check] := $Failed;
foo[x_] := x^2

api = CloudDeploy[
    APIFunction[{"x" -> "Number"}, foo[#x] &]
  , Permissions -> "Public"
]



foo[2]     (* -> $Failed*)
foo[1.2]   (* -> 1.44 *)



URLExecute[api, {"x" -> 2}]    (* -> 4*) !!!!!!!!!!!
URLExecute[api, {"x" -> 1.2}]  (* -> 1.44*)

The first URLExecute is wrong, it is caused by missing definition of check.

One can confirm that by

Import[api, "Text"]
Language`ExtendedFullDefinition[] = Language`DefinitionList[ 
  HoldForm[foo] -> {..., DownValues -> {
    HoldPattern[foo[(x_)?check]] :> $Failed, 
    HoldPattern[foo[x_]] :> x^2
    }, ...
 }];

APIFunction[{"x" -> "Number"}, foo[#x] & ]

Questions

  • Is this expected? Are there any new guidelines how to write code so it could be collected well? Or is it a flaw in Language`?

  • Is there anything I could read to learn working with the Cloud features in such a way that I won't have to come back here with a question/problem about a basic issue like deployment of dependencies?

Links

  1. Clean package update for API/FormFunctions

  2. https://mathematica.stackexchange.com/q/104739/5478

  3. https://mathematica.stackexchange.com/q/125837/5478

POSTED BY: Kuba Podkalicki
4 Replies

My package is heavily populated with symbolic wrappers similar to e.g. built-in File or atomic examples like RegionMesh, etc. So many of my functions have down values based on those heads, that is

foo[x_MyFile]:=...

bar[x_?MyRegionMeshQ]:=...

etc.

I don't need to inject all symbols but I need to pick all relevant symbols. There is a lot of them and they are spread over many files, that is why I'd go with mindless injection as opposed to cumbersome picking.

p.s. Blank arguments are not respected either, so foo[x_MyFile]:=... will not force MyFile definitions to be saved. You can add this to the list.

POSTED BY: Kuba Podkalicki

The issue with PatternTest is the only one I am aware of. I would be surprised if you had to manually inject most or all of your dependencies unless they really do all depend on this corner case. Do you have different examples where you expect definitions to be picked up but aren't?

POSTED BY: Andrew de Laix

Thanks for the feedback Andrew. Is there any other limitation of this feature which also makes the quote from documentation false?

Thanks for the workaround but I can't use it in this form, I probably need to automatically inject all symbols from all packages that constitute my dependencies. Leonid's fix from the linked mma.se topic looks promising, will let you know how it went.

And yes, HTTPErrorResponse and friends are the way to go but this was just an example.

POSTED BY: Kuba Podkalicki

This is a limitation in the code that infers dependencies. It isn't traversing the second argument in the PatternTest appearing in your definition of foo and therefore not picking up the definitions for test. We'll be improving that in an upcoming release, but until then there is a workaround. With an admitted hack, you can get the definitions into the deployment by explicitly including the symbol in the deployed code

api = CloudDeploy[
    APIFunction[{"x" -> "Number"}, (check;foo[#x]) &]
  , Permissions -> "Public"
]

Notice that check doesn't do anything, but having the symbol in the pure function is enough to do the job. You should now see the expected results for integer and non-integer values. Also, as an alternative to returning $Failed for the cases where test is true, you might want to consider returning an HTTPErrorResponse which will return an HTTP error code making error handling in any client app simpler.

POSTED BY: Andrew de Laix
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract