[rust-dev] Place for discussions

2014-07-30 Thread Tobias Müller
Hello,

I'm following rust for quite a while, but the discussions are more and more
distributed between different places.
The mailing list was probably first, then with more user attention reddit
and StackOverflow, and now the discourse forum.

I understand that StackOverflow and Reddit are more for users, not
developers, but the discourse forum seems mostly redundant.

What's the reason for that split? Is the mailing list deprecated? Which one
is the future?

I for myself prefer the mailing list because of the gmane NNTP service, I
can use my usual usenet software and have all my forums in one place.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-22 Thread Tobias Müller
Patrick Walton pcwal...@mozilla.com wrote:
 On 7/21/14 2:22 PM, Tobias Müller wrote:
 We discussed this with Bartosz literally for weeks (him being a fan of
 auto_ptr for too long, later completely converted against it and I take
 credit for that :o)). With auto_ptr this was possible:
 
 auto_ptrint a(new int);
 auto_ptrint b = a;
 
 It would nullify a with copy syntax. That code won't compile with
 unique_ptr; you'd need an explicit move(a).
 
 It only got worse from there: passing into functions, member variables...
 
 MOVING WITH COPY SYNTAX DOES NOT WORK.
 
 It's cut and dried.

Please don't snip the attribution, that was a quote!

 ... in C++. Not in Rust. That's because, unlike C++, Rust is designed 
 from the ground up to support moves and copies in a first class way.
 
 It's just strange that you can change the semantic of an already existing
 operation just by adding new capabilities. Adding traits should define new
 operations with new semantics, not changing the semantics of existing
 operations. At least that's how it works for all other traits, and
 deviating from that is at least surprising.
 
 Hence the Opt-In Built-In Traits proposal

Opt-In built-In traits makes things a bit better but my point is still
valid. By adding Copy (implicitly or explicitly) you remove the possibility
of move semantics from the type.
Usually you don't work alone on a project and some coworker adding Copy to
a type that I expected to be Move may be fatal.

No other trait removed works like that.

 Maybe the syntax was just too heavy?
 
 Any syntax at all is too much. I am convinced of that.

I'm still not convinced but maybe my fear is unjustified. Time will tell.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-21 Thread Tobias Müller
Patrick Walton pcwal...@mozilla.com wrote:
 On 7/21/14 8:49 AM, Tobias Müller wrote:
 As a rust newbie, that aspect aways makes me a bit nervous. Two quite
 different operations with the same syntax and and simply changing a detail
 in the struct can be enough to switch between the two.
 
 This is the reason for Opt-In Built-In Traits.
 
 AFAIK this also was one of the reasons (if not _the_ reason) why
 std::auto_ptr was deprecated in C++.
 
 No, `auto_ptr` was deprecated because it copies, not moves, making it 
 hard to sensibly use in containers (among other things).

Quoting Andrei Alexandrescu on digitalmars.d:

We discussed this with Bartosz literally for weeks (him being a fan of
auto_ptr for too long, later completely converted against it and I take
credit for that :o)). With auto_ptr this was possible:

auto_ptrint a(new int); 
auto_ptrint b = a;

It would nullify a with copy syntax. That code won't compile with
unique_ptr; you'd need an explicit move(a).

It only got worse from there: passing into functions, member variables...

MOVING WITH COPY SYNTAX DOES NOT WORK.

It's cut and dried.

Andrei
-

But you are right, Rust is not C++, it's actually the other way round that
makes me nervous.

 Comparisons between C++ aren't really relevant anyway because the 
 compiler catches any use-after-move at *compile time*, rather than at 
 runtime. This means that mistaking the two doesn't cause any harm:
 
 * Causing a move when you thought you were copying results in a compiler 
 error.

 * Causing a copy when you thought you were moving is harmless, as any 
 implicit copy in Rust has *exactly the same runtime semantics* as a 
 move, except that the compiler prevents you from using the value again.

From a performance point of view that may be true, but you may lose desired
semantics.

If you want an instance of a type to be move-only, but later decide that
copying that type is still useful in another place, then you lose the
guarantee in the first place.

It's just strange that you can change the semantic of an already existing
operation just by adding new capabilities. Adding traits should define new
operations with new semantics, not changing the semantics of existing
operations. At least that's how it works for all other traits, and
deviating from that is at least surprising.

 Again, we had that world before. It was extremely annoying to write 
 move all over the place. Be careful what you wish for.

Maybe the syntax was just too heavy?

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Virtual fn is a bad idea

2014-03-14 Thread Tobias Müller
Ziad Hatahet hata...@gmail.com wrote:
 Kind of off-topic, but there is a heated discussion on the D language
 forums about why having non-virtual base class methods by default is a bad 
 idea:
 
 a
 href=http://forum.dlang.org/thread/lfqoan$5qq$1...@digitalmars.com;http://forum.dlang.org/thread/lfqoan$5qq$1...@digitalmars.com/a
 
 Also comes up here: a
 href=http://forum.dlang.org/thread/zkmunpiikmrezbzme...@forum.dlang.org;http://forum.dlang.org/thread/zkmunpiikmrezbzme...@forum.dlang.org/a

I've just read the entire thread (~250 posts by now) and the discussion is
mainly about pro/cons of breaking changes to the language, not about the
feature itself.

The conclusion of that thread seems to be
- Almost everyone agrees that non-virtual (=final) by default is a _good_
thing.
- The lead developers feel that it's not worth a breaking change.
- Many users don't agree with that decision.

Where did you find a point against non-virtual by default? (Except that
it's a breaking change, of course)

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Alternative to Option types

2014-02-28 Thread Tobias Müller
Eric Reed ecr...@cs.washington.edu wrote:
 In general, monads require higher-kinded types because for a type to be a
 monad it must take a type variable. That is, OptionT and ListT could
 be monads, but int and TcpSocket can't be monads. So imagine we wanted to
 define a trait Monad in Rust.

Just for my understanding. Is there an inherent reason that a monad has to
be a higher kinded type (type constructor)? Couldn't it also be represented
somehow as a multiparam trait/typeclass?
AFAIK, higher kinded types are standard haskell, while MPTCs are not, so
it's the obvious choice for haskell. Is it also for rust?

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-14 Thread Tobias Müller
Lee Braiden leebr...@gmail.com wrote:
 On 14/01/14 01:50, Palmer Cox wrote:
 
 On Mon, Jan 13, 2014 at 12:18 PM, Tobias Müller
 trop...@bluewin.ch 
 mailto:trop...@bluewin.ch wrote:
 
 Daniel Micay danielmi...@gmail.com
 mailto:danielmi...@gmail.com wrote:
  Do you know what undefined behavior is? It doesn't mean unspecified.
 
 True, but despite beeing so often cited it won't format your hard disk
  (even in C).
 
 Actually, it's possible, at least on systems without MMU protection --- 
 some embedded systems, for example.  Ints are often used (not just in 
 your own code but in library code) to index a jump table. If that index 
 is a different number than you expected it to be, you could end up 
 executing calling random functions in memory.  Said functions could 
 (and probably would) crash within 1--2 instructions, but even then, it's 
 not INCONCEIVABLE that those instructions could equate to 1) load hard 
 drive device number into the first arg register; 2) call the OS  format_drive 
 function.

But this is just as likely with wrapping integers. _Any_ deviation from the
expected behavior is as dangerous as UB.

 This all leaves the realm of remote possibility and enters the realm of 
 unacceptable risk, at least for some software on some systems, when you 
 factor in malicious individuals trying to manipulate what address gets 
 called and/or what code is sitting at the address called, waiting to  execute.
 
 As I understand it, there are essentially three bugs that can cause a 
 segfault: 1) write to memory you're not allowed to write to.  2) read 
 memory you're not allowed to read from.  3) execute code in memory 
 you're not allowed to execute code from.  The third kind of bug is 
 basically saying do anything you like computer, I don't care.  It's 
 very much undefined behaviour, very much like calling a function pointer 
 that's NULL.  Mostly, you get a segfault, thanks to the MMU, but in 
 portable code, you can't depend on that -- either the compiler handles 
 it, or you have to remember to check everything carefully, treating your 
 coding environment as a hostile one, full of adversaries.

And that's just why I want to help the programmer with those checks as much
as possible. Lifetimes and non-nullable pointers do a great job ensuring
this for memory management, int overflow is missing such a feature.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-14 Thread Tobias Müller
comex com...@gmail.com wrote:
 On Mon, Jan 13, 2014 at 4:06 PM, Tobias Müller trop...@bluewin.ch wrote:
 intl1,u1 + intl2,u2 = intl1+l2,u1+u2
 ...
 
 If the result does not fit into an int the compiler throws an error.
 To resolve an error, you can:
 - annotate the operands with appropriate bounds
 - use a bigger type for the operation and check the result.
 
 I remember wondering whether this type of solution would be feasible
 or too much of a hassle in practice.  As I see it, many values which
 might be arithmetic operands are sizes or counts, and really ought to
 be size_t sized, and any mutable variable which is operated on in a
 loop can't be bounded with a lot more complexity, so it might lean
 toward the latter.

You are right, mutations that depend on previous values of the same
variable are a problem. For example it would be impossible to determine
bounds for i in 'i = i + 1'.
But you could shadow i like 'let i = i + 1'. However that is no more
mutation but definition of a new variable.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-13 Thread Tobias Müller
Daniel Micay danielmi...@gmail.com wrote:
 On Sun, Jan 12, 2014 at 1:23 PM, Tobias Müller trop...@bluewin.ch wrote:
 Isaac Dupree
 m...@isaac.cedarswampstudios.org wrote:
 In general, Rust is a systems language, so fixed-size integral types are
 important to have.  They are better-behaved than in C and C++ in that
 signed types are modulo, not undefined behaviour, on overflow.  It could
 be nice to have integral types that are task-failure on overflow as an
 option too.  As you note, bignum integers are important too; it's good
 they're available.  I think bignum rationals would be a fine additional
 choice to have (Haskell and GMP offer them, for example).
 
 Wrapping overflow is just as bad as undefined behavior IMO.
 
 Do you know what undefined behavior is? It doesn't mean unspecified.

True, but despite beeing so often cited it won't format your hard disk
(even in C).
The result of an integer addition will always be an integer in every
compiler I know so in this specific case I don't fear the UB.

 I cannot remember a single case of using signed integers where wrapping
 would make any sense.
 
 It often makes sense in codecs, hashing algorithms and cryptography.

I'm sure there exist many cases where _unsigned_ int overflow makes sense.
For _signed_ integers I'm a bit sceptical but I am no expert in that field.

In any case it should not be the default but rather 'opt-in'. 

But this is not what I meant. Let me rephrase it differently:
Assume that signed int overflow is UB (like in C). That means, all actual
overflows at runtime have to be considered bugs.
Now I cannot imagine any such case (bug) where guaranteed wrapping would
actually behave nicer.

 If you don't have clear bounds and don't want modular arithmetic, you
 need big integers.

Or proper input validation. The type defines the bounds.

 And you lose some optimization opportunities.
 
 It's treated as undefined because there are more optimization
 opportunities that way.

That's what I wanted to say. If you guarantee wrapping overflow you lose
those opportunities.

 So why not take the path of the rust memory management and enforce bounds
 statically? It would need annotations on the types, like lifetimes, but it
 would be very rusty. Like C but safe.
 
 Rust isn't supposed to be really hard to write. Complex dependent typing would

I'm not sure that this would be so complex. At least not more than the
lifetime system. Is simple arithmetics on the bounds.

In reality (rust beeing a systems PL) fixed width ints _will_ be used, and
I am sure that overflow will often just be neglected. So why not enforce it
statically?

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-13 Thread Tobias Müller
Carter Schonwald carter.schonw...@gmail.com
wrote:
 enforce what statically?  There is  a very really very subtle tradeoff in
 how powerful a static verification scheme can be vs how easily it can be
 used (the sweet spot being somewhere in between nothing  and complete
 proof based verification).

Enforce that integer overflow never happens.

Roughly, I was thinking of the following:

Every int variable/parameter/binding has an associated range (lower and
upper bound):
intl,u
If no bound is specified, the min and max values of the type are used.

Every operation on ints specify the range of the result using the range of
the operands:

intl1,u1 + intl2,u2 = intl1+l2,u1+u2
...

If the result does not fit into an int the compiler throws an error.
To resolve an error, you can:
- annotate the operands with appropriate bounds
- use a bigger type for the operation and check the result.

To go from a bigger to a smaller range you use:
let x : int
match x {
   int0,255 = ...
   _ = fail()
}

Sorry for the sketchy syntax, I'm just following this list but have never
actually used rust.

 It sounds like there are valid arguments for several different error
 semantics for fixed size numbers, and those should perhaps be different
 builtin types. Everyone is right about the tradeoffs for their own needs,
 and choosing one semantics over another in that context is a mixed bag /
 iffy proposition. Tradeoffs are real, the best a language can do is make
 it easy to choose the right tradeoffs for you!

But also different languages choose different tradeoffs and rust aims to be
a systems PL.

By banning the fastest int version from the language by making overflow
wrapping or failing at runtime, you actually limit the choice already. 

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-13 Thread Tobias Müller
Carter Schonwald carter.schonw...@gmail.com
wrote:
 indeed, hence why i was saying there should be sized int variants for
 each of those semantics (wrapping, trapping, overflowing, etc). This is
 something that many people seem to favor, and is the right choice for
 supporting smart engineers build reliable sophisticated software. Namely,
 really spell out what each alternative means, make sure they're all first
 class options, etc etc.
 
 staticly verifying bounded ranges in a language is really subtle. You're
 proposing what easily turns into a pretty tricky flow analysis (to have
 it have any precision!), and it'd have to happen in type checker too...

I was actually trying to avoid flow analysis. With my proposal, the range
would be attached to the type and cannot change over time.
That's why I was proposing a case match binding for going to a smaller
range.

Some time ago I was reading a blog post (I think it was from Patrick
Walton) about why you abandoned type state and how it can be replaced with
a less dynamic system that is easier to reason about.
In that system the dynamic type state was replaced by a more static type
parameter.
I don't want type state for integers but this 'replacement'. (I don't know
how it was called, need to read it up again)

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

2014-01-12 Thread Tobias Müller
Isaac Dupree
m...@isaac.cedarswampstudios.org wrote:
 In general, Rust is a systems language, so fixed-size integral types are 
 important to have.  They are better-behaved than in C and C++ in that 
 signed types are modulo, not undefined behaviour, on overflow.  It could 
 be nice to have integral types that are task-failure on overflow as an 
 option too.  As you note, bignum integers are important too; it's good 
 they're available.  I think bignum rationals would be a fine additional 
 choice to have (Haskell and GMP offer them, for example).

Wrapping overflow is just as bad as undefined behavior IMO. I cannot
remember a single case of using signed integers where wrapping would make
any sense.
And you lose some optimization opportunities.

Trapping overflow is a bit better security wise, but performance is worse.
Also IIRC it does not play nicely with existing code that assumes
otherwise.
Checking only at runtime is also not optimal. 

Bigints are secure but IMO not suited as default for a systems PL.

So why not take the path of the rust memory management and enforce bounds
statically? It would need annotations on the types, like lifetimes, but it
would be very rusty. Like C but safe.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Rust forum

2013-12-03 Thread Tobias Müller
David Piepgrass qwertie...@gmail.com wrote:
 Okay, well, I've never liked mailing lists at all, because:
 
 1. In non-digest mode, My inbox gets flooded.
 2. In digest mode, it's quite inconvenient to write a reply, having to
 cut out all the messages that I don't want to reply to and manually edit
 the subject line. Also, unrelated messages are grouped together while
 threads are broken apart, making discussions harder to follow.
 3. In email I don't get a threaded view. If I go to mailing list archives
 to see a threaded view, I can't reply.

Just use NNTP (gmane.comp.lang.rust.devel on news.gmane.org). Most
newsreader support threaded view (Thunderbird does). You can configure the
mailing list s.t. mails are not actually delivered to your email address
even if you are registered.

But looking at your email address you are already using gmane.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Tobias Müller
Andres Osinski andres.osin...@gmail.com
wrote:
 Hi all, I have a question which I'm sure must have already been discussed
 and dealt with, but I wanted to understand the design rationale:
 
 A lot of trait-level functionality would be enhanced if a trait could
 specify members to be included in the struct which implements the trait.
 This can be solved in practice by wrapping member access in accessor
 methods, but I fail to see why that would be preferable.

IMO this would completely defeat the  advantage of traits over inheritance
based interfaces.

The beauty of traits is, that the trait and the type are separated, only
connected by the implementation:
- You can add an implementation for your custom trait to any existing type.
- You can add an implementation for any existing trait to your custom type.

Now if you add a fields specification to the trait, the former isn't true
anymore. The type has now a dependency on the trait since it must at least
contain a field of a given type, if not even with a given name.

If you the concrete type is under your control, this is obviously not a
problem, as it is the case with inheritance based interfaces. But you
cannot simply assume that for every use case.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev