Re: [rust-dev] real-time programming? usability?
On Sat, Oct 19, 2013 at 12:45 AM, Jerry Morrison jhm...@gmail.com wrote: On Fri, Oct 18, 2013 at 6:13 PM, Daniel Micay danielmi...@gmail.comwrote: On Fri, Oct 18, 2013 at 7:37 PM, Jerry Morrison jhm...@gmail.com wrote: (1) Rust has great potential for *real-time programming* as well as secure programming. Perhaps this just needs a library call to fork real-time threads that never do garbage collection. (Real-time means predictably meeting time deadlines, e.g. in avionics, video capture, medical x-ray, and robotics. Speed is important but the crucial point is reliably meeting deadlines. Garbage collectors, JIT compilers, and run-time optimizers are bad for predictability.) Maybe Rust already has this. What determines whether a thread-local managed heap uses reference counting? Ref-counting may be OK in a real-time thread if it doesn't deallocate a variable-length chain of nodes at an inconvenient time. Rust leaves memory allocation up to the user as much as C++. Most code can simply use unboxed values and lightweight references, with occasional usage of owned boxes (single-owner heap allocations, with lifetime tied to scope). Ideally, forking a real-time thread could ensure that (1) no GC pauses the thread just to find out there's no garbage to collect, and (2) something would catch the mistake if it ever calls code (directly or indirectly) that evolves to using GC memory. Rust doesn't currently have a way to forbid features only in some parts of the code but not others. Avoiding garbage collection as a hard requirement will likely mean using rust-core (or whatever it evolves to, maybe a special profile of the standard library). If you need shared ownership, it's available via the `Rc`/`RcMut` types. Every split of ownership is explicit via a `clone` call since moves are the default. There will be a task-local garbage collector providing garbage collected pointers, but it still needs to be implemented. Sounds good, although I don't understand the details. Does the program pick between GC allocation and ref counting allocation via the choice of pointer sigils? Via the choice of library calls? Reference counting is implemented as a library type, so you would make a reference counted allocation with `Rc::new(value)` and make an explicit reference count with `box.clone()` (the implementation: https://github.com/mozilla/rust/blob/master/src/libstd/rc.rs). There are managed pointers sigils for garbage collection (@, @mut) but I think consensus is trending towards replacing the syntax with a type similar to `Rc` allowing cycles and implicit copies. The compiler support could be exposed via attributes hooks like the operator traits, rather than syntax. The standard library implements N:M concurrency and exposes a blocking API for asynchronous I/O. I don't think it would be suitable for a real-time application, but you can avoid the standard library: https://github.com/thestinger/rust-core What's N:M concurrency? The concurrency model implemented in the standard library treats real threads as schedulers, and maps cooperatively scheduled tasks onto them. If the task doesn't make calls to functions with yields, it will monopolize a scheduler thread. It's a very good model for I/O or for high throughput on many CPU-bound batch jobs (https://www.threadingbuildingblocks.org/), but it's not going to be suitable for real-time needs. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Strange behavior about Writer trait
I run into the following problem (the code below is a toy example). ``` use std::io::Writer; // Makes no difference if added/removed. trait PrintWithSpice { fn print(self, writer: Writer, spice: bool); } struct Bar { bar: ~PrintWithSpice, } impl Bar { pub fn print(self, writer: Writer) { self.bar.print(writer, false); Bar::print_via_borrowed(writer, self.bar); } fn print_via_borrowed(writer: Writer, data: PrintWithSpice) { // Invoking the `print` function via the borrowed pointer to the `PrintWithSpice` trait: // Works fine, as expected.. data.print(writer, true); } } struct Foo { foo: bool } impl PrintWithSpice for Foo { fn print(self, writer: Writer, spice: bool) { // Invoking the `write_str` function via the borrowed pointer to the `Writer` trait: // error: failed to find an implementation of trait std::io::Writer for std::io::Writerno-bounds // What is going on? writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice)); } } ``` I didn't understand what the compiler is complaining about. failed to find an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling a function via a borrowed pointer to a trait should just work (it does a few lines above). After digging I discovered what the compiler really meant (I think). The `write_str` method is defined for `WriterUtils` rather than for `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it compiles fine. So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am using that instead of `Writer` all over my code. I can see doing that as a workaround, but it doesn't smell right to me. So: * Why is the compiler complaining about not finding an implementation for `Writer` when the method I invoke is from `WriterUtil`? * Since there is an `implT: Writer for WriterUtil`, shouldn't the compiler be sufficiently smart to deduce that the code is valid in the 1st place? * Until the compiler is sufficiently smart (or, if there is a good reason why it would never be), shouldn't we rename `Writer` to `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become more usable? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Strange behavior about Writer trait
Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but I can't cast any @Writer (such as `io::stdout()`) to it. I guess I should just use `@Writer` everywhere for now :-( This raises the question of how come the compiler is smart enough to figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough to figure out a `Writer` has the trait... On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.org wrote: I run into the following problem (the code below is a toy example). ``` use std::io::Writer; // Makes no difference if added/removed. trait PrintWithSpice { fn print(self, writer: Writer, spice: bool); } struct Bar { bar: ~PrintWithSpice, } impl Bar { pub fn print(self, writer: Writer) { self.bar.print(writer, false); Bar::print_via_borrowed(writer, self.bar); } fn print_via_borrowed(writer: Writer, data: PrintWithSpice) { // Invoking the `print` function via the borrowed pointer to the `PrintWithSpice` trait: // Works fine, as expected.. data.print(writer, true); } } struct Foo { foo: bool } impl PrintWithSpice for Foo { fn print(self, writer: Writer, spice: bool) { // Invoking the `write_str` function via the borrowed pointer to the `Writer` trait: // error: failed to find an implementation of trait std::io::Writer for std::io::Writerno-bounds // What is going on? writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice)); } } ``` I didn't understand what the compiler is complaining about. failed to find an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling a function via a borrowed pointer to a trait should just work (it does a few lines above). After digging I discovered what the compiler really meant (I think). The `write_str` method is defined for `WriterUtils` rather than for `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it compiles fine. So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am using that instead of `Writer` all over my code. I can see doing that as a workaround, but it doesn't smell right to me. So: * Why is the compiler complaining about not finding an implementation for `Writer` when the method I invoke is from `WriterUtil`? * Since there is an `implT: Writer for WriterUtil`, shouldn't the compiler be sufficiently smart to deduce that the code is valid in the 1st place? * Until the compiler is sufficiently smart (or, if there is a good reason why it would never be), shouldn't we rename `Writer` to `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become more usable? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Strange behavior about Writer trait
If T is a trait, its trait objects ~T, @T and T do not implement T. There is an implementation of Writer for @Writer, but not for ~Writer or Writer which is why you're seeing that error. Steven Fackler On Fri, Oct 18, 2013 at 11:27 PM, Oren Ben-Kiki o...@ben-kiki.org wrote: Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but I can't cast any @Writer (such as `io::stdout()`) to it. I guess I should just use `@Writer` everywhere for now :-( This raises the question of how come the compiler is smart enough to figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough to figure out a `Writer` has the trait... On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.org wrote: I run into the following problem (the code below is a toy example). ``` use std::io::Writer; // Makes no difference if added/removed. trait PrintWithSpice { fn print(self, writer: Writer, spice: bool); } struct Bar { bar: ~PrintWithSpice, } impl Bar { pub fn print(self, writer: Writer) { self.bar.print(writer, false); Bar::print_via_borrowed(writer, self.bar); } fn print_via_borrowed(writer: Writer, data: PrintWithSpice) { // Invoking the `print` function via the borrowed pointer to the `PrintWithSpice` trait: // Works fine, as expected.. data.print(writer, true); } } struct Foo { foo: bool } impl PrintWithSpice for Foo { fn print(self, writer: Writer, spice: bool) { // Invoking the `write_str` function via the borrowed pointer to the `Writer` trait: // error: failed to find an implementation of trait std::io::Writer for std::io::Writerno-bounds // What is going on? writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice)); } } ``` I didn't understand what the compiler is complaining about. failed to find an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling a function via a borrowed pointer to a trait should just work (it does a few lines above). After digging I discovered what the compiler really meant (I think). The `write_str` method is defined for `WriterUtils` rather than for `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it compiles fine. So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am using that instead of `Writer` all over my code. I can see doing that as a workaround, but it doesn't smell right to me. So: * Why is the compiler complaining about not finding an implementation for `Writer` when the method I invoke is from `WriterUtil`? * Since there is an `implT: Writer for WriterUtil`, shouldn't the compiler be sufficiently smart to deduce that the code is valid in the 1st place? * Until the compiler is sufficiently smart (or, if there is a good reason why it would never be), shouldn't we rename `Writer` to `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become more usable? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Strange behavior about Writer trait
Hmmm That sounds strange. Shouldn't `obj: T` allow me to invoke `obj.method_of_T()`? For example, how did I manage to invoke the `data.print(...)` method via the borrowed `data: PrintWithSpice` pointer? Automatic dereference? And if so, why didn't it work for `Writer` as well? On Sat, Oct 19, 2013 at 9:29 AM, Steven Fackler sfack...@gmail.com wrote: If T is a trait, its trait objects ~T, @T and T do not implement T. There is an implementation of Writer for @Writer, but not for ~Writer or Writer which is why you're seeing that error. Steven Fackler On Fri, Oct 18, 2013 at 11:27 PM, Oren Ben-Kiki o...@ben-kiki.org wrote: Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but I can't cast any @Writer (such as `io::stdout()`) to it. I guess I should just use `@Writer` everywhere for now :-( This raises the question of how come the compiler is smart enough to figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough to figure out a `Writer` has the trait... On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.org wrote: I run into the following problem (the code below is a toy example). ``` use std::io::Writer; // Makes no difference if added/removed. trait PrintWithSpice { fn print(self, writer: Writer, spice: bool); } struct Bar { bar: ~PrintWithSpice, } impl Bar { pub fn print(self, writer: Writer) { self.bar.print(writer, false); Bar::print_via_borrowed(writer, self.bar); } fn print_via_borrowed(writer: Writer, data: PrintWithSpice) { // Invoking the `print` function via the borrowed pointer to the `PrintWithSpice` trait: // Works fine, as expected.. data.print(writer, true); } } struct Foo { foo: bool } impl PrintWithSpice for Foo { fn print(self, writer: Writer, spice: bool) { // Invoking the `write_str` function via the borrowed pointer to the `Writer` trait: // error: failed to find an implementation of trait std::io::Writer for std::io::Writerno-bounds // What is going on? writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice)); } } ``` I didn't understand what the compiler is complaining about. failed to find an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling a function via a borrowed pointer to a trait should just work (it does a few lines above). After digging I discovered what the compiler really meant (I think). The `write_str` method is defined for `WriterUtils` rather than for `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it compiles fine. So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am using that instead of `Writer` all over my code. I can see doing that as a workaround, but it doesn't smell right to me. So: * Why is the compiler complaining about not finding an implementation for `Writer` when the method I invoke is from `WriterUtil`? * Since there is an `implT: Writer for WriterUtil`, shouldn't the compiler be sufficiently smart to deduce that the code is valid in the 1st place? * Until the compiler is sufficiently smart (or, if there is a good reason why it would never be), shouldn't we rename `Writer` to `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become more usable? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
Interesting idea; in that case, one could string together any series of functions - basically, `.` would become the equivalent of `|` (or whatever other name you want to call it). That is, instead of writing `baz(bar(foo(x), y), z)` one could write `foo(x).bar(y).baz(z)`. This would make it easier to write things in functional style, using the same syntax as the object style. It could be viewed as the natural complement for the `do` keyword, which adds a last block parameter to the end of the function. I'm less certain about giving up `impl Foo { ... }`, though - that is useful for logically grouping, documenting and accessing functions (as in `Foo::foo(...)`). But it seems we don't have to give it up, just make it optional? On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq matthieu.monr...@gmail.com wrote: I see no reason for the restriction of self. Why not simply say that any function can be called with first_arg.func(...) style ? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] mutable vs. functional APIs
Date: Fri, 18 Oct 2013 10:54:23 -0700 From: Jeff Petkau j...@google.com On my code (disclaimer: only toy projects to learn Rust so far), I've been pretty happy with a mut_ prefix for mutable versions. newthing = oldthing.push(foo) anything.mut_push(foo) x = bagofun.sort() bagosadness.mut_sort() etc. Advantages: - consistent meaning with the 'mut' keyword. - works with pretty much any name. - makes mutable versions just a bit uglier than immutable code. Disadvantages: - If an API is inherently mutable, it gets pretty noisy. - A bit ugly, probably turns off newcomers. - If the compiler warns on ignoring return values, and mutating methods return (), then a convention might be unnecessary. --Jeff What about establishing a convention that mutable methods start with an uppercase letter while non-mutating methods start with a lowercase letter? It would be lightweight in terms of character count/looks and at the same time give mutable methods a slight visual emphasis, which makes sense I think. I know this convention is already used by Traits, but when I looked through some code with the above proposal in mind it would be easy to distinguish between these two uses of the same convention due to the differing contexts they're used in. -Eric ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Should I/O use conditions?
On Saturday, 19 October 2013, Florian Weimer wrote: The problem is that if err is of type error, err != nil is true after the assignment of a pointer value to err. So the usual error checking idiom doesn't work if your function returns a pointer-to-struct (that implements the error interface) instead of a (relatively opaque) error interface value. Don't do that. Return an error, not a naked error implementation. If people want to inspect it rather than treat it as a string, they'll do a type assertion rather than just a nil check. Rust doesn't have type assertions, however I feel this could be handled satisfactorily by using concrete error types in Rust. Also, the whole nil vs nil thing is irrelevant to Rust. Or put differently, if you put a typed null pointer into an interface value, the interface value keeps the type information and is therefore no longer equal to nil. Don't do that. Return either a nil error or a valid value of your error type. Seriously, the nil interface vs nil contents thing is only a tripping point for novices who don't understand what interfaces are, it's not something you run into once you've familiarized yourself with the language. This wouldn't be an issue in Rust, since people would really have to go out of their way to conflate an Err(None) with an Ok(v). That's not a chaining mechanism. You're going to need to explain what you mean by this, then, and how it would apply to Rust. Note that if it's something very particular to how Go code is written, it's probably not constructive here. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] #rust-osdev
This is right up my alley for interest, but I'm not often on IRC. Will they be logged somewhere? On Fri, Oct 18, 2013 at 5:28 AM, Léo Testard leo.test...@gmail.com wrote: Hello, A new channel appeared on IRC today following a discussion about exo and microkernels on #rust. This chan is #rust-osdev and is about... guess what... OS development with Rust. That's it. We will discuss how to use Rust for OS development : how to compile and run Rust code without the runtime, how to make it boot on the hardware, how to link it with C or assembly, how to implement some things with Rust, etc. etc. and many other fun things I created a wiki page ( https://github.com/mozilla/rust/wiki/Operating-system-development) that will reference resources, projects, etc. It's quite empty for now but I hope it will be filled soon :) Leo ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Should I/O use conditions?
This is how we implemented error handling in Java. We defined an abstract class ErrorSink like in: class ErrorSink { void addError(String s); boolean hasError(s); // few more methods to add extra attributes like line, file, column etc of errors } A default implementation of the class just throws in the addError method, but the requirement for addError callers is to assume that method would not throw and try to recover or return some sensible value. For example, a method like readFileAsString in case of IOException reported that and returned an empty string. A configuration parser that calls readFileAsString to read included files has a custom implementation of ErrorSink that does not throw but rather adds all errors on the list. At the end of parsing all those errors plus all syntax violations was converted into a new detailed report with proper line numbers etc and reported to the original sink. This has number of benefits. All unexpected errors like dns failure when reading URL are nicely formated showing the error origin. Various low-level helpers like a date parser do not need to worry about including proper context in the error message as that was responsibility of the caller. This allowed to reuse the same parser in GUI dialogs for a date input showing short and very informative tooltip when user typed invalid date. It was trivial to add warnings to the system extending the ErrorSink with an addWarning method and turn those warnings into hard errors at runtime during testing via simple throw. The callers would not need to check for errors at the every method call. The biggest drawback was the need to pass ErrorSink to a lot of methods or store that as a member of many classes. We experimented with using Java's thread locals instead, but that was rather inflexible and inefficient. I wonder why such error reporting is not used in other programs or languages. On 18 October 2013 23:20, Florian Weimer f...@deneb.enyo.de wrote: * Igor Bukanov: So the Go style is to call a function, check if the was an error, update the error object (or create a new wrapping the old one) with extra information relevant to the current call stack frame and propagate the updated error object to the caller. It's more common to simply return the object. Due to some obscure feature of Go's type system, error values have to be interfaces and cannot be struct types, so I have not seen anyone trying to updating an existing error. Wrapping might happen, but there is no general chaining mechanism like there is in Java. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
On Sat, Oct 19, 2013 at 4:08 PM, Oren Ben-Kiki o...@ben-kiki.org wrote: I'm less certain about giving up `impl Foo { ... }`, though - that is useful for logically grouping, documenting and accessing functions (as in `Foo::foo(...)`). But it seems we don't have to give it up, just make it optional? Interesting point. I think this argues in favor of removing anonymous `impl`s, even as sugar. I was focused on normal (selfish) methods in my previous letter, rather than static (selfless) ones. You could still achieve much the same effect, if you wanted to, by writing: struct Foo { .. } fn get_thing(self: Foo) - Bar { .. } // for `some_foo.get_thing()` syntax mod Foo { fn new() - Foo { .. } // for `Foo::new()` syntax } Rust already allows this trickery: the type and module are imported together when you write `use some_mod::Foo`. Keeping this seems fine, and making it more explicit (relative to `impl`) seems like a good thing. What you lose is that in the case of a generic type, you would have to write the generic-bits for each function, which is the more typing disadvantage from earlier. I think losing the `impl` sugar is a small price to pay for the simplification of the language. Modules would be modules and types would be types. Append to the advantages list: - The complexity related to (possibly-generic) types in paths would go away On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq matthieu.monr...@gmail.com wrote: I see no reason for the restriction of self. Why not simply say that any function can be called with first_arg.func(...) style ? Yeah, as I mentioned in the last bullet of the previous letter, you could do this. I don't think it makes much difference either way and don't have a strong opinion. In favor of explicit `self` is that it's, well, explicit: you can and should call this using method syntax. I can imagine there might be function signatures where using method syntax wouldn't make sense (though you might say, then don't use it, and I would be inclined to agree). A non-method function (one without a `self` arg) also wouldn't cause ambiguity if it were in scope at the same time as you were calling another method with the same name. In favor of always allowing method syntax on the first argument is that you could destructure it in the definition, e.g. `fn area((x, y): (int, int)) - int { x * y }`, and still call the function using method syntax. They're all pretty minor. -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
I think it's unfortunately too late to overhaul the language like this. This will require redesigns of all Rust code in existence. I do like unified function/method call syntax, but I think it can be done in a backwards compatible way. Patrick Gábor Lehel illiss...@gmail.com wrote: On Sat, Oct 19, 2013 at 4:08 PM, Oren Ben-Kiki o...@ben-kiki.org wrote: I'm less certain about giving up `impl Foo { ... }`, though - that is useful for logically grouping, documenting and accessing functions (as in `Foo::foo(...)`). But it seems we don't have to give it up, just make it optional? Interesting point. I think this argues in favor of removing anonymous `impl`s, even as sugar. I was focused on normal (selfish) methods in my previous letter, rather than static (selfless) ones. You could still achieve much the same effect, if you wanted to, by writing: struct Foo { .. } fn get_thing(self: Foo) - Bar { .. } // for `some_foo.get_thing()` syntax mod Foo { fn new() - Foo { .. } // for `Foo::new()` syntax } Rust already allows this trickery: the type and module are imported together when you write `use some_mod::Foo`. Keeping this seems fine, and making it more explicit (relative to `impl`) seems like a good thing. What you lose is that in the case of a generic type, you would have to write the generic-bits for each function, which is the more typing disadvantage from earlier. I think losing the `impl` sugar is a small price to pay for the simplification of the language. Modules would be modules and types would be types. Append to the advantages list: - The complexity related to (possibly-generic) types in paths would go away On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq matthieu.monr...@gmail.com wrote: I see no reason for the restriction of self. Why not simply say that any function can be called with first_arg.func(...) style ? Yeah, as I mentioned in the last bullet of the previous letter, you could do this. I don't think it makes much difference either way and don't have a strong opinion. In favor of explicit `self` is that it's, well, explicit: you can and should call this using method syntax. I can imagine there might be function signatures where using method syntax wouldn't make sense (though you might say, then don't use it, and I would be inclined to agree). A non-method function (one without a `self` arg) also wouldn't cause ambiguity if it were in scope at the same time as you were calling another method with the same name. In favor of always allowing method syntax on the first argument is that you could destructure it in the definition, e.g. `fn area((x, y): (int, int)) - int { x * y }`, and still call the function using method syntax. They're all pretty minor. -- Your ship was destroyed in a monadic eruption. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev -- Sent from my Android phone with K-9 Mail. Please excuse my brevity.___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] real-time programming? usability?
On Fri, Oct 18, 2013 at 11:02 PM, Daniel Micay danielmi...@gmail.comwrote: On Sat, Oct 19, 2013 at 12:45 AM, Jerry Morrison jhm...@gmail.com wrote: On Fri, Oct 18, 2013 at 6:13 PM, Daniel Micay danielmi...@gmail.comwrote: On Fri, Oct 18, 2013 at 7:37 PM, Jerry Morrison jhm...@gmail.comwrote: (1) Rust has great potential for *real-time programming* as well as secure programming. Perhaps this just needs a library call to fork real-time threads that never do garbage collection. (Real-time means predictably meeting time deadlines, e.g. in avionics, video capture, medical x-ray, and robotics. Speed is important but the crucial point is reliably meeting deadlines. Garbage collectors, JIT compilers, and run-time optimizers are bad for predictability.) Maybe Rust already has this. What determines whether a thread-local managed heap uses reference counting? Ref-counting may be OK in a real-time thread if it doesn't deallocate a variable-length chain of nodes at an inconvenient time. Rust leaves memory allocation up to the user as much as C++. Most code can simply use unboxed values and lightweight references, with occasional usage of owned boxes (single-owner heap allocations, with lifetime tied to scope). Ideally, forking a real-time thread could ensure that (1) no GC pauses the thread just to find out there's no garbage to collect, and (2) something would catch the mistake if it ever calls code (directly or indirectly) that evolves to using GC memory. Rust doesn't currently have a way to forbid features only in some parts of the code but not others. Avoiding garbage collection as a hard requirement will likely mean using rust-core (or whatever it evolves to, maybe a special profile of the standard library). So with a suitable library, real-time threads can avoid garbage collection pauses. Can it enforce linking to this library for all the code it calls, or else arrange for the standard GC memory allocator to fail!() if it accidentally called? If you need shared ownership, it's available via the `Rc`/`RcMut` types. Every split of ownership is explicit via a `clone` call since moves are the default. There will be a task-local garbage collector providing garbage collected pointers, but it still needs to be implemented. Sounds good, although I don't understand the details. Does the program pick between GC allocation and ref counting allocation via the choice of pointer sigils? Via the choice of library calls? Reference counting is implemented as a library type, so you would make a reference counted allocation with `Rc::new(value)` and make an explicit reference count with `box.clone()` (the implementation: https://github.com/mozilla/rust/blob/master/src/libstd/rc.rs). There are managed pointers sigils for garbage collection (@, @mut) but I think consensus is trending towards replacing the syntax with a type similar to `Rc` allowing cycles and implicit copies. The compiler support could be exposed via attributes hooks like the operator traits, rather than syntax. Nice. The standard library implements N:M concurrency and exposes a blocking API for asynchronous I/O. I don't think it would be suitable for a real-time application, but you can avoid the standard library: https://github.com/thestinger/rust-core What's N:M concurrency? The concurrency model implemented in the standard library treats real threads as schedulers, and maps cooperatively scheduled tasks onto them. If the task doesn't make calls to functions with yields, it will monopolize a scheduler thread. It's a very good model for I/O or for high throughput on many CPU-bound batch jobs (https://www.threadingbuildingblocks.org/), but it's not going to be suitable for real-time needs. Thanks. That makes sense. -- Jerry @1fish2 ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
On Sat, Oct 19, 2013 at 1:52 PM, Patrick Walton pwal...@mozilla.com wrote: I think it's unfortunately too late to overhaul the language like this. This will require redesigns of all Rust code in existence. I do like unified function/method call syntax, but I think it can be done in a backwards compatible way. What do you have in mind at the moment? Implementing UFCS while still keeping the `impl` syntax around for structs? What about for primitive types, e.g. would `fn double(a: int) - { 2*a }` be callable as `2.double()`, without breaking backward compatibility? Thanks -- Ziad ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] real-time programming? usability?
On Sat, Oct 19, 2013 at 2:33 PM, Jerry Morrison jhm...@gmail.com wrote: So with a suitable library, real-time threads can avoid garbage collection pauses. Can it enforce linking to this library for all the code it calls, or else arrange for the standard GC memory allocator to fail!() if it accidentally called? There's no dynamic checking needed; you just need to include the #[deny(managed_heap_memory)] attribute in the crate file. (There's also a way to do the same thing with a command-line flag.) This will result in a compile-time failure if any code might use garbage collection (including code in external libraries that's called by your code). Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt Being queer is not about a right to privacy; it is about the freedom to be public, to just be who we are. -- anonymous, June 1990 ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] real-time programming? usability?
On Sat, Oct 19, 2013 at 2:36 PM, Tim Chevalier catamorph...@gmail.comwrote: On Sat, Oct 19, 2013 at 2:33 PM, Jerry Morrison jhm...@gmail.com wrote: So with a suitable library, real-time threads can avoid garbage collection pauses. Can it enforce linking to this library for all the code it calls, or else arrange for the standard GC memory allocator to fail!() if it accidentally called? There's no dynamic checking needed; you just need to include the #[deny(managed_heap_memory)] attribute in the crate file. (There's also a way to do the same thing with a command-line flag.) This will result in a compile-time failure if any code might use garbage collection (including code in external libraries that's called by your code). Cheers, Tim Fantastic. Thanks, Tim! For a program with some real-time threads plus other code like UI, I assume the other code can be in a crate that allows managed_heap_memory. -- Jerry ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] real-time programming? usability?
On Sat, Oct 19, 2013 at 5:43 PM, Jerry Morrison jhm...@gmail.com wrote: On Sat, Oct 19, 2013 at 2:36 PM, Tim Chevalier catamorph...@gmail.comwrote: On Sat, Oct 19, 2013 at 2:33 PM, Jerry Morrison jhm...@gmail.com wrote: So with a suitable library, real-time threads can avoid garbage collection pauses. Can it enforce linking to this library for all the code it calls, or else arrange for the standard GC memory allocator to fail!() if it accidentally called? There's no dynamic checking needed; you just need to include the #[deny(managed_heap_memory)] attribute in the crate file. (There's also a way to do the same thing with a command-line flag.) This will result in a compile-time failure if any code might use garbage collection (including code in external libraries that's called by your code). Cheers, Tim Fantastic. Thanks, Tim! For a program with some real-time threads plus other code like UI, I assume the other code can be in a crate that allows managed_heap_memory. -- Jerry The `managed_heap_memory` lint will prevent using any types containing managed pointers, but won't strictly prevent calling code using garbage collection. In a `#[no_std]` codebase, the compiler will prevent using managed pointers unless the hooks for them are defined. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Strange behavior about Writer trait
Consider this program: trait AdderIncr { fn add(self, x: Self) - Self; fn incr(mut self); } impl AdderIncr for int { fn add(self, x: int) - int { *self + x } fn incr(mut self) { *self += 1; } } fn incrAdd(x: mut AdderIncr, y: mut AdderIncr) { x.incr(); x.add(y); } fn main() {} It fails to compile: Documents/test.rs:13:1: 13:10 error: cannot call a method whose type contains a self-type through an object Documents/test.rs:13x.add(y); ^ The Self type is meaningless in object methods, since I have no way to ensure that y has the same underlying type as x. Thus, only a subset of the methods of a trait are available on the corresponding object, which means that objects can't automatically implement their corresponding trait. That means any impls that implement a trait for all types that implement AdderIncr, for example, won't implement that trait for AdderIncr, since AdderIncr doesn't implement AdderIncr. On Sat, Oct 19, 2013 at 2:47 AM, Oren Ben-Kiki o...@ben-kiki.org wrote: Hmmm That sounds strange. Shouldn't `obj: T` allow me to invoke `obj.method_of_T()`? For example, how did I manage to invoke the `data.print(...)` method via the borrowed `data: PrintWithSpice` pointer? Automatic dereference? And if so, why didn't it work for `Writer` as well? On Sat, Oct 19, 2013 at 9:29 AM, Steven Fackler sfack...@gmail.comwrote: If T is a trait, its trait objects ~T, @T and T do not implement T. There is an implementation of Writer for @Writer, but not for ~Writer or Writer which is why you're seeing that error. Steven Fackler On Fri, Oct 18, 2013 at 11:27 PM, Oren Ben-Kiki o...@ben-kiki.orgwrote: Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but I can't cast any @Writer (such as `io::stdout()`) to it. I guess I should just use `@Writer` everywhere for now :-( This raises the question of how come the compiler is smart enough to figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough to figure out a `Writer` has the trait... On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.orgwrote: I run into the following problem (the code below is a toy example). ``` use std::io::Writer; // Makes no difference if added/removed. trait PrintWithSpice { fn print(self, writer: Writer, spice: bool); } struct Bar { bar: ~PrintWithSpice, } impl Bar { pub fn print(self, writer: Writer) { self.bar.print(writer, false); Bar::print_via_borrowed(writer, self.bar); } fn print_via_borrowed(writer: Writer, data: PrintWithSpice) { // Invoking the `print` function via the borrowed pointer to the `PrintWithSpice` trait: // Works fine, as expected.. data.print(writer, true); } } struct Foo { foo: bool } impl PrintWithSpice for Foo { fn print(self, writer: Writer, spice: bool) { // Invoking the `write_str` function via the borrowed pointer to the `Writer` trait: // error: failed to find an implementation of trait std::io::Writer for std::io::Writerno-bounds // What is going on? writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice)); } } ``` I didn't understand what the compiler is complaining about. failed to find an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling a function via a borrowed pointer to a trait should just work (it does a few lines above). After digging I discovered what the compiler really meant (I think). The `write_str` method is defined for `WriterUtils` rather than for `Writer`. So, if I replace `Writer` by `WriterUtil` in the above code, it compiles fine. So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am using that instead of `Writer` all over my code. I can see doing that as a workaround, but it doesn't smell right to me. So: * Why is the compiler complaining about not finding an implementation for `Writer` when the method I invoke is from `WriterUtil`? * Since there is an `implT: Writer for WriterUtil`, shouldn't the compiler be sufficiently smart to deduce that the code is valid in the 1st place? * Until the compiler is sufficiently smart (or, if there is a good reason why it would never be), shouldn't we rename `Writer` to `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become more usable? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
This is meant as a followup to an earlier thread[1] on the subject and the related ticket[2]. [1]: http://thread.gmane.org/gmane.comp.lang.rust.devel/2622/ [2]: https://github.com/mozilla/rust/issues/6974 The idea in those earlier discussions is that methods could also be called using function syntax, supplying `self` as the first argument, so instead of `self_arg.method(arg)`, you could write `method(self_arg, arg)`. I'm wondering if this could be taken a couple steps further to simplify the whole story regarding functions, methods, traits, and impls. The idea is that the distiction between functions and methods would be erased almost completely, and methods (now being just functions) would be imported explicitly. It would involve the following pieces: - If the first argument of a top-level `fn` is named `self`, it can be called using method syntax. So if you have `fn foo(self: MyType, n: int) { .. }` at the top level, you can write `object_of_my_type.foo(123)`. You can also still call it using function syntax: `foo(object_of_my_type, 123)`. I see no reason for the restriction of self. Why not simply say that any function can be called with first_arg.func(...) style ? D has that rule (which they call UFCS), and I find it confusing sometimes. When a function is declared with function syntax and it makes sense or feels right that it should be a function, my mind is not expecting to see method syntax and I may have trouble figuring out later what an apparent method call refers to, even if I've seen the function declaration. Mind you it is worse in D than Rust, because in D, function declarations can be hidden inside what they call eponymous templates, which has stumped me in the past. In any case, wouldn't it help narrow down searches if you could search for fn foo(self instead of only fn foo? (again though, Rust is not as bad for searching as the C-family languages that have no fn keyword.) In C# it's nice that I can find all the so-called extension methods by searching for (this . ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
On Sat, Oct 19, 2013 at 4:35 PM, David Piepgrass qwertie...@gmail.comwrote: In C# it's nice that I can find all the so-called extension methods by searching for (this . Aren't `impl`s in Rust somewhat similar to extension methods in C#? For instance: trait Doubler { fn double(self) - Self; } impl Doubler for int { fn double(self) - int { *self * 2 } } Then you can call 5.double(). -- Ziad ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] This Week in Rust
Welcome to another issue of *This Week in Rust*, a weekly summary of Rust's progress and happenings in the community. # What's cooking in master? 48 PRs were merged this week. ## Breaking changes - Slices are now represented as [number of elements, not number of bytes](https://github.com/mozilla/rust/pull/9885). - `fmt!` has been [completely removed](https://github.com/mozilla/rust/pull/9919). - Some fields in `std::comm` [have been made private](https://github.com/mozilla/rust/pull/9935). - `std::sys::refcount` [has been moved](https://github.com/mozilla/rust/pull/9922) to `std::managed::refcount`. - [A bunch of functions](https://github.com/mozilla/rust/pull/9896/files#diff-69196c6d2488bf8d5b3471084e854407L22) have moved from `std::sys` to `std::mem`. - `once fn` is [now a feature gate](https://github.com/mozilla/rust/pull/9863) rather than a `-Z` flag. - `Path` has been [completely rewritten](https://github.com/mozilla/rust/pull/9655). - `extra::flatpipes` [has been removed](https://github.com/mozilla/rust/pull/9886). ## Other changes - `jemalloc` has been [removed from the runtime](https://github.com/mozilla/rust/pull/9933). The [associated issue](https://github.com/mozilla/rust/issues/9925) is quite scary. - `rustdoc` [struct field visibility](https://github.com/mozilla/rust/pull/9946) is now corrected (it stripped fields where it should not have). - `rustdoc` also [uses the actual privacy rules](https://github.com/mozilla/rust/pull/9941) to strip methods. - `format!` now gives [much better](https://github.com/mozilla/rust/pull/9932) error messages for invalid format strings. - The `fmt::Default` trait, used for default formatting with `format!`, is [now documented](https://github.com/mozilla/rust/pull/9938). - `include_bin!` has been optimized, and the `k-nucleotides` benchmark now compiles [187x faster](https://github.com/mozilla/rust/pull/9851). - Vectors now have [`starts_with` and `ends_with` methods](https://github.com/mozilla/rust/pull/9907), which take slices. - An `abort` intrinsic [has been added](https://github.com/mozilla/rust/pull/9860). - Vectors now have a [`get_opt` method](https://github.com/mozilla/rust/pull/9608). ## New contributors A new section for new contributors! The new contributors this week are (as reported by git): - Chris Sainty - Eduard Burtescu - Erik Lyon - Harry Marr - Sébastien Chauvel - Vijay Korapaty - Ziad Hatahet - chitra # Weekly Meeting The [weekly meeting](https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-10-15) discussed removing rusti, changing the attribute syntax, destructors in statics, and more multi-crate packages with rustpkg. # Announcements etc - Rust (and Servo) are participating in the [GNOME Outreach Program for Women](https://groups.google.com/forum/#!topic/mozilla.dev.servo/7kX_E0FlfkA). A bunch of people have already come into IRC about it. - http://exercism.io [is getting full Rust support](https://github.com/kytrinyx/exercism.io/pull/866). This is a very cool resource, and could help a lot getting newcomers acclimated. - [Unified Function/method Call Syntax and further simplification](https://mail.mozilla.org/pipermail/rust-dev/2013-October/006034.html). - [Safe Memory Management in Cyclone](http://www.reddit.com/r/rust/comments/1osbq2/safe_manual_memory_management_in_cyclone_research/). - [Audio](http://opensourcebridge.org/sessions/970) from Tim's talk in June is finally available! - An [OSdev](https://github.com/mozilla/rust/wiki/Operating-system-development) community has sprung up! The channel is `#rust-osdev`. - [Should I/O use conditions?](http://www.reddit.com/r/rust/comments/1omw47/should_io_use_conditions/). - [Pointers in Rust: A Guide](http://www.reddit.com/r/rust/comments/1opo36/pointers_in_rust_a_guide/). - I am on a [Rust hiatus](http://cmr.github.io/blog/2013/10/14/rust-hiatus/), for the time being. TWiR will still be happening, as you are reading it right now. - [rust-core](https://github.com/thestinger/rust-core) - A stub standard library. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Unified function/method call syntax and further simplification
On Saturday, October 19, 2013, Ziad Hatahet wrote: On Sat, Oct 19, 2013 at 4:35 PM, David Piepgrass qwertie...@gmail.comjavascript:_e({}, 'cvml', 'qwertie...@gmail.com'); wrote: In C# it's nice that I can find all the so-called extension methods by searching for (this . Aren't `impl`s in Rust somewhat similar to extension methods in C#? Loosely, if you ignore that each impl overloads an abstract interface (trait) over the Self type, and that you can constrain a type parameter based on whether there's an overload of a certain abstract interface for it. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev