Thanks for the reply, Jose! I'd be happy to dive in, but it's probably going to be Sunday before I can take a look at it.
On Mon, Sep 16, 2019 at 12:51 AM José Valim <[email protected]> wrote: > > @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. > > Sure, the first step is to get Elixir test suite passing locally. You can > follow the steps here: > https://github.com/elixir-lang/elixir/#compiling-from-source > > Next, you should find the source for String.replace/3 and change things > like this: > > def replace(subject, pattern, replacement, options) > > To this: > > def replace(subject, pattern, replacement, options) when is_list(options) > > Or similar. This is not a step by step guide, so feel free to ask more > questions. > > > For context with another language, if I call "1234".gsub(:nope, > "banana") in Ruby, I get this error: [...] In > Python, "1234".replace(1234, "banana", 1) produces this > > To be fair, those are not good examples because those methods are > implemented in C in those languages, and languages typically do type > checking when crossing the C boundary (otherwise you can end-up with > segmentation faults or similar). String.replace/3 is implemented in pure > Elixir which is why the error can happen deep inside the stacktrace. A > similar example in Ruby would likely raise a NoMethodError on one of the > objects given as parameters or lead to something like "TypeError: no > implicit conversion of Symbol into Integer" for something like > "string"[:global]. > > I am not saying this to excuse the behaviour but rather to say that a > similar behaviour to our current one will also be frequently found in other > dynamic languages whenever you go past the built-in functions. > > > *José Valim* > www.plataformatec.com.br > Skype: jv.ptec > Founder and Director of R&D > > > On Sun, Sep 15, 2019 at 5:42 PM Landon Schropp <[email protected]> wrote: > >> @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]> >>> 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 >> <https://groups.google.com/d/msgid/elixir-lang-core/52657dee-f2e3-44de-a430-0b8d72eeccad%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- > 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/CAGnRm4LVm9tq4%2BQ1G3Gk0zTaaNiCySBy3XYYmhJHkj28DpDxXQ%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LVm9tq4%2BQ1G3Gk0zTaaNiCySBy3XYYmhJHkj28DpDxXQ%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- 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/CANG3DMWSw4CzXDdaE3cDw2GFO-ctY8vJ2DYx2J4heM_yOwwKjQ%40mail.gmail.com.
