Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Julia violating principle of least surprise??

540 views
Skip to first unread message

Ian Watson

unread,
Jul 22, 2012, 10:40:12 AM7/22/12
to juli...@googlegroups.com
I just ran into two things that surprised me.

First, I needed to round an Int down to the nearest 5, so I did what I would do in any other language and tried

i = i / 5 * 5

and was very surprised to find that the result of i/5 was a Float. This surprised me.

My other surprise is the behaviour of the 'next' directive in a loop. Consider

for i = 1:2
  if (2 == 2)
    next
  end

  println("Hello world")
end

Should this print "Hello world" or not? It does. What about the corresponding programmes in perl, python, ruby and c++? None of them print anything. Again, for me, Julia has violated the principle of least surprise.

Is this a bug or a feature?

#include <iostream>
int
main()
{
  for (int i = 0; i < 2; i++) {
    if (2 == 2) {
      continue;
    }

    std::cout << "Hello world\n";
  }
}

#!/usr/bin/env ruby

[1,2].each do |i|
  if (2 == 2)
    next
  end

  $stdout << "Hello world\n"
end

#!/usr/bin/env perl

for ($i = 0; $i < 2; $i++) {
  if (2 == 2) {
    next;
  }

  PRINT STDOUT "Hello world\n";
}

#!/usr/bin/env python

for i in range(1,3):
  if (2 == 2):
    continue

  print "Hello world"

Tim Holy

unread,
Jul 22, 2012, 11:06:54 AM7/22/12
to juli...@googlegroups.com
The problem with such principles is that it's very background-dependent. A
Matlab person would be very surprised if i/5 didn't produce a float. Try
5*div(i, 5).

For your second example, change next to "continue" and I think you will be
happy.

--Tim

Ian Watson

unread,
Jul 22, 2012, 11:22:18 AM7/22/12
to juli...@googlegroups.com
OOPS, yes, you are right, my apologies - too many languages, too many syntaxes to remember. Using 'continue' gets me what I want, no surprise.

Which leads to the question of how did Julia interpret the 'next' word in that wrong code I posted? It seemed to execute without complaint? That is still surprising.

You are also right about surprise being a function of from where one is coming. Since Julia has aligned itself with Matlab type concepts, Matlab behaviour drives things. I have never used Matlab. . I imagine this behaviour will also surprise others coming from non Matlab environments.

Thanks Tim

Ian

Stefan Karpinski

unread,
Jul 22, 2012, 11:49:56 AM7/22/12
to juli...@googlegroups.com
The next object is a a generic function that is used to implement for loops and other iteration constructs. Your code evaluates it and then does nothing with the value. You can see what next is pretty easily in the repl:

julia> next
Methods for generic function next
next(Range{T<:Real},Any) at range.jl:101
next(Range1{T<:Real},Any) at range.jl:102
next((Any...,),Any) at tuple.jl:13
...

Regarding division of two integers returning a float, Python changed *to* that same behavior in 3.x, at the cost of breaking compatibility with all prior versions because producing a float is more intuitive to the newcomer. I would argue that unless you've been trained to expect integer division, it's very unexpected for 1/2 to return 0. Having truncated integer division be the default is very much a legacy of a time when floating-point arithmetic was far too expensive to be the default.

--
 
 
 

Ian Watson

unread,
Jul 22, 2012, 1:31:32 PM7/22/12
to juli...@googlegroups.com
Thanks Stefan

For those of us who grew up with the concept of integer division, this is strange, but I also agree that it is anachronistic, so if the world is moving away from that concept, I'll move and adapt just fine. I don't think C or C++ could ever change.

The 'next' thing is a little unfortunate, since it will facilitate some inter-language syntax confusion, as just happened here - step away from a language for a couple of weeks and spend time working with languages that do it the other way.... I sure do wish there had been some consistency in 'continue' and 'next' between languages. Too late for that now.

Thanks as always!

Ian

Stefan Karpinski

unread,
Jul 22, 2012, 2:04:45 PM7/22/12
to juli...@googlegroups.com
I like C just the way it is too :-)

The next thing may be alleviated by modules since the start/next/done machinery can possibly not be in the default set of imports, since it's mostly "under the hood".

--
 
 
 

Jeff Bezanson

unread,
Jul 22, 2012, 2:55:06 PM7/22/12
to juli...@googlegroups.com
One way to discover this is to use one of the editor modes, and see
that "next" isn't colored.
> --
>
>
>

dslate

unread,
Jul 22, 2012, 5:21:01 PM7/22/12
to juli...@googlegroups.com
Regarding integer division truncating the result, there is is a big difference between C/C++ and languages with dynamic run-time typing like Julia, Python, etc.  I always thought it was a bad idea for the "/" operator in dynamic languages to truncate results if and only if both operands happened to be integers.  At least in statically-typed languages it's possible to know what's going to happen by looking at the code.   Long before Python "bit the bullet" and changed to always returning a float (painfully breaking compatibility with existing code), I was complaining to programming acquaintances who were Python fans about this issue.  They mostly thought truncation was just fine, and were probably surprised when even the Python developers changed their minds about this.

-- Dave Slate


On Sunday, July 22, 2012 12:31:32 PM UTC-5, Ian Watson wrote:
Thanks Stefan

For those of us who grew up with the concept of integer division, this is strange, but I also agree that it is anachronistic, so if the world is moving away from that concept, I'll move and adapt just fine. I don't think C or C++ could ever change.

The 'next' thing is a little unfortunate, since it will facilitate some inter-language syntax confusion, as just happened here - step away from a language for a couple of weeks and spend time working with languages that do it the other way.... I sure do wish there had been some consistency in 'continue' and 'next' between languages. Too late for that now.

Thanks as always!

Ian

On Sunday, July 22, 2012 11:49:56 AM UTC-4, Stefan Karpinski wrote:
The next object is a a generic function that is used to implement for loops and other iteration constructs. Your code evaluates it and then does nothing with the value. You can see what next is pretty easily in the repl:

julia> next
Methods for generic function next
next(Range{T<:Real},Any) at range.jl:101
next(Range1{T<:Real},Any) at range.jl:102
next((Any...,),Any) at tuple.jl:13
...
Regarding division of two integers returning a float, Python changed *to* that same behavior in 3.x, at the cost of breaking compatibility with all prior versions because producing a float is more intuitive to the newcomer. I would argue that unless you've been trained to expect integer division, it's very unexpected for 1/2 to return 0. Having truncated integer division be the default is very much a legacy of a time when floating-point arithmetic was far too expensive to be the default.

John Cowan

unread,
Jul 22, 2012, 6:51:57 PM7/22/12
to juli...@googlegroups.com
On Sun, Jul 22, 2012 at 5:21 PM, dslate <rusti...@gmail.com> wrote:

> I always thought it was a bad idea for the "/" operator
> in dynamic languages to truncate results if and only if both operands
> happened to be integers.

I agree entirely. Returning the wrong answer is never the right idea.
Even in ML and Haskell, which are statically typed, / returns a float
and div and quot are used for integer division.

Of course C/C++ are trapped by backward compatibility.

--
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures

Bill Hart

unread,
Jul 22, 2012, 7:05:25 PM7/22/12
to juli...@googlegroups.com
On 22 July 2012 23:51, John Cowan <johnw...@gmail.com> wrote:
> On Sun, Jul 22, 2012 at 5:21 PM, dslate <rusti...@gmail.com> wrote:
>
>> I always thought it was a bad idea for the "/" operator
>> in dynamic languages to truncate results if and only if both operands
>> happened to be integers.
>
> I agree entirely. Returning the wrong answer is never the right idea.

Mathematically a float can't exactly return the correct answer. So by
that reasoning it should return a fraction not a float.

> Even in ML and Haskell, which are statically typed, / returns a float
> and div and quot are used for integer division.
>
> Of course C/C++ are trapped by backward compatibility.
>
> --
> GMail doesn't have rotating .sigs, but you can see mine at
> http://www.ccil.org/~cowan/signatures
>
> --
>
>
>

John Myles White

unread,
Jul 22, 2012, 7:13:15 PM7/22/12
to juli...@googlegroups.com
I think John was making the value-laden assertion (which I basically agree with) that no one wants integer division as their default definition of Int / Int. After all, most programmers aren't reimplementing the Euclidean algorithm day after day.

-- John
> --
>
>
>

Bill Hart

unread,
Jul 22, 2012, 7:22:54 PM7/22/12
to juli...@googlegroups.com
On 23 July 2012 00:13, John Myles White <johnmyl...@gmail.com> wrote:
> I think John was making the value-laden assertion (which I basically agree with) that no one wants integer division as their default definition of Int / Int. After all, most programmers aren't reimplementing the Euclidean algorithm day after day.

Computer algebraists would see things differently. But algebra is a
small part of mathematics. There are many more numerically minded
people.

Bill.

>
> -- John
>
> On Jul 22, 2012, at 4:05 PM, Bill Hart wrote:
>
>> On 22 July 2012 23:51, John Cowan <johnw...@gmail.com> wrote:
>>> On Sun, Jul 22, 2012 at 5:21 PM, dslate <rusti...@gmail.com> wrote:
>>>
>>>> I always thought it was a bad idea for the "/" operator
>>>> in dynamic languages to truncate results if and only if both operands
>>>> happened to be integers.
>>>
>>> I agree entirely. Returning the wrong answer is never the right idea.
>>
>> Mathematically a float can't exactly return the correct answer. So by
>> that reasoning it should return a fraction not a float.
>>
>>> Even in ML and Haskell, which are statically typed, / returns a float
>>> and div and quot are used for integer division.
>>>
>>> Of course C/C++ are trapped by backward compatibility.
>>>
>>> --
>>> GMail doesn't have rotating .sigs, but you can see mine at
>>> http://www.ccil.org/~cowan/signatures
>>>
>>> --
>>>
>>>
>>>
>>
>> --
>>
>>
>>
>
> --
>
>
>

John Cowan

unread,
Jul 22, 2012, 7:26:44 PM7/22/12
to juli...@googlegroups.com
On Sun, Jul 22, 2012 at 7:05 PM, Bill Hart <goodwi...@googlemail.com> wrote:

> Mathematically a float can't exactly return the correct answer. So by
> that reasoning it should return a fraction not a float.

Well, yes, but something is owed to numerical efficiency in a
scientific programming language. In Scheme, where numbers are either
exact or inexact, implementations may at their discretion return
either 0.6 (inexact) or 3/5 (exact) as the result of dividing 3 by 5;
what they may not return is 0. The Chicken implementation has a
default mode in which there are only machine integers (31 or 63 bits
as the case may be) and floats, but you can load a "numbers" module to
get full support for arbitrary-size integers, exact rationals, and
complex numbers both exact and inexact.

Jeff Bezanson

unread,
Jul 22, 2012, 7:30:05 PM7/22/12
to juli...@googlegroups.com
Eventually we will support fast rational arithmetic (complex is ok,
but also needs performance work). Then it would be totally reasonable
to write a module with definitions appropriate to a different
discipline. It could also include things like integers that
automatically promote to bigints. After all, this is a big part of the
motivation for julia's design --- so you can get a different / with
the same compiler goodness!
> --
>
>
>

John Cowan

unread,
Jul 22, 2012, 10:00:02 PM7/22/12
to juli...@googlegroups.com
On Sun, Jul 22, 2012 at 7:30 PM, Jeff Bezanson <jeff.b...@gmail.com> wrote:

> Eventually we will support fast rational arithmetic (complex is ok,
> but also needs performance work).

At that point you have to decide which representation to use. There
are three reasonable possibilities:

1) A pair of unlimited-precision integers (most Schemes and Lisps, also Pure)

2) A pair of machine integers (Wraith Scheme uses a pair of 64-bit ints)

3) Unlimited-precision floats (CLisp provides this as a type of float
rather than rational)

Bill Hart

unread,
Jul 22, 2012, 11:12:29 PM7/22/12
to juli...@googlegroups.com
Not that it matters, but my strong preference is for 1.

Of course I can write my own either way, so not too much of a hassle.

Bill.
> --
>
>
>

Jeffrey Sarnoff

unread,
Jul 22, 2012, 11:25:43 PM7/22/12
to juli...@googlegroups.com, goodwi...@googlemail.com
+1

Kevin Squire

unread,
Jul 23, 2012, 2:09:31 PM7/23/12
to juli...@googlegroups.com
Rational is already a parametric type in julia, so wouldn't any of these be allowed?

Kevin

Stefan Karpinski

unread,
Jul 23, 2012, 4:36:30 PM7/23/12
to juli...@googlegroups.com
On Mon, Jul 23, 2012 at 2:09 PM, Kevin Squire <kevin....@gmail.com> wrote:
 
Rational is already a parametric type in julia, so wouldn't any of these be allowed?

Yup. 
Reply all
Reply to author
Forward
0 new messages