Carl Love

Carl Love

28055 Reputation

25 Badges

12 years, 354 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

You are mistaken about two things: NULL is an "actual" value, and it can be (and very often is) the return value of a procedure. However, it can't (in its "naked" form) be a member of a sequence, in particular a sequence of return values for a multiple assignment statement. But, it can be done with unevaluation quotes, like this:

P:= proc()
local a:= 1, b:= NULL, c:= 3;
    `if`(a=NULL, 'NULL', a), `if`(b=NULL, 'NULL', b), `if`(c=NULL, 'NULL', c)
end proc
:
(a, b, c):= P();
                     a, b, c := 1, NULL, 3

evalb(b=NULL);
                              true

My personal coding preference is to replace NULL (which is a named constant, and thus requires evaluation) with its evaluated form, (). This avoids a few unneeded evaluations. The code above becomes: 

P:= proc()
local a:= 1, b:= (), c:= 3;
    `if`(a=(), ''()'', a), `if`(b=(), ''()'', b), `if`(c=(), ''()'', c)
end proc
:
(a, b, c):= P();
                      a, b, c := 1, '()', 3

evalb(b=NULL);
                              true

evalb(b=());
                              true

 

The answer to your first question is yes.

The answer to your second question is yes, even though this interupts the usual flow control implied by the return in the catch clause.

So, what are you trying to accomplish in the finally clause? They are rarely used.

Acer's statement beginning "One point..." needs to be amended: The finally clause is executed if any of these occur (Acer left off #3):

  1. There is no error.
  2. An error is caught.
  3. An error occurs that would've been caught had there been a catch clause for it.

So, the finally clause is a weird and powerful thing that should probably be reserved for things like closing files.

In light of point #3 above, you could do this instead:

try
   ...
catch "time expired":
   return ...
catch: #any other error

   #what used to be in your finally clause
end try;

This isn't the same as your original because of point #1, but it may be what you actually want.

Both the R and Maple histograms are wrong, and for the same reason: You have only 16 bins, but 17 discrete values (0 - 16), so one of the bins must be used to count 2 of the values. R happens to lump 0 and 1 together in the first bin, while Maple lumps 15 and 16 together in the 16th bin. To get a correct histogram for a discrete data set:

Statistics:-Histogram(
    subscribers, discrete, bincount= 17,
    frequencyscale= absolute, 
    labels= ["subscribers", "frequency"], labeldirections= ["horizontal", "vertical"], 
    thickness= 20, view= [-1..17, default]
);

The code of a module's "body" (those things that are neither locals nor exports of the module) is not stored in the .mla (nor is it stored anywhere else). So your code that reset currentdir and :-libname was not stored. If there is certain code that you want executed whenever the module is retrieved from the .mla, put that code in a procedure named ModuleLoad, which can be a local or export of the module. Usually, this should be done with any code that changes global variables. Calls to TypeTools:-AddType should also be put there. 

Often, when you're done with the module, it's a good idea to restore the global state to what it was before the module was retrieved from the .mla. The code to do that should be put in a procedure named ModuleUnload.

While it's very common to use a ModuleLoad to change globals, doing that with libname seems strange to me.

In order to facilitate the development phase of the module, the module body should consist of the single command ModuleLoad() so that it'll work when the module is not being retrieved from an .mla.

Unfortunately, generating Taylor series coefficients is a bad example of something to be done with Threads. Because memory is shared by the parallel processes, most Maple commands are not "threadsafe" and can't be used with Threads (see help page ?index,threadsafe).

Please go back to your earlier Question and let me know if you understand my "divide-and-conquer" Answer. 

Why not just divide by y?

expr/~y;

Another way, which'll work for any number of lists of the same size, is f~(A, B).

There's no way to do it using map. (I was wrong: Kitonum found a way with map, shown below.) There is zip, as shown by Acer, but it won't work for more than two lists.

If you don't like ~, you could define a procedure so that you only need to use ~ once:

MapThread:= f-> f~(_rest):

Then MapThread(f, A, B) will work for all future uses.

Before you can understand how that example works, you need to understand how divide-and-conquer recursion works, without the use of multiprocessing. The procedure below multiplies a list of numbers. I chose this instead of adding a list of numbers because the below turns out to be a very efficient method for multiplying. The algorithm logic would be identical for adding. So, please study this procedure closely, and let me know if you have any questions about it.

The keyword thisproc invokes a recursive call to the procedure.

Mul:= proc(L::list, i::posint:= 1, j::posint:= -1)
local k;
    if j = -1 then thisproc(L, 1, nops(L)) #initial call
    elif i = j then L[i]
    else
        k:= iquo(i+j, 2); #floor((i+j)/2)
        thisproc(L, i, k) * thisproc(L, k+1, j)
    fi
end proc
:

The above is a very efficient procedure for multiplying integers. It beats the default builtin mul by a huge factor:

n:= 2^17-1:  L:= ['rand'()$n]:
r1:= CodeTools:-Usage(Mul(L)):
memory used=107.55MiB, alloc change=0 bytes, 
cpu time=1.78s, real time=1.64s, gc time=484.38ms

r2:= CodeTools:-Usage(mul(L)):
memory used=38.42GiB, alloc change=0 bytes, 
cpu time=75.06s, real time=51.87s, gc time=64.33s

r1 - r2;
                               0


 

If the problem is as you describe, then a workaround is to put a page break (Ctrl-Enter) after the plot.

Click on the <> icon on the toolbar. Paste or type text in the white dialog box that appears. When you dismiss the dialog, the grey box will appear, and you can continue to edit it. The text will not appear correctly formatted until it's in the grey box.

Try just closing worksheet A before running B.

Procedure parameters can't have indices, such as beta[1]. They can have subscripts, as in beta__1.

The legal values for symbol are "asterisk", "box", "cross", "circle", "diagonalcross", "diamond", "point", "solidcircle", "solidbox", or "soliddiamond", with or without quotes.

The best way to get a better curve is to have more data points. Is that possible?

The situation is not as described by Rouben. A complete symbolic solution is mathematically trivial (although too big to do by hand). I don't know why dsolve won't do it. Here's how to do it. After your A1 is entered as above, do

Eq7:= value(dsolve({A1, f[3](0)=0, D(f[3])(0)=0})):
BC1:= eval(rhs(Eq7), x= 1) = 0:
BC2:= eval(diff(rhs(Eq7), x), x= 1) = 0:
Csol:= solve({BC1, BC2}, indets(Eq7, suffixed(_C))):
Eq7A:= eval(Eq7, Csol):

The solution Eq7A is easily displayable and about half the size of A1.

What Rouben failed to see was that your ODE was of the trivial form diff(f(x), x$4) = P(x), where P(x) is just a polynomial (with coefficients with 5 parameters).

Your use of seq is not bad. All of the empty lists can be removed at once by subs([]= (), ...). Here's my procedure:

Tlist:= (L::listlist)-> 
    subs([]=(), [seq]([seq](x[i], x= L), i= 1..nops(L[1])))
;

This matrix-transpose-based version might be faster. I haven't speed tested it:

Tlist2:= (L::listlist)->
local _; 
    (M-> [seq]([seq](M[i]), i= 1..nops(L[1])))
        (subs(_= (), rtable(subs([]= _, L)))^+)
;

First 92 93 94 95 96 97 98 Last Page 94 of 395