I forgot to mention two things...
1) it is not just "next", "break" is also affected. E.g. try using
break in reduce, it also produce nil. Or even more funny
irb(main):001:0> [0, 1, 2].map { |a| break 15 }
=> 15
2) recommended way at least in recent ruby is to use each_with_object
instead of reduce
( http://apidock.com/rails/Enumerable/each_with_object )
which do not use return value, but modify passed object.
Example code
irb(main):002:0> [0, 1, 2].each_with_object({}) { |a, res| a == 1 ? next :
res[a] = a.to_s }
=> {0=>"0", 2=>"2"}
On Wed, 18 Nov 2015 11:33:23 +0100
Josef Reidinger <[email protected]> wrote:
> On Wed, 18 Nov 2015 10:13:45 +0100
> Stefan Hundhammer <[email protected]> wrote:
>
> > On 18.11.2015 09:56, Josef Reidinger wrote:
> > > And to be honest it can happen in any code in any language ( just
> > > depending how often it can happen ).
> >
> > Wrong.
> >
> > Any halfway decent parser will realize that in one case you do
> > return something from your function, and in another you don't.
> > That's what happened here.
>
> Preciselly speak you always return something. Just maybe default value
> for return is not so common in other languages. I know that e.g. C++
> can check it during compilation, but ruby is not compiled, so in the
> end, you in both cases ends up with runtime error or error catched by
> test suite.
>
> >
> > Better yet, if you have to DECLARE your stuff (functions,
> > variables), you are making a commitment (or a contract, however you
> > want to name this) what you are going to do with that thing and
> > what you don't. And the parser (no matter if it's an interpreter or
> > a compiler) can catch those problems.
>
> This is discussion between static and dynamic languages and about
> explicit types specification. I think there is enough discussion on
> internet regarding this stuff and I worry I cannot add anything new
> here.
>
> >
> >
> > > E.g. in ycp one nil can result in cascade of nils.
> >
> > I really wouldn't call YCP, of all things, a shining example of
> > good behaviour when it comes to this. Yet, even it had (after years
> > of painful debugging) static type checking that at least did some
> > minimal amount of plausibility checks.
> >
> >
> > > What is ruby philosophy how to solve it? Tests. Do not trust code
> > > that is not tested. Of course some tools can detect some misusage,
> > > but only good tests can prove that code really works.
> >
> > Tests are good, but they have limits. In particular, when your
> > number of code paths is too high, the possible permutations just
> > explode. That's why achieving good test coverage is so difficult.
>
> Thats more phylosophy discussion about egg or the egg problem. Ruby
> phylosophy is that if something is not tested ( manually or automatic
> ), then you cannot believe in code. And with good code design almost
> everything can be tested.
>
> >
> > Ruby (and the tools in its ecosystem like Rubocop) try to make you
> > believe that you can easily handle this by dumbing down functions
> > enough so they become trivial. Well, that would be good - if only
> > there were a practical way to go through each code path at least
> > once (better yet, with some permutations of your data set /
> > variables to test fringe cases in the less frequently taken code
> > paths, too).
>
> well, trivial = single purpose. Actually what you mention already
> exists for ruby - https://github.com/mbj/mutant it tests if you do not
> have fake test coverage ( martin played with it in past ). Regarding
> automatic tool to go thrue all path, it is still not enough as
> 1) that tool need to know behavior, sometimes exception is correct
> 2) need to verify it do what is expected, just passing function
> without exception is not enough
>
> >
> > But as seen in this example, this is often not practical. If your
> > code depends on the status of things beyond your immediate control,
> > you'd have to mock all that. In this particular case, who would have
> > foreseen that a seemingly unrelated scenario like having a RAID on
> > the previous installation might lead to such a crash?
>
> If it happen first time like in this case I usually capture target map
> ( as hand crafting target map is pain ) and then write at least
> regression test, that I know that covering this case.
>
> >
> > Sure, better test coverage might have caught this. But it would
> > have been even simpler (very much simpler!) to have the parser
> > throw an error if the code is inconsistent - like not returning a
> > value in this case if in the other case it does.
>
> It is question if you are on side at least have some check or having
> good tests that verify working solution. Again it is part of mandatory
> types discussion topic.
>
> >
> > And to cut the reply that immediately comes to mind short: If in
> > some pathological case I want the code to return 'nil', I can
> > explicitly make it return 'nil'.
>
> On other hand there is many cases where nil is nature return code like
> in each, find, etc. So for language authors it can mean to use
> specific statement for other loops or be consistent, which can cause
> troubles.
>
>
> >
> > IMHO there is no real excuse for the Ruby parser to behave this
> > dumb. They just became collateral damage of their own "anything
> > goes" philosophy.
>
> I agree that faster failure during runtime will be better, but there
> can be maybe code that use this code path.
>
> Josef
>
> >
> >
> > CU
>
--
To unsubscribe, e-mail: [email protected]
To contact the owner, e-mail: [email protected]