Search code examples
recursionerlang

Passing list to function results in no case clause matching


I am attempting to pass a list into a function and I am just now learning erlang. So I am new. I get this error in my shell when I attempt to build my erl file.

exception error: no case clause matching [{atom,{3,9},lists}]
  in function  erl_parse:build_attribute/2 (erl_parse.yrl, line 1395)
  in call from erl_parse:yeccpars2_654/7 (erl_parse.yrl, line 127)
  in call from erl_parse:yeccpars0/5 (/daily_build/otp_src/bootstrap/lib/parsetools/include/yeccpre.hrl, line 57)
  in call from epp:parse_file/1 (epp.erl, line 364)
  in call from epp:parse_file/1 (epp.erl, line 366)
  in call from epp:parse_file/2 (epp.erl, line 337)
  in call from compile:do_parse_module/2 (compile.erl, line 1037)
  in call from compile:parse_module/2 (compile.erl, line 1011)

Here is my code that is causing it.

It is in my for function, the rest of the code is just test work as I am practicing.

 % hello world program
-module(helloworld).
-import(lists).
-import(io,[fwrite/1]).
-export([start/0,greet/2,for/3]). 


greet(male, Name) ->
    io:format("Hello, Mr. ~s!\n", [Name]);
    greet(female, Name) ->
    io:format("Hello, Mrs. ~s!\n", [Name]);
    greet(_, Name) ->
    io:format("Hello, ~s!\n", [Name]).

for(Nums <- [H|T], Idx, Target) ->
    Val = lists:nth(Idx, Nums),
    S = if Val == Target -> Idx;
       Idx >= len(Nums) -> -1;
       true -> for(Nums, Idx + 1, Target);
    end,
    S.
    
   

start() -> 
   fwrite("Hello, world!\n").

Also, I am curious that is actually going to return recursively.


Solution

  • The problem is this line:

    -import(lists).
    

    As noted in this answer, the one-argument form of the -import directive was removed in Erlang R16B (released in 2013). These days -import directives require two arguments, the module name and a list of functions to import, like the one on the line below:

    -import(io,[fwrite/1]).
    

    In general, importing functions is discouraged in Erlang. It is often clearer to include the module name every time you're calling a function. For example, when reading the start function:

    start() -> 
       fwrite("Hello, world!\n").
    

    the call to fwrite looks like a local function call, and it's only by looking at the -import directive that you realise that it's actually a call to io:fwrite.

    So I would recommend removing both -import directives, and changing the start function to call io:fwrite explicitly, like this:

    start() -> 
       io:fwrite("Hello, world!\n").