Shell within Erlang process prints input many times - io

I built a REPL for a language in Erlang. I run it from the shell, like so:
repl:main(Args).
It reads using io_getchars until it encounters a ;, then parses and lexes it:
getchar(eof) -> throw(eof);
getchar([C]) -> C.
getchar() -> getchar(io:get_chars("", 1)).
read_term() ->
case getchar() of
$; -> ";";
C -> [C|read_term()]
end.
That's all well and good, but the interaction with the repl looks like this:
willow% erl -name MyName
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
Eshell V7.3 (abort with ^G)
(MyName)1> repl:main(Args).
Master is <0.39.0> in init_workers
1> map(fn(x)=x+1, '[1 2 3 4 5]);
ap(fn(x)=x+1, '[1 2 3 4 5]);
p(fn(x)=x+1, '[1 2 3 4 5]);
(fn(x)=x+1, '[1 2 3 4 5]);
fn(x)=x+1, '[1 2 3 4 5]);
n(x)=x+1, '[1 2 3 4 5]);
(x)=x+1, '[1 2 3 4 5]);
x)=x+1, '[1 2 3 4 5]);
)=x+1, '[1 2 3 4 5]);
=x+1, '[1 2 3 4 5]);
x+1, '[1 2 3 4 5]);
+1, '[1 2 3 4 5]);
1, '[1 2 3 4 5]);
, '[1 2 3 4 5]);
'[1 2 3 4 5]);
'[1 2 3 4 5]);
[1 2 3 4 5]);
1 2 3 4 5]);
2 3 4 5]);
2 3 4 5]);
3 4 5]);
3 4 5]);
4 5]);
4 5]);
5]);
5]);
]);
);
;
Delegated packet 0
Delegated packet 1
Delegated packet 2
Delegated packet 3
Delegated packet 4
(2 3 4 5 6)
2>
I also tried:
read_term(Acc) ->
case io:request(standard_io, {get_until, '', scanner, token, [1]}) of
{ok, EndToken={';;', _}, _} -> Acc ++ [EndToken];
{ok, Token, _} -> read_term(Acc ++ [Token]);
{error, token} -> {error, scanning_error};
{eof, _} -> Acc
end.
And it unfortunately has the same effect.
I'd rather not see every possible right-moving slice of the string I entered. What is causing this and how can I stop it?
EDIT: If I run it as erl -noshell -eval 'repl:main()' from the shell instead, this printing does not happen. Why?

You will have to use io:get_line instead, and iterate over the received string. Then you have to decide what to do if the received string does not contain any ";"
for example:
1> Eval = fun(X) -> io:format("evaluation of ~p~n",[X]) end.
#Fun<erl_eval.6.50752066>
2> F = fun() ->
R = io:get_line("Enter a string : "),
L = string:tokens(R,";"),
[Eval(X) || X <- L]
end.
#Fun<erl_eval.20.50752066>
3> F().
Enter a string : map(fn(x)=x+1, '[1 2 3 4 5]);map(fn(x)=x+5, '[1 2 3 4 5]);uncomplete
evaluation of " map(fn(x)=x+1, '[1 2 3 4 5])"
evaluation of "map(fn(x)=x+5, '[1 2 3 4 5])"
evaluation of "uncomplete\n"
[ok,ok,ok]
4> F().
Enter a string : map(fn(x)=x+1, '[1 2 3 4 5]);
evaluation of " map(fn(x)=x+1, '[1 2 3 4 5])"
evaluation of "\n"
[ok,ok]
5>
[edit]
io:get_chars/2 is taking the number of chars given as parameter from the shell input, 1 in your case, and let the rest. The shell can't know that you will invoke again the io:get_chars/2 function, so it prints again the rest of the input string, and it does the same again and again at each call of the read_term/0 function, it is why you see this weird behavior.
io:get_line/2 takes the whole input from the shell and return it in a string (in erlang it is a list of integer), it is why you have a clean behavior in the shell window, then it is up to you to choose your favorite algorithm to analyze this string. I have chosen string:tokens/2 because I try to use library functions when they exists, I think it is easier to read, and does not need documentation :o)
If you don't want to take care of possible incorrect input, you can replace the F/0 function by
2> F = fun() ->
2> Rep = io:get_line("Enter a string : "),
2> [L,"\n"] = string:tokens(Rep,";"),
2> L
2> end.
and it will do the same thing that your read_term/0 function (except it removes the last $;, but it checks its presence):
3> F().
Enter a string : correct input;
"correct input"
4> F().
Enter a string : missing semi colon
** exception error: no match of right hand side value ["missing semi colon\n"]
5> F().
Enter a string : correct input; but extracharacters after semi colon
** exception error: no match of right hand side value ["correct input"," but extracharacters after semi colon\n"]

Related

I want to export my Data in a Cell Array to an Excel file, as tidy as possible, without semi-colons for new rows

I have a Cell Array of dimensions 2 by 40, and each cell contains a matrix of dimensions 3 by 3:
[3x3 double] [3x3 double] [3x3 double] ... [3x3 double]
[3x3 double] [3x3 double] [3x3 double] ... [3x3 double]
Now, I need to print this Cell Array and show it to my study group. Below is the detailed example of what I am trying to achieve.
Print should show each matrix in the cell clearly and separately, so that we can study it better, similar to this:
[1 2 3] [5 2 3]
[4 5 6] [1 2 2] ...
[7 8 9] [7 8 9]
[5 2 3] [4 5 6]
[3 5 6] [7 2 9] ...
[7 1 9] [5 2 3]
I tried converting Cell to Table, unfortunately this was untidy, as it showed each new row of matrices with semi-colons:
[1 2 3; 4 5 6; 7 8 9]
Also, I tried converting Cell to Double with:
data = [cell{1,:};cell{2,:}];
resulting in 6 by 120 double, looking like this:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
I can export this to an Excel file, however you can see that it is still cumbersome. I can cut and paste the rows 4,5,6 and shift them below so that it looks like:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
however I still need to divide every other 3 columns, so that I can achieve what I want, which is very impractical:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
I would really appreciate your help on this one. Thank you in advance.
To display a complex cell array like this, you can use celldisp to display the cell in an understandable way.
% Create some example data
D = arrayfun(#(x)rand(3,3), ones(2,2), 'uni', 0);
% Display it
celldisp(D)
Another possible way to display this is to create a custom little routine to print the data.
formatspec = '%10.4f';
format = repmat([repmat([formatspec ' '], [1 size(D{1},2)]), ' '], [1 size(D,2)]);
arrayfun(#(k)fprintf('%s\n', sprintf([format, '\n'], cat(2, D{k,:}).')), 1:size(D,1))
A third option, if you really want to export to Excel, you will want to alter the fprintf statement to create a CSV file.
fid = fopen('data.csv', 'w');
% Create the format specifier for a row
format = repmat([repmat('%0.4f,', [1 size(D{1}, 2)]), ','], [1 size(D,2)]);
format(end-1:end) = '';
for k = 1:size(D, 1)
fprintf(fid, [format '\n'], cat(2, D{k,:}).');
% Create an empty row
fprintf(fid, ',\n');
end
fclose(fid);
The result when loaded in Excel.

Haskell blank space after new line

I have the following function which takes a number as a parameter and should return a string.
fun n = unwords [foldl (\acc x -> acc ++ (unwords[show x] ++ " ")) "" [1..nr] ++ "\n"| nr <- [n, n - 1..0]]
The returned value for 5 is:
fun 5
"1 2 3 4 5 \n 1 2 3 4 \n 1 2 3 \n 1 2 \n 1 \n \n"
and
putStrLn $ fun 5
1 2 3 4 5
1 2 3 4
1 2 3
1 2
1
My question is where does the blank space from the start of the lines appear from? My expected result for the function is
fun 5
"1 2 3 4 5 \n1 2 3 4 \n1 2 3\n 1 2\n 1\n\n
The space comes from the outermost use of unwords, whose documentation states:
It joins words with separating spaces.
If you changed that unwords to concat, you would remove the spaces after newlines.

Align two strings perfectly (python)

Is it possible to align the spaces and characters of two strings perfectly?
I have two functions, resulting in two strings.
One just adds a " " between a list of digits:
digits = 34567
new_digits = 3 4 5 6 7
The second function takes the string and prints out the index of the string, such that:
digits = 34567
index_of_digits = 1 2 3 4 5
Now the issue that I am having is when the length of the string is greater than 10, the alignment is off:
I am supposed to get something like this:
Please advice.
If your digits are in a list, you can use format to space them uniformly:
L = [3,4,2,5,6,3,6,2,5,1,4,1]
print(''.join([format(n,'3') for n in range(1,len(L)+1)]))
print(''.join([format(n,'3') for n in L]))
Or with f-string formatting (Python 3.6+):
L = [3,4,2,5,6,3,6,2,5,1,4,1]
print(''.join([f'{n+1:3}' for n in range(len(L))]))
print(''.join([f'{n:3}' for n in L]))
Output:
1 2 3 4 5 6 7 8 9 10 11 12
3 4 2 5 6 3 6 2 5 1 4 1
Ref: join, format, range, list comprehensions

How to remove an element from a list in J by index?

The rather verbose fork I came up with is
({. , (>:#[ }. ]))
E.g.,
3 ({. , (>:#[ }. ])) 0 1 2 3 4 5
0 1 2 4 5
Works great, but is there a more idiomatic way? What is the usual way to do this in J?
Yes, the J-way is to use a 3-level boxing:
(<<<5) { i.10
0 1 2 3 4 6 7 8 9
(<<<1 3) { i.10
0 2 4 5 6 7 8 9
It's a small note in the dictionary for {:
Note that the result in the very last dyadic example, that is, (<<<_1){m , is all except the last item.
and a bit more in Learning J: Chapter 6 - Indexing: 6.2.5 Excluding Things.
Another approach is to use the monadic and dyadic forms of # (Tally and Copy). This idiom of using Copy to remove an item is something that I use frequently.
The hook (i. i.##) uses Tally (monadic #) and monadic and dyadic i. (Integers and Index of) to generate the filter string:
2 (i. i.##) 'abcde'
1 1 0 1 1
which Copy (dyadic #) uses to omit the appropriate item.
2 ((i. i.##) # ]) 0 1 2 3 4 5
0 1 3 4 5
2 ((i. i.##) # ]) 'abcde'
abde

How can I implement a grouping algorithm in J?

I'm trying to implement A006751 in J. It's pretty easy to do in Haskell, something like:
concat . map (\g -> concat [show $ length g, [g !! 0]]) . group . show
(Obviously that's not complete, but it's the basic heart of it. I spent about 10 seconds on that, so treat it accordingly.) I can implement any of this fairly easily in J, but the part that eludes me is a good, idiomatic J algorithm that corresponds to Haskell's group function. I can write a clumsy one, but it doesn't feel like good J.
Can anyone implement Haskell's group in good J?
Groups are usually done with the /. adverb.
1 1 2 1 </. 'abcd'
┌───┬─┐
│abd│c│
└───┴─┘
As you can see, it's not sequential. Just make your key sequential like so (essentially determining if an item is different from the next, and do a running sum of the resulting 0's and 1's):
neq =. 13 : '0, (}. y) ~: (}: y)'
seqkey =. 13 : '+/\neq y'
(seqkey 1 1 2 1) </. 'abcd'
┌──┬─┬─┐
│ab│c│d│
└──┴─┴─┘
What I need then is a function which counts the items (#), and tells me what they are ({. to just pick the first). I got some inspiration from nubcount:
diffseqcount =. 13 : ',(seqkey y) (#,{.)/. y'
diffseqcount 2
1 2
diffseqcount 1 2
1 1 1 2
diffseqcount 1 1 1 2
3 1 1 2
If you want the nth result, just use power:
diffseqcount(^:10) 2 NB. 10th result
1 3 2 1 1 3 2 1 3 2 2 1 1 3 3 1 1 2 1 3 2 1 2 3 2 2 2 1 1 2
I agree that /. ( Key ) is the best general method for applying verbs to groups in J. An alternative in this case, where we need to group consecutive numbers that are the same, is dyadic ;. (Cut):
1 1 0 0 1 0 1 <(;.1) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘
We can form the frets to use as the left argument as follows:
1 , 2 ~:/\ 3 1 1 1 2 2 3 NB. inserts ~: in the running sets of 2 numbers
1 1 0 0 1 0 1
Putting the two together:
(] <;.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘
Using the same mechanism as suggested previously:
,#(] (# , {.);.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
1 3 3 1 2 2 1 3
If you are looking for a nice J implementation of the look-and-say sequence then I'd suggest the one on Rosetta Code:
las=: ,#((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)#]^:(1+i.#[)
5 las 1 NB. left arg is sequence length, right arg is starting number
11 21 1211 111221 312211

Resources