convert a string into another format - erlang

I would like to convert the binary string <<"abc">> into the following string "<a><b><c>" .
In other words, each byte shall be written between one "less than" char and one "greater than" char.
I suppose that the function is recursive ? Note that abc is just an example !

1>lists:flatten([[$<,C,$>]||C<-binary_to_list(<<"abc">>)]).
"<a><b><c>"
alternative
lists:flatmap(fun(C)-> [$<,C,$>] end,binary_to_list(<<"abc">>)).
or
f(C) -> [$<,C,$>].
lists:flatmap(fun f/1,binary_to_list(<<"abc">>)).

The most efficient if you want a flat list would probably be:
fr(<<C,Rest/binary>>) ->
[$<,C,$>|fr(Rest)];
fr(<<>>) -> [].
This expansion is similar to what a list/binary comprehension expands to.

Use a binary comprehension:
2> [[$<, C, $>] || <<C:1/binary>> <= <<"abc">>].
[[60,<<"a">>,62],[60,<<"b">>,62],[60,<<"c">>,62]]
So you don't have to process the binary into a list first and then work on it. It is probably a bit faster, especially for large lists, so if performance matter to you, it may be a viable alternative option.

this answer is probably not best one in terms of efficiency(i didn't compare it to other solutions) but it certainly helps to understand how you can invent your own iterators over different collections in erlang aimed for achieving your specific goal instead of using predefined iterators
fr(<<>>, Output) -> Output;
fr(<<"b", Rest/binary>>, Output) ->
fr(Rest, <<Output, "b">>);
fr(<<C:8, Rest/binary>>, Output) ->
fr(Rest, <<Output/binary, $<, C:8, $>>>).
f(Input) -> fr(Input, <<>>).
P.S. it looks like this solution is actually the most efficient :)

Related

How to output text from lists of variable sizes using printf?

I'm trying to automate some output using printf but I'm struggling to find a way to pass to it the list of arguments expr_1, ..., expr_n in
printf (dest, string, expr_1, ..., expr_n)
I thought of using something like Javascript's spread operator but I'm not even sure I should need it.
For instace, say I have a list of strings to be output
a:["foo","bar","foobar"];
a string of appropriate format descriptors, say
s: "~a ~a ~a ~%";
and an output stream, say os. How can I invoke printf using these things in such a way that the result will be the same as writing
printf(os,s,a[1],a[2],a[3]);
Then I could generalize it to output lists of variable size.
Any suggestions?
Thanks.
EDIT:
I just learned about apply and, using the conditions I posed in my OP, the following seems to work wonderfully:
apply(printf,append([os,s],a));
Maxima printf implements most or maybe all of the formatting operators from Common Lisp FORMAT, which are quite extensive; see: http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm See also ? printf in Maxima to get an abbreviated list of formatting operators.
In particular for a list you can do something like:
printf (os, "my list: ~{~a~^, ~}~%", a);
to get the elements of a separated by ,. Here "~{...~}" tells printf to expect a list, and ~a is how to format each element, ~^ means omit the inter-element stuff after the last element, and , means put that between elements. Of course , could be anything.
There are many variations on that; if that's not what you're looking for, maybe I can help you find it.

Can I match against a string that contains non-ASCII characters?

I am writing an program in which I am dealing with strings in the form, e.g., of "\001SOURCE\001". That is, the strings contained alphanumeric text with an ASCII character of value 1 at each end. I am trying to write a function to match strings like these. I have tried a match like this:
handle(<<1,"SOURCE",1>>) -> ok.
But the match does not succeed. I have tried a few variations on this theme, but all have failed.
Is there a way to match a string that contains mostly alphanumeric text, with the exception of a non-alpha character at each end?
You can also do the following
[1] ++ "SOURCE" ++ [1] == "\001SOURCE\001".
Or convert to binary using list_to_binary and pattern match as
<<1,"SOURCE",1>> == <<"\001SOURCE\001">>.
Strings are syntactic sugar for lists. Lists are a type and binaries are a different type, so your match isn't working out because you're trying to match a list against a binary (same problem if you tried to match {1, "STRING", 1} to it, tuples aren't lists).
Remembering that strings are lists, we have a few options:
handle([1,83,84,82,73,78,71,1]) -> ok.
This will work just fine. Another, more readable (but uglier, sort of) way is to use character literals:
handle([1, $S,$T,$R,$I,$N,$G, 1]) -> ok.
Yet another way would be to strip the non-character values, and then pass that on to a handler:
handle(String) -> dispatch(string:strip(String, both, 1)).
dispatch("STRING") -> do_stuff();
dispatch("OTHER") -> do_other_stuff().
And, if at all possible, the best case is if you just stop using strings for text values entirely (if that's feasible) and process binaries directly instead. The syntax of binaries is much friendlier, they take up way fewer resources, and quite a few binary operations are significantly more efficient than their string/list counterparts. But that doesn't fit every case! (But its awesome when dealing with sockets...)

Why doesn't Haskell's Prelude.read return a Maybe?

Is there a good reason why the type of Prelude.read is
read :: Read a => String -> a
rather than returning a Maybe value?
read :: Read a => String -> Maybe a
Since the string might fail to be parseable Haskell, wouldn't the latter be be more natural?
Or even an Either String a, where Left would contain the original string if it didn't parse, and Right the result if it did?
Edit:
I'm not trying to get others to write a corresponding wrapper for me. Just seeking reassurance that it's safe to do so.
Edit: As of GHC 7.6, readMaybe is available in the Text.Read module in the base package, along with readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v:readMaybe
Great question! The type of read itself isn't changing anytime soon because that would break lots of things. However, there should be a maybeRead function.
Why isn't there? The answer is "inertia". There was a discussion in '08 which got derailed by a discussion over "fail."
The good news is that folks were sufficiently convinced to start moving away from fail in the libraries. The bad news is that the proposal got lost in the shuffle. There should be such a function, although one is easy to write (and there are zillions of very similar versions floating around many codebases).
See also this discussion.
Personally, I use the version from the safe package.
Yeah, it would be handy with a read function that returns Maybe. You can make one yourself:
readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
[(x, "")] -> Just x
_ -> Nothing
Apart from inertia and/or changing insights, another reason might be that it's aesthetically pleasing to have a function that can act as a kind of inverse of show. That is, you want that read . show is the identity (for types which are an instance of Show and Read) and that show . read is the identity on the range of show (i.e. show . read . show == show)
Having a Maybe in the type of read breaks the symmetry with show :: a -> String.
As #augustss pointed out, you can make your own safe read function. However, his readMaybe isn't completely consistent with read, as it doesn't ignore whitespace at the end of a string. (I made this mistake once, I don't quite remember the context)
Looking at the definition of read in the Haskell 98 report, we can modify it to implement a readMaybe that is perfectly consistent with read, and this is not too inconvenient because all the functions it depends on are defined in the Prelude:
readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case [x | (x,t) <- reads s, ("","") <- lex t] of
[x] -> Just x
_ -> Nothing
This function (called readMaybe) is now in the Haskell prelude! (As of the current base -- 4.6)

ERlang - Trying to find LENGTH of constituents of List

guess its getting late, and Im a beginner, just need a little help..
Im trying to find the length of a list.. BUT NOT of the lists themselves, rather the length of the values within..
I take something like:
Other = [<<"366">>,0,
<<1>>,
<<"344">>,<<"Really"
<<1>>,
<<"989">>,<<"NotReally">>
<<1>>,
<<"345">>,4,
<<1>>,
<<"155">>,"209.191"]
I would really want to first convert Other into its RAW constituent binary
Example:
Other = [<<3>>,<<4>>,<<7>>,<<56>>,<<45>>,<<56>>...]
This, of course, is an example of way the original Other would look like(Not right conversion values). So that all of the values in there are there most basic binary data.
Then I could simply iterate through counting each <<_>> and determining the total message length.
Hope I was clear enough to find a solution.
Thanks all for the help, GN
iolist_size/1 is what you are looking for.
1> iolist_size([<<"366">>,0,<<1>>,<<"344">>,<<"Really">>,<<1>>,<<"989">>,<<"NotReally">>,<<1>>,<<"345">>,4,<<1>>,<<"155">>,"209.191"]).
43
2> v(1) - 1.
42
P.S.: Why your example data have this one surplus character? ;-)
If all you're trying to do is find the length of the entire structure, I'd try something like this:
my_length(X) when is_integer(X) -> 1;
my_length(X) when is_binary(X) -> erlang:size(X);
my_length(Lst) when is_list(Lst) ->
lists:sum([my_length(X) || X <- Lst]).
If you really want to build a flat version of your structure, then erlang:list_to_binary gets you pretty close to what you need, then just call size on that. (Actually, this may be better than my first attempt.)
1> erlang:list_to_binary([<<"366">>,0,<<"155">>,"209.191"]).
<<51,54,54,0,49,53,53,50,48,57,46,49,57,49>>

String splitting problems in Erlang

I've been playing around with the splitting of atoms and have a problem with strings. The input data will always be an atom that consists of some letters and then some numbers, for instance ms444, r64 or min1. Since the function lists:splitwith/2 takes a list the atom is first converted into a list:
24> lists:splitwith(fun (C) -> is_atom(C) end, [m,s,4,4,4]).
{[m,s],[4,4,4]}
25> lists:splitwith(fun (C) -> is_atom(C) end, atom_to_list(ms444)).
{[],"ms444"}
26> atom_to_list(ms444).
"ms444"
I want to separate the letters from the numbers and I've succeeded in doing that when using a list, but since I start out with an atom I get a "string" as result to put into my splitwith function...
Is it interpreting each item in the list as a string or what is going on?
You might want to have a look at the string module documentation:
http://www.erlang.org/doc/man/string.html
The following function might interest you:
tokens(String, SeparatorList) -> Tokens
Since strings in Erlang are just a list() of integer() the test in the fun will be made if the item is an atom() when it is in fact an integer(). If the test is changed to look for letters it works:
29> lists:splitwith(fun (C) -> (C >= $a) and (C =< $Z) end, atom_to_list(ms444)).
{"ms","444"}
An atom in erlang is a named constant and not a variable (or not like a variable is in an imperative language).
You should really not create atoms in dynamic fashion (that is, don't convert things to atoms at runtime)
They are used more in pattern matching and send recive code.
Pid ! {matchthis, X}
recive
{foobar,Y} -> doY(Y);
{matchthis,X} -> doX(X);
Other -> doother(Other)
end
A variable, like X could be set to an atom. For example X=if 1==1 -> ok; true -> fail end. I could suffer from poor imagination but I can't think of a way why you would like to parse atom. You should be in charge of what atoms you write and not use list_to_atom(CharIntegerList).
Can you perhaps give a more overview of what you like to accomplish?
A "string" in Erlang is not a primitive type: it is just a list() of integers(). So if you want to "separate" the letters from the digits, you'll have to do comparison with the integer representation of the characters.

Resources