C_R

3942 Reputation

21 Badges

6 years, 329 days

MaplePrimes Activity


These are replies submitted by C_R

@Carl Love

Yes, you are right. With respect to functional programming this is probably the most compact code but I did not want to go too far away from the original question of adding a given list.

I only picked the add because it is selfexplaining and it links to `+` and to `%+` . It also does not require op

dabug's question is an intersting one because it touches many Maple aspects which might be (one day) of interest for a Maple starter:

  • automatic simplification
  • inert functions
  • prefix n-ary operator `+` vs infix binary operator +
  • The non-existance of Add (which I tried straight away, realising later that such an uppercase construct would create similar output as %add if it was implemented in-line with Maple's inert conventions).
  • mathematical functions, Maple functions, operators, functional operators and function names

I also tired to find out whether `+` and add point to the same Maple prodecure. I do not think so because  `+`(L) - add(L) does not simplify to zero.

By the way: Maple AI crashes when asked to explain your code

This is great. It seems that by using terse functional forms we have a way to identify whether the code was written by a human. We can still create code that is alien to machines!

I made the same observation with the example from ?CUDA.

@janhardo 
That way is similar to this way. Both ways define a local intermediate variable that permits to point from passed names to passed values.  I will see which one is better to debug when it comes to coding.
Thank you

@Carl Love 

That is tricky. Defining a local name to have something to refer to local variables created during run time. 

To complete my list of attempts:

  • conversion to string -> replacement of "=" with ":=" StringTools -> parse
  • local evaln(lhs~params)~:=(rhs~params)
  • replacing operators `=` with `:=` 

I think I finally know now why nothing worked.

Thank you very much!

@janhardo 

Yes, but the variable needs to be declared (or has to be named) explicitly.

The " local localSequence; clause" (see ?procedure) does not accept the following

foo2:=
proc(param)
   local lhs(param):=rhs(param);
end proc
Error, `(` unexpected
foo2(a=1);

meaning that it is not possible to declare something undefined on the lhs of ":=" that needs evaluation during runtime (i.e. when foo2 is invoked). An explict name has to be declared after the word "local".

@acer

What an unfortunate sequence of misinterpretations originating from a too broad interpretation of declaration functionality in ?local_scopes which let me write an unclear example. I thought it was clear that the error message of the second call to foo (including the comment and the original title) demonstrated sufficiently that global names were unintendedly assigned to values, instead of values beeing assigned to identical local names.

Many Maple library procedures process expressions with names and leave names (at the level of the procedure call) unassigned (e.g. global names). They must do it differently from what I had in mind. It’s embarrassing that I made all of you spend time on the idea of “passing names to a procedure that should be used as local variable names in the scope of the procedure call”. Maple does not seem to allow this. Other languages do. Perhaps variable variables or dynamic variable assignment would have described this topic better. Can the title be change to something that other users with the same idea/question can easier look-up this topic?

Not as an excuse but for your understanding, I prefer to assign on a global scope level as little names as possible to values. And: algebra first, numeric at the last possible moment where parameters are defined by equations (which are then used in subs or eval calls). Given the rich library of Maple commands, for my purposes, I hardly need to write procedures where Maple provides no solutions. Hence my naivity.

Thank you for the clarifications!

@janhardo  No, it does not make sense. The interpretation of the scope of the assign call is wrong.

@janhardo 
Carl's first answer proposed a way that does not require explicit mentioning of names. He declared parameters unevaluated

params::uneval

and performed the local declaration

local check:= eval(params, 1); 

before calling assign.

Maple AI could not provide an explanation why the call to assign declares the passed names as local names although the arguments of the assign call assign(params) are exactly the same that lead to gobals in my attempts. There is a rule at work that I could not find in Maple's documentation.

Can your AI explain this and ideally direct to the relevant documentation?

By the way, the most intiutive way for me was

local assign(params);

which does not work because assign returns NULL.

@acer

Thank you for expanging on the keywords. This is probably what I will use (without considering it in the first place as an option). Carl's solution, which I still do not fully understand (in the meantime I consulted the ProgrammingGuide and the asked AI which interpreted eval(params,1) as op(1,params)...) is probably only needed in cases where:

  • a list/set/seq comes from a third party and a procedure processes it without poluting the gobal environement with names or, even worse, reassigning existing names

I chose a list in my foo example only because it is easier to debug (a set is most appropriate and even a sequence cloud be used, but I wanted to stay away from potential complications caused by sorting or merging with other sequences).

I did not mention any objective in terms of terse and/or understanable code yet because I was looking for a solution in the first place.
I was expecting the case of declaring local names during runtime a common use case and mentionned in the documentation.

@Carl Love 

My key challenge here (again…) is that I do not have gained enough (intuitive) understanding of Maple’s evaluation process yet. Maple's evaluation machinery is still a grey box for me.

My current interpretation of your code: Your call to local declares check as local name and then assigns params to check. By calling assign(check), check fully evaluates to params. Then assign is  executed with the argument params. What makes this different form calling assign(params) directly? Do the names in params inherit locality from check? Is there anything that explains what happens in your code in ?local_scopes (which I consulted before writing the post).

Also, Acer mentioned a second `assign` call in my code. However, I can only identify one `assign` call. This tells me that I miss something what is going on in my code.

From the attached attempts I conclude that the declaration params::uneval is essential. Therefore, type checking cannot be performed in the parameter declaration of the procedure and must be done inside the procedure. Is that correct?

local_assignement_attempts.mw

@Carl Love 

I wanded to achieve what

local b:=2,c:=3,d:=4;

does without doing it explicitly as in janhardo's example.

I also tried 

local assign(params[]);

Instead of print I could have used a type/local check

@acer 

I have rewritten my original post. The objective is to only assign locally without entering the parameter names explictly.
The example I have given is not the best one. I was supposed to show an attempt of declaring local names before assigning them to values using the assign command.

@acer 

I upvoted as well. What made me hesitating with my version was the use of sets and "minus" which AI considred clear and concise (which I did not, hence the post).

What I realized when it comes to simplicity, a level of understanding of Maple's language should be indicated. I did not. AI so far boils Maple code down to an ordinary computer language. It looses all its beauty.

My current favorite is this modification

remove((p -> convert(p,'unit_free')=convert(simplify(p),'unit_free'))@rhs, [L]);

only because I like one-liners.
This is more than debateable because it removed the name of the helper function which can be used to explain the action of the helper function, makeing further code comments dispensible in the best case. Understandable code without comments is a strong criteria for simplicity.

@dharr

I am still undecided.

“Simple” can be interpreted in two ways: either that as little code as possible is used, or that the code is understandable. I will focus on the second interpretation in the following:

I had a version with evalb that created a list with true and false values. I did not like it very much because looking up which parameters were not in SI base units was not obvious at a glance. Applying remove the way you did makes it much easier.
Because I was somehow preconditioned, I decided to ask Maple AI which of the two version is easier to understand. The AI pointed towards two elements that are not easily understandable in your version, which are the type declaration and evalb. AI provided improved versions which all did not work… which led me to use a large model … which consumed a quarter of this month credits, still throwing errors. AI also proposed a “simpler” version of mine by splitting up processing steps in several statements. For me, this is a bit too much of simplicity.

However, I also noticed in my attempts that one extra statement can improve readability and simplicity allot. Defining a new one-argument function (as inbaseunits) also enables function composition. My attempts to define a real functional operator (separating functions from arguments) have definitely not led to anything simple. Here is where I stopped:

((((`{}`@op)@(`~`[round]))@(`~`[op]))@simplify)(`~`[`-`~([(Units:-Split)@rhs], [((Units:-Split)@simplify)@rhs])]([params]));

Functional programming driven ad absurdum.

The reason in this case, I think, is that there is no single argument function that extracts only the coefficient of a physical quantity. Again, an indexed version of op (i.e. op[i]) would have helped.

So, as of today I am undecided about my favorite version, but it looks like that two-liners can provide a good compromise of the above two interpretations of simple.

@janhardo 

This new worksheet is easier to follow than the previous AI worksheets you provided. Some more thoughts:

  • Since the solutions are symbolic, I am wondering why numerical values for parameters are used right from the beginning. Personally, if possible, I would go for the general solution with assumptions on the parameters and then investigate particular solutions.
  • I am also wondering whether a skilled programmer would implement part of the code as modules. Shouldn't simple procedures handle (all the input) equally good with less overhead?  
  • I would also pretty print essential input as the pde in 2D-Math. AI does not really exploit the benefits of using Maple. The whole output formatting looks inconsistent. I am more and more inclined to say that beauty of well-made Maple documents is not achieved by todays AI. For me, there is no joy of studying AI output.
  • Also parameters are not defined and what they physically represent is not explained. Typical input errors like inconsistent units are not handled. “k” in the pde and “k” in the boundary conditions are not the same physical quantities (thermal diffusivity vs. thermal conductivity).
  • Maple provides sophisticated functionality for symbolically handling expressions with units but the AI is not profiting from it.
  • Explanatory text passages are only provided as code comments but not as Maple text passages.

Maybe with improved prompts some of the above could be fixed.

It’s still 1D heat conduction what we are discussing but it completes the picture of options. Ultimately, I want to modulate spatially and temporarily the heat distribution in an easy way. It looks like that I have to do it myself numerically. I will use symbolical solutions to verify the output and Maple units to guarantee as much as possible consistent and meaningful input. I will also use 2D-Math for better readability and clarity of input and output.

Thank you all for your contributions!

@dharr

Thank you for clarifying the list and simplification questions.

I am currently modifying code that required parameters in SI base units. For better readability and clarity, I thought of adding units to values and then removing them to make my old code work. To avoid data lookup errors (some references use KJ instead of J for example) I thought of a consistency check before removing the units. Hence the questions. I did not think any further. Now I have realised the that simplify as I have used it in my code construct removes unit inconsistencies and makes the check pointless if simplify is applied before convert/unit_free.

So, for the case of numerical integration the check is not needed, but the question remains whether such a check cannot be done in a simpler way.

1 2 3 4 5 6 7 Last Page 1 of 81