foo!(x, y, z);
// expands to
fn xx(self) -> T {..}
fn xy(self) -> T {..}
...
fn xxx(self) -> T {..}
fn xxy(self) -> T {..}
fn xyz(self) -> T {..}
fn xzx(self) -> T {..}
//and so on
...
Is it possible for macros to generate additional data? I would like to implement vector swizzling. There are many combinations for a Vector4. 4 + 2^2 + 3^3 + 4^4 = 291 combinations
I haven't done anything with macros besides simple substitution, so I am wondering if something like that could be expressed or do I need compiler plugins for that?
Rust supports 3 methods of code generation:
macros declared with macro!
procedural macros relying on plugins (unstable)
build.rs
The latter is a built-in build script specifically supporting code generation/3rd-party libraries build (such as C libraries).
In your case, you are specifically interesting in the Code Generation part, which is simple enough (quoting the docs):
// build.rs
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("hello.rs");
let mut f = File::create(&dest_path).unwrap();
f.write_all(b"
pub fn message() -> &'static str {
\"Hello, World!\"
}
").unwrap();
}
Given this, you can automatically generate any .rs file before the build starts without encountering the macro hygiene issue or having to rely on a nightly compiler.
Related
The following example is a minimal example that I found that explains the problem I am having:
use std::borrow::BorrowMut;
use std::ops::DerefMut;
#[derive(Debug, Clone)]
enum ConnectionState {
NotStarted,
}
type StateChangedCallback = Box<FnMut(ConnectionState) + Send + Sync>;
fn thread_func(mut on_state_changed: StateChangedCallback) {
let new_state = ConnectionState::NotStarted;
let f: &mut BorrowMut<StateChangedCallback> = &mut on_state_changed;
f.borrow_mut().deref_mut()(new_state);
}
fn main() {
let on_state_changed = Box::new(|new_state| {
println!("New state: {:?}", new_state);
});
let join_handle = std::thread::spawn(|| thread_func(on_state_changed));
join_handle.join().unwrap();
}
I have a simple thread that needs to call a callback passed from main. The callback is the signature Box<FnMut(ConnectionState) + Send + Sync>, since I want to call it multiple times. The only way I managed to call the callback was with this weird syntax:
let f: &mut BorrowMut<StateChangedCallback> = &mut on_state_changed;
f.borrow_mut().deref_mut()(new_state);
I searched and did not find a reasonable explanation for this. I am doing something wrong? Or is this the way Rust works?
If it is so, could someone explain the reason for this syntax?
You are overcomplicating things.
You might explain, why you think, that you have to do borrow_mut(), since there is no borrowing involved in your signature.
Your function thread_func can be simplified to this:
fn thread_func(mut on_state_changed: StateChangedCallback) {
let new_state = ConnectionState::NotStarted;
on_state_changed(new_state);
}
Please note, that in contrast to your sentence "I want to call it (the callback) multiple times" you can't, because you move your closure into the function.
In math it is common to write the amount of a number x as |x|. I would like to adopt a similar method to my code. My try on this looks like this:
prefix operator |
postfix operator |
extension Int {
lazy var absolute = false
static prefix func | (right: Int) -> Int {
assert(right.absolute, "Missed closing absolute value bar.")
right.absolute = false
if right < 0 {
return -value
}
return value
}
static postfix func | (left: Int) -> Int {
assert(!left.absolute, "Missed opening absolute value bar.")
left.absolute = true
return left
}
}
(I think this code won't compile as you cannot add stored properties in extensions as far as I know. It is only there to demonstrate my attempt. I added this functionality to my custom types.)
Despite the fact that this feels like a rather bad solution to me, another problem with this code is, that it won't throw any error, if I forget the opening bar. The assert will only break the running program whenever I call another amount function after forgetting the opening bar in the previous amount function call.
Let me know if you have a better solution!
Thanks.
Let me first say that I don't think this is a good idea. It's much more trouble than it's worth. But here goes:
prefix operator |
postfix operator |
prefix func | <T: Comparable & SignedNumeric>(f: () -> T) -> T {
return f()
}
postfix func | <T: Comparable & SignedNumeric>(n: T) -> () -> T {
return { abs(n) }
}
|42| // returns 42
|(-42)| // returns 42
The idea is that the postfix operator returns a function that is then used as the argument to the prefix operator, which then returns the end result. I originally had it the other way around (the prefix operator returning the function), but the compiler did not like that – it seems the postfix operator has a higher precedence.
The advantage of returning a function is that |42 doesn't compile (because the argument types don't match) and while 42| compiles, you will get an error as soon as you use it in a computation because of a type mismatch.
If you use this with literals, you still have to parenthesize negative numbers because Swift can't parse two consecutive prefix operators. I also haven't tested this very much, there may be other edge cases where it doesn't compile.
Why do I get stuck in a compile loop in Playground when trying to run the following?
func makeIncrementer(byHowMuch: Int) -> ((Int) -> Int) {
func addArg(number: Int) -> Int {
return 2 + number
}
return addArg
}
var twoTimesIncrementer = makeIncrementer(2)
twoTimesIncrementer(7)
Also, how do you call a function returning a function in a non-functional language? Lambda still?
Firstly I do not get stuck in a compile loop, it returns 9 as expected. And Playground has its fair amount of bugs, if something does not work in playground, stick it into an actual project, try to run it and there you will see wether or not it actually works.
Secondly a function returning a function is simply still a function, its naming does not change with its return type. The only thing to note is that in Swift you can have functions as First-Class Objects, your twoTimesIncrementer is a variable as any other.
Other than that my recommendation is not trying to get over-obsessed with the naming of certain patterns or features. Do you have an example of a non-functional language where you can define functions that return functions?
In c++, one can introduce an alias reference as follows:
StructType & alias = lengthyExpresionThatEvaluatesToStuctType;
alias.anAttribute = value; // modify "anAttribute" on the original struct
Is there a similar syntactic sugar for manipulating a (value typed) struct in Swift?
Update 1: For example: Let say the struct is contained in a dictionary of kind [String:StructType], and that I like to modify several attributes in the the struct myDict["hello"]. I could make a temporary copy of that entry. Modify the copy, and then copy the temporary struct back to the dictionary, as follows:
var temp = myDict["hello"]!
temp.anAttribute = 1
temp.anotherAttribute = "hej"
myDict["hello"] = temp
However, if my function has several exit points I would have to write myDict["hello"] = temp before each exit point, and it would therefore be more convinient if I could just introduce and alias (reference) for myDict["hello"] , as follows:
var & alias = myDict["hello"]! // how to do this in swift ???
alias.anAttribute = 1
alias.anotherAttribute = "hej"
Update 2: Before down- or close- voting this question: Please look at Building Better Apps with Value Types in swift (from WWWDC15)!! Value type is an important feature of Swift! As you may know, Swift has borrowed several features from C++, and value types are maybe the most important feature of C++ (when C++ is compared to Java and such languages). When it comes to value types, C++ has some syntactic sugar, and my questions is: Does Swift have a similar sugar hidden in its language?. I am sure Swift will have, eventually... Please, do not close-vote this question if you do not understand it!
I have just read Deitel's book on Swift. While I'am not an expert (yet) I am not completely novel. I am trying to use Swift as efficient as possible!
Swift doesn't allow reference semantics to value types generally speaking, except when used as function parameters declared inout. You can pass a reference to the struct to a function that works on an inout version (I believe, citation needed, that this is implemented as a copy-write, not as a memory reference). You can also capture variables in nested functions for similar semantics. In both cases you can return early from the mutating function, while still guaranteeing appropriate assignment. Here is a sample playground that I ran in Xcode 6.3.2 and Xcode 7-beta1:
//: Playground - noun: a place where people can play
import Foundation
var str = "Hello, playground"
struct Foo {
var value: Int
}
var d = ["nine": Foo(value: 9), "ten": Foo(value: 10)]
func doStuff(key: String) {
let myNewValue = Int(arc4random())
func doMutation(inout temp: Foo) {
temp.value = myNewValue
}
if d[key] != nil {
doMutation(&d[key]!)
}
}
doStuff("nine")
d // d["nine"] has changed... unless you're really lucky
// alternate approach without using inout
func doStuff2(key: String) {
if var temp = d[key] {
func updateValues() {
temp.value = Int(arc4random())
}
updateValues()
d[key] = temp
}
}
doStuff2("ten")
d // d["ten"] has changed
You don't have to make the doMutation function nested in your outer function, I just did that to demonstrate the you can capture values like myNewValue from the surrounding function, which might make implementation easier. updateValues, however, must be nested because it captures temp.
Despite the fact that this works, based on your sample code, I think that using a class here (possibly a final class if you are concerned about performance) is really more idiomatic imperative-flavored Swift.
You can, if you really want to, get a raw pointer using the standard library function withUnsafeMutablePointer. You can probably also chuck the value into an inner class that only has a single member. There are also functional-flavored approaches that might mitigate the early-return issue.
I find myself reading large CSV files and collecting the numerical elements into a Vec<&str>. Thereafter I have to convert them to numeric types and the simplest way I've found to do that is to implement a function like this:
fn to_u32(str: &str) -> u32
{
let str_num: Option<u32> = str.parse();
match str_num
{
Some(num) => num,
None => panic!("Failed to read number"),
}
}
This seems like a fairly common operation so I've sifted through the reference docs but haven't found anything that matches it. Is there a cleaner way to do this?
The Option type has a large variety of adapter methods which can be used to munge the data around more nicely than repeated matchs.
For example, there's unwrap and expect for just extracting the data out of a Some, panicking if the Option is None. The expect method is actually the closest to your written code: str.parse().expect("Failed to read number.").
However, it can often makes sense to use other the functions listed there, to propagate errors, avoiding the hard "crash" of a panic and allowing users (or yourself) to handle errors more centrally and with more control. It also often makes sense to use Result for this, which gives you the chance to pass along more information in the error case, and also allows one to use the try! macro, that said, one can easily define an equivalent of try! for Option:
macro_rules! option_try {
($e: expr) => {
match $e {
Some(x) => x,
None => return None
}
}
}
Well, you can use unwrap() to avoid pattern matching, but you should do it sparingly - with unwrap() you can't handle the actual parse error, so if the string does not represent a number, it'll panic:
let str_num: u32 = str.parse().unwrap();
if let is also an option:
if let Some(str_num) = str.parse::<u32>() {
// ...
}
You can also use unwrap_or() if you want to specify some default value:
let str_num: u32 = str.parse().unwrap_or(42);
Or you can use unwrap_or_default() which employs Default instance for u32:
let str_num: u32 = str.parse().unwrap_or_default();