Rust experiments Entry: Rustboot Date: Sun Sep 15 17:30:39 EDT 2013 https://github.com/charliesome/rustboot Entry: Getting stuck on iterators Date: Sat Sep 21 21:29:06 EDT 2013 Seems the language has changed quite a bit recently. Compiling today's version... Doesn't change much except for breaking my code.. Switched back to 0.7 and wrote 'range' manually as in [1] [1] https://github.com/charliesome/rustboot/blob/master/main.rs Entry: 4 million task switches per second is a bit much Date: Sat Sep 21 22:57:01 EDT 2013 Running salea at 4MHz, with each byte going through the channel. It chokes on that.. But it looks like it can handle 100kHz. Preliminary conclusion: tasks are not state machines.. A little disappointing but not really surprising. Entry: Buffered channels Date: Sat Sep 21 23:26:57 EDT 2013 From here[1] it seems that context switches happen as soon as there is a write to a waiting reader. For logic.rs this is too inefficient. How to implement a Port differently such that we can send larger chunks? For the logic analyser it might even make sense to encode events in a differential way. Is Port a trait? -> NO Seems though that it should be possible to just abstract the input of parsers to a trait that allows both ports and state machines. Probably just the iterator interface? static trop_len = 1024 trait Trop { fn vcer(&self); } impl Trop for Port { fn vcer(&self) { self.recv(); } } [1] https://mail.mozilla.org/pipermail/rust-dev/2013-May/004127.html Entry: Buffered channels : again Date: Sun Oct 6 10:17:54 EDT 2013 Let's do this. A buffered channel needs two ends. How does that map into traits? Probably two traits are needed, and a "constructor" returns an object that supports two traits, but is exposed only one side through each interface? This doesn't seem to be the right approach: trait BufPort { fn recv(&self) -> T; } trait BufChan { fn send(&self, T); } struct WrappedStream { p : Port, c : Chan, } impl BufPort for WrappedStream { fn recv(&self) -> T { self.p.recv() } } -> error: instantiating a type parameter with an incompatible type `T`, which does not fulfill `Send` Need to modify the *endpoints* of a channel, not the channel type itself. Hmm.. Getting the same errors with this: trait BufPort { fn _recv(&self) -> T; } trait BufChan { fn _send(&self, T); } struct WrappedPort { p : Port } struct WrappedChan { c : Chan } impl BufPort for WrappedPort { fn _recv(&self) -> T { self.p.recv() } } impl BufChan for WrappedChan { fn _send(&self, e:T) { self.c.send(e); } } Start simpler? Looking around the docs, I ran into `SendDeferred' http://static.rust-lang.org/doc/0.8/std/rt/comm/trait.SendDeferred.html It needs: use std::rt::comm::SendDeferred; It doesn't seem to solve the performance issue. Next? Go back to the prev buffer impl and figure out what the error means. Check this: "Implementation for ChanOne where " from http://static.rust-lang.org/doc/0.8/std/comm.html The "Send" trait is mentioned here as a special trait, implemented by the compiler: http://pcwalton.github.io/blog/2012/08/08/a-gentle-introduction-to-traits-in-rust/ "Other special traits include send, which is a trait that indicates the type is sendable" So I misread. This is not a channel constraint, but a sendable data constraint. With annotation fixed: trait BufPort { fn recv(&self) -> T; } trait BufChan { fn send(&self, T); } struct WrappedPort { p : Port } struct WrappedChan { c : Chan } impl BufPort for WrappedPort { fn recv(&self) -> T { self.p.recv() } } impl BufChan for WrappedChan { fn send(&self, e:T) { self.c.send(e); } } Entry: #[start] and/or #[no_std] Date: Thu Nov 14 01:35:43 EST 2013 https://github.com/pcwalton/zero.rs : This is deprecated and is no longer maintained. It is no longer necessary to use this to achieve runtime-less operation; just use #[start] and/or #[no_std] and avoid the runtime. http://osdir.com/ml/rust-mozilla-developemnt/2013-10/msg00032.html : Entry: #[no_std] Date: Mon Dec 9 21:40:05 EST 2013 Doesn't work out of the box. https://github.com/thestinger/rust-core/blob/master/example.rs Entry: Project Date: Tue Dec 10 15:07:40 EST 2013 What am I building? Support code for the synth. A sound playback / recording engine? I don't have specs for this, so probably not a good candidate. What do I have specs for? A state machine OS? Entry: FFI Date: Sun Aug 10 21:47:30 EDT 2014 I'd like to make some bindings to zl (to be) used in PDP / libprim / packetforth.. FFI seems really simple. [1] http://doc.rust-lang.org/guide-ffi.html Entry: No more segmented stacks Date: Mon Aug 11 00:15:15 EDT 2014 https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html Entry: Cross compiler ARM Date: Mon Aug 11 12:26:42 EDT 2014 ./configure --target=arm-unknown-linux-gnueabi && make rustc --target=arm-unknown-linux-gnueabi --linker=arm-linux-gnueabi-gcc hello.rs [1] https://mail.mozilla.org/pipermail/rust-dev/2014-February/008556.html Entry: Byte pointer to rust array? Date: Tue Aug 12 20:12:08 EDT 2014 Is it possible to access a raw byte segment as a rust array? I don't see a way to do this so let's just copy. How to create an unintialized array? http://www.reddit.com/r/rust/comments/29ymbx/a_macro_to_fill_a_fixed_length_array/ Entry: Rust on ARM Date: Fri Sep 12 21:51:49 CEST 2014 Adapted from [1] See also [2] # rust-compile-arch.sh arm-unknown-linux-gnueabihf ARCH=build-arm-none-eabi mkdir build-$ARCH cd build-$ARCH ../configure --target=$ARCH --prefix=$HOME/local/rust-$ARCH make -j8 && make install Now this gives both: lib/rustlib/arm-unknown-linux-gnueabihf/lib/libstd-e32fa708-0.11.0.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x5e4e77d08ff8b891de8b2de6111b670b34592974, not stripped lib/libstd-e32fa708-0.11.0.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x20f6f1b890229f5ae1164e60a00e4f5bc72d63ec, not stripped How to invoke the ARM compiler? $ bin/rustc --target=arm-unknown-linux-gnueabi /tmp/test.rs /tmp/test.rs:1:1: 1:1 error: can't find crate for `std` /tmp/test.rs:1 fn main() { Not using --target compiles a native binary. EDIT: Read [1]: to invoke PATH=$HOME/local/rust-arm-unknown-linux-gnueabihf:$PATH rustc -C linker=/usr/bin/arm-linux-gnueabihf-gcc -C target=arm-unknown-linux-gnueabihf test.rs [1] https://gist.github.com/mcpherrinm/11239842 [2] http://zwizwa.be/darcs/pool/bin/rust-compile-arch.sh Entry: armboot Date: Sat Sep 13 11:06:19 CEST 2014 The way it works for armboot[1] is to output LLVM IR and compile that manually. This means no std. So it seems the main point for "./configure --target" is to cross-compile the libraries tied to a particular processor,system,abi. Questions: - what is the difference between *.so in lib/ *.so and *.rlib in lib/rustlib/x86_64-unknown-linux-gnu/lib/ lib/rustlib/arm-unknown-linux-gnueabihf/lib/ [1] https://github.com/neykov/armboot/blob/master/Makefile [2] http://comments.gmane.org/gmane.comp.lang.rust.devel/8476 Entry: Crosscompile Date: Sat Sep 13 13:48:34 CEST 2014 ./configure --target=arm-unknown-linux-gnueabi && make rustc --target arm-unknown-linux-gnueabihf -C linker=arm-linux-gnueabihf-g++ hello.rs test.rs:1:1: 1:1 error: can't find crate for `std` Adding the path explicitly seems to work: rustc --target arm-unknown-linux-gnueabi -L/home/tom/git/rust/build/20140913-114516/x86_64-unknown-linux-gnu/stage2/lib/rustlib/arm-unknown-linux-gnueabi/lib/ -C linker=arm-linux-gnueabi-g++ /tmp/test.rs Entry: pyla Date: Mon Sep 15 01:13:41 CEST 2014 Maybe I should add rust support to the pyla code. Just to give a point of comparison. What it will feel like to write state machines in rust.. The combination with BeagleLogic would be nice as well. Entry: armboot Date: Tue Sep 30 20:01:01 CEST 2014 Allow C types. Is this unsafe? #![allow(ctypes)] Don't use the standard library, see [2]. #![no_std] Open some feature gates. "mark certain features as either deprecated or experimental and subject to change" [3] #![feature(macro_rules)] see [4] #![feature(globs)] #![feature(lang_items)] Found these files from the name ./libsyntax/ext/tt/macro_rules.rs ./librustc/middle/lang_items.rs #![crate_id="blinky#0.3.2"] [1] https://github.com/neykov/armboot [2] http://doc.rust-lang.org/guide-unsafe.html [3] http://cmr.github.io/blog/2014/01/12/the-state-of-rust-0-dot-9/ [4] http://rustbyexample.com/staging/macros.html Entry: browsing rust code Date: Tue Sep 30 20:18:45 CEST 2014 It's not small: [zwizwa_2014-09-13] tom@zni:~/git/rust/src$ cat `find -name '*.rs'` | wc 452236 1835277 16678526 [zwizwa_2014-09-13] tom@zni:~/git/rust/src$ for i in *; do echo -e "$(find $i -name '*.rs' | wc -l)\t$i"; done 0 compiler-rt 7 compiletest 0 doc 1 driver 0 etc 1 grammar 0 gyp 0 jemalloc 7 liballoc 1 libarena 0 libbacktrace 18 libcollections 49 libcore 33 libcoretest 4 libdebug 1 libflate 1 libfmt_macros 1 libfourcc 1 libgetopts 1 libglob 2 libgraphviz 11 libgreen 1 libhexfloat 1 liblibc 3 liblog 17 libnative 5 libnum 10 librand 2 librbml 10 libregex 1 libregex_macros 1 librlibc 155 librustc 13 librustc_back 3 librustc_llvm 22 librustdoc 20 librustrt 20 librustuv 1 libsemver 6 libserialize 75 libstd 18 libsync 66 libsyntax 6 libterm 2 libtest 1 libtime 5 libunicode 1 liburl 1 libuuid 0 libuv 0 llvm 0 README.md 0 rt 0 rustllvm 0 snapshots.txt 3613 test Entry: Unsafe code Date: Tue Sep 30 20:59:13 CEST 2014 http://doc.rust-lang.org/guide-unsafe.html Entry: pyla - streams Date: Wed Oct 1 10:59:27 CEST 2014 So, what about writing logic analyzer core routines in rust in a functional style, and then bind them to loops over buffers? THE single most important (and simple!) problem I keep encountering. Not so much about how to write the nitty gritty, but how to organize it so it stays efficient. If I understand correctly, Rust should be able to do this. Start with (s,i)->(s,o) First problem is parametric polymorphism. A generic iterator should not care about the atom types, just the containers. Let's have a look at the Iterator library[1]. [1] http://doc.rust-lang.org/std/iter/trait.Iterator.html Entry: Project Date: Tue Jan 20 14:38:45 EST 2015 Audio controller in rust. Something that can run on an embedded device with touchscreen. I want dancing waveforms on the screen, but don't need 3D. The problem has always been widgets. So let's fix that. Entry: gui requirements Date: Tue Jan 20 16:50:18 EST 2015 - smooth. it's fucking 2015. no more excuses for not having smooth guis that update at full framerate and have no tearing. - this means double buffering. I'd also like to use this for embedded systems, so allow for selective redraw. - So start with an OpenGL application that syncs to the display and uses double buffering. - Should have midi learn Entry: picking up again Date: Fri Jan 30 12:14:20 EST 2015 Not clear why io is now old_io. https://www.reddit.com/r/rust/comments/2tdudy/psa_io_old_io/ Entry: rust logic: external iterators Date: Fri Jan 30 14:32:41 EST 2015 It seems easiest to abstract things as external iterators. So let's abstract the buffer sequence flattening as an iterator. there is already flat_map() http://doc.rust-lang.org/core/iter/trait.IteratorExt.html Entry: Functional vs. Mutation Date: Fri Jan 30 15:21:28 EST 2015 So for the logic analyzer, and important question is to use in-place update or not. Is a rust "fold" smart enough to use in-place update for an object that stays mostly the same? It seems that even if the fold would be smart enough to take care of performance concerns, there is still the element that a mutating algorithm is a lot easier to read and write (less code!). I think (hearsay) this is also part of what Lens is doing for Haskell: provide a mutable interface for small updates. Entry: General idea for logic analyzer Date: Fri Jan 30 15:28:21 EST 2015 For performance reasons it's important to keep data in chunks. This translates to a nested iterator for the outer management layer: sequence of buffers of bytes. The internal layer does not bother with protocols. Encode protocols in byte streams. For performance reasons, all state is private and updated in-place. EDIT: see lars project Entry: Checking inner loops Date: Sun Feb 1 15:48:23 EST 2015 So I have some code that iterates over a trait operation. AFAIK this should be possible to optimize. How to find that loop in llvm IR or asm? Entry: printing types Date: Sun Feb 1 20:46:20 EST 2015 Just a note that if you want to quickly determine the type of an expression, you can do let () = { /* my expression here */ } [1] https://www.reddit.com/r/rust/comments/2h26cj/functions_returning_iterators/ Entry: iterators and associated types Date: Sun Feb 1 20:51:20 EST 2015 wtf is this? Why not simply a type parameter? pub trait Iterator { type Item; // associated type ... } and pub trait Iterator { // parameter ... } [1] https://www.reddit.com/r/rust/comments/2mdcyy/associated_types/ Entry: Iterator Date: Sun Feb 1 20:55:30 EST 2015 What is the difference between: expected `core::iter::Iterator`, found `core::slice::Iter<'_, u8>` A type is not a trait. [1] https://www.reddit.com/r/rust/comments/2l2c2r/beginner_iteratorvector_problem/ Entry: hours Date: Sun Feb 1 21:13:29 EST 2015 Entry: Iterators Date: Sun Feb 1 21:25:41 EST 2015 Seems that passing around iterators is a mess. What about passing around things that can produce iterators? Is there a trait for the .iter() method? Entry: Sinking in Date: Sun Feb 1 23:37:55 EST 2015 So Iterator is a trait, not a type. Apparently it's not (yet) possible to have a function be typed to return a trait. [1] https://stackoverflow.com/questions/26953280/how-to-create-a-non-consuming-iterator-from-a-vector Entry: Not copying iterators Date: Sun Feb 1 23:41:10 EST 2015 One way seems to be to just create iterators from iterators. I.e. map, filter, fold. Let's look at filter and mimick its operation. This still has the problem of needing to type return values.. It seems simplest to just implement the iterator Trait for all processors, and use a pull-style anyway. [1] https://www.reddit.com/r/rust/comments/2h26cj/functions_returning_iterators/ Entry: Switching to Iterators and pull style Date: Sun Feb 1 23:51:52 EST 2015 Seems to fit better with the way rust treats sequences. Entry: expected bound lifetime parameter , found concrete lifetime Date: Mon Feb 2 11:21:40 EST 2015 http://stackoverflow.com/questions/24847331/rust-lifetime-error-expected-concrete-lifetime-but-found-bound-lifetime Entry: Reporting bug Date: Mon Feb 2 11:49:44 EST 2015 To reproduce: https://github.com/zwizwa/lars d0a9cae2d174c181f80a3e2716118dd59945be78 bug compiling la.elf ( make la.elf ) This is on Debian wheezy/jessie/sid cocktail. rustc 1.0.0-nightly (1d00c545e 2015-01-30 19:56:34 +0000) binary: rustc commit-hash: 1d00c545ede609b9d43fdf9f252c15da5a66dac7 commit-date: 2015-01-30 19:56:34 +0000 host: x86_64-unknown-linux-gnu release: 1.0.0-nightly [master] tom@zoo:~/lars$ make la.elf RUST_BACKTRACE=1 rustc la.rs -o la.elf ERROR:rbml::reader: failed to find block with tag 7 error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html note: run with `RUST_BACKTRACE=1` for a backtrace thread 'rustc' panicked at 'explicit panic', /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/librbml/lib.rs:266 stack backtrace: 1: 0x2b9353530870 - sys::backtrace::write::h26b40214a7757117H8t 2: 0x2b9353553be0 - failure::on_fail::h7a79bf921b6662fbzkB 3: 0x2b93534c01f0 - rt::unwind::begin_unwind_inner::hfe1c0e12f5e834cfAZA 4: 0x2b935a46b550 - rt::unwind::begin_unwind::h13771489483523584678 5: 0x2b935a46a2e0 - reader::get_doc::hca9c74691b431218nLa 6: 0x2b93553feac0 - metadata::decoder::item_type::h11e3fdce04437c2aTqh 7: 0x2b935540fa40 - metadata::decoder::get_type::h81f5136878596756uDh 8: 0x2b93553be9b0 - metadata::csearch::get_type::h9b0725336787e95fjuk 9: 0x2b9353fb38d0 - collect::CollectCtxt<'a, 'tcx>.AstConv<'tcx>::get_item_type_scheme::ha84927afd1cd11a416u 10: 0x2b9353fa2550 - astconv::ast_path_to_ty::h5eef35501e32996d3It 11: 0x2b9353fa3a40 - astconv::ast_ty_to_ty::closure.32670 12: 0x2b9353f3d7f0 - astconv::ast_ty_to_ty::hdfd5055274123a4bN9t 13: 0x2b9353f9c060 - vec::Vec.FromIterator::from_iter::h13503769950079175686 14: 0x2b9353f99cc0 - astconv::convert_angle_bracketed_parameters::h9025012b833df2f4Vit 15: 0x2b9353f3d260 - astconv::ast_path_substs_for_ty::hb223d380e0653eb777s 16: 0x2b9353fa2550 - astconv::ast_path_to_ty::h5eef35501e32996d3It 17: 0x2b9353fa3a40 - astconv::ast_ty_to_ty::closure.32670 18: 0x2b9353f3d7f0 - astconv::ast_ty_to_ty::hdfd5055274123a4bN9t 19: 0x2b9353f9cb70 - astconv::convert_ty_with_lifetime_elision::h6aef1296b36bbcec2mt 20: 0x2b9353fa78d0 - astconv::ty_of_method_or_bare_fn::hfbbddbe9dd8fd2d8Dtu 21: 0x2b9353fa7750 - astconv::ty_of_method::h90bdcfba9a641a98Zru 22: 0x2b9353fcba40 - collect::convert_methods::ty_of_method::h37cc71cdb4ced048svv 23: 0x2b9353fb94e0 - collect::convert::hbd254ededfa34065yyv 24: 0x2b9353ff3670 - check_crate::closure.33797 25: 0x2b9353ff15b0 - check_crate::hd5b0ce5ac42bd86cIEz 26: 0x2b935311bf50 - driver::phase_3_run_analysis_passes::h3a3da09b2eae9713NFa 27: 0x2b9353103330 - driver::compile_input::h802d2a6759ac022fBba 28: 0x2b93531c9230 - run_compiler::h4517938d3296cfc5l9b 29: 0x2b93531c78c0 - thunk::F.Invoke::invoke::h5452441173088021345 30: 0x2b93531c67f0 - rt::unwind::try::try_fn::h8490101008730471441 31: 0x2b93535bef60 - rust_try_inner 32: 0x2b93535bef50 - rust_try 33: 0x2b93531c6aa0 - thunk::F.Invoke::invoke::h13338196279056651375 34: 0x2b93535403b0 - sys::thread::thread_start::h395b8c6815673c5cN3w 35: 0x2b935950bfe0 - start_thread 36: 0x2b9353b73c99 - __clone 37: 0x0 - make: *** [la.elf] Error 101 http://doc.rust-lang.org/complement-bugreport.html Entry: unboxed closures Date: Mon Feb 2 14:02:40 EST 2015 https://www.reddit.com/r/rust/comments/2lo6yt/closures_vs_unboxed_closures/ Entry: Function pointers Date: Mon Feb 2 14:27:41 EST 2015 So I want to parameterize a function with a kind of continuation, i.e. some sink that takes a value while i'm going through a loop. How does it know its state, and does the function type need to reflect this? There are a couple of options: closures and the call operators [1][2]. (expected fn pointer, found closure) [3] [1] http://doc.rust-lang.org/std/ops/trait.Fn.html [2] http://doc.rust-lang.org/std/ops/trait.FnMut.html [3] https://stackoverflow.com/questions/24979454/differences-between-fn-and-in-type-for-an-array-of-functions [4] https://www.reddit.com/r/rust/comments/2lpdvn/callbacks/ Entry: trait objects Date: Mon Feb 2 15:00:58 EST 2015 [1] https://huonw.github.io/blog/2015/01/peeking-inside-trait-objects/ Entry: frustrated Date: Mon Feb 2 16:33:40 EST 2015 * Maybe this is for another time when I have some more patience. The type system is complex and takes a long time to absorb in my current state of mind. * There is no way around knowing all (most?) there is to know about the trait system to do any reasonable abstraction. * It is hard to find documentation that is up-to-date. Again, no patience to weed through all this. Maybe wait for 1.0? Maybe wait to relax and go with the flow.. Entry: Rust Types Date: Mon Feb 2 16:55:20 EST 2015 [1] http://cosmic.mearie.org/2014/01/periodic-table-of-rust-types/ Entry: Traits Date: Mon Feb 2 17:06:33 EST 2015 So it seems that to use traits in arguments (or return types) the options are: - Use trait pointers, which will resolve type dispatching dynamically. - Write the function as a trait, which allows type-dispatch at compile time. Entry: traits Date: Mon Feb 2 17:11:11 EST 2015 So basically it seems that a lot of programming in rust needs generics. Even for simple callbacks it's necessary to implement behavior as a trait or resort to trait objects, delegating type dispatch to run time. Two points where this gets a little annoying: - Iterators - Closures: Fn / FnMut Traits seem to work due to the interplay of parameterized structs and constraints on the trait and implementation. Elaborate. Entry: slices Date: Mon Feb 2 20:41:11 EST 2015 &[T] is a fat pointer (pointer + size), implemented by std::raw::Slice. https://stackoverflow.com/questions/25027751/is-t-literally-an-alias-of-slice-in-rust Entry: "Explicit lifetime bound required" Date: Mon Feb 2 21:32:16 EST 2015 hint: I've seen many cases where a trait was accidentally used instead of a regular type and there was no obvious hint as to why a lifetime bound would be required at all. Don't confuse types and traits. In: pub fn stream<'a,I>(i: I) -> Stream<'a,I> where I:Iterator, { ... } The I can't just be substituted. It seems that the where clause means something like I implements the trait ... These are called Bounds[2]. [1] https://github.com/rust-lang/rust/issues/16948 [2] http://rustbyexample.com/bounds.html Entry: generic programming in rust Date: Mon Feb 2 22:19:17 EST 2015 - create a struct to contain state data - have the struct implement a trait - wrap the struct in a function that instantiates it - call trait methods on the result of that function call Entry: still running into corner cases with iterator Date: Tue Feb 3 13:59:49 EST 2015 /* It's not possible to type ther return value as an Iterator because that's a trait so would either require trait objects (which seem to cause lifetime problems) or implement the Iterator trait using a struct which requires a lot of boiler plate. It seems easier to just type the functions with the concrete return type (that implements the Iterator trait). https://www.reddit.com/r/rust/comments/2h26cj/functions_returning_iterators/ */ use std::iter::{Counter,Take,Map,count}; use std::ops::{Range}; //use core::ops::{Fn}; extern crate core; fn bits_bit(c: &Config, v: usize) -> Take> { count(v,0).take(c.period) } fn bits_frame(c: &Config, v: usize) -> Map,Fn(usize)->usize> { (0us..c.nb_bits+2).map(|&:bit:usize| (((v | (1 << c.nb_bits)) << 1) >> bit) & 1) } fn bits_samples(c: &Config, data: &Vec) -> Vec { data.iter().flat_map(|&x| bits_frame(c, x)).collect() } Entry: flat_map Date: Thu Feb 5 01:46:26 EST 2015 01:44 < doelie> hi, any idea why this gives a lifetime error: 01:44 < doelie> fn main() { for _ in (0u8..10).flat_map(|x| (0u8..10).map(|y| x+y)) {} } 01:44 < lfairy> since contributors disagree on that 01:44 < eddyb_> doelie: flat_map stores its result 01:45 < eddyb_> doelie: maybe move |y| x+y will work for the inner closure 01:45 < doelie> eddyb_: thanks for the pointer 01:46 < eddyb_> doelie: the result of calling the closure you gave to it, to be precise (which in this case, contains another closure, which borrows x by default) have a look at flat_map implementation. Entry: UI on embedded box Date: Fri Feb 13 19:26:49 EST 2015 As a UI, what is realistic to expect? - OpenGL ES - touch screen Maybe best not to worry about it too much and just go ahead with linux / OpenGL. Otoh directFB might be interesting. Dev box? Let's just stick with OpenGL and mouse for now. Entry: cross-compile Date: Sun Feb 15 17:27:10 EST 2015 BUILD=build-20150215 PREFIX=$(readlink -f ~/lib/rust/$BUILD) LD_LIBRARY_PATH=$PREFIX/lib mkdir -p $PREFIX mkdir -p ~/git/rust/$BUILD cd ~/git/rust/$BUILD ../configure --target=arm-unknown-linux-gnueabi --prefix=$PREFIX && make -j4 && make install Entry: trait objects Date: Sun Feb 15 18:43:40 EST 2015 Composing iterators from higher order functions works well, as long as you keep them "inside" a function. data_in.iter() // expand data word into bits FIXME: add frame strobe, polarities .flat_map(|&data| (0..nb_bits).flat_map(move |shift| { let bit = (data >> (nb_bits - 1 - shift)) & 1; // expand bit into clocked bit sequence (0..2).map(move |clock| (clock << c.clock_channel) | (bit << c.data_channel)) })) // oversample .flat_map(|bus| (0..period).map(move |_| bus))) Trying to turn them into trait objects becomes problematic[1]: You can't put anything meaningful in **what goes here**. The closure you define has a compiler-generated type that you can't name (that is, until abstract return types are implemented). Creating an iterator object should be possible if the closures are boxed as well, but requires a wrapper struct for the Fn trait so at this point, the simplest way to reuse that code is to make a macro. [1] https://stackoverflow.com/questions/27496278/how-to-return-a-generic-map-struct Entry: Moving Vec out of mutable borrowed object. Date: Tue Feb 17 18:09:06 EST 2015 18:07 < doelie> Hi. I have Vec living inside a borrowed mutable object. I'd like to move this vec somewhere and replace it with a new one. Rust doesn't let me move it because owner is borrowed. Is there a way to "copy and empty" into a new vector without actually copying the data? 18:07 <@kmc> doelie: mem::replace 18:07 < doelie> thanks! http://doc.rust-lang.org/std/mem/fn.replace.html Entry: graphics Date: Fri Feb 20 21:25:43 EST 2015 glium seems the best way in. [1] https://tomaka.github.io/glium/glium/index.html Entry: opengl terminal emulator Date: Fri Feb 20 21:35:16 EST 2015 Not really what I'm looking for. What I want is a notebook style thing. I.e. what is possible in emacs, but using widgets. Maybe drracket is the thing to go for? The thing is, what I want to do is really simple. Just give me a black-and-white frame buffer and I'll figure it out. https://www.reddit.com/r/programming/comments/1dsjyj/i_wrote_an_open_source_terminal_emulator_which/ Entry: job vranish on embedded rust Date: Fri Feb 20 23:46:23 EST 2015 http://spin.atomicobject.com/2015/02/20/rust-language-c-embedded/ https://lobste.rs/s/3twwvw/embedded_rust_right_now Entry: intrinsics / volatile Date: Sun Feb 22 20:04:39 EST 2015 http://doc.rust-lang.org/std/intrinsics/ Entry: Rust on STM32F1,4 Date: Mon Feb 23 23:27:36 EST 2015 Seems like it is mostly trivial, as objects can be mixed. Startup can be done in C for now, on top of libopencm3. I just need an application. The app would be a minimal core for running RAI processors on the discovery & AXO boards. Entry: Rust OpenGL stuff Date: Tue Feb 24 01:35:04 EST 2015 Two parts: - glutin: OpenGL context provider - glium: OpenGL high level wrapper Another strain: - gfx-rs: A high-performance, bindless graphics API - glfw: glfw3 bindings - gfx-gl: OpenGL bindings for gfx, based on gl-rs - gl: OpenGL bindings It was heavy on the shaders so maybe that's just how OpenGL is these days? Let's just suck up the examples. Start with the explanation from the author[1]. And the other strain.. which to pick? I really just want raw OpenGL. I have C++ widget code already.. My take: this needs to run on an embedded device eventually. I'm thinking of an LCD screen as an Eurorack module, or a stand-alone box. Let's split it in two parts: - Find an embedded arm board that can host an LCD (touch) screen. No android or apple shit: start from scratch. This would probably need to be OpenGL ES. - Should not be too hard to develop on PC / regular OpenGL and keep portability in mind. [1] https://www.reddit.com/r/rust_gamedev/comments/2mkbs9/gliums_design_choices/ [2] https://gfx-rs.github.io/2014/07/25/intro.html Entry: Too much at once Date: Tue Feb 24 21:51:56 EST 2015 - Libraries are not stable. Hard to get a working example to run. - OpenGL has gotten complicated. This is going to take some time to absorb. So where to start? Either go back to C and stick with the familiar approach or push through to get a working Rust example. Entry: Build failures Date: Tue Feb 24 21:57:05 EST 2015 So building a library and it fails. Probably due to missing dev packages for the C libs, but how to find out? Getting obscure things like: src/khronos_api/src/lib.rs:4:36: 4:68 error: couldn't read src/khronos_api/api/gl.xml: couldn't open path as file (no such file or directory (No such file or directory); path=src/khronos_api/api/gl.xml; mode=open; access=read) src/khronos_api/src/lib.rs:4 pub static GL_XML: &'static [u8] = include_bytes!("../api/gl.xml"); Yeah I can't do this while I'm sick and tired.. Start with just reading this source https://github.com/bjz/gl-rs/blob/master/examples/static_triangle.rs Straightforward red tape.. Entry: Are there any iterators that own an array? Date: Sat Feb 28 20:36:39 EST 2015 I wrote this struct InArr2 { a: [f32; 2], i: usize } fn in_arr2(a: [f32;2]) -> InArr2 { InArr2 { a:a, i:0 } } impl Iterator for InArr2 { type Item = f32; fn next(&mut self) -> Option { if self.i == self.a.len() { return None; } let rv = self.a[self.i]; self.i += 1; return Some(rv); } } Because this (0..2).flat_map(|i| [0,1].into_iter().cloned()); says that [0,1] doesn't live long enough. I think the reason for that is that into_iter() takes a reference, not ownership. I think I understand why. Arrays are a bit special in that they are statically allocated. It seems hard to do things like "turn an array into an iterator" because the storage of the array should actually be inside the iterator in the first place. That is why the above works, but it seems this is hard to do generically. Entry: Ownership woes: trees versus traversals Date: Sun Mar 1 17:32:51 EST 2015 Rust has some rough edges. Most of those can be worked around by finding a simpler solution. Managing ownership isn't always easy. A simple thing to keep in mind is that when you want to order objects in many different ways it is often possible to use one of those orderings as a way to handle the ownership (tree), and implement the other orderings as traversals. Entry: Next Date: Mon Mar 2 00:55:31 EST 2015 Basics are there: - event - draw The rest should be filling in the blanks and maybe doing some reactive stuff. What widgets? Maybe reconstruct a 303 - Pattern sequencer: buttons, sliders, note numbers - VU meter - Waveform display Entry: Pointer Date: Mon Mar 2 00:56:45 EST 2015 Box owned trait object &Trait borrowed trait object Entry: boilerplate Date: Thu Mar 5 01:02:56 EST 2015 Is there a way around this? The type annotation is cumbersome and repeated 3 times: - struct def - constructor - trait implementation struct FIR2 where I:Iterator, T:Clone { last: T, iter: I } fn fir2 (iter: I, init: T) -> FIR2 where I:Iterator, T:Clone { FIR2 { last: init, iter: iter } } impl Iterator for FIR2 where I:Iterator, T:Clone { type Item = (T,T); fn next(&mut self) -> Option<(T,T)> { match (self.iter.next()) { None => None, Some(current) => { let last = mem::replace(&mut self.last, current.clone()); Some((current, last)) } } } }