| Author |
Message |
< Erlang ~ Matching question |
| autophile |
Posted: Mon Dec 03, 2007 1:59 am |
|
|
|
User
Joined: 12 Jan 2007
Posts: 31
Location: Maryland, USA
|
Hi all,
Is there any way to do something like this:
Code:
% Input = string()
% Prefix = string()
Prefix = generate_complicated_prefix(),
case Input of
[ Prefix | Tail ] ->
do_something(Tail);
[ $X, Prefix | Tail ] ->
do_something_else(Tail)
end.
Obviously this won't work, because the case clauses turn out to be deep lists -- I need a flattened list to match against. Any ideas as to the Erlangy way to do this? I'm kind of dreading that the answer will turn out to require lists module calls
Thanks,
--Rob |
|
|
| Back to top |
|
| michal |
Posted: Mon Dec 03, 2007 12:39 pm |
|
|
|
User
Joined: 20 Jul 2006
Posts: 44
Location: London
|
If all your lists are short, you can rewrite your case statement as:
Code:
case Input of
Prefix ++ Tail ->
do_something(Tail);
[$X|Prefix] ++ Tail ->
do_something_else(Tail)
end.
However ++ operator is quite expensive and if Tail or Prefix are long lists it will impact the performance.
Michal |
_________________ http://www.erlang-consulting.com |
|
| Back to top |
|
| autophile |
Posted: Mon Dec 03, 2007 1:55 pm |
|
|
|
User
Joined: 12 Jan 2007
Posts: 31
Location: Maryland, USA
|
According to the erl shell, Prefix ++ Tail is an illegal pattern. I guess all variables in a ++ expression have to be bound, and Tail is not bound.
Any other ideas? |
|
|
| Back to top |
|
| Adam |
Posted: Tue Dec 11, 2007 2:34 pm |
|
|
|
User
Joined: 23 Aug 2006
Posts: 71
Location: London
|
In a function header you can write:
Code: func("test" ++ Rest) ->
Rest.
Which in the case of the input "teststring" will bind Rest to "string". Should be the same for any pattern matching. |
_________________ Adam
Erlang Training & Consulting |
|
| Back to top |
|
| autophile |
Posted: Tue Dec 11, 2007 8:32 pm |
|
|
|
User
Joined: 12 Jan 2007
Posts: 31
Location: Maryland, USA
|
| Well, I'm not matching against a fixed string. I'm matching against a variable. |
|
|
| Back to top |
|
| bluefly |
Posted: Mon Jan 07, 2008 12:08 am |
|
|
|
User
Joined: 06 Jan 2008
Posts: 10
|
I am an Erlang newbie, but I feel I have a fair handle on the language in general. Here would be my approach to your problem. I am assuming that you want to match a sublist in a list (or a substring in a string).
There is no way to match a sublist in a list in a guard expression. For one, there is no syntax for it (the syntax is limited to things like the head vs tail of the list). For another, there is no BIF (akin to is_list(), is_integer()) or operator that does this; this means you cannot do this matching in a guard expression either. These two issues knock out unique function header matching and use of "when".
Remember that guards are not allowed to have potential side effects, so they are extra limited.
However, we can still store the results of a match in a variable and then make simple comparisons against the variable.
Here is some tested code that demonstrates the concept, including it crashing when we reach an unexpected prefix situation:
Code: -module(junk).
-export([start/0]).
start() ->
Prefix = generate_complicated_prefix(),
Input = Prefix ++ "this is the tail",
io:format("Input with prefix: ~s~n", [Input]),
process_input(Prefix, Input),
XInput = [$X | Input],
io:format("Input with complicated prefix: ~s~n", [XInput]),
process_input(Prefix, XInput),
BadInput = [$B | Input],
io:format("Bad input: ~s~n", [BadInput]),
process_input(Prefix, BadInput).
generate_complicated_prefix() ->
"some complicated prefix 123_yeah".
process_input(Prefix, Input) ->
{Prefix_Type, Tail} = get_tail(Prefix, Input),
case Prefix_Type of
simple -> do_something(Tail);
complicated -> do_something_else(Tail)
end.
get_tail(Prefix, Input) ->
Is_Simple_Prefix = string:equal(
string:substr(Input, 1, length(Prefix)),
Prefix
),
Is_Complicated_Prefix = string:equal(
string:substr(Input, 1, length(Prefix) + 1),
[$X | Prefix]
),
if
Is_Simple_Prefix -> get_tail(Prefix, Input, simple);
Is_Complicated_Prefix -> get_tail(Prefix, Input, complicated)
end.
get_tail(Prefix, Input, simple) ->
{simple, string:substr(Input, length(Prefix) + 1)};
get_tail(Prefix, Input, complicated) ->
{complicated, string:substr(Input, length(Prefix) + 2)}.
do_something(Tail) ->
io:format("do_something(~s)~n", [Tail]).
do_something_else(Tail) ->
io:format("do_something_else(~s)~n", [Tail]).
I tried to make this elegant, but I welcome comments on how to improve this. |
|
|
| Back to top |
|
|
|
All times are GMT
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|
|