11
$\begingroup$

Bug fixed in V11.2

Previously dependencies collector failed to collect check if check was only mentioned in lhs: foo[x_?check] := $Failed;


Cross posted on community.wolfram.com

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 on Wolfram Cloud

  2. Why my cloud application failed to display manipulate element correctly?

  3. Using CloudDeploy with dependent functions

$\endgroup$
  • $\begingroup$ foo[x_?check] := (Hold[check]; $Failed); will work. This kind of new cloud programming paradigm ("mention all symbols somewhere on the right of := ") should probably be followed until the Wolfram Cloud system stays in its current beta-phase and until it is properly documented. I heard that better documentation is being worked on. And that is promising. (Andre?). $\endgroup$ – Rolf Mertig Jun 12 '17 at 20:26
  • 1
    $\begingroup$ I added documentation+bugs as WRI confirmed it is a "limitation". A limitation not mentioned in documentation. $\endgroup$ – Kuba Jun 13 '17 at 5:51
5
$\begingroup$

This is probably not a direct answer to the question, but too long for a comment. Regarding the collection of definitions, I can offer a hack which seems to work (I did answer this question before on a Russian-speaking Mathematica forum). The idea is to use Manipulate to collect the dependencies. Here is the code:

ClearAll[extractDefinitions];
SetAttributes[extractDefinitions,HoldAllComplete];
extractDefinitions[code_]:=
  Block[{$ContextPath},
    DeleteCases[
      First @ Cases[
        MakeBoxes[#]& @ Manipulate[code,SaveDefinitions->True],
        Verbatim[RuleDelayed][Initialization,rhs_]:>HoldComplete[rhs],
        Infinity
      ],
      x_Set/;!FreeQ[Unevaluated[x],HoldPattern[Typeset`initDone$$]],
      Infinity
    ]
  ];

ClearAll[embedDependencies];
embedDependencies[APIFunction[params_,f_,rest___]]:=
  With[{initCode=extractDefinitions[f]},
    APIFunction[params,(ReleaseHold[initCode];f[#])&]
  ]

Now you can do:

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

(I slightly modified your example). Now, here is the result of embedDependencies:

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

(*
APIFunction[
  {"x" -> "Number"}, 
  (ReleaseHold[HoldComplete[CompoundExpression[
    {foo[x_?check] := x, foo[x_] := x^2, x = True,check = IntegerQ}]]];
    (foo[#x] &)[#1]
  ) &
]
*)

And this works fine when deployed:

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


URLExecute[api, {"x" -> 2}]
URLExecute[api, {"x" -> 1.2}]

(* 2 *)

(* 1.44 *)

This is of course a hack, so while I feel it is rather reliable, I can give no guarantees here.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.