@Jose Thanks for the quick reply! I agree that this would provide a better 
experience for Elixir. I'd be happy to contribute, but I'm very new to the 
language. I may be able to do it with some hand-holding if you're up for it.

@Dmitry I disagree—I don't think this error message is clear. 
String.replace/4 is calling Keyword.get/3 somewhere under the hood, and 
that's where the error message is being thrown. As someone who's new to the 
language, it's hard for me to tell what I did wrong when calling the method.

For context with another language, if I call "1234".gsub(:nope, "banana") 
in Ruby, I get this error:

Traceback (most recent call last):
        1: from test.rb:1:in `<main>'
test.rb:1:in `gsub': wrong argument type Symbol (expected Regexp) 
(TypeError)

In Python, "1234".replace(1234, "banana", 1) produces this:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: replace() argument 1 must be str, not int

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: replace() argument 1 must be str, not int

On Sunday, September 15, 2019 at 4:03:04 PM UTC-7, Dmitry Belyaev wrote:
>
> The error message is clear:
> BracketPush.check_brackets makes a call to 
> https://hexdocs.pm/elixir/String.html#replace/4 and passes empty string 
> "" as the last argument instead of a list.
>
> In dynamically typed languages we expect the caller to pass the correct 
> data for the function to behave as documented. Imagine every function 
> typechecked every argument to the deepest primitive types - the code would 
> become an incomprehensible mess and performance would be terrible wth every 
> function type checking the data in runtime which was already typechecked 
> one level higher.
>
> On 16 September 2019 7:50:56 am AEST, Landon Schropp <[email protected] 
> <javascript:>> wrote:
>>
>> Hello!
>>
>> I'm new to Elixir development, so I'm approaching the language with fresh 
>> eyes. One of the issues I've run into is difficulty understand the error 
>> messages from the standard library. For example, today I ran this code:
>>
>> string
>> |> String.replace(string, ~r/[^\[\](){}]/, "")
>> |> IO.inspect(label: "\n")
>> |> String.codepoints
>> |> check_brackets([])
>>
>> When I run this code through one of my test cases, I get the following 
>> error:
>>
>>   1) test math expression (BracketPushTest)
>>      test/bracket_push_test.exs:52
>>      ** (FunctionClauseError) no function clause matching in Keyword.get/
>> 3
>>      The following arguments were given to Keyword.get/3:
>>
>>
>>          # 1                                                             
>>                                                                             
>>                   ""
>>
>>
>>          # 2
>>          :insert_replaced
>>
>>
>>          # 3
>>          nil
>>                                                                           
>>                                                                             
>>              Attempted function clauses (showing 1 out of 1):
>>
>>
>>          def get(keywords, key, default) when is_list(keywords) and 
>> is_atom(key)
>>
>>
>>      code: assert BracketPush.check_brackets("(((185 + 223.85) * 15) - 
>> 543)/2") == true
>>      stacktrace:
>>        (elixir) lib/keyword.ex:195: Keyword.get/3
>>        (elixir) lib/string.ex:1372: String.replace/4
>>        (bracket_push) lib/bracket_push.ex:15: BracketPush.check_brackets/
>> 1
>>        test/bracket_push_test.exs:53: (test)
>>
>>      test/bracket_push_test.exs:52
>>      ** (FunctionClauseError) no function clause matching in Keyword.get/
>> 3
>>      The following arguments were given to Keyword.get/3:
>>
>>
>>          # 1                                                             
>>                                                                             
>>                   ""
>>
>>
>>          # 2
>>          :insert_replaced
>>
>>
>>          # 3
>>          nil
>>                                                                           
>>                                                                             
>>              Attempted function clauses (showing 1 out of 1):
>>
>>
>>          def get(keywords, key, default) when is_list(keywords) and 
>> is_atom(key)
>>
>>
>>      code: assert BracketPush.check_brackets("(((185 + 223.85) * 15) - 
>> 543)/2") == true
>>      stacktrace:
>>        (elixir) lib/keyword.ex:195: Keyword.get/3
>>        (elixir) lib/string.ex:1372: String.replace/4
>>        (bracket_push) lib/bracket_push.ex:15: BracketPush.check_brackets/
>> 1
>>
>> As a new language user, it's really hard to understand what I did wrong 
>> when the error is thrown from inside the inner implementation of 
>> String.replace/4. In order to debug this, I'd either have to look at the 
>> inner implementation of String.replace/4 or attempt to fiddle with the 
>> arguments. My preference would be for standard library functions to guard 
>> their own interfaces, and throw specific and actionable messages back to 
>> the developer.
>>
>> Thanks for taking the time to read!
>>
>>
> -- 
> Kind regards,
> Dmitry Belyaev
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/52657dee-f2e3-44de-a430-0b8d72eeccad%40googlegroups.com.

Reply via email to