[erlang-questions] I think I wish I could write case Any of whatever -> _ end.

Richard O'Keefe ok@REDACTED
Tue May 18 01:09:09 CEST 2010


On May 18, 2010, at 2:00 AM, Eric Newhuis (personal) wrote:

> For the record, I might still disagree, so far.  I'm not sure.   
> Simply for argument's sake...
>
> The context in which this might be maximally useful is the following.
>
> case some_module:some_function(...) of
> 	{some, pattern} -> _;
> 	{some, other, pattern} -> _;
> 	_ -> whatever
> end.

What is wrong with

     case X = some_module:some_function(...)
       of {some, pattern} -> X
        ; {some, other, pattern} -> X
        ; _ -> whatever
     end
>
> Note that I belong to the school of philosophy that suggests that  
> the number of temporary variables should be minimized.

By using the wild card, you have *NOT* minimised the number of temporary
variables.  All you have done is to carefully deprive your reader of any
clues as to what it is about.


>  I don't understand why the above would be called wild-card abuse.

Because the whole *point* of the wild-card is that each and
every occurrence of "_" should represent a DIFFERENT variable.
That's what it means in Prolog, Mercury, Strand88, Parlog, GHC,
ML, Haskell, Clean, ...  Every time, a different variable.
But you are relying on the "_" in each arm of the case being
the *SAME* variable.

You are also creating great confusion.
Suppose I have

	case foo()
	  of {ping,_} -> _
	   ; {_,pong} -> _
	end

The wild cards *following* the arrows are the *same* variable;
what about the wild cards inside the patterns?  If not, why not?

What if I write
	case foo() of _ -> case bar() of _ -> _ end end
Does this mean the same as
	case foo() of X -> case bar() of X -> X end end
or	case foo() of X -> case bar() of Y -> X end end
or	case foo() of X -> case bar() of Y -> Y end end
or what?

There's another point.  In Erlang as it stands, _every_
variable _without exception_ must be visibly present at
the point where it is bound.  (Wild cards are no exceptions
to this rule).  You are introducing a new reading of "_"
that violates this rule.  If you want to think of the
variable as bound in the pattern, write
	case Expr
	  of X = Pattern when Guard -> X
If you want to think of the variable as bound in the head,
write
	case X = Expr
	  of Pattern when Guard -> X
In either case, the variable X is *visibly* bound.

>  It is clear from context that the wild-card represents something  
> other than matching.

Yes, but we already *have* something we can use for this purpose.
Ordinary variable names.


>  We've seen this idea before.  There are those grammars that expose  
> variables whose value is whatever matched.

I have no idea what you are referring to.  Can you explain?

"Exposing variables" is different from "invisibly binding anonymous
variables".

>
> I suppose the following is where this great idea of mine might break  
> down.
>
> case some_module:some_function(...) of
> 	{some, pattern} ->
> 		{encapsulated, _};
> 	{some, other, pattern} ->
> 		{another, _, encapsulation}
> end.
>
> Although I still don't have a problem with that.

You may not.  I do.

>  From context I know that the right hand side of the arrow isn't  
> pattern matching.

You as author may; your reader WILL have to work harder in reading
to find out what the context *is*, especially if (as is often the
case) the arrow is on the previous screen.

This would be better as

	case X = some_module:some_function(...)
	  of {some, pattern} ->
	         {encapsulated, X}
	   ; {some, other, pattern} ->
	         {another, X, encapsulation}
	end

There is not one of your examples that would not be massively improved
by introducing a named variable, even a literal X.
>
> I guess where readability might break down is in nesting:
>
> case some_module:some_function(...) of
> 	{some, _, pattern} -> % _1
> 		case _ of ->  % _2
> 			{some, great, pattern} ->
> 				not_so_bad;
> 			_ -> % _3
> 				{_, Kind, _} = _, % _4, _5, _6
> 				Kind
> 		end
> end.
>
> Although I can still read the above once I learn that underscore  
> ('_') is context sensitive.
>
> _1 :: any()
> _2 :: {some, any(), pattern}
> _3 :: {some, any(), pattern}, not {some, great, pattern}
> _4 :: some
> _5 :: pattern
> _6 :: _3

If I want to play at silly puzzles I do the Sudoku problem in the
newspaper.  If I'm reading a program, I do *NOT* enjoy pointless
stumbling-blocks placed in my path to understanding.

Let's rewrite your example.

	case some_module:some_function(...)
	  of {some,Kind,pattern} ->
	         case Kind
                    of great -> not_so_bad
		      _     -> Kind
		 end
	end

There is now *no* puzzle-solving for the reader.

Let me raise my usual refrain:
	let's have a REAL example.




More information about the erlang-questions mailing list