Nice formatting of numbers inside Messages - wolfram-mathematica

When printing string with StyleBox by default we get nicely formatted numbers inside string:
StyleBox["some text 1000000"] // DisplayForm
I mean that the numbers look as if would have additional little spaces: "1 000 000".
But in Messages all numbers are displayed without formatting:
f::NoMoreMemory =
"There are less than `1` bytes of free physical memory (`2` bytes \
is free). $Failed is returned.";
Message[f::NoMoreMemory, 1000000, 98000000]
Is there a way to get numbers inside Messages to be formatted?

I'd use Style to apply the AutoNumberFormatting option:
You can use it to target specific messages:
f::NoMoreMemory =
"There are less than `1` bytes of free physical memory (`2` bytes is free). $Failed is returned.";
Message[f::NoMoreMemory,
Style[1000000, AutoNumberFormatting -> True],
Style[98000000, AutoNumberFormatting -> True]]
or you can use it with $MessagePrePrint to apply it to all the messages:
$MessagePrePrint = Style[#, AutoNumberFormatting -> True] &;
Message[f::NoMoreMemory, 1000000, 98000000]

I think you want $MessagePrePrint
$MessagePrePrint =
NumberForm[#, DigitBlock -> 3, NumberSeparator -> " "] &;
Or, incorporating Sjoerd's suggestion:
With[
{opts =
AbsoluteOptions[EvaluationNotebook[],
{DigitBlock, NumberSeparator}]},
$MessagePrePrint = NumberForm[#, Sequence ## opts] &];
Adapting Brett Champion's method, I believe this allows for copy & paste as you requested:
$MessagePrePrint = StyleForm[#, AutoNumberFormatting -> True] &;

Related

Performance gain on call chaining?

Do you gain any performance, even if it's minor, by chaining function calls as shown below or is it just coding style preference?
execute() ->
step4(step3(step2(step1())).
Instead of
execute() ->
S1 = step1(),
S2 = step2(S1),
S3 = step3(S2),
step4(S3).
I was thinking whether in the 2nd version the garbage collector has some work to do for S1, S2, S3. Should that apply for the 1st version as well?
They are identical after compilation. You can confirm this by running the erl file through erlc -S and reading the generated .S file:
$ cat a.erl
-module(a).
-compile(export_all).
step1() -> ok.
step2(_) -> ok.
step3(_) -> ok.
step4(_) -> ok.
execute1() ->
step4(step3(step2(step1()))).
execute2() ->
S1 = step1(),
S2 = step2(S1),
S3 = step3(S2),
step4(S3).
$ erlc -S a.erl
$ cat a.S
{module, a}. %% version = 0
...
{function, execute1, 0, 10}.
{label,9}.
{line,[{location,"a.erl",9}]}.
{func_info,{atom,a},{atom,execute1},0}.
{label,10}.
{allocate,0,0}.
{line,[{location,"a.erl",10}]}.
{call,0,{f,2}}.
{line,[{location,"a.erl",10}]}.
{call,1,{f,4}}.
{line,[{location,"a.erl",10}]}.
{call,1,{f,6}}.
{call_last,1,{f,8},0}.
{function, execute2, 0, 12}.
{label,11}.
{line,[{location,"a.erl",12}]}.
{func_info,{atom,a},{atom,execute2},0}.
{label,12}.
{allocate,0,0}.
{line,[{location,"a.erl",13}]}.
{call,0,{f,2}}.
{line,[{location,"a.erl",14}]}.
{call,1,{f,4}}.
{line,[{location,"a.erl",15}]}.
{call,1,{f,6}}.
{call_last,1,{f,8},0}.
...
As you can see, both execute1 and execute2 result in identical code (the only thing different are line numbers and label numbers.

Lists garbage collection

If I do the following:
List2 = [V || V <- List1, ...]
It seems that the List2 refers to the List1 and erlang:garbage_collect() doesn't clear memory. How is it possible to create a new list without references and discard the old?
In any language with garbage collection you simply need to 'lose' all references to a piece of data before it can be garbage collected. Simply returning from the function that generates the original list, while not storing it in any other 'persistent' location (e.g. the process dictionary), should allow the memory to be reclaimed.
The VM is supposed to manage the garbage collecting. If you use a gen_server, or if you use a "home made" server_loop(State), you should have always the same pattern:
server_loop(State) ->
A = somefunc(State),
B = receive
mesg1 -> func1(...);
...
after Timeout ->
func2(...)
end,
NewState = func3(...),
server_loop(NewState).
As long as a process is alive, executing this loop, the VM will allocate and manage memory areas to store all needed information (variables, message queue...+ some margin) As far as I know, there is some spare memory allocated to the process, and if the VM does not try to recover the memory very fast after it has been released, but if you force a garbage collecting, using erlang:garbage_collect(Pid) you can verify that the memory is free - see example bellow.
startloop() -> spawn(?MODULE,loop,[{lists:seq(1,1000),infinity}]).
loop(endloop) -> ok;
loop({S,T}) ->
NewState = receive
biglist -> {lists:seq(1,5000000),T};
{timeout,V} -> {S,V};
sizelist -> io:format("Size of the list = ~p~n",[length(S)]),
{S,T};
endloop -> endloop
after T ->
L = length(S) div 2,
{lists:seq(1,L),T}
end,
loop(NewState).
%% Here, NewState is a copy of State or a totally new data, depending on the
%% received message. In general, for performance consideration it can be
%% interesting to take care of the function used to avoid big copies,
%% and allow the compiler optimize the beam code
%% [H|Q] rather than Q ++ [H] to add a term to a list for example
and the results in the VM:
2> P = lattice:startloop().
<0.57.0>
...
6> application:start(sasl).
....
ok
7> application:start(os_mon).
...
ok
...
11> P ! biglist.
biglist
...
% get_memory_data() -> {Total,Allocated,Worst}.
14> memsup:get_memory_data().
{8109199360,5346488320,{<0.57.0>,80244336}}
...
23> P ! {timeout,1000}.
{timeout,1000}
24> memsup:get_memory_data().
{8109199360,5367361536,{<0.57.0>,80244336}}
the worst case is the loop process: {<0.57.0>,80244336}
...
28> P ! sizelist.
Size of the list = 0
sizelist
...
31> P ! {timeout,infinity}.
{timeout,infinity}
32> P ! biglist.
biglist
33> P ! sizelist.
Size of the list = 5000000
sizelist
...
36> P ! {timeout,1000}.
{timeout,1000}
37> memsup:get_memory_data().
{8109199360,5314289664,{<0.57.0>,10770968}}
%% note the garbage collecting in the previous line: {<0.57.0>,10770968}
38> P ! sizelist.
sizelist
Size of the list = 156250
39> memsup:get_memory_data().
{8109199360,5314289664,{<0.57.0>,10770968}}
...
46> P ! sizelist.
Size of the list = 0
sizelist
47> memsup:get_memory_data().
{8109199360,5281882112,{<0.57.0>,10770968}}
...
50> erlang:garbage_collect(P).
true
51> memsup:get_memory_data().
{8109199360,5298778112,{<0.51.0>,688728}}
%% after GC, the process <0.57.0> is no more the worst case
If you create new list like this, the new list will have elements from the first one, some elements will be shared between both the lists. And if you throw the first list away, shared elements will still be reachable from the new list and won't count as garbage.
How do you check if the first list is garbage collected? Do you test this in erlang console? The console stores results of evaluation each expression that may be the cause you don't see the list garbage collected.

ruby serialport gem, who is responsible to check parity errors?

gems
serialport (1.0.4)
Authors: Guillaume Pierronnet, Alan Stern, Daniel E. Shipton, Tobin
Richard, Hector Parra, Ryan C. Payne
Homepage: http://github.com/hparra/ruby-serialport/
Library for using RS-232 serial ports.
I am using this gem, and my device's specifications are as follows.
9600bps
7bits
1 stop bit
EVEN parity
When I receive data like below, the unpacked data is still with parity bit.
sp = SerialPort.new("/dev/serial-device", 9600, 7, 1, SerialPort::EVEN)
data = sp.gets
data.chars.each do |char|
puts char.unpack("B*")
end
ex. if sp receives a, the unpacked data is 11100001 instead of 01100001, because it's EVEN parity.
To convert the byte back the what it should be, I do like this
data = sp.gets #gets 11100001 for 'a' (even parity)
data.bytes.to_a.each do |byte|
puts (byte & 127).chr
end
now, to me, this is a way low-level. I was expecting the serialport gem was to do this parity check, but as far as I read its document, it doesn't say anything about parity check.
Am I missing a method that is already implemented in the gem, or is my work around above is nessesary since it's my responsibity to check the parity and find error?
SerialPort::ODD, SerialPort::MARK, SerialPort::SPACE
(MARK and SPACE are not supported on Posix)
Raise an argError on bad argument.
SerialPort::new and SerialPort::open without a block return an
instance of SerialPort. SerialPort::open with a block passes
a SerialPort to the block and closes it when the block exits
(like File::open).
** Instance methods **
modem_params() -> aHash
modem_params=(aHash) -> aHash
get_modem_params() -> aHash
set_modem_params(aHash) -> aHash
set_modem_params(baudrate [, databits [, stopbits [, parity]]])
Get and set the modem parameters. Hash keys are "baud", "data_bits",
"stop_bits", and "parity" (see above).
Parameters not present in the hash or set to nil remain unchanged.
Default parameter values for the set_modem_params method are:
databits = 8, stopbits = 1, parity = (databits == 8 ?
SerialPort::NONE : SerialPort::EVEN).
baud() -> anInteger
baud=(anInteger) -> anInteger
data_bits() -> 4, 5, 6, 7, or 8
data_bits=(anInteger) -> anInteger
stop_bits() -> 1 or 2
stop_bits=(anInteger) -> anInteger
parity() -> anInteger: SerialPort::NONE, SerialPort::EVEN,
SerialPort::ODD, SerialPort::MARK, or SerialPort::SPACE
parity=(anInteger) -> anInteger
Get and set the corresponding modem parameter.
flow_control() -> anInteger
flow_control=(anInteger) -> anInteger
Get and set the flow control: SerialPort::NONE, SerialPort::HARD,
SerialPort::SOFT, or (SerialPort::HARD | SerialPort::SOFT).
Note: SerialPort::HARD mode is not supported on all platforms.
SerialPort::HARD uses RTS/CTS handshaking; DSR/DTR is not
supported.
read_timeout() -> anInteger
read_timeout=(anInteger) -> anInteger
write_timeout() -> anInteger
write_timeout=(anInteger) -> anInteger
Get and set timeout values (in milliseconds) for reading and writing.
A negative read timeout will return all the available data without
waiting, a zero read timeout will not return until at least one
byte is available, and a positive read timeout returns when the
requested number of bytes is available or the interval between the
arrival of two bytes exceeds the timeout value.
Note: Read timeouts don't mix well with multi-threading.
Note: Under Posix, write timeouts are not implemented.
break(time) -> nil
Send a break for the given time.
time -> anInteger: tenths-of-a-second for the break.
Note: Under Posix, this value is very approximate.
signals() -> aHash
Return a hash with the state of each line status bit. Keys are
"rts", "dtr", "cts", "dsr", "dcd", and "ri".
Note: Under Windows, the rts and dtr values are not included.
rts()
dtr()
cts()
dsr()
dcd()
ri() -> 0 or 1
rts=(0 or 1)
dtr=(0 or 1) -> 0 or 1
Get and set the corresponding line status bit.
Note: Under Windows, rts() and dtr() are not implemented

ActiveState Perl 5.14 fails to compare certain values?

Basically, using the following code on a file stream, I get the following:
$basis = $2 * 1.0;
$cost = ($basis - 2500.0) ** 1.05;
# The above should ensure that both cost & basis are floats
printf " %f -> %f", $basis, $cost;
if ($basis gt $cost) { # <- *** THIS WAS MY ERROR: gt forces lexical!
$cost = $basis;
printf " -> %f", $cost;
}
Outputs:
10667.000000 -> 12813.438340
30667.000000 -> 47014.045519
26667.000000 -> 40029.842300
66667.000000 -> 111603.373367 -> 66667.000000
8000.000000 -> 8460.203780
10667.000000 -> 12813.438340
73333.000000 -> 123807.632158 -> 73333.000000
6667.000000 -> 6321.420427 -> 6667.000000
80000.000000 -> 136071.379474 -> 80000.000000
As you can see, for most values, the code appears to work fine.
But for some values.... 66667, 80000, and a few others, ActivePerl 5.14 tells me that 66667 > 1111603!!!
Does anyone know anything about this - or have an alternate Perl interpreter I might use (Windows). Because this is ridiculous.
You are using a lexical comparison instead of the numerical one
$cost = ($basis - 2500.0) ** 1.05;
printf " %f -> %f", $basis, $cost;
if ($basis > $cost) {
$cost = $basis;
printf " -> %f", $cost;
}
ps: revised to match the updated question
The first few chapters of Learning Perl will clear this up for you. Scalar values are can be either strings or numbers, or both at the same time. Perl uses the operator to decide how to treat them. If you want to do numeric comparisons, you use the numeric comparison operators. If you want to do string comparisons, you use the string comparison operators.
The scalar values themselves don't have a type, despite other answers and comments using words like "float" and "cast". It's just strings and numbers.
Not sure why you need to compare as lexical, but you can force it using sprintf
$basis_real = sprintf("%015.6f",$basis);
$cost_real = sprintf("%015.6f",$cost);
printf " %s -> %s", $basis_real, $cost_real;
if ($basis_real gt $cost_real) {
$cost = $basis;
printf " -> %015.6f", $cost;
}
Output:
00010667.000000 -> 00012813.438340
00030667.000000 -> 00047014.045519
00026667.000000 -> 00040029.842300
00066667.000000 -> 00111603.373367
00008000.000000 -> 00008460.203780
00010667.000000 -> 00012813.438340
00073333.000000 -> 00123807.632158
00006667.000000 -> 00006321.420427 -> 00006667.000000
00080000.000000 -> 00136071.379474
The reason it was failing as you noted, the lexical compare does character to character compare, so when it hits the decimal point in 6667. it actually is alphabetically before 111603. , so it is greater.
To fix this, you must make all the numbers the same size, especially where the decimal lines up. The %015 is the total size of number, including the period and the decimals.

PlotLegends` default options

I'm trying to redefine an option of the PlotLegends package after having loaded it,
but I get for example
Needs["PlotLegends`"]
SetOptions[ListPlot,LegendPosition->{0,0.5}]
=> SetOptions::optnf: LegendPosition is not a known option for ListPlot.
I expect such a thing as the options in the PlotLegends package aren't built-in to Plot and ListPlot.
Is there a way to redefine the default options of the PlotLegends package?
The problem is not really in the defaults for PlotLegends`. To see it, you should inspect the ListPlot implementation:
In[28]:= Needs["PlotLegends`"]
In[50]:= DownValues[ListPlot]
Out[50]=
{HoldPattern[ListPlot[PlotLegends`Private`a:PatternSequence[___,
Except[_?OptionQ]]|PatternSequence[],PlotLegends`Private`opts__?OptionQ]]:>
PlotLegends`Private`legendListPlot[ListPlot,PlotLegends`Private`a,
PlotLegend/.Flatten[{PlotLegends`Private`opts}],PlotLegends`Private`opts]
/;!FreeQ[Flatten[{PlotLegends`Private`opts}],PlotLegend]}
What you see from here is that options must be passed explicitly for it to work, and moreover, PlotLegend option must be present.
One way to achieve what you want is to use my option configuration manager, which imitates global options by passing local ones. Here is a version where option-filtering is made optional:
ClearAll[setOptionConfiguration, getOptionConfiguration, withOptionConfiguration];
SetAttributes[withOptionConfiguration, HoldFirst];
Module[{optionConfiguration}, optionConfiguration[_][_] = {};
setOptionConfiguration[f_, tag_, {opts___?OptionQ}, filterQ : (True | False) : True] :=
optionConfiguration[f][tag] =
If[filterQ, FilterRules[{opts}, Options[f]], {opts}];
getOptionConfiguration[f_, tag_] := optionConfiguration[f][tag];
withOptionConfiguration[f_[args___], tag_] :=
f[args, Sequence ## optionConfiguration[f][tag]];
];
To use this, first define your configuration and a short-cut macro, as follows:
setOptionConfiguration[ListPlot,"myConfig", {LegendPosition -> {0.8, -0.8}}, False];
withMyConfig = Function[code, withOptionConfiguration[code, "myConfig"], HoldAll];
Now, here you go:
withMyConfig[
ListPlot[{#, Sin[#]} & /# Range[0, 2 Pi, 0.1], PlotLegend -> {"sine"}]
]
LegendsPosition works in ListPlot without problems (for me at least). You don't happen to have forgotten to load the package by using Needs["PlotLegends"]`?
#Leonid, I added the possibility to setOptionConfiguration to set default options to f without having to use a short-cut macro.
I use the trick exposed by Alexey Popkov in What is in your Mathematica tool bag?
Example:
Needs["PlotLegends`"];
setOptionConfiguration[ListPlot, "myConfig", {LegendPosition -> {0.8, -0.8}},SetAsDefault -> True]
ListPlot[{#, Sin[#]} & /# Range[0, 2 Pi, 0.1], PlotLegend -> {"sine"}]
Here is the implementation
Options[setOptionConfiguration] = {FilterQ -> False, SetAsDefault -> False};
setOptionConfiguration[f_, tag_, {opts___?OptionQ}, OptionsPattern[]] :=
Module[{protectedFunction},
optionConfiguration[f][tag] =
If[OptionValue#FilterQ, FilterRules[{opts},
Options[f]]
,
{opts}
];
If[OptionValue#SetAsDefault,
If[(protectedFunction = MemberQ[Attributes[f], Protected]),
Unprotect[f];
];
DownValues[f] =
Union[
{
(*I want this new rule to be the first in the DownValues of f*)
HoldPattern[f[args___]] :>
Block[{$inF = True},
withOptionConfiguration[f[args], tag]
] /; ! TrueQ[$inF]
}
,
DownValues[f]
];
If[protectedFunction,
Protect[f];
];
];
];

Resources