Message Boards Message Boards

GROUPS:

[WSG22] Daily Study Group: Writing a Wolfram Language Function

Posted 1 month ago
848 Views
|
23 Replies
|
20 Total Likes
|

A Wolfram U Daily Study Group on "Writing a Wolfram Language Function" begins on September 12, 2022.

Join me and a group of fellow learners in an exploration of what it takes to make a "good" function in the Wolfram Language. We'll begin with standard function structure and then cover arguments, patterns, options and how to extend function capability with overloading, recursion and iteration, memoization and up-values. Later sessions will discuss error handling and extra tips.

Sessions include short lessons, poll questions to review key concepts, practice problems and live Q&A. A certificate of program completion will be awarded to participants who attend online sessions and pass a quiz.

Some prior Wolfram Language experience or knowledge is recommended for this Study Group.

REGISTER HERE

Wolfram U Banner

POSTED BY: Daniel Robinson
23 Replies

This is a reminder that Daily Study Group: Writing a Wolfram Language Function begins on Monday, September 12. It runs for just one week. Register today: https://wolfr.am/16funYdYF

POSTED BY: Jamie Peterson

Some additional resources (Especially for beginners in the Wolfram Language):

  • Defining Your Own Functions -- a video lesson from the interactive course An Elementary Introduction to the Wolfram Langauge (Please sign in with your Wolfram ID to access free interactive courses on Wolfram U)
  • Function Definitions -- a chapter from the online tutorial The Wolfram Language: Fast Introduction for Programmers
Posted 14 days ago

I'd like some help to understand the statements in Wednesday's lesson, which I'll copy here and hope you can identify back to the lesson workbook.

(* When no explicit RoundingRadius is given, scale it with the \
FrameMargin: *)
frameText[text_String, options : OptionsPattern[]] /; 
   FreeQ[{options}, RoundingRadius] := Framed[
   Text[text],
   RoundingRadius -> OptionValue[FrameMargins]/2,
   Sequence @@ 
    DeleteCases[{options}, Alternatives[RoundingRadius -> _]]
   ];

I don't understand how to inquire on the value of text and options when the function call is parsed ie. frameText[text_String, options : OptionsPattern[]] . Perhaps first question is whether once can inquire what would be assigned to text and to options?

In any case the programmer placed option is a List ie {options} inside function calls to FreeQ and DeleteCases. They also knew it was sufficient to ask test {options} with RoundingRadius instead of "RoundingRadius" in FreeQ. which isn't entirely obvious from the Help Documentation of FreeQ.

I'm also not entirely sure how to interpret Alternatives[RoundingRadius -> _ used inside the call to DeleteCases. The documentation of Alternatives describes usage with more than one alternative to choose from so Alternative[arg] is vague. Lastly my understanding of the syntax RoundingRadius->_ would require that RoundingRadius->val was assigned which FreeQ would have screen out as False so would this whole statement not be redundant and so never called upon?

Thanks.

POSTED BY: John Burgers

Hi John,

I don't quite understand your first point about parsing... Could you clarify what you mean by this?

When an options pattern is defined as options:OptionsPattern[], callling options will return a Sequence. Try evaluating the following to see what I mean:

Options[f] = {"a" -> 1, "b" -> 2};
f[options : OptionsPattern[]] := options;
f["a" -> 3, "b" -> 4]

I therefore generally wrap options in a List to make it easier to deal with. In fact, the functions FreeQ and DeleteCases will not work if they are fed a (multi-element) sequence in the first argument.

I tested for RoundingRadius instead of "RoundingRadius" because the Framed function accepts the option name without quotes. (It also accepts it with quotes.)

You are correct in both of your last points! Using Alternatives inside DeleteCases isn't necessary when there is only one case to delete, and the entire statement could be replaced with options because the rounding radius option is being taken care of by the Condition. Thanks for pointing these out – I will remove them from the notebook.

POSTED BY: Daniel Robinson
Posted 14 days ago

Thank you Daniel, that helped me understand how to determine what is assigned to options. No need to worry about what I meant by parsing, you provided all the information I needed. John

POSTED BY: John Burgers
Posted 14 days ago

Hello Daniel,

On second sober thought (less foggy mind this morning), Looking again at the Alternatives documentation it does say ... represents any of the p's , which with a little extra thought includes that a single p be tested.

So up to you, but I'd now be happy that the lesson workbook stay as is.

Thanks again. John

POSTED BY: John Burgers
Posted 14 days ago

Further to my question posted in the Chat on Wednesday, I attach a notebook as further detail here.

In a 2D FEA task I needed to do create a Piecewise function to assign Material properties to mesh regions. The mesh being generated from geometry variables (x,y) and would have many regions, most suitably generated from Mathematica expressions who themselves where created by the Mathematica code, using ToExpression and Strings assembled using Table.

This would yield expr:=f(x,y);

From which I wanted the Mathematica statement f[x,y]:=Piecewise [ expr(x,y) ] to generate the Piecewise function.

Please see the attahced code for how I worked this out, with help from Mathematica Stackexchange, but with a critical eye on what may still be wrong.

Thanks, John

Attachments:
POSTED BY: John Burgers

Hi John,

Looking at your attached notebook: if you don't know what variables are going to be in expr, then localising with Block seems fine to me.

That said... if you're localising particular variables (say, x and y), that suggests to me that you do know what variables are going to be in expr...? If that's the case, I would define it as expr[x_, y_] := Plus[x, y]. Then, if you define f as f[x_, y_] := expr[x, y], you can do without the Block.

In other words:

ClearAll[f1, f2, expr1, expr2, x, y];
x = 1; y = 2;

(* What you're doing now: *)
expr1 := Plus[x, y];
Block[{x, y}, f1[x_, y_] := Evaluate[expr1]]
f1[3, 4]

(* What I would do instead, if possible: *)
expr2[x_, y_] := Plus[x, y];
f2[x_, y_] := expr2[x, y];
f2[3, 4]

Side note: have you used \[FormalX] and \[FormalY] before? They can be handy for avoiding conflicts with global variables.

POSTED BY: Daniel Robinson
Posted 13 days ago

Thanks Daniel,
I'll look into \Formal[x] \Formal[y].

I've attached another notebook which I hope illustrates the problem I encountered.

I'd like to know if there is a correct way to define a function f[x,y] from an expression such as expr = x+y when they are typed into an input field as f[x,y]:= epxr

Thanks.

Attachments:
POSTED BY: John Burgers
Posted 14 days ago

Just curious. Can a local notebook retrieve a function definition made by CloudPut/CloudObject ?

I knew there is ResourceFunction , that is still experimental. But it needs internet connection all the time of the ResourceFunction usage/call. If the above is possible, I'm wondering if the (functions) definition can be 'downloaded' once.. and used throughout the local notebook lifetime.

POSTED BY: M Firdaus

You can retrieve cloud code with CloudGet or CloudImport:

obj = CloudPut[Hold[f[x_] := x^2;], IncludeDefinitions -> True];
ClearAll[f];
ReleaseHold[CloudGet[obj]];
f[3]

(I included the ClearAll[f] to be absolutely sure that the definition for f was being pulled from the cloud and not locally.) If you then wanted to save the definition of f locally, you could save the output of Definition[f] to a file.

Also, you can download the source code of a resource function by clicking the 'Source Notebook' button. And while resource functions are not "official" Wolfram Language functions, many are provided by Wolfram staff and are quite robust.

POSTED BY: Daniel Robinson
Posted 13 days ago

The answer to quiz question #8 that the autograder accepts as correct looks incorrect to me. Can someone please check? Thanks!

POSTED BY: Rohit Namjoshi

Hi Rohit, I can confirm autograder is accepting the right answer for #8.

Posted 13 days ago

Hi Abrita,

I cannot post my answer here so I created a cloud notebook with my answer and shared it with you. Check your gMail email.

Thanks, Rohit

POSTED BY: Rohit Namjoshi

Thanks for your thoughtfulness about sharing answers. I'll take a look.

If a function f depends on functions gi containing certain restrictions on their arguments, e.g. g1[x,yInteger] (for technical reasons I could not insert the underscore). How to modify f, so that it will inherit the restrictions from all g without putting them explicitly (and manually) in f's definition? Thanks.

Could you please post the link to the quiz.

We will be sharing the link to the quiz during the Study Group session and will also include the link in the reminder emails for the live sessions as well as the recordings.

Quiz: For some reason the autograder does not work for me.

Posted 11 days ago

I found it necessary to answer all the questions before grading.

POSTED BY: John Burgers

Ooops! Thanks. Is this an error, or a new policy?

Thank you. I did not get it, but it is already discussed above. :( :)

In manipulate, I display dynamic graphics (the major display) and would also like to add a couple of minor displays for dynamic data. I am looking for demos where the data are added nicely, and interactively (say the frequency of updates and other parameters are controllable), without obstructing the view. Thank you.

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