Skip to main content

bugs - Problems with Dataset's querying on a fresh Kernel


Bug introduced in V10.4.1 or earlier and fixed in V11.3




A support case with the identification [CASE:3710757]


[...] I checked and reproduced the issue at my end and have reported the issue to our developers. [...]





I've faced a problem while answering Assigning ::usage in a package for in Private generated symbols?


ds = Dataset@{<|"name" -> "Kuba"|>};

Hold[Evaluate[Symbol[#name]]] & /@ ds


First time it gives:


$Failed


OwnValues::sym: Argument Symbol[Str] at position 1 is expected to be a symbol.

The second evaluation takes long time to return and only from the third on it behaves correctly.


Any insights?



Answer



The behaviour we see is due to a bug. Specifically, it is caused by an evaluation leak during the type-inference stage of query evaluation. (This analysis is current as of version 11.0.0.0).



Cause


The exhibited error message can be reproduced at will by evaluating the following expression which represents only a small portion of the full query execution:


TypeSystem`ResetTypeApplyCache[]

TypeSystem`TypeApply[
Hold[Evaluate[Symbol[#name]]] &
, { TypeSystem`Assoc[TypeSystem`Atom[String], TypeSystem`Atom[String], 1]}
]

(* >> OwnValues::sym: Argument Symbol[Str] at position 1 is expected to be a symbol.


TypeSystem`UnknownType
*)

A careful inspection of a trace of this evaluation reveals that the type inferencer is not taking enough care to prevent evaluation of the components of the Hold[...] expression as it recursively descends into it. This bug is somewhat understandable since the ability to "quote" code in Mathematica is idiomatic rather than a first class concept. This makes it fiendishly difficult to prevent all evaluation of arbitrary code. But fiendishly difficult does not mean impossible, so it should be possible (if tedious) for WRI to fix this problem.


Why Does The First Evaluation Fail?


By default, any dataset query will fail in the event that any message is issued during its evaluation. The TypeApply expression we examined issues an error message, so the query fails.


We can rewrite the original query to an equivalent form:


ds[All, Hold[Evaluate[Symbol[#name]]] &]


After doing so, we can add the FailureAction option to tell the query to proceed even in the event that a message is issued:


ds[All, Hold[Evaluate[Symbol[#name]]] &, FailureAction -> None]

If this expression is evaluated in a fresh kernel session we still get the error message but the expected result is returned.


Why Does The Second Evaluation Succeed?


The type inferencing process caches its results. As we have seen, the TypeApply expression discussed earlier still produces a result (TypeSystem`UnknownType) even though it issued an error message. This result is cached. On subsequent executions the cached result is used, so no further messages are issued and the query evaluates without incident.


We can cause the query to fail every time if we clear the type cache first:


TypeSystem`ResetTypeApplyCache[]

Hold[Evaluate[Symbol[#name]]] & /@ ds


(* ... error ... *)

Work-around


We can avoid the error by replacing Symbol with Symbol&[] in an effort to hide it from the type system:


TypeSystem`ResetTypeApplyCache[]

ds = Dataset@{<|"name" -> "Kuba"|>};

Hold[Evaluate[Symbol&[][#name]]] & /@ ds


(* Hold["Kuba"] *)

Obviously, this is a hack that is very specific to this case. Symbol@@{#name} could also be used. By this gimmick, we cause the inferencer to give up and return Unknown earlier in the process. Such hacks may become unnecessary (or even harmful) in future releases as the type inferencer evolves.


The trick of hiding the head of an expression is actually a reasonably common idiom to work around the lack of a bulletproof mechanism for quoting code. Common examples include:



  • Sequence@@{...} to prevent inappropriate sequence expansion due to the ambiguity as to whether Sequence[...] means to use a sequence within the executing code or within the computed result.

  • With@@Hold[...] or Function@@{...} to prevent variable renaming during code generation


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...