7
$\begingroup$

Hello my second question here might be very hard.

I am asking for something "magical", if i define a function g and i call it inside a function f, how can g have information about the outer function f?

To be more precise: Suppose there is a unknown number of functions {f1,f2,f3,...}, how can g know in which Function it was evaluated?

Pseudocode:

f1[g] "--inside-of-g-->" f1
f3[g] "--inside-of-g-->" f3

I have an Idear how to work on this problem, but it works not in every case.

EDIT:

ok, i wanted to reduce my problem to the relevant point, but i can also explain you, what i exactly want to do with it.

I want to build up a function myTicks[plotRange] that generates Axes-Ticks for a Plot the way i want. My first function works like this:

Plot[Sin[x], {x,0,10}, Ticks->{myTicks[{0,10}, StepSize-> 0.5], Automatic}]

Now i want to change the plotRange of myTicks to an optional argument like:

MyTicks[plotRange_:Automatic, opt:OptionsPattern[]] := Module[{},
If[plotRange =!= Automatic, Range[plotRange〚1〛, plotRange〚2〛,
OptionValue[StepSize]], (* magical lookup for the PlotRange of the Plot *)]]

So now it should be possible to call myTicks without giving the actual PlotRange of the outer Plotfunction.

I hope that i did not confuse you more.

EDIT2: here goes my simple Solution that doesn't work in general for me:

My simple Solution is a little hackish and works not in every case:

In:

g[arg_: "default"] := Module[{read, expr},
 read = NotebookRead[EvaluationCell[]];
 expr = ToExpression[ReplaceAll[read, Cell[x__, y__] :> x], 
    StandardForm, Hold];
 Print[expr];
  Sin[arg]
  ]

f[g[2]]

Out:

Hold[f[g[2]]]

f[Sin[2]]

In this Case expr holds enough Information to work with, so that one could filter out the functionname f, but there is a big problem with this solution:

It only works, if the function g appears explicitly in the EvaluationCell. something like:

h[a_] := a*f[g[2]];

h[2]

wont work (expr == Hold[h[2]])

A second problem is, that when the EvaluationCell holds more than one line, it gets very complicated to filter out in wich line the function was called. Just think about if the function g is called more than once in the EvaluationCell.

So my solution is not very satisfying in general.

A good example of a functionality like this, is the build-in-Mathematica function OptionValue. So there must be a better way to do this!

$\endgroup$
  • $\begingroup$ Please, give a more precise example of what you try to do. $\endgroup$ – SquareOne Feb 26 '15 at 2:04
  • 1
    $\begingroup$ Have a look at Stack, et. al. ... $\endgroup$ – ciao Feb 26 '15 at 2:26
  • $\begingroup$ Ok rasher, Stack looks promissing to me, but i have to check out if i can solve my problem with it. Thanks for the good hint! $\endgroup$ – sacratus Feb 26 '15 at 2:39
7
$\begingroup$

I believe the first part of your question is answered by Stack. Observe:

g := Stack[]

something[f1[g], f3[g]]
something[f1[{something, f1}], f3[{something, f3}]]

So you can find that g was evaluated in f1 or f3 and further that these were evaluated in something.

However this should not be necessary for your Ticks application. The value of Ticks can be a function, and this function is already provided with the plot range! :-)

Here is a simplified example to demonstrate this, using SubValues syntax:

MyTicks[plotRange_: Automatic][min_, max_] :=
  If[
    plotRange === Automatic,
    Range[⌊min⌋, ⌈max⌉],
    Range @@ plotRange
  ]

Examples:

Plot[Sin[x], {x, 0, 10}, Ticks -> {MyTicks[{2, 7, 1.5}], Automatic}]

enter image description here

Plot[Sin[x], {x, 0, 10}, Ticks -> {MyTicks[], Automatic}]

enter image description here

To get your full syntax working I recommend that you first read:

Then observe this application:

ClearAll[MyTicks]

SetAttributes[MyTicks, NHoldAll]

Options[MyTicks] = {"StepSize" -> 1};

MyTicks[
  plotRange : (Automatic | {a_, b_}) : Automatic,
  OptionsPattern[]
][min_, max_] :=
  If[
    plotRange === Automatic,
    Range[⌊min⌋, ⌈max⌉, OptionValue["StepSize"]],
    Range[a, b, OptionValue["StepSize"]]
  ]

You can then use:

Plot[Sin[x], {x, 0, 10}, Ticks -> {MyTicks[{5, 10}], Automatic}]

Plot[Sin[x], {x, 0, 10}, Ticks -> {MyTicks[{2, 8}, "StepSize" -> 2], Automatic}]

Plot[Sin[x], {x, 0, 10}, Ticks -> {MyTicks["StepSize" -> 3], Automatic}]
$\endgroup$
  • $\begingroup$ sooooo cool :), thank you very much! I would upvote your answer, but i dont have enough reputations to do it. (i am very new). I did not knew that Ticks can be a function that works with min and max, and that min and max is provided to this function from the plot itself. So the functionality i was looking for is allready build into Mathematica. I have seen the refered Question about the optional argumentes and options before and i lerned a lot from it. Thanks also for the second link, very interesting! Lets see if i can help someone. $\endgroup$ – sacratus Feb 26 '15 at 11:53
  • $\begingroup$ btw, thanks for correcting my english :) (its not my native language) I recently recived the ability to upvote and upvoted your helpfull answer! $\endgroup$ – sacratus Feb 27 '15 at 1:56
  • 1
    $\begingroup$ maybe this belongs to another question: Your MyTicks example works nice, but with one little exception: if you look closely the numbers on the x-Axis you see that they are no Integers anymore, it seams that the head of OptionValue["StepSize"] changed automatically from Integer to Real! I have tested this out, by Print[OptionValue["StepSize"][[0]]]; inside the module. This only happens, if MyTicks is used inside of Plot! I want to be able to Set the stepSize to π, but it is automatically replaced with 3.14159.... has this a reason, or is this just a bug? $\endgroup$ – sacratus Feb 27 '15 at 12:01
  • 1
    $\begingroup$ @sacratus Good catch. Somewhere N is probably applied and it threads its way down to that value. Use SetAttributes[MyTicks, NHoldAll] to avoid that. I'll edit my answer to include this. $\endgroup$ – Mr.Wizard Feb 28 '15 at 0:43
  • $\begingroup$ I did not even knew this Attribut, because i never needed it before. I meanwhile found a workaround with using a second function. MyTicks2[args__]:= MyTicks[args][#1,#2]& You now can use MyTicks2 like MyTicks before, but without the N-Problem. I dont really understand why this makes a difference... Anyhow the solution with NHoldAll makes more sence to me and is more elegant. Thanks again :-) $\endgroup$ – sacratus Feb 28 '15 at 4:37

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.