Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
I think my least favorite thing about refactoring so far has been trying to isolate parts of a chain of iterators. The result of a .map().filter().whatever() has a gnarly result type.

Adbot
ADBOT LOVES YOU

Workaday Wizard
Oct 23, 2009

by Pragmatica

Asymmetrikon posted:

I think my least favorite thing about refactoring so far has been trying to isolate parts of a chain of iterators. The result of a .map().filter().whatever() has a gnarly result type.

Let the compiler help you! The following will give you a compiler error with what you need:

code:
let () = my.very(long).expression(blah, bleh, bloh);
e: This works by failing to destructure a pattern. If this actually compiles then your expression is returning `()`.

Workaday Wizard fucked around with this message at 21:02 on Jan 3, 2017

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

Asymmetrikon posted:

I think my least favorite thing about refactoring so far has been trying to isolate parts of a chain of iterators. The result of a .map().filter().whatever() has a gnarly result type.

There's also inspect: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.inspect

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
Filter is parameterized over a P: FnMut, which the compiler just represents as an anonymous closure, though. How do you express that kind of type concretely?

gonadic io
Feb 16, 2011

>>=

Asymmetrikon posted:

I think my least favorite thing about refactoring so far has been trying to isolate parts of a chain of iterators. The result of a .map().filter().whatever() has a gnarly result type.

Will 'impl trait' help for this case?

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Asymmetrikon posted:

Filter is parameterized over a P: FnMut, which the compiler just represents as an anonymous closure, though. How do you express that kind of type concretely?
You'd have to implement a filtering iterator directly, with the predicate inlined into the implementation of next. Or restructure your code to avoid needing to do so, with generics and/or impl Trait.

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!

gonadic io posted:

Will 'impl trait' help for this case?

Yeah. Is that out of nightly yet?

gonadic io
Feb 16, 2011

>>=

Asymmetrikon posted:

Yeah. Is that out of nightly yet?

Nope! And with good reason, there's still plenty of edge cases and bugs that are falling out. The main functionality works fine though.

Dehumanise yourself and face to nightly.

Or just make extensive use of type inference, either adding no explicit type sig, or use lots of underscores in it.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
So, I'm at a point with rust where I am comfortable with all of the syntax, but am still struggling with borrowing, lifetimes and references. This tutorial is tremendously helpful:

http://cglab.ca/~abeinges/blah/too-many-lists/book/README.html

It walks you through building a number of linked lists, gradually increasing in complexity. It specifically addresses things like Box, Rc, Arc, mem::Replace, &mut, *mut, *const, Copy, and how you'll need to use those things to build a simple data structure in Rust. It's really helped me.

The format is a little annoying (probably too jokey for most people's taste) but the content is solid.

DONT THREAD ON ME fucked around with this message at 19:01 on Jan 7, 2017

xtal
Jan 9, 2011

by Fluffdaddy
Is there such a thing as a function composition or pipelining operator in Rust? I'm also interested in a macro to combine `fn` and `match` since all of my functions match anyway. Yes I come from Haskell and be glad you don't work with me.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

xtal posted:

Is there such a thing as a function composition or pipelining operator in Rust?
No operator, you're supposed to just use the concise closure syntax (e.g. |x| g(f(x))) for that if you really need it. You could write a composition function yourself, but it might be pretty annoying to try to use. A lot of things that work very cleanly in Haskell turn awkward and inconvenient with Rust because the language is much closer to the hardware. When half your functions/accessors take/return references and half don't thinks don't compose as tidily; auto-deref helps for regular first-order code but a naive compose operator wouldn't permit it to work.

Rust is, to its credit, not a great language for point-free shenanigans.

xtal posted:

I'm also interested in a macro to combine `fn` and `match` since all of my functions match anyway. Yes I come from Haskell and be glad you don't work with me.
I hardly ever see this idiom even in Haskell, when it comes to real-world code. Still, is there anything stopping you?

gonadic io
Feb 16, 2011

>>=
On the plus side I got rust's cross-compiling intrinsics working. On the downside now I have this in my code:

Rust code:
 // Extern definitions
extern {
    static mut __etext: usize;
    static mut __data_start__: usize;
    static mut __data_end__: usize;
    static mut __bss_start__: usize;
    static mut __bss_end__: usize;
}
...
// Inside the init function
let data_size = & __data_end__ as *const usize as usize - & __data_start__ as *const usize as usize; 
ptr::copy_nonoverlapping(& __etext as *const usize, &mut __data_start__ as *mut usize, data_size);

let bss_size = & __bss_end__ as *const usize as usize - & __bss_start__ as *const usize as usize; 
ptr::write_bytes(&mut __bss_start__ as *mut usize, 0, bss_size);
Is there a better way to get the addresses of variables? Or the size of the range between two address/pointers? I checked and the core pointer types don't implement any arithmetic operators.

gonadic io fucked around with this message at 22:30 on Jan 28, 2017

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.

gonadic io posted:

On the plus side I got rust's cross-compiling intrinsics working. On the downside now I have this in my code:

Rust code:
 // Extern definitions
extern {
    static mut __etext: usize;
    static mut __data_start__: usize;
    static mut __data_end__: usize;
    static mut __bss_start__: usize;
    static mut __bss_end__: usize;
}
...
// Inside the init function
let data_size = & __data_end__ as *const usize as usize - & __data_start__ as *const usize as usize; 
ptr::copy_nonoverlapping(& __etext as *const usize, &mut __data_start__ as *mut usize, data_size);

let bss_size = & __bss_end__ as *const usize as usize - & __bss_start__ as *const usize as usize; 
ptr::write_bytes(&mut __bss_start__ as *mut usize, 0, bss_size);
Is there a better way to get the addresses of variables? Or the size of the range between two address/pointers? I checked and the core pointer types don't implement any arithmetic operators.

&T and &mut T references will automatically coerce into *const T and *mut T pointers, respectively, so the "as (*const|*mut) usize" isn't necessary for the copy/write calls. Unfortunately, I don't know any shortcuts for getting pointer difference, though.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

gonadic io posted:

On the plus side I got rust's cross-compiling intrinsics working. On the downside now I have this in my code:

Rust code:
 // Extern definitions
extern {
    static mut __etext: usize;
    static mut __data_start__: usize;
    static mut __data_end__: usize;
    static mut __bss_start__: usize;
    static mut __bss_end__: usize;
}
...
// Inside the init function
let data_size = & __data_end__ as *const usize as usize - & __data_start__ as *const usize as usize; 
ptr::copy_nonoverlapping(& __etext as *const usize, &mut __data_start__ as *mut usize, data_size);

let bss_size = & __bss_end__ as *const usize as usize - & __bss_start__ as *const usize as usize; 
ptr::write_bytes(&mut __bss_start__ as *mut usize, 0, bss_size);
Is there a better way to get the addresses of variables? Or the size of the range between two address/pointers? I checked and the core pointer types don't implement any arithmetic operators.

If those are symbols coming from your linker script, they shouldn't have the type "usize", by the way. "()" is way more appropriate, because there's no data backing them. In C or C++ you normally declare them like this:

code:
struct Opaque;
extern struct Opaque __data_start;

This is to prevent you from accidentally trying to read or write a value (the only thing you can do to a variable of an incomplete type is take its address).

gonadic io
Feb 16, 2011

>>=

ShoulderDaemon posted:

If those are symbols coming from your linker script, they shouldn't have the type "usize", by the way. "()" is way more appropriate, because there's no data backing them.

In the C code I'm looking at they're all defined "extern unsigned int" but I suppose that's just bad practice.

I figured out a way to take advantage of the auto-coerce:
code:
fn ptr_diff<T, U>(ptr_1: *const T, ptr_2: *const U) -> usize {
    ptr_1 as usize - ptr_2 as usize
}
...
let data_size = ptr_diff(& __data_end__, & __data_start__); 
ptr::copy_nonoverlapping(& __etext, &mut __data_start__, data_size);

let bss_size = ptr_diff(& __bss_end__, & __bss_start__); 
ptr::write_bytes(&mut __bss_start__, 0, bss_size);

gonadic io
Feb 16, 2011

>>=
"static mut __etext: ();" triggers
code:
warning: found Rust tuple type in foreign module; consider using a struct instead, #[warn(improper_ctypes)] on by default
After some research, the canonical Rust way to produce a zero-sized type for use in FFI is "enum Foo {}": https://internals.rust-lang.org/t/pre-rfc-opaque-structs/4005

For now honestly I think that I'm just going to disable that warning for those definitions as, unlike other sizes of tuples, the memory layout of () is guaranteed.

gonadic io fucked around with this message at 10:58 on Jan 29, 2017

General_Failure
Apr 17, 2005
Oh cool! A Rust thread!

I came over to TCoC to ask a question but this seems like the best place.
I've been trying to get into programming in Rust. I like the idea behind it but grasping the weirdness has slowed me down. Beside the point for this question.

What I'm after is an IDE, or even a decent text editor with Rust support. I really don't feel like going the vim or emacs route. Atom seems okay but it has a few things that bug me.
* It feels clunky and ponderous. It shouldn't be like that!
* It's a royal PITA to build, or at least get the dependencies set up for.
* It seems to have that lovely blurry anti aliasing going on that makes me loathe Ubuntu OOTB. You know what I mean.

Adding to those points I want to use it on an old netbook, a Raspberry Pi running Raspbian and an Orange Pi PC running Armbian. It might seem like a weird choice but I'm ADD as all hell and running on a more resource constrained system helps stop me from goofing off. Plus power has gotten so goddamn expensive I'd rather be burning less watts than a PC if I can.

So what's out there that supports Rust syntax that isn't a poster child for bloat?
Honestly if Rust had been ported to RISC OS I'd use it on that just so I could use Zap or StrongEd. Really nice text editors.

gonadic io
Feb 16, 2011

>>=
I use Visual Studio Code and I like it a lot. It has support for auto-builds, syntax highlighting, error underlining, name lookup, autocomplete (some amount anyway), formatting code and stuff.

No semantic rename yet though sadly.
https://github.com/saviorisdead/RustyCode

e: if you want something leaner and are willing to put up with 1) nagging to pay, and 2) much worse rust support (but still syntax highlighting and goto definition) then there's always sublime

gonadic io fucked around with this message at 23:14 on Jan 31, 2017

Workaday Wizard
Oct 23, 2009

by Pragmatica
intellij-rust is a much more straightforward ide that doesn't require anything extra. makes development real easy.

General_Failure
Apr 17, 2005
Thanks for the suggestions.

Sublime seems pretty good but the closed source nature is problematic because I can't run it on what I want to.

So IntelliJ rust is far enough along to be usable?

Been meaning to try out VS core. Setting up toolchains in Windows is kind of obnoxious so I haven't. IIRC it has a Linux version too, right?

Workaday Wizard
Oct 23, 2009

by Pragmatica

General_Failure posted:

So IntelliJ rust is far enough along to be usable?

It's good enough for me, a terrible programmer.

The most important feature for me, quick navigation between files and definitions, works really well even with stuff in the standard library. I also find the code outline feature really helpful especially when reading third party code with many trait implementations.

You should try it anyway. It won't take much to set up (get intellij, install plugin, point plugin to rust toolkit, voila) and it works with regular old Cargo projects.

General_Failure
Apr 17, 2005

Shinku ABOOKEN posted:

It's good enough for me, a terrible programmer.

The most important feature for me, quick navigation between files and definitions, works really well even with stuff in the standard library. I also find the code outline feature really helpful especially when reading third party code with many trait implementations.

You should try it anyway. It won't take much to set up (get intellij, install plugin, point plugin to rust toolkit, voila) and it works with regular old Cargo projects.

Nice. Cargo projects are actually one of the things that made me want to learn Rust. Leagues ahead of makefiles. On par with a lot of other languages.

Just popped in to say that i got VS Code to build and run on the Pi 3. It seems to have a lot in common with Atom. Is there common code? Haven't worked out how to add plugins yet. It seems to support Rust syntax. What else does it need?
Most of my ham fisted fumbling trying to get Atom to compile came in handy because I'd almost got it right enough to build VS Code. Looks nice. I've been cursing the slow disappearance of decent syntax highlighting editors in Linux.

I'm going to have a crack at IntelliJ Rust too. I've used IntelliJ for Java before. it was okay. I have a violent hatred for Eclipse, so when a new player came about I had another crack at it. Admittedly most of my Java experience was writing programs in vi on a remote Solaris server. My later attempts using Eclipse always ended badly because I got incredibly pissed off at pretty much every aspect of the UI design.

It seems weird but Rust reminds me of Pascal in a way. A positive way. It's a shame it's a dying language these days.

e: Google answered my question. VS Code is based off Atom.

General_Failure fucked around with this message at 13:24 on Feb 1, 2017

Pollyzoid
Nov 2, 2010

GRUUAGH you say?
I did my first thing (a RPN parser/calculator) using Rust and would appreciate any pointers.

https://gist.github.com/pollyzoid/f0a392949d6da38d2aa957d65c7d6587

I have no idea what I'm doing. First version was just a bunch of nested matches, which I rewrote into a recursive function by accessing the Vec<Token> directly with index. Then I rejiggered that into using a reversed iterator instead. It's shorter at least, but I don't know if it's more readable. Maybe I should've just kept the iterative + stack approach.

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.

Pollyzoid posted:

I did my first thing (a RPN parser/calculator) using Rust and would appreciate any pointers.

https://gist.github.com/pollyzoid/f0a392949d6da38d2aa957d65c7d6587

I have no idea what I'm doing. First version was just a bunch of nested matches, which I rewrote into a recursive function by accessing the Vec<Token> directly with index. Then I rejiggered that into using a reversed iterator instead. It's shorter at least, but I don't know if it's more readable. Maybe I should've just kept the iterative + stack approach.

I know I personally prefer an iterative+stack approach, and even started writing a version before realizing that's what your second link was. :v:

Though honestly, with the refactoring you did when you did the reverse-iterator method, converting it back to an iterative method made it a little nicer. Here's the version I came up with. (I even put it on the i32 playground, which has the top crates available, including lazy_static.)

Here are some tips that cleaned up the code a little:

  • "if let" owns. If your match block would have one "useful" match and one "_"/throwaway match, you can save a level of indentation by using "if let" instead. I've got a couple examples in the "exec_stack" function when I use the operators. This is really nice for Options because None is really the same as _ there.
  • If you need to unpack multiple things at the same time, you can match on a tuple of them. I did that when pulling two values out of the stack for the binary ops. (Note that this won't work for values that depend on each other, like if you need to unpack the first to get the second.)
  • When I wrote the return value, I screwed around a little and used an Option combinator to turn it into one line. .ok_or() is a way to turn an Option into a Result by giving an Err value it can use for Nones.
  • Also, that .into_iter() in your parse() function wasn't doing anything.

I will admit that's still kinda deep nesting, though. You can take out one level by factoring the single-token processing into another function, but at that point that's refactoring for purely aesthetic reasons.

mrbass21
Feb 1, 2009
I'm a complete newcomer to Rust, and I just ran through the matching game, and I have a question about some code:

code:
 let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_)  => continue
        };
In the case of the Err, what happens with the assignment? Is continue just executed as an evaluated expression before the assignment, and the assignment never happens?

Edit: After reading a little more of the book, is it that this is binding guess to a pattern? It's still confusing to me if anyone could go into a little more detail and describe what's happening here.

mrbass21 fucked around with this message at 10:42 on Feb 27, 2017

Vanadium
Jan 8, 2005

Yeah, the assignment never happens. It's just that a lot of things in Rust are expressions, so you're more flexibly with what goes where than in C or whatever. You can also write stupid poo poo like return (return (return (return continue))) because continue and return are just divergent expressions of type !. I don't think patterns are relevant at this point.

It's like an .unwrap_or_else(|| continue) if you could magically use continue across closures.

You can also write stuff like this:
code:
let foo = {
  let x = do_a_bunch_of_stuff();
  struct MaybeEvenDeclareALocalType {...}
  ...;

  ultimately_just_put_the_value_for_foo_here(x)
};
and it'll do all the stuff in the block before assigning the result of the final expression to foo. giving you opportunity to return or panic!() or anything.

eth0.n
Jun 1, 2012
Why does this code:

code:
use std::collections::HashMap;
struct foo {
    pub vars: HashMap<String, String>,
}

impl foo {
    fn bar(&mut self, name: &str, val: &str) -> &str {
        if let Some(r) = self.vars.get(name) {
            return r
        }
        return self.vars.entry(name.to_string()).or_insert(val.to_string())
    }
}

fn main() {
    let mut f = foo{vars: HashMap::new()};
    f.bar("hello", "world");
}
give me this error:

code:
error[E0502]: cannot borrow `self.vars` as mutable because it is also borrowed as immutable
  --> src/main.rs:14:16
   |
10 |             if let Some(r) = self.vars.get(name) {
   |                              --------- immutable borrow occurs here
...
14 |         return self.vars.entry(name.to_string()).or_insert(val.to_string())
   |                ^^^^^^^^^ mutable borrow occurs here
15 |     }
   |     - immutable borrow ends here
I figured out that returning a String instead (and cloning the two returns) satisfies the checker, but that could be a needless copy. Is there some other way to fix it, and still return a reference?

I also discovered that "if let" keeps borrows active through the else for some reason, but in other cases, adding the return and moving the "else if" into an "if" was a workaround.

Vanadium
Jan 8, 2005

Ideally you just use the Entry based API for you lookup-or-insert thing, but I guess they're still arguing about how to design the API that doesn't require an up-front copy of the key.

Lifetimes extending past where you'd except them to is a thing they've been posting about for ages, Niko Matsakis has been blogging about it recently so maybe things are happening there, search for non-lexical lifetimes. The if-let thing might be a bug that's fixed in nightly or something.

Workaday Wizard
Oct 23, 2009

by Pragmatica
IIRC the if let thing is because it's sugar for match.

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.

Shinku ABOOKEN posted:

IIRC the if let thing is because it's sugar for match.

This, basically. An "if let" renders the same under the hood as a "match" with one real pattern and one _ pattern.

I might toss this snippet into IRC later today and see if this is a bug. The "if let" there shouldn't extend the borrow past that one block there, even with purely-lexical borrows. For the moment, I got it to work by changing the condition up:

code:
use std::collections::HashMap;
struct foo {
    pub vars: HashMap<String, String>,
}

impl foo {
    fn bar(&mut self, name: &str, val: &str) -> &str {
        if self.vars.contains_key(name) {
            return self.vars.get(name).unwrap();
        }
        self.vars.entry(name.to_string()).or_insert(val.to_string())
    }
}

fn main() {
    let mut f = foo{vars: HashMap::new()};
    f.bar("hello", "world");
}
Kinda awkward to have the unwrap in there, but compiling is better than purity in this case, I guess.

EDIT: According to IRC, this is, in fact, a problem of lexical lifetimes, just one that defies initial understanding. The article linked in chat describes it better, but basically because the "if let" creates a borrow that extends outside the function, it's still treated as borrowed for the rest of the function. The solution suggested in the article (pre-non-lexical-lifetimes) is just like the one I put here: Make the initial branch not create a borrow, so that the rest of the function doesn't treat the map as being borrowed.

QuietMisdreavus fucked around with this message at 19:23 on Mar 2, 2017

Vanadium
Jan 8, 2005

https://github.com/rust-lang/rfcs/pull/1769 sometimes rust just feels like complete bullshit.

xtal
Jan 9, 2011

by Fluffdaddy
You know what the tech community is really missing out on? Bureaucracy​

Workaday Wizard
Oct 23, 2009

by Pragmatica

xtal posted:

You know what the tech community is really missing out on? Bureaucracy​

I don't see how having a documented change process is bad v:shobon:v

Or are you referring to something specific?

eth0.n
Jun 1, 2012

icesoldier posted:

EDIT: According to IRC, this is, in fact, a problem of lexical lifetimes, just one that defies initial understanding. The article linked in chat describes it better, but basically because the "if let" creates a borrow that extends outside the function, it's still treated as borrowed for the rest of the function. The solution suggested in the article (pre-non-lexical-lifetimes) is just like the one I put here: Make the initial branch not create a borrow, so that the rest of the function doesn't treat the map as being borrowed.

Thanks!

In my case, cloning and returning by value is better than doing extra lookups, since I'd always need to do the clone later anyway.

gonadic io
Feb 16, 2011

>>=
Hmm, I'm running into a problem that isn't complex in itself but I'm sure that my solution is really unidiomatic. I'm continuing with my rust-for-arduino project and my RTC alarm enum looks like this

code:
pub enum RtcMode2Alarm {
    OFF, // Never
    SS { // Every Minute
        second: u8
    },
    MMSS { // Every Hour
        minute: u8, second: u8
    },
    HHMMSS { // Every Day
        hour: u8, minute: u8, second: u8
    },
    ...
}
And the goal is to set all of the relevant bits in the alarm match and then set the type of alarm.

Since Rust enums aren't fully-fledged objects that can have static members for each variant like Scala, and if-let blocks don't allow multiple patterns, and I don't really want to write and implement a HasSeconds/HasMinutes trait for this single method I went with this approach (which I don't really like):

code:
        let mut bits = 0u32;
        match alarm {
            SS { second } |
            MMSS { second, .. } |
            HHMMSS { second, .. } |
            DHHMMSS { second, .. } => {
                if second >= (1 << 6) { panic!("{:?} is too large, maximum 6 bits", second); }
                bits |= (second as u32) << 0; // The shifting isn't needed for second, but it is for the other fields
            },
            _ => {}
        }
        ... // do the same for minute, hour, day, month, and year

        self.ALARM.write(bits);
        self.wait_for_sync();

        let mask_val: u8 = match alarm {
            SS {..} => RTC_MODE2_MASK_SEL_SS_VAL,
            ...,
        };

        self.MASK.write(mask_val);
        self.wait_for_sync();
Any suggestions for a better way to do this?
Full snippet is here: https://gist.github.com/djmcgill/91556f58d1aedff2adc7428a6443aac2
Full code is here: https://github.com/djmcgill/to-the-moon/blob/master/src/component/rtc/mod.rs#L142

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.
If this is literally the only place the Alarm enum is being used this might be overkill, but you can implement methods on enums. I'd try implementing a kind of fn seconds(&self) -> Option<u8> that returns Some(second) if available and None if not, just to "hide away" the cumbersome pattern. Plus, you could double that same seconds() call as an OFF detector, since OFF is the only variant that doesn't have a seconds field. As-is, I wouldn't necessarily call that bad, just unfortunate.

syncathetic
Oct 21, 2010
I was going to make the same suggestion, except with a macro https://gist.github.com/anonymous/81b4b2dde02467feb13bc8c2de671ded

gonadic io
Feb 16, 2011

>>=
That is much better thanks, although making a new file and enum for every method is going to bloat my code somewhat...
I went with the explicit approach over the recursive macro for maintenance /ease of understanding purposes.

Next question:
I need to be able to attach a callback to the alarm interrupt. The way this is done in the C is to have a global mutable function pointer. When the alarm goes off if the pointer isn't null then execute the function.

I think I can use a static mut AtomicPtr<&'static Fn() > for this. I can't use Mutex or lazy_static because they both depend on std.

Amy better ways present themselves?

e: hmm, I could at least make the pointer private and the callback a parameter to the set_alarm method.

gonadic io fucked around with this message at 12:45 on Mar 10, 2017

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.
I'd thought the static wouldn't need to be mut because all the loads/stores/swaps/etc only need a shared reference, but apparently there's no const AtomicPtr like there is for the other atomic types, so you'd need to initialize it somehow. :sigh:

Either way that probably works, though the type inside could probably be better served as a fn() or unsafe fn() if you're doing FFI and need the function to be blanket unsafe or whatever. Note the lowercase fn, that's directly a function pointer instead of one of the closure traits.

EDIT: Also, I totally didn't realize the atomic types were in core, huh.

QuietMisdreavus fucked around with this message at 03:23 on Mar 11, 2017

Adbot
ADBOT LOVES YOU

gonadic io
Feb 16, 2011

>>=
Is there a way to generate an identifier inside a macro?

I have a macro that creates a struct that implements a trait (similar to closure structs implementing Fn)

code:
pub trait EightSegment {
    unsafe fn new() -> Self;
    fn display(&mut self, count: u32);
}

macro_rules! create_eight_segment (
    ($struct_name: ident,
     ...
    ) => {{
        pub struct $struct_name;
        impl EightSegment for $struct_name {
            ...
        }
        $struct_name::new()
    }}
);
Which is called like
code:
fn main() {
  let mut digit = unsafe {
    create_eight_segment!(EightSegment2, D7, D6, D3, D4, D5, D8, D9, D2)
  };
  loop {
    let s = ...
    digit.display(s);
  }
}
But I don't like that you have to explicitly specify the name of the struct. Is there a way to generate some name that you can never refer to, like how closure objects work?

Full code is here.

gonadic io fucked around with this message at 16:30 on Mar 22, 2017

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply