# [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
23 Replies
Sort By:
Posted 22 days ago
 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 15 days ago
 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 14 days ago
 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 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 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 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 13 days ago
 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 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]:= epxrThanks. Attachments:
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 13 days ago
 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 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 13 days ago
 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 13 days ago
Posted 13 days ago
 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.
Posted 13 days ago
Posted 13 days ago
 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.
Posted 11 days ago
 Quiz: For some reason the autograder does not work for me.
Posted 11 days ago